Erlo

一个《跳动的爱心》代码,纯HTML+JS,双击直接运行

收藏 2022-12-18 15:30:43   40   博客园
页面报错/反馈
点赞

HTML+JS实现的一个跳动的爱心。集合了web动画库GSAP JS、OBJ 文件加载器OBJLoader、WebGL第三方库Three.js等。效果非常棒!

实际效果:

image

由于是纯前端项目,JS代码没有任何加密,所以赶快给心爱的人,做一个跳动的爱心吧!

目录结构:

image

HTML代码






  
  爱心
  




  
  
  
  
  
  


  

CSS代码

* {
  padding: 0;
  margin: 0;
}
body {
  background: #ff5555;
  overflow: hidden;
  margin: 0;
  /* background-color: #000 !important; */
}
/**
* 主容器
*/
div#main {
  width: 100vw;
  height: 100vh;
}

/**
* 设置无限的动效
* 单次动效时间3s
*/
heart {
  position: absolute;
  width: 20px;
  height: 20px;
  color: #FFF;
  text-align: center;
  /* background: #e74c3c; */
  font-size: 30px;
  transform: rotate(360deg) scale(.6);
  opacity: .5;
  animation-name: opacity;
  animation-duration: 3s;
  animation-iteration-count: infinite;
}

/**
* 用伪类在heart  content即是展示的文字效果
*/
heart::before {
  position: absolute;
  content: 'love-code';
  width: 200px;
  height: 20px;
  /* background: #e74c3c; */
  border-radius: 50%;
  transform: translateX(-10px);
}

/**
*用伪类在heart
*/

heart::after {
  position: absolute;
  content: '';
  width: 20px;
  height: 20px;
  /* background: #e74c3c; */
  border-radius: 50%;
  transform: translateY(-10px);
}

/**
* 改变透明度
*/
@keyframes opacity {
  25%,
  75% {
      opacity: 1;
  }
  50%,
  100% {
      opacity: .5;
  }
}

js代码:

gsap.min.jsOBJLoader.jssimplex-noise.jsthree.min.jsTrackballControls.js 这几个JS都是现成的。
script.js代码:

console.clear();

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);

const renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setClearColor(0xff5555);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

camera.position.z = 1;

const controls = new THREE.TrackballControls(camera, renderer.domElement);
controls.noPan = true;
controls.maxDistance = 3;
controls.minDistance = 0.7;

const group = new THREE.Group();
scene.add(group);

let heart = null;
let sampler = null;
let originHeart = null;
//new THREE.OBJLoader().load('./obj/heart_2.obj',obj => {
new THREE.OBJLoader().load('https://assets.codepen.io/127738/heart_2.obj',obj => {
  heart = obj.children[0];
  heart.geometry.rotateX(-Math.PI * 0.5);
  heart.geometry.scale(0.04, 0.04, 0.04);
  heart.geometry.translate(0, -0.4, 0);
  group.add(heart);
  
  heart.material = new THREE.MeshBasicMaterial({
    color: 0xff5555    
  });
  originHeart = Array.from(heart.geometry.attributes.position.array);
  sampler = new THREE.MeshSurfaceSampler(heart).build();
  init();
  renderer.setAnimationLoop(render);
});

let positions = [];
const geometry = new THREE.BufferGeometry();
const material = new THREE.LineBasicMaterial({
  color: 0xffffff
});
const lines = new THREE.LineSegments(geometry, material);
group.add(lines);

const simplex = new SimplexNoise();
const pos = new THREE.Vector3();
class Grass {
  constructor () {
    sampler.sample(pos);
    this.pos = pos.clone();
    this.scale = Math.random() * 0.01 + 0.001;
    this.one = null;
    this.two = null;
  }
  update (a) {
    const noise = simplex.noise4D(this.pos.x*1.5, this.pos.y*1.5, this.pos.z*1.5, a * 0.0005) + 1;
    this.one = this.pos.clone().multiplyScalar(1.01 + (noise * 0.15 * beat.a));
    this.two = this.one.clone().add(this.one.clone().setLength(this.scale));
  }
}

let spikes = [];
function init (a) {
  positions = [];
  for (let i = 0; i < 20000; i++) {
    const g = new Grass();
    spikes.push(g);
  }
}

const beat = { a: 0 };
gsap.timeline({
  repeat: -1,
  repeatDelay: 0.3
}).to(beat, {
  a: 1.2,
  duration: 0.6,
  ease: 'power2.in'
}).to(beat, {
  a: 0.0,
  duration: 0.6,
  ease: 'power3.out'
});
gsap.to(group.rotation, {
  y: Math.PI * 2,
  duration: 12,
  ease: 'none',
  repeat: -1
});

function render(a) {
  positions = [];
  spikes.forEach(g => {
    g.update(a);
    positions.push(g.one.x, g.one.y, g.one.z);
    positions.push(g.two.x, g.two.y, g.two.z);
  });
  geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(positions), 3));
  
  const vs = heart.geometry.attributes.position.array;
  for (let i = 0; i < vs.length; i+=3) {
    const v = new THREE.Vector3(originHeart[i], originHeart[i+1], originHeart[i+2]);
    const noise = simplex.noise4D(originHeart[i]*1.5, originHeart[i+1]*1.5, originHeart[i+2]*1.5, a * 0.0005) + 1;
    v.multiplyScalar(1 + (noise * 0.15 * beat.a));
    vs[i] = v.x;
    vs[i+1] = v.y;
    vs[i+2] = v.z;
  }
  heart.geometry.attributes.position.needsUpdate = true;
  
  controls.update();
  renderer.render(scene, camera);
}

window.addEventListener("resize", onWindowResize, false);
function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}

简单的修改

  • 页面闪烁的love-code一共展现520个。可在index.html调整,大约在42行处
  • love-code可以换成你想要的,可在css/style.css里修改,大约在43行处
  • 爱心是读取的网络的3dmax文件,你也可以修改为自己的3dmax文件,位置是js/script.js文件,大约在32行处。

完整文件下载

下载方式:
扫描公众号二维码,或搜索公众号DotNet宝藏库关注我,回复爱心下载。

欢迎大家关注我的微信公众号,一起进步,一起成长

登录查看全部

参与评论

评论留言

还没有评论留言,赶紧来抢楼吧~~

返回顶部

给这篇文章打个标签吧~

棒极了 糟糕透顶 好文章 PHP JAVA JS 小程序 Python SEO MySql 确认