关于javascript:可视化场景内任意绘制线段并测量距离

26次阅读

共计 6337 个字符,预计需要花费 16 分钟才能阅读完成。

在数字孪生可视化场景中,可能会遇到这个问题,即须要测量数字孪生可视化场景中的不同指标之间的间隔。通过这个测量,能够明确的晓得可视化场景中各个指标的地位以及各个指标之间的间隔,便于做出正当的布局。这个需要并不难,咱们须要做的是确定须要测量的对象的坐标点终点和起点地位。
运行成果如下:

在 ThingJS 中要晓得场景中两点间的空间间隔能够通过调用三维空间内所有坐标点,计算两个坐标点的间隔去量算出两点之间的空间间隔,须要通过鼠标点击能力获取到两点之间的空间间隔。比方我要晓得场景中某两个场景间隔有多长,就能够通过鼠标点击两个甚至多个场景地位,来计算三维场景中任意三维点的空间间隔。上面一起看一下操作步骤:
1、增加注册事件,注册测量详情界面拖拽事件,设置可拖拽范畴不能超出屏幕。

registerEvent() {
 var _this = this;
 // 注册测量详情界面敞开按钮点击事件
 $('#dataDetails .tj-close').on('click', function() {$('#dataDetails').css('display', 'none');
 });
 
 // 注册测量详情界面拖拽事件,设置可拖拽范畴,不能超出屏幕
 $('#dataDetails .tj-title').on('mousedown', function(ev) {ev.preventDefault();
 var domEle = $('#dataDetails .tj-panel');
 var spacX = ev.pageX - domEle[0].offsetLeft;
 var spacY = ev.pageY - domEle[0].offsetTop;
 $(document).bind('mousemove', function(event) {
 var x = event.pageX - spacX;
 var y = event.pageY - spacY;
 if (event.pageX < 0 || event.pageX > $(window).width() || event.pageY < 0 || event.pageY > $(window).height()) {$(document).unbind('mousemove');
 }
 if (x <= 0) x = 0;
 if (x > ($(window).width() - domEle.width())) {x = $(window).width() - domEle.width();
 }
 if (y <= 0) y = 0;
 if (y > ($(window).height() - domEle.height())) {y = $(window).height() - domEle.height();
 }
 domEle.css('left', x + 'px').css('top', y + 'px');
 });
 }).on('mouseup', function() {$(document).unbind('mousemove');
 });
 
 // 注册单击事件,创立测距线段实例
 app.on(THING.EventType.SingleClick, '*', function(e) {if (e.button == 0) {
 _this.lineNum++;
 let line = new DrawLine({
 app: app,
 modelNum: _this.lineNum,
 currPosition: e.pickedPosition
 })
 app.pauseEvent(THING.EventType.SingleClick, '*', '创立测距线');
 }
 }, "创立测距线");
 }
}

2、ThingJS 应用 Constructor () 作为对象结构器函数,用来结构一种“对象类型”,即创立雷同类型的对象框架。Constructor () 结构器为对象的属性赋初始值,JS 中能够任意扩大结构参数 option,实现动静绑定。绘制测量线的结构参数创立如下:

class DrawLine {
 /**
 * 结构器
 * @param {JSON} option - 结构参数
 */
 constructor(option) {
 this.opts = option;
 this.pointsArr = [this.opts.currPosition]; // 鼠标挪动中坐标点的汇合
 this.coordinatesArr = [this.opts.currPosition]; // 存储鼠标点击后坐标点的汇合
 this.ePosition = null; // 存储触发事件后鼠标的地位
 this.lineCoor = [this.opts.currPosition]; // 存储以后两个坐标点
 this.disArr = []; // 存储所有坐标点与坐标点间的间隔
 this.numIndex = 0; // 自增变量
 this.reSetDistance; // 存储两点间的间隔
 this.lastStatus = false; // 判断是否绘制完结值为 false 为未完结 true 为完结
 this.pointsObjArr = [];
 this.rianleyDom = $('#marker'); // 追随鼠标的提醒
 this.pointCardDom = $('#pointMarker'); // 鼠标挪动至节点的提醒
 this.init(); // 初始化
 this.appClick(); // 调用办法}

3、单击鼠标左键增加点位,双击或单击鼠标右键完结。如果是多线段测量,挪动鼠标能够继续绘制。

appClick() {
 var _this = this;
 // 点击左键增加节点右键完结绘制
 _this.opts.app.on('SingleClick', function(e) {if (e.button == 0) {if (!e.picked) return;
 _this.numIndex++;
 _this.ePosition = e.pickedPosition;
 _this.createPoint(_this.ePosition);
 _this.coordinatesArr.push(_this.ePosition);
 _this.lineCoor.push(_this.ePosition);
 _this.createLine(_this.coordinatesArr);
 _this.getDistance();
 _this.template =
 `<div id="line` + _this.opts.modelNum + _this.numIndex + `" class="card-label card-line` + _this.opts.modelNum + `">
 <span class="text">`;
 if (_this.lineDistanceAll != null) {_this.template += _this.lineDistanceAll + ` 米 `;} else {_this.template += `<span style="color:#f45905; border-right: 1px solid #ccc;margin-right: 5px">` + _this.lineId + `</span> 终点 `}
 _this.template +=
 `</span>
 <span><img id="linePoints` + _this.opts.modelNum + _this.numIndex + `" src="/guide/examples/images/measure/remove.png"></span> 
 </div>`;
 _this.boardId = 'line' + _this.opts.modelNum + _this.numIndex;
 _this.createCard(_this.regionPoint);
 _this.pointsObj = {
 id: 'linePoints' + _this.opts.modelNum + _this.numIndex,
 parent: 'line' + _this.opts.modelNum + _this.numIndex,
 coor: _this.ePosition,
 distance: _this.lineDistance
 }
 _this.pointsObjArr.push(_this.pointsObj);
 _this.cardClick();} else {if (_this.coordinatesArr.length < 2) {_this.destroyAll();
 _this.rianleyDom.css('display', 'none');
 return;
 };
 _this.end();}
 _this.rianleyDom.css('display', 'none');
 }, '点击');
 
 // 鼠标挪动继续绘制测量线段
 _this.opts.app.on('MouseMove', function(e) {if (e.picked) {
 _this.ePosition = e.pickedPosition;
 _this.pointsArr = [..._this.coordinatesArr, _this.ePosition];
 _this.createLine(_this.pointsArr);
 _this.line.style.color = '#f88020';
 if (_this.pointsArr.length >= 2) {_this.moveDistance = THING.Math.getDistance(_this.pointsArr[_this.pointsArr.length - 1], _this.pointsArr[_this.pointsArr.length - 2]);
 let countNum = 0;
 _this.disArr.forEach(v => {countNum += parseFloat(v);
 });
 countNum = 1 * parseFloat(countNum).toFixed(2) + 1 * parseFloat(_this.moveDistance).toFixed(2);
 _this.rianleyDom.css('display', 'block');
 _this.rianleyDom.find('span.value').text(countNum.toFixed(2));
 _this.rianleyDom.css('left', e.clientX + 10 + 'px');
 _this.rianleyDom.css('top', e.clientY + 'px');
 }
 }
 }, '挪动');
 
 // 完结绘制以后测量线段
 _this.opts.app.on('DBLClick', function(ev) {if (_this.coordinatesArr.length < 2) {_this.destroyAll();
 _this.rianleyDom.css('display', 'none');
 return;
 };
 _this.end();}, '双击');
 }
 
 /**
 * 创立节点
 * @param {Array} ePosition - 坐标点
 */
 createPoint(ePosition) {
 var _this = this;
 _this.regionPoint = _this.opts.app.create({
 type: 'Sphere',
 id: 'linePoints' + _this.opts.modelNum + _this.numIndex,
 name: 'linePoints' + _this.opts.modelNum,
 radius: 0.2, // 半径
 widthSegments: 16,
 heightSegments: 16,
 position: ePosition, // 球体坐标
 style: {
 color: '#c10000',
 roughness: 50,
 opacity: 0.8
 }
 });
 }

4、创立节点、线段和节点顶牌这些根本元素,确定终点、各个节点的坐标。其中线段属于所有鼠标点击后的坐标点汇合,即测量的总间隔。

createPoint(ePosition) {
 var _this = this;
 _this.regionPoint = _this.opts.app.create({
 type: 'Sphere',
 id: 'linePoints' + _this.opts.modelNum + _this.numIndex,
 name: 'linePoints' + _this.opts.modelNum,
 radius: 0.2, // 半径
 widthSegments: 16,
 heightSegments: 16,
 position: ePosition, // 球体坐标
 style: {
 color: '#c10000',
 roughness: 50,
 opacity: 0.8
 }
 });
 }
 
 /**
 * 创立线段
 * @param {Array} coordinates - 所有鼠标点击后的坐标点汇合
 */
 createLine(coordinates) {
 let id = this.opts.modelNum >= 10 ? this.opts.modelNum : '0' + this.opts.modelNum;
 if (this.line) {this.line.destroy();
 }
 this.lineId = 'Line' + id;
 this.line = this.opts.app.create({
 type: 'PolygonLine',
 name: 'line',
 id: 'Line' + id,
 width: 0.05,
 points: coordinates,
 style: {
 color: '#f45905',
 roughness: 5,
 opacity: 0.9
 }
 });
 }
 
 /**
 * 计算两个坐标点间的间隔
 */
 getDistance() {if (this.lineCoor.length < 2) return;
 if (this.coordinatesArr.length > 2) {this.lineCoor.shift();
 }
 this.lineDistance = THING.Math.getDistance(this.lineCoor[0], this.lineCoor[1]);
 this.lineDistance = this.lineDistance.toFixed(2);
 this.disArr.push(this.lineDistance);
 let countNum = 0;
 this.disArr.forEach(v => {countNum += parseFloat(v);
 });
 this.lineDistanceAll = countNum.toFixed(2);
 }
 
 /**
 * 创立节点顶牌
 * @param {Object} parent - 顶牌父物体
 */
 createCard(parent) {$('#div3d').append(this.template);
 this.srcElem = document.getElementById(this.boardId);
 this.imgElem = document.getElementById('linePoints' + this.opts.modelNum + this.numIndex);
 this.ui = this.opts.app.create({
 type: 'UIAnchor',
 parent: parent,
 element: this.srcElem,
 localPosition: [0.4, 0.3, 0.4],
 pivotPixel: [0, 0]
 });
 }

通过以上的操作,能够实现多点线段绘制并计算出多点线段之间的间隔。上图展现了多点线段长度的测试后果。快来试试看吧!
—————————————————
数字孪生可视化:https://www.thingjs.com/

正文完
 0