最近学习了 HT for Web flow 插件,除了正常的 flow 效果,其中还有两个十分好用的两个接口 getPercentPosition() 和 getPercentAngle(), 经过这两个接口能够达到不少的效果,这个 demo 我就是利用这两个接口进行对的巡逻人员的角度位置和速度进行控制。
html
首先结合 addBottomPainter() 在 HT 拓扑图形组件 graphView 底层上使用 Canvas 画笔进行绘制背景色。html5
// 画背景 graphView.addBottomPainter(function (g) { g.save(); g.beginPath(); g.rect(0, 0, 2000, 1600); g.fillStyle = "rgb(39,48,74)"; g.fill(); g.restore(); });
而后将视图背景、人员视角俯视图和提示经过 setImage() 在拓扑组件 graphView 上以图元的形式加载出来,用 setScale() 控制图元的缩放比例使视图更具备真实感,用 setAnchor() 更改锚点,以便旋转时有视角旋转的感受,最后经过加入 dataModel 的方式使图元加载到拓扑组件 graphView 上,其设计原理是 Object View Mapping (OVM),经过统一的模型驱动视图组件。canvas
// 加载人物基础图元 var people = new ht.Node(); // 设置 Tag people.setTag(id + 'People'); people.setImage('people'); // 设置缩放倍数 people.setScale(10, 10); people.setPosition(100, 100); // 设置锚点 people.setAnchor(.5, .2); dataModel.add(people);
将巡逻路径和相关人员属性以对象形式设置,其中巡逻路径按照点的形式保存在 points ,其中的转折逻辑经过 segments 进行控制,其规则以下:app
var people4 = { id: '437904', source: {x: 270,y: 352,}, target: {x: 270,y: 352,}, points: [ {x: 262,y: 220,},{x: 380,y: 228,},{x: 509,y: 234,},{x: 509,y: 316,},{x: 513,y: 452,},{x: 382,y: 454,},{x: 278,y: 454,} ], segments: [1, 3, 3, 3, 3] };
经过 getPercentPosition() 和 getPercentAngle() 得到路径 edge 上的点和角度,从而能够经过 setPosition() 控制基础图元位置,再加上动画函数 startAnim() , 从而达到在路径上进行运动旋转的效果。函数
var position = graphView.getPercentPosition(data, i); var angle = graphView.getPercentAngle(data, i) - Math.PI * .5;
// 转角大小 var rotationAngle = Math.abs((people.getRotation() - angle) % (Math.PI * 2)); // 经过转角大小判断是否须要动画 if (rotationAngle > .2) { // 判断转角是否大于180度 if (rotationAngle > Math.PI) { if (people.getRotation() - angle < 0) { people.setRotation(angle + (Math.PI * 2 - rotationAngle)); } else { people.setRotation(angle - (Math.PI * 2 - rotationAngle)); } }
经过路径上各个点的距离计算出总路径而后按距离控制控制路径百分比得到相应的点和旋转角度。学习
// 计算路径长短 var distance = 0; for (let i = 0; i + 1 < path.points.length; i++) { var x = path.points[i + 1].x - path.points[i].x; var y = path.points[i + 1].y - path.points[i].y; var pathDistance = Math.sqrt(x * x + y * y); distance += pathDistance; }
var preMoveData, preClickData; // 增长鼠标移动标记显示 graphView.getView().addEventListener('mousemove', (e) => { const data = graphView.getDataAt(e); if (preMoveData === preClickData && (!data || !data.mark)) return; if (!data || !data.mark) { preMoveData && preMoveData.mark && preMoveData.mark.s('2d.visible', false); return; } data.mark.s('2d.visible', true); preMoveData = data; }); // 增长鼠标点击标记显示 graphView.mi(e => { if (e.kind === 'clickData' && e.data.mark) { preClickData && preClickData.mark.s('2d.visible', false); e.data.mark.s('2d.visible', true); if (preClickData === e.data) { e.data.mark.s('2d.visible', false); preClickData = undefined; }else { preClickData = e.data; } } })
flow 是十分适合这种 2d 路线规划,或者是 SCADA 的可视化数据展现,尤为是 getPercentPosition() 和 getPercentAngle() 两个接口, 十分适合用于高自定义的路线可视化图形展现。动画