赞
踩
由于OpenGL Core Profile与 大多数平台上WebGL渲染器的限制,无论如何设置该值,线宽始终为1。 解决方法:线用面来代替,首选使用现成的库,今天就使用MeshLine.js
原版github.com/spite/THREE…
es版代码地址,使用这一版 github.com/utsuboco/TH…
- npm i three.meshline
- 复制代码
- import { MeshLine, MeshLineMaterial, MeshLineRaycast } from 'meshline';
- 复制代码
setPoints
- setPoints(points: Float32Array | Array<number>, wcb?: (p: number) => any): void;
- 复制代码
根据传入的顶点数据生成几何体
setGeometry
- setGeometry(g: THREE.BufferGeometry, c: (p: number) => any): void;
- 复制代码
根据一个THREE.BufferGeometry来获取顶点数据生成几何体
MeshLineMaterial继承自ShaderMaterial,所以ShaderMateria上的有些属性也是可以用的(比如 wireframe: true)
- export class MeshLineMaterial extends THREE.ShaderMaterial
- 复制代码
map
- 贴图 THREE.TextureuseMap
- 是否使用贴图 (0 - 不使用,用color中的颜色, 1 - 使用)alphaMap
- 一张灰度纹理,用于控制整个表面的不透明度 THREE.TextureuseAlphaMap
- 是否使用灰度贴图 (0-不使用, 1-使用)repeat
- 设置纹理的重复 THREE.Vector2color
- 线的颜色opacity
- 透明度 (transparent
需要透明设置为 true`)alphaTest
- 透明度测试,设置一个0-1的值,透明度小于这值的就不会显示dashArray
- 通俗解释为 一组虚线(有颜色部分跟间隔部分加起来)占总长度的比例,决定绘制多少组虚线(详见后面示例)dashOffset
- 一组虚线中间隔开始的位置,改变其位置用来实现动画 (详见后面示例)dashRatio
- 定义一组虚线中无颜色的间隔部分占比为多少 0-1(详见后面示例)resolution
- 指定画布大小THREE.Vector2
sizeAttenuation
- 线的大小是否会受相机影响。(0 - 不会, 1 - 会)lineWidth
- 线宽- mesh.raycast = MeshLineRaycast
- 复制代码
把线模型这样设置后,raycaster.intersectObjects([线模型])的时候,就能捕捉到线模型了
开启wireframe: true,看出生成的几何体,是跟着相机在不断调整朝向,才看起来不是一个片
- ....省去基本场景的搭建
- // 生成一段贝赛尔曲线
- const curve = new THREE.CubicBezierCurve3(
- new THREE.Vector3(-100, 0, 0),
- new THREE.Vector3(-50, 150, 0),
- new THREE.Vector3(200, 150, 0),
- new THREE.Vector3(100, 0, 0)
- )
- // 获取这段线上51个坐标点
- const points = curve.getPoints(50)
- // 将坐标数据存入positions中
- const positions = []
- for (let j = 0; j < points.length; j++) {
- positions.push(points[j].x, points[j].y, points[j].z)
- }
- // 初始化MeshLine
- const line = new MeshLine()
- // 传入顶点坐标数据
- line.setPoints(positions)
- // 获取纹理,官方案例中的纹理
- this.texture = new THREE.TextureLoader().load('static/material/stroke.png')
- this.texture.wrapS = this.texture.wrapT = THREE.RepeatWrapping
- // 生成线材质
- this.material = new MeshLineMaterial({
- useMap: 0,
- color: new THREE.Color(0x006666),
- opacity: 1,
- resolution: new THREE.Vector2(window.innerWidth, window.innerHeight),
- sizeAttenuation: 1,
- lineWidth: 20,
- transparent: true,
- wireframe: true,
- map: this.texture
- })
- // 生成模型
- const mesh = new THREE.Mesh(line.geometry, this.material)
- this.scene.add(mesh)
- 复制代码
- this.material = new MeshLineMaterial({
- useMap: 1, //修改
- color: new THREE.Color(0x006666),
- opacity: 1,
- resolution: new THREE.Vector2(window.innerWidth, window.innerHeight),
- sizeAttenuation: 1,
- lineWidth: 20,
- transparent: true,
- // wireframe: true, //修改
- map: this.texture
- })
- 复制代码
为了直观注释掉transparent: true
- this.material = new MeshLineMaterial({
- useMap: 1,
- color: new THREE.Color(0x006666),
- opacity: 1,
- resolution: new THREE.Vector2(window.innerWidth, window.innerHeight),
- sizeAttenuation: 1,
- lineWidth: 20,
- // transparent: true, // 修改
- // wireframe: true,
- dashArray: 0.5, // 修改
- dashRatio: 0.1, // 新增
- repeat: new THREE.Vector2(2, 1), // 新增
- map: this.texture
- })
- 复制代码
dashArray: 0.5,就是每组占0.5,所以分成了两组
repeat: new THREE.Vector2(2, 1),纹理x重复为2,就平铺为两个
dashRatio: 0.1,每组中,间隔部分占比为0.1
- this.material = new MeshLineMaterial({
- useMap: 0, // 修改
- color: new THREE.Color(0x006666),
- opacity: 1,
- resolution: new THREE.Vector2(window.innerWidth, window.innerHeight),
- sizeAttenuation: 1,
- lineWidth: 20,
- transparent: true,
- // useDash: 1,
- // wireframe: true,
- dashArray: 0.5,
- dashRatio: 0.1,
- dashOffset: 0, // 新增
- repeat: new THREE.Vector2(2, 1),
- map: this.texture
- })
- 复制代码
动态改变dashOffset
- // 渲染
- _animate() {
- requestAnimationFrame(this._animate.bind(this))
- if (this.material) {
- this.material.uniforms.dashOffset.value -= 0.005
- }
- }
- 复制代码
不使用纹理时
useMap改为1,使用纹理时
问题来了来,纯色时看着正常,换为纹理时,看得出dashOffset修改的是间隔的位置,纹理的uv并没有动,要想uv动,需要修改源码
参考大佬的修改方式 github.com/maptalks/ma… 下载meshline源码,在源码src中找到material.js,学习上面的方式修改,加入offset参数相关代码,使纹理位置可以改变
( 修改完后可以build出meshline.es.js来使用,或者不压缩直接把meshline文件夹下的文件都放入项目中使用)
同步改变间隔跟新增的offset参数,问题解决
- // 渲染
- _animate() {
- requestAnimationFrame(this._animate.bind(this))
- if (this.material) {
- this.material.uniforms.offset.value.x -= 0.005
- this.material.uniforms.dashOffset.value -= 0.005
- }
- }
- 复制代码
- // 用一个正方体来生成线
- const geometry = new THREE.BoxGeometry(100, 100, 100)
- line.setGeometry(geometry)
- 复制代码
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。