2021年的时候,做过一个数据可视化大屏,记得有一个效果是加载地图的动画视频,一个格子地面上,放着一个地图,然后移动视角来实现一个动画的效果。
格子背景动画
动画效果
今天看到这个视频后,就想着有没有办法通过代码来实现这种效果呢?我们先剔除掉地图,只要格子背景。
实现思路
首先创建一个3d场景,
然后,我们需要一个格子图片,让格子图片平铺实现为一个大的网格地面
再然后我们我们调整视角,就达成了我们想要的效果了。
实现代码
首先使用threejs创建一个场景
安装threejs
pnpm i three
threejs版本号
"three": "^0.154.0",
引入three
import * as THREE from 'three';
创建场景
var scene = new THREE.Scene();
创建一个地面
创建一个矩形平面作为地面,然后给地面添加格子纹理贴图,设置阵列,以及重复数量,然后将模型加入到场景中。
/**
* 创建一个地面
*/
var geometry = new THREE.PlaneGeometry(2000, 2000); //矩形平面
// 加载纹理贴图
var texture = new THREE.TextureLoader().load("gezi.png");
// 设置阵列
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
// uv两个方向纹理重复数量
texture.repeat.set(200, 200);
var material = new THREE.MeshLambertMaterial({
map: texture,
});
var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
scene.add(mesh); //网格模型添加到场景中
mesh.rotateX(-Math.PI / 2);
到这里我们的格子地面就出来了。
移动视角
接下来我们就需要移动视角让地面动起来了。移动视角我们需要一个补间动画插件gsap来实现。
我们来准备三个坐标,让相机从初始位置 移动到第二位置,再从第二位置移动到第三位。
// 初始位置
var pos1 = {x: 154.7561874999998, y: 232.13428124999965, z: 154.7561874999998};
// 第二位置
var pos2 = {x: 58.39780486775444, y: 87.59670730163171, z: 58.397804867754445};
// 第三位置
var pos3 = {x: 66.81948313671211, y: 59.54709665418934, z: 51.41563818571308};
// 创建时间线
var tl = gsap.timeline();
// 移动到第二位置
tl.to(camera.position, {
duration: 2, // 持续时间,单位是秒
x: pos2.x,
y: pos2.y,
z: pos2.z,
onUpdate: () => camera.lookAt(scene.position), // 每帧更新时调用的函数
ease: "power1.inOut", // 缓动类型
});
// // 然后移动到第三位置
tl.to(camera.position, {
duration: 3,
x: pos3.x,
y: pos3.y,
z: pos3.z,
onUpdate: () => camera.lookAt(scene.position),
ease: "power1.inOut",
});
最终效果
演示地址
完整实例代码下载
项目运行环境 vue3 vite js nodejs 14