2D面板与三维物体的之间进行连线,对于可视化的呈现会更加直观,并且有联动的效果。
实现原理:
1、获取面板与对象点位集合,将2D信息面板的坐标转成3D坐标
2、创建类型为Line的像素线
3、当物体移动时,使用update方法,不断更新物体位置,达到物体与2D面板一直处于连接状态
实现源码
kotlin
/**
* @description 面板与孪生体连线
*/
class PanelLines {
object: any;
infoDom: any;
lines: any;
lightPointers: any;
app: any;
dot: any;
constructor(object: any, infoDom: any) {
this.object = object;
this.infoDom = infoDom;
this.lines = null;
this.lightPointers = null;
this.app = THING.App.current;
this.dot = {
x: -12,
y: 10,
imgUrl: '/image/dot.png',
width: 12,
height: 12,
};
}
/**
* @description 获取面板与对象点位集合
* @returns {Array} 点位集合
*/
_getPos() {
const boundingBoxY = this.object.boundingBox.size[1] / 2;
const domStyle = window.getComputedStyle(this.infoDom);
const domLeft = parseFloat(domStyle.left) || 0;
const domTop = parseFloat(domStyle.top) || 0;
const y = domTop + this.dot.height / 2 + this.dot.y;
const x = domLeft + this.dot.width / 2 + this.dot.x;
// 3D物体对象的坐标
const getPos1 = () => THING.Math.addVector(this.object.position, [0, boundingBoxY, 0]);
// 连线拐点位置的坐标
const conerPoint = () => this.app.camera.screenToWorld([x - 20, y, 0]);
// 2D信息面板的坐标
const getPos2 = () => this.app.camera.screenToWorld([x, y, 0]);
return [getPos1(), conerPoint(), getPos2()];
}
/**
* @description 创建像素线
*/
createLine() {
const points = this._getPos();
this.lines = this.app.create({
type: 'Line',
name: 'panel_lines',
color: 'rgba(255, 255, 255, 0.5)', // 轨迹线颜色
points,
style: {
alwaysOnTop: true,
},
});
this.createLinePoints();
}
/**
* @description 创建线两端光点
*/
createLinePoints() {
const points = this._getPos();
this.lightPointers = [points[0], points[points.length - 1]].map((point) => {
const distance = THING.Math.getDistance(point, THING.App.current.camera.position);
const marker = this.app.create({
name: 'panel_dots',
type: 'Marker',
url: this.dot.imgUrl,
position: point,
localScale: THING.Math.scaleVector([1, 1, 1], (1 * distance) / 38),
keepSize: true,
style: {
alwaysOnTop: true,
},
});
return {
marker,
point,
};
});
}
/**
* @description 更新线
*/
updateLines() {
this.app.on(
'update',
() => {
const panelPos = this._getPos();
if (this.lines) {
panelPos.forEach((v, i) => {
this.lines.setPoint(i, v);
});
}
if (this.lightPointers) {
this.lightPointers[0].marker.position = panelPos[0];
this.lightPointers[1].marker.position = panelPos[2];
}
},
'createlines'
);
}
/**
* @description 删除线
*
*/
destroyLines() {
const getLine = this.app.query('panel_lines');
const getPoint = this.app.query('panel_dots');
if (getLine.length) {
getLine.destroy();
getPoint.destroy();
}
this.app.off('update', null, 'createlines');
}
}
export default PanelLines;
如何应用呢?
typescript
import PanelLine from './PanelLines';
import panel from "./panel.vue";
// 信息面板与孪生体连线
const panelDom = document.querySelector('.panel'); // 2D面板的dom
const object = app.query('物体')[0]; // 查询的物体对象
const lines = new PanelLine(object, panelDom); // 连线方法
lines.createLine(); // 创建连线
lines.updateLines(); // 更新连线
// 移除面板与孪生体的连线
if (lines) {
lines.destroyLines();
}
创建连线两端的端点图片,是白色的,图片看起来会不太明显