ThreeJS + vue3.0 实现 粒子波浪

<template>
  <div class="LatheBufferGeometry">
  </div>
</template>
<script>
import * as Three from 'Three'
import Stats from 'stats-js'
export default {
  name: 'LatheBufferGeometry',
  setup () {
    // FPS引入
    const stats = new Stats()
    stats.showPanel(1) // 0: fps, 1: ms, 2: mb, 3+: custom
    document.body.appendChild(stats.dom)

    const SEPARATION = 60; const AMOUNTX = 50; const AMOUNTY = 50
    let container
    let camera, scene, renderer
    let particles; let particle; let count = 0
    let mouseX = 0
    let mouseY = 0
    let windowHalfX = window.innerWidth / 2
    let windowHalfY = window.innerHeight / 2

    const init = () => {
      container = document.createElement('div')
      document.body.appendChild(container)
      camera = new Three.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000)
      camera.position.z = 1000
      scene = new Three.Scene()

      // 添加背景图
      const texture = new Three.TextureLoader().load(require('../assets/img/bg-04.jpg'))
      scene.background = texture

      particles = []
      const PI2 = Math.PI * 1
      const material = new Three.SpriteMaterial({
        color: '#DFF9FE',
        program: (context) => {
          context.beginPath()
          context.arc(0, 0, 1, 0, PI2, true)
          context.fill()
        }
      })

      let i = 0
      for (let ix = 0; ix < AMOUNTX; ix++) {
        for (let iy = 0; iy < AMOUNTY; iy++) {
          particle = particles[i++] = new Three.Sprite(material)
          particle.position.x = ix * SEPARATION - ((AMOUNTX * SEPARATION) / 2)
          particle.position.z = iy * SEPARATION - ((AMOUNTY * SEPARATION) / 2)
          scene.add(particle)
        }
      }
      renderer = new Three.WebGLRenderer({ antialias: true, alpha: true })
      // 设置透明度
      renderer.setClearAlpha(0.2)
      renderer.setSize(window.innerWidth, window.innerHeight)
      container.appendChild(renderer.domElement)

      document.addEventListener('mousemove', onDocumentMouseMove, false)
      document.addEventListener('touchstart', onDocumentTouchStart, false)
      document.addEventListener('touchmove', onDocumentTouchMove, false)
      window.addEventListener('resize', onWindowResize, false)
    }

    const onWindowResize = () => {
      windowHalfX = window.innerWidth / 2
      windowHalfY = window.innerHeight / 2
      camera.aspect = window.innerWidth / window.innerHeight
      camera.updateProjectionMatrix()
      renderer.setSize(window.innerWidth, window.innerHeight)
    }

    const onDocumentMouseMove = (event) => {
      mouseX = event.clientX - windowHalfX
      mouseY = event.clientY - windowHalfY
    }

    const onDocumentTouchStart = (event) => {
      if (event.touches.length === 1) {
        event.preventDefault()
        mouseX = event.touches[0].pageX - windowHalfX
        mouseY = event.touches[0].pageY - windowHalfY
      }
    }

    const onDocumentTouchMove = (event) => {
      if (event.touches.length === 1) {
        event.preventDefault()
        mouseX = event.touches[0].pageX - windowHalfX
        mouseY = event.touches[0].pageY - windowHalfY
      }
    }

    const animate = () => {
      stats.begin()
      stats.end()
      requestAnimationFrame(animate)
      render()
    }

    const render = () => {
      camera.position.x += (mouseX - camera.position.x) * 0.05
      camera.position.y += (-mouseY - camera.position.y) * 0.05
      camera.lookAt(scene.position)

      let i = 0
      for (let ix = 0; ix < AMOUNTX; ix++) {
        for (let iy = 0; iy < AMOUNTY; iy++) {
          particle = particles[i++]
          particle.position.y = (Math.sin((ix + count) * 0.3) * 50) + (Math.sin((iy + count) * 0.5) * 50)
          particle.scale.x = particle.scale.y = (Math.sin((ix + count) * 0.3) + 1) * 2 + (Math.sin((iy + count) * 0.5) + 1) * 2
        }
      }

      renderer.render(scene, camera)
      count += 0.1
    }

    // 初始化
    init()
    animate()
  }
}
</script>

在这里插入图片描述

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Huang-ioi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值