tree.js 实现 腾讯云banner动画

673 阅读1分钟
  • 产品最近看上了腾讯云首页的banner效果,跟我一顿称兄道弟后,让我搞一搞

SDGIF_Rusult_1.gif

  • 主要的难点在Ui建模,前端这边选用tree.js 去实现效果。

难点分析

  • 模型要跟随鼠标旋转,而不是移动,
  • 鼠标无需点击,要使用 mousemove 监听移动。
  • 生成的3d 要背景透明
  • 灯光

直接上代码

<template>
  <div>
    <canvas id="mainCanvas"></canvas>
  </div>
</template>
<script>
import * as THREE from 'three'
// import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
var data = {
  camera: null,
  scene: null,
  mesh: null,
  modelPath: './qing.fbx'
}
export default {
  data() {
    return {
      renderer: null,
      controls: null,
      targetRotation: 0,
      plane: null,
      cube: null,
      mouse: 0,
      time1: null,
      time: null,
      raycaster: null,
      targetRotationOnMouseDown: 0,
      x: 0,
      y: 0,
      z: 0
    }
  },
  methods: {
    init() {
      // 初始化场景
      data.scene = new THREE.Scene()
      // 创建渲染器
      this.renderer = new THREE.WebGLRenderer({
        canvas: document.getElementById('mainCanvas'),
        antialias: true, // 抗锯齿
        alpha: true
      })
      this.renderer.setSize(600, 600)
      this.renderer.setClearColor(0xb9d3ff, 0)
      // 创建透视相机
      data.camera = new THREE.PerspectiveCamera(55, 1, 0.1, 1000)
      data.camera.position.set(30, 10, 55)
      // 参数初始化
      this.mouse = new THREE.Vector2()
      this.raycaster = new THREE.Raycaster()
      // 环境光;
      // var ambientLight = new THREE.AmbientLight(0x606060, 1)
      // data.scene.add(ambientLight)
      //点光
      var dianLight = new THREE.PointLight('#f3f8ff')
      dianLight.intensity = 1
      dianLight.position.set(20, 30, 20)
      data.scene.add(dianLight)
      // 平行光
      var directionalLight = new THREE.DirectionalLight(0xbcd2ee)
      directionalLight.position.set(1, 0.75, 0.5).normalize()
      data.scene.add(directionalLight)
      // //半球光
      // var hemiLight = new THREE.HemisphereLight('#f3f8ff', '#f3f8ff', 0.6)
      // hemiLight.position.set(0, 500, 0)
      // data.scene.add(hemiLight)

      let fbxLoader = new FBXLoader()
      fbxLoader.load(data.modelPath, function (object) {
        data.mesh = object
        data.scene.add(object)
      })
    },

    animate() {
      requestAnimationFrame(this.animate)
      this.renderer.render(data.scene, data.camera)
    },
    MouseMove(event) {
      //移动的时候鼠标相对位置
      // event.preventDefault()
      data.mesh.rotation.x += event.movementY / 1500
      data.mesh.rotation.y += event.movementX / 1500
      this.x = data.mesh.rotation.x
      this.y = data.mesh.rotation.y
    },
    MouseLeave() {
      let x = this.x
      let y = this.y
      clearInterval(this.time1)
      clearInterval(this.time)
      // data.mesh.rotation.y = 0
      // data.mesh.rotation.x = 0
      x = Number(x)
      let count1 = Number(x / 10)
      y = Number(y)
      let count2 = Number(y / 10)

      this.time = setInterval(() => {
        if (x > 0.01 || x < -0.01) {
          x = Number(x - count1)
          data.mesh.rotation.x = x
        } else {
          data.mesh.rotation.x = 0
          clearInterval(this.time)
        }
      }, 20)

      this.time1 = setInterval(() => {
        if (y > 0.01 || y < -0.01) {
          y = Number(y - count2)
          data.mesh.rotation.y = y
        } else {
          data.mesh.rotation.y = 0
          clearInterval(this.time1)
        }
      }, 20)
    }
  },
  mounted() {
    this.init()
    // this.helper();
    this.animate()
    document.getElementById('mainCanvas').addEventListener('mousemove', this.MouseMove, false)
    document.getElementById('mainCanvas').addEventListener('mouseleave', this.MouseLeave, false)
  }
}
</script>
<style scoped></style>

实现效果如下

SDGIF_Rusult_1.gif

背景跟随移动,这个简单,只要使用mosemove 监听鼠标移动事件 mousemoveX 和mousemoveY 改变背景div 的transfrom下的translate 坐标即可,需要注意的是3d模型的旋转速率要跟 背景图的移动距离保持一致,这里需要不断微调。