three.js标签标注、场景信息标注------系统总结,总有一款适合你
视频总结:www.bilibili.com/video/BV1gC...
下面是具体的文字总结
标注技术分类
标注效果分类
CSS2DRenderer渲染HTML元素
HTML元素作为标签使用,标签尺寸不随场景缩放变化
CSS3DRenderer渲染HTML元素
HTML元素作为标签使用,标签尺寸随场景缩放变化
精灵模型Sprite标注
精灵模型可以图片或canvas画布作为纹理,然后标注,可以实现类似CSS3DRenderer渲染HTML元素的效果。
默认区别在于Sprite本质上是threejs模型对象,会被其他模型物体遮挡,但是CSS3标签,本质上是HTML元素,只是叠加到canvas画布上,不是threejs物体的一部分,如果CSS3标签你想隐藏遮挡,需要手动添加代码,通过射线的方式,判断标签是否被其他模型遮挡,然后设置标签的style属性隐藏即可。
图片创建纹理对象,作为精灵Sprite材质的map属性值
canvas画布创建纹理对象,作为精灵Sprite材质的map属性值
2D标注:矩形平面网格模型
地面导航箭头(矩形平面+背景透明的颜色贴图)
地面指南针方向(矩形平面+背景透明的颜色贴图)
地图可视化,地面的波动光圈
3D标注:立体网格模型
智慧城市、地图场景中的热点标注(四棱锥)
火焰特效(序列帧动画或shader)
CSS2DRenderer
(HTML元素作为标签)
下面给大家介绍一个threejs的扩展库CSS2DRenderer.js
,通过CSS2DRenderer.js
可以把HTML元素作为标签标注三维场景。
引入扩展库CSS2DRenderer.js
在threejs文件包目录examples/jsm/renderers/
,你可以找到CSS2DRenderer.js
扩展库。
threejs扩展库CSS2DRenderer.js提供了两个类CSS2渲染器CSS2DRenderer
、CSS2模型对象CSS2DObject
。
js
// 引入CSS2渲染器CSS2DRenderer和CSS2模型对象CSS2DObject
import { CSS2DRenderer,CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
js
// 引入CSS2渲染器CSS2DRenderer
import { CSS2DRenderer } from 'three/addons/renderers/CSS2DRenderer.js';
// 引入CSS2模型对象CSS2DObject
import { CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
总体思路
本节课先为大家演示标签标注最基本的内容,更多需要完善优化的的细节,可以关注后面几节课讲解。
- 1.HTML元素创建标签
- 2.CSS2模型对象
CSS2DObject
- 3.CSS2渲染器
CSS2DRenderer
- 4.
CSS2Renderer.domElement
重新定位
1. HTML元素创建标签
你可以根据需要,使用HTML、CSS代码创建你想要的标签。如果基于vue或react开发,也可以用vue或react创建的UI组件表示标签。
js
<div id="tag">标签内容</div>
如果你想用HTML元素作为标签标注三维场景中模型信息,就需要考虑定位的问题。比如一个模型,在代码中你可以知道它的局部坐标或世界坐标xyz,但是你并不知道渲染后在canvas画布上位置,距离web页面顶部top和左侧的像素px值。
自己写代码把世界坐标xyz,转化为像素px表示屏幕坐标,比较麻烦,不过threejs扩展库CSS2DRenderer.js
可以帮助你实现坐标转化,给HTML元素标签定位,下面给大家演示如何实现。
2. CSS2模型对象CSS2DObject
js
// 引入CSS2模型对象CSS2DObject
import { CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
通过CSS2DObject
类,可以把一个HTML元素转化为一个类似threejs网格模型的对象,换句话说就是你可以把CSS2DObject
当成threejs的一个模型一样去设置位置.position
或添加到场景中。
js
const div = document.getElementById('tag');
// HTML元素转化为threejs的CSS2模型对象
const tag = new CSS2DObject(div);
你想把HTML标签标注在那个位置,你通过.position
属性设置标签模型对象的xyz坐标。
js
tag.position.set(50,0,50);
把HTML元素对应的CSS2模型对象添加到其它模型对象或三维场景中。
js
scene.add(tag);
js
const group = new THREE.Group();
group.add(tag);
3. CSS2渲染器CSS2DRenderer
js
// 引入CSS2渲染器CSS2DRenderer
import { CSS2DRenderer } from 'three/addons/renderers/CSS2DRenderer.js';
js
// 创建一个CSS2渲染器CSS2DRenderer
const css2Renderer = new CSS2DRenderer();
CSS2渲染器CSS2DRenderer
和WebGL渲染器WebGLRenderer
虽然不同,但是有些属性和方法是相似的,可以类比记忆学习。比如.domElement
、.setSize()
、.render()
。可以先参考webgl渲染器写代码,然后再给大家解释其中的含义。
3.1 CSS2Renderer.render()
渲染HTML标签
CSS2渲染器CSS2DRenderer
和常用的WebGL渲染器WebGLRenderer
一样都是渲染器,只是渲染模型对象不同,WebGLRenderer
主要是渲染threejs自身的网格、点、线等模型,CSS2DRenderer
用来渲染HTML元素标签对应的CSS2模型对象CSS2DObject
。
js
// 用法和webgl渲染器渲染方法类似
css2Renderer.render(scene, camera);
// renderer.render(scene, camera);
3.2 CSS2Renderer.setSize()
设置CSS2Renderer.render()
渲染输出标签的尺寸范围,一般和threejs canvas画布宽高度一致即可。
js
// width, height:canvas画布宽高度
css2Renderer.setSize(width, height);
3.3 渲染结果CSS2Renderer.domElement
CSS2Renderer.render()
渲染会输出标签对应的HTML元素,也就是css2Renderer.domElement
,你可以插入到web网页中任何你想放的位置。
js
document.body.appendChild(css2Renderer.domElement);
查看css2Renderer.render()
渲染结果CSS2Renderer.domElement
threejs执行css2Renderer.render()
之后,你打开浏览器控制台元素 选项,找到你创建的HTML标签<div id="tag">标签内容</div>
,你可以发现<div id="tag"></div>
外面多了一层div父元素,CSS2Renderer.domElement
对应的就是<div id="tag"></div>
外面的父元素。
js
document.body.appendChild(css2Renderer.domElement);
// 渲染HTML标签对应的CSS2DObject模型对象
css2Renderer.render(scene, camera);
外面父元素的宽高度也被CSS2Renderer
设置为threejs canvas画布的宽高度,就是css2Renderer.setSize(width, height);
设置的结果。
js
css2Renderer.setSize(width, height);
html
<!-- `<div id="tag"></div>`外面多了一层div父元素 -->
<div style="overflow: hidden; width: 600px; height: 300px;">
</div>
4. CSS2Renderer.domElement
重新定位
<div id="tag"></div>
外面div父元素重新定位,叠加到canvas画布上,与canvas画布重合即可,你可以可以看到HTML标签的标注效果。
CSS2Renderer.domElement
定位方法很多,不过这都是普通前端CSS知识,也不一定要与课程相同,你可以根据你自己的前端CSS知识,自由发挥。你只要能让标签父元素叠加到threejs canvas画布上面且重合就行。
下面是本节课案例中布局方式写法,后面也会给大家演示其它的布局写法。
js
css2Renderer.domElement.style.position = 'absolute';
css2Renderer.domElement.style.top = '0px';
你可以测试下面两个div元素的布局规律,会知道为什么设置.style.top = '0px'
。
js
<div style="height: 300px;background: #999;">默认定位元素</div>
<div style="position: absolute;">绝对定位</div>
改变canvas画布在网页的布局位置,标签父元素css2Renderer.domElement
也要跟着重新定位
js
// 改变canvas画布在网页位置,标签父元素也要重新定位
renderer.domElement.style.marginTop = '200px';
css2Renderer.domElement.style.top = '200px';
css2Renderer.render()
渲染本质
<div id="tag"></div>
本身也多了一些CSS位置相关属性,这些都是css2Renderer.render()
渲染的结果。你也可以发现,你创建的HTML标签<div id="tag"></div>
不在原来的位置了,其实是被CSS2Renderer
改变了位置。
css2Renderer.render()
渲染HTML元素对应的CSS2模型对象,本质上就是根据CSS2模型对象的xyz世界坐标,计算HTML标签元素在canvas画布上的屏幕像素坐标位置。
js
const div = document.getElementById('tag');
// HTML元素转化为threejs的CSS2模型对象
const tag = new CSS2DObject(div);
js
// 渲染HTML标签对应的CSS2DObject模型对象
css2Renderer.render(scene, camera);
测试
改变模型mesh位置。
js
mesh.position.set(100,0,0);
如果你想用HTML元素标注模型,可以把CSS2模型对象也设置在mesh对应的位置。
js
tag.position.set(100,0,0);
CSS3DRenderer渲染HTML标签
CSS3渲染器CSS3DRenderer
和CSS2渲染器CSS2DRenderer
整体使用流程基本相同,只是在HTML标签渲染效果方面不同,比如CSS3渲染的标签会跟着场景相机同步缩放,而CSS2渲染的标签默认保持自身像素值。
下面就在CSS2渲染器代码基础上给大家讲解。
设置CSS3渲染器代码
和CSS2渲染器代码一样设置,只需要把CSS2换成CSS3即可。
JavaScript
// 引入CSS3渲染器CSS3DRenderer
import {CSS3DRenderer} from 'three/addons/renderers/CSS3DRenderer.js';
JavaScript
// 创建一个CSS3渲染器CSS3DRenderer
const css3Renderer = new CSS3DRenderer();
css3Renderer.setSize(width, height);
// HTML标签<div id="tag"></div>外面父元素叠加到canvas画布上且重合
css3Renderer.domElement.style.position = 'absolute';
css3Renderer.domElement.style.top = '0px';
//设置.pointerEvents=none,解决HTML元素标签对threejs canvas画布鼠标事件的遮挡
css3Renderer.domElement.style.pointerEvents = 'none';
document.body.appendChild(css3Renderer.domElement);
JavaScript
// 渲染循环
function render() {
css3Renderer.render(scene, camera);
// ...
requestAnimationFrame(render);
}
JavaScript
window.onresize = function () {
...
// HTML标签css3Renderer.domElement尺寸重新设置
css3Renderer.setSize(width,height);
};
CSS3对象模型CSS3DObject
CSS3对象模型CSS3DObject
可以类比前面介绍的CSS2模型对象CSS2DObject
学习。
js
// 引入CSS3模型对象CSS3DObject
import { CSS3DObject } from 'three/addons/renderers/CSS3DRenderer.js';
通过CSS3DObject
类,可以把一个HTML元素转化为一个CSS3模型对象,就像threejs的网格模型一样,可以添加到场景中,可以设置位置,可以作为其它模型对象的子对象。
js
const div = document.getElementById('tag');
// HTML元素转化为threejs的CSS3模型对象
const tag = new CSS3DObject(div);
//标签tag作为mesh子对象,默认标注在模型局部坐标系坐标原点
mesh.add(tag);
// 相对父对象局部坐标原点偏移80,刚好标注在圆锥
tag.position.y += 80;
tag.position.y += 80;
标注圆锥模型的顶部
js
const geometry = new THREE.ConeGeometry(25, 80);
geometry.translate(0, 40, 0);
const mesh = new THREE.Mesh(geometry, material);
mesh.add(tag);
// 相对父对象局部坐标原点偏移80,刚好标注在圆锥顶部
tag.position.y += 80;
CSS3DObject
渲染效果测试
CSS3模型对象CSS3DObject
渲染结果,就像一个矩形平面网格模型一样。你通过相机控件OrbitControls
旋转、缩放三维场景,CSS3模型对象CSS3DObject
跟着旋转、缩放。
旋转过程中HTML元素标签的正反面都可以看到。
一个网格模型被另一个不透明网格模型遮挡,canvas画布上不会显示,不过注意一点CSS3DObject
模型本质上渲染到网页上还是HTML元素,这就是说模型背面的HTML标签并不会被遮挡,CSS3DObject
标签是以HTMl元素形式叠加在canvas画布上的,不受threejs内部模型对象影响。
禁止CSS3DObject
标签对应HTMl元素背面显示
js
<div id="tag" style="backface-visibility: hidden;">标签内容</div>
标签相对标注点的位置
默认情况下CSS3模型对象渲染的标签的几何中心默认和标注位置的坐标重合。
CSS3DRenderer渲染的HTML标签尺寸
CSS2DRenderer渲染HTML元素标签,默认情况下,HTML元素会保持本身尺寸的像素值,除非你通过代码缩放。
CSS3DRenderer渲染的HTML元素,你可以把HTML标签对象想象为一个矩形平面网格模型Mesh,HTML标签对象在threejs中的尺寸来源是HTML元素的像素尺寸值,比如HTML像素高度40px,那么HTML标签对象在threejs中的数字相当于高度为40的矩形平面网格模型。
测试验证上面规律总结:把标签的高度设置为160px,160的一半是80,也就是圆锥的高度,这样HTML标签下半部分和圆锥底部重合。
js
<div id="tag" style="height: 160px;">标签内容</div>
border、padding、height、width都会影响标签渲染大小,你可以分别测试体验。
html
<style>
#tag {
padding: 0px 10px;
border: #00ffff solid 1px;
height: 40px;
border-radius: 5px;
width: 65px;
}
</style>
缩放标签
js
const div = document.getElementById('tag');
const tag = new CSS3DObject(div);
tag.scale.set(0.5,0.5,1);//缩放标签尺寸
标签偏移
CSS2渲染HTML标签偏移方式
JavaScript
const div = document.getElementById('tag');
// id="tag"元素高度322px,默认标签中心与标注点
div.style.top = '-161px'; //平移-161px,指示线端点和标注点重合
CSS2渲染的标签和CSS3渲染的标签偏移方式不同,CSS3标签,直接按照threejs模型尺寸修改方式改变,比用HTML像素方式更方便准确。
js
tag.scale.set(0.5,0.5,1);//缩放标签尺寸
tag.position.y += 10;//累加标签高度一半,标签底部和圆锥顶部标注位置重合
CSS3精灵模型CSS3DSprite
js
// 引入CSS3精灵模型对象CSS3DSprite
import { CSS3DSprite } from 'three/addons/renderers/CSS3DRenderer.js';
CSS3对象模型CSS3DObject
渲染效果类似矩形平面网格模型Mesh
。
CSS3精灵模型CSS3DSprite
渲染效果类似以前学习的精灵模型对象Sprite
。
js
const div = document.getElementById('tag');
// HTML元素转化为threejs的CSS3精灵模型`CSS3DSprite`
const tag = new CSS3DSprite(div);
//标签tag作为mesh子对象,默认标注在模型局部坐标系坐标原点
mesh.add(tag);
// 相对父对象局部坐标原点偏移80,刚好标注在圆锥
tag.position.y += 80;
CSS3精灵模型CSS3DSprite
渲染特点
CSS3精灵模型CSS3DSprite
对应的HTML标签,可以跟着场景缩放,位置可以跟着场景旋转,但是自身的姿态角度始终平行于canvas画布,不受旋转影响,就像精灵模型一样Sprite
CSS3精灵模型CSS3DSprite
尺寸、位置、缩放等渲染规律和CSS3对象模型CSS3DObject
基本一致。
标签局部遮挡鼠标事件
HTML标签<div id="tag"></div>
外面的父元素css3Renderer.domElement
防止鼠标遮挡canvas事件方式,和CSS2渲染器一样。
js
//设置.pointerEvents=none,解决HTML元素标签对threejs canvas画布鼠标事件的遮挡
css3Renderer.domElement.style.pointerEvents = 'none';
标签<div id="tag"></div>
在CSS3渲染器渲染的时候,默认会被设置为pointer-events: auto;
,这时候虽然css3Renderer.domElement
不遮挡canvas画布的鼠标事件,但是<div id="tag"></div>
遮挡canvas画布的鼠标事件。
这时候你可以通过代码强制改变CSS3渲染器给标签设置的.style.pointerEvents = 'auto'
,设置为.style.pointerEvents = 'none'
,这时候注意一点,修改.style.pointerEvents
,要在实例化new CSS3DObject(div)
之后,因为执行new CSS3DObject(div)
的时候,会把HTML标签设置为.style.pointerEvents = 'auto'
。
js
const div = document.getElementById('tag');
// HTML元素转化为threejs的CSS3模型对象
const tag = new CSS3DObject(div);
// new CSS3DObject(div);之后设置style.pointerEvents
div.style.pointerEvents = 'none';
Sprite
作为标签标注设备
实际开发的时候,可以使用精灵模型Sprite
+ 颜色贴图作为标签,标注三维场景。
下面具体知识点,在精灵模型章节基本都讲解过,学习下面内容之前,你可以尝试用精灵模型去标注工厂设备。
精灵模型标签
如果你想想用精灵模型表达什么含义,可以美术提供一个对应的贴图。
JavaScript
const texLoader= new THREE.TextureLoader();
const texture = texLoader.load("./警告.png");
const spriteMaterial = new THREE.SpriteMaterial({
map: texture,
});
const sprite = new THREE.Sprite(spriteMaterial);
可以根据标注的场景尺寸量级,设置精灵模型大小,不要过大或过小,先大概标注,比如精灵标签比设备尺寸小一个数量级,然后再精确调整。
JavaScript
sprite.scale.set(5, 5, 1);
sprite.position.y = 5 / 2; //标签底部箭头和空对象标注点重合
标注工厂设备
在工厂三维模型需要标注的位置,设置一个空对象,用来控制精灵模型标签的位置。
JavaScript
// obj是建模软件中创建的一个空对象
const obj = gltf.scene.getObjectByName('设备A标注');
//tag会标注在空对象obj对应的位置
obj.add(sprite);
精灵模型底部和标注位置重合
设置精灵模型位置属性,使精灵标签底部和空对象标注位置重合。
JavaScript
sprite.scale.set(4, 4, 1);
//标签底部箭头和空对象标注点重合
sprite.position.y = 4/2;
精灵模型Sprite
和CSS3精灵模型CSS3DSprite
标签差异
精灵模型渲染Sprite
的标签,默认可以被其他网格模型遮挡,但是CSS3渲染器渲染的HTML元素标签是叠加在canvas画布上,不会被其它网格模型遮挡。
标注多个设备状态
封装一个创建精灵标签的函数,可以根据需要调用,标注任何设备。
JavaScript
import * as THREE from 'three';
// 标注位置对应的模型对象obj
function createSprite(obj,state) {
const texLoader= new THREE.TextureLoader();
let texture = null;
if(state == '警告'){
texture= texLoader.load("./警告.png");
}else{
texture = texLoader.load("./故障.png");
}
const spriteMaterial = new THREE.SpriteMaterial({
map: texture,
});
const sprite = new THREE.Sprite(spriteMaterial);
// 控制精灵大小
sprite.scale.set(5, 5, 1);
sprite.position.y = 5 / 2; //标签底部箭头和空对象标注点重合
obj.add(sprite); //tag会标注在空对象obj对应的位置
}
export default createSprite;
Sprite标签(Canvas作为贴图)
上节课案例创建标签的方式,是把一张图片作为Sprite
精灵模型的颜色贴图,本节给大家演示把Canvas画布作为Sprite
精灵模型的颜色贴图,实现一个标签。
注意:本节课主要是技术方案讲解,默认你有Canvas基础,如果没有Canvas基础,可以学习之后再来学习本节课内容。
Canvas画布绘制一个标签
你可以使用Canvas绘制特定轮廓的标签,比如加上指引线或箭头,可以输入特定文字。
下面代码自动适配了不同长度的文字标注,文字符号越多,canvas画布越长。
JavaScript
// 生成一个canvas对象,标注文字为参数name
function createCanvas(name) {
/**
* 创建一个canvas对象,绘制几何图案或添加文字
*/
const canvas = document.createElement("canvas");
const arr = name.split(""); //分割为单独字符串
let num = 0;
const reg = /[\u4e00-\u9fa5]/;
for (let i = 0; i < arr.length; i++) {
if (reg.test(arr[i])) { //判断是不是汉字
num += 1;
} else {
num += 0.5; //英文字母或数字累加0.5
}
}
// 根据字符串符号类型和数量、文字font-size大小来设置canvas画布宽高度
const h = 80; //根据渲染像素大小设置,过大性能差,过小不清晰
const w = h + num * 32;
canvas.width = w;
canvas.height = h;
const h1 = h * 0.8;
const c = canvas.getContext('2d');
// 定义轮廓颜色,黑色半透明
c.fillStyle = "rgba(0,0,0,0.5)";
// 绘制半圆+矩形轮廓
const R = h1 / 2;
c.arc(R, R, R, -Math.PI / 2, Math.PI / 2, true); //顺时针半圆
c.arc(w - R, R, R, Math.PI / 2, -Math.PI / 2, true); //顺时针半圆
c.fill();
// 绘制箭头
c.beginPath();
const h2 = h - h1;
c.moveTo(w / 2 - h2 * 0.6, h1);
c.lineTo(w / 2 + h2 * 0.6, h1);
c.lineTo(w / 2, h);
c.fill();
// 文字
c.beginPath();
c.translate(w / 2, h1 / 2);
c.fillStyle = "#ffffff"; //文本填充颜色
c.font = "normal 32px 宋体"; //字体样式设置
c.textBaseline = "middle"; //文本与fillText定义的纵坐标
c.textAlign = "center"; //文本居中(以fillText定义的横坐标)
c.fillText(name, 0, 0);
return canvas;
}
const canvas = createCanvas('设备A')
CanvasTexture
把canvas转化为纹理对象
canvas
画布作为CanvasTexture
的参数创建一个纹理对象,本质上你可以理解为CanvasTexture
把canvas画布当做图片,读取参数canvas画布上的像素值,创建纹理贴图Texture
。
JavaScript
loader.load("../工厂.glb", function (gltf) {
model.add(gltf.scene);
const canvas = createCanvas('设备A');//创建一个canvas画布
// canvas画布作为CanvasTexture的参数创建一个纹理对象
// 本质上你可以理解为CanvasTexture读取参数canvas画布上的像素值
const texture = new THREE.CanvasTexture(canvas);
const spriteMaterial = new THREE.SpriteMaterial({
map: texture,
});
const sprite = new THREE.Sprite(spriteMaterial);
})
精灵模型尺寸和位置设置
精灵模型尺寸和位置设置具体思路可以参考上节课讲解。
注意精灵模型宽高比和canvas画布宽高比保持一致即可。
JavaScript
const y = 4;//精灵y方向尺寸
// sprite宽高比和canvas画布保持一致
const x = canvas.width/canvas.height*y;//精灵x方向尺寸
sprite.scale.set(x, y, 1);// 控制精灵大小
sprite.position.y = y / 2; //标签底部箭头和空对象标注点重合
const obj = gltf.scene.getObjectByName('设备A标注'); // obj是建模软件中创建的一个空对象
obj.add(sprite); //tag会标注在空对象obj对应的位置
cavnas精灵标签封装(标注多个)
封装一个创建cavnas精灵标签的函数,可以根据需要调用,标注任何需要标注的地方。
JavaScript
import * as THREE from 'three';
import createCanvas from './canvas';
// 标注位置对应的模型对象obj
// name:标注文字
function createSprite(obj,name) {
const canvas = createCanvas(name);//创建一个canvas画布
// canvas画布作为CanvasTexture的参数创建一个纹理对象
const texture = new THREE.CanvasTexture(canvas);
const spriteMaterial = new THREE.SpriteMaterial({
map: texture,
});
const sprite = new THREE.Sprite(spriteMaterial);
// 控制精灵大小(sprite宽高比和canvas画布保持一致)
const s = 0.05;//通过canvas宽高度缩放后,设置sprite.scale,避免图文宽高比变形
const x = canvas.width*s;
const y = canvas.height*s;
sprite.scale.set(x, y, 1);
sprite.position.y = y / 2; //标签底部箭头和空对象标注点重合
obj.add(sprite); //tag会标注在空对象obj对应的位置
}
export default createSprite;
Canvas包含外部图片
如果Canvas包含外部图片作为背景,注意创建CanvasTexture
的时候,不管你的代码结构怎么组织,主要要等图像加载完成再执行THREE.CanvasTexture(canvas)
,如果还未加载完成,创建纹理时候,读取画布像素时候,会不包含图片。
JavaScript
// 生成一个canvas对象,标注文字为参数name
function createCanvas(img,name) {
/**
* 创建一个canvas对象,绘制几何图案或添加文字
*/
const canvas = document.createElement("canvas");
const w = 140; //根据渲染像素大小设置,过大性能差,过小不清晰
const h = 80;
canvas.width = w;
canvas.height = h;
const h1 = h * 0.8;
const c = canvas.getContext('2d');
c.fillStyle = "rgba(0,0,0,0.0)"; //背景透明
c.fillRect(0, 0, w, h);
c.drawImage(img, 0, 0, w, h);//图片绘制到canvas画布上
// 文字
c.beginPath();
c.translate(w / 2, h1 / 2);
c.fillStyle = "#ffffff"; //文本填充颜色
c.font = "normal 32px 宋体"; //字体样式设置
c.textBaseline = "middle"; //文本与fillText定义的纵坐标
c.textAlign = "center"; //文本居中(以fillText定义的横坐标)
c.fillText(name, 0, 0);
return canvas;
}
JavaScript
const img = new Image();
img.src = "./标签箭头背景.png";
img.onload = function () {
const canvas = createCanvas(img,'设备A');//创建一个canvas画布
// 图片加载完成后,读取canvas像素数据创建CanvasTexture
const texture = new THREE.CanvasTexture(canvas);
...
const sprite = new THREE.Sprite(spriteMaterial);
...
}
矩形Mesh+背景透明png贴图(场景标注)
three.js项目开发中,把一个背景透明的.png
图像作为平面矩形网格模型Mesh的颜色贴图是一个非常有用的功能,通过这样一个功能,可以对three.js三维场景进行标注。
整体思路:创建一个矩形平面,设置颜色贴图.map
,注意选择背景透明的.png
图像作为颜色贴图,同时材质设置transparent: true
,这样png图片背景完全透明的部分不显示。
javascript
// 矩形平面网格模型设置背景透明的png贴图
const geometry = new THREE.PlaneGeometry(60, 60); //默认在XOY平面上
const textureLoader = new THREE.TextureLoader();
const material = new THREE.MeshBasicMaterial({
map: textureLoader.load('./指南针.png'),
transparent: true, //使用背景透明的png贴图,注意开启透明计算
});
const mesh = new THREE.Mesh(geometry, material);
mesh.rotateX(-Math.PI / 2);
网格地面辅助观察GridHelper
javascript
// 添加一个辅助网格地面
const gridHelper = new THREE.GridHelper(300, 25, 0x004444, 0x004444);
矩形平面PlaneGeometry
设置颜色贴图
javascript
const geometry = new THREE.PlaneGeometry(60, 60);
const textureLoader = new THREE.TextureLoader();
const material = new THREE.MeshBasicMaterial({
map: textureLoader.load('./指南针.png'),
});
const mesh = new THREE.Mesh(geometry, material);
开启透明transparent: true
javascript
const material = new THREE.MeshBasicMaterial({
map: textureLoader.load('./指南针.png'),
//transparent: true:使用背景透明的png贴图,注意允许透明
transparent: true,
});
旋转平移矩形平面
PlaneGeometry
矩形平面默认是在XOY平面上,如果你想平行于XOZ平面,就需要手动旋转。
javascript
mesh.rotateX(-Math.PI/2);//平行地面:矩形Mesh默认单面可见,注意旋转-Math.PI / 2
如果你不想矩形平面Mesh与地面网格线重合,可以通过位置属性.position
偏移。
javascript
mesh.position.y = 1;//适当偏移,不与地面重合