前言
上一节实现了天空盒、扩散墙、扩散圆,这一节来添加飞线,飞点。
思路
主要思路是通过两个点和高度创建贝塞尔曲线,然后把该曲线的点构造成MeshLine
(这个插件可以生成有宽度的线),然后把想要效果的图贴到线上。
- 飞点:
- 飞线
这里用到了别人写的MeshLine
插件(github.com/spite/THREE… ),对这个代码做了一点点修改,可进行模型材质的uv移动(THREE
高版本有问题,我这边用的是127版本没有问题)。
这个修改是借鉴的deckgl
(deck.gl/ )具体的修改就是把UV
偏移量传进去实现偏移。
代码
import * as THREE from 'three';
import { Geometry } from 'three/examples/jsm/deprecated/Geometry';
import { MeshLine, MeshLineMaterial } from './THREE.MeshLine';THREE.Geometry = Geometry;
/*** 波纹散射图层* @param options.img 照片地址* @param options.lineWidth 线宽度* @param options.side 贴图样式* @param options.camera 相机* @param options.height 高度* @param options.v0 点一* @param options.v1 点二* @param options.speed 流动速度* @param options.el 节目场景元素* @param options.type 线类型分run和top* @param options.maxheight 当类型为top时最高上升高度* @param options.line 存储线* @param options.thing 存储setInterval事件* @example*/
class RunLine {constructor(option) {this.img = option.img || '';this.lineWidth = option.lineWidth || 1;this.side = option.side || THREE.FrontSide;this.camera = option.camera || '';this.height = option.height || 100;this.v0 = option.v0 || new THREE.Vector3(0, 0, 0);this.v1 = option.v1 || new THREE.Vector3(0, 0, 0);this.speed = option.speed / 100 || 0.01;this.el = option.el || '';this.scene = option.scene || '';this.type = option.type || 'run';this.maxheight = option.maxheight || 300;this.line = '';this.thing = '';this.creatline();}creatline() {const textureLoader = new THREE.TextureLoader();textureLoader.load(this.img, (texture) => {this.texture = texture;this.texture.anisotropy = 16;this.texture.wrapS = THREE.RepeatWrapping; // 每个都重复this.texture.wrapT = THREE.RepeatWrapping;const resolution = new THREE.Vector2(this.el.offsetWidth, this.el.offsetHeight);const material1 = new MeshLineMaterial({color: '',map: this.texture,useMap: true,lineWidth: this.lineWidth,resolution,dashArray: 0, // 破折号之间的长度和间距。(0 -无破折号)dashRatio: 0.7, // 定义可见和不可见之间的比率(0 -更可见,1 -更不可见)。dashOffset: 1,transparent: true,sizeAttenuation: 1, // 使线宽不变,不管距离(1个单位是屏幕上的1px)(0 -衰减,1 -不衰减)side: THREE.FrontSide,depthTest: false,blending: THREE.AdditiveBlending,near: this.camera.near,far: this.camera.far,});this.line = this.createAnimateLine({kind: 'sphere', // 默认不填 为普通 ; 如为sphere,则表示球面建点type: 'line', // 默认不填 为MeshLine ; 如为pipe,则表示管道线sphereHeightPointsArgs: [this.v0, this.v1],material: material1,number: 50,radius: 3, // 默认});if (this.type === 'run') {this.line1 = this.createAnimateLine({kind: 'sphere', // 默认不填 为普通 ; 如为sphere,则表示球面建点type: 'line', // 默认不填 为MeshLine ; 如为pipe,则表示管道线sphereHeightPointsArgs: [this.v0, this.v1],material: material1,number: 50,radius: 3, // 默认});}this.scene.add(this.line);this.scene.add(this.line1);const { speed } = this;if (this.type === 'run') {this.thing = setInterval(() => {this.line.material.uniforms.offset.value.x -= speed;this.line1.material.uniforms.offset.value.x -= speed;}, 30);} else if (this.type === 'top') {this.thing = setInterval(() => {if (this.line.position.y < this.maxheight) {this.line.position.y += this.speed * 100;} else {this.line.position.y = 0;}}, 30);}});}createAnimateLine(option) {let curve;if (option.kind === 'sphere') {// 由两点之间连线成贝塞尔曲线const { sphereHeightPointsArgs } = option;const vX = (sphereHeightPointsArgs[1].x + sphereHeightPointsArgs[0].x) / 2;const vZ = (sphereHeightPointsArgs[1].z + sphereHeightPointsArgs[0].z) / 2;if (this.type === 'run') {curve = new THREE.CubicBezierCurve3(sphereHeightPointsArgs[0],new THREE.Vector3(vX, this.height, vZ),new THREE.Vector3(vX, this.height, vZ),sphereHeightPointsArgs[1],);} else {curve = new THREE.CubicBezierCurve3(sphereHeightPointsArgs[0],new THREE.Vector3(vX, this.height, vZ),new THREE.Vector3(vX, this.height, vZ),sphereHeightPointsArgs[1],);}}if (option.type === 'line') {const geo = new THREE.Geometry();geo.setFromPoints(curve.getPoints(100));// const geo = new Geometry();// geo.vertices = option.sphereHeightPointsArgs;const meshLine = new MeshLine();meshLine.setGeometry(geo);return new THREE.Mesh(meshLine.geometry, option.material);} // 使用 meshLinereturn '';}delete() {if (this.line) {this.scene.remove(this.line);this.scene.remove(this.line1);}if (this.thing) {clearInterval(this.thing);}}
}export default RunLine;
调用代码
this.runline5 = new RunLine({img: "n.png",camera: camera,height: 140,v0: new THREE.Vector3(614, 18, 130),v1: new THREE.Vector3(-17.5, 111.5, -23),el: document.getElementById("scene"),scene: scene,speed: 1,lineWidth: 12,type: "run",});
效果图
完整项目源码获取:关注公众号「码农园区」,回复 【智慧城市】,即可获取完整项目源
附送250套精选项目源码
源码截图
源码获取:关注公众号「码农园区」,回复 【源码】,即可获取全套源码下载链接