需求就是一个飞机动画,飞机飞到哪里,轨迹线就画到哪里。
我的轨迹线非常长,从我国出发一直到欧洲那边,光是经过的点就有7000多个。
刚开始的时候想要使用的是entity的画线方法进行轨迹线的绘制,如果数据量不大,应该是可以实现的。
整体思路就是:先创建一个PolyLine对象,然后监听时间,每一帧都对实体线对象进行position的更换。伪代码如下:
// 定义折线实体var polylineEntity = viewer.entities.add({ polyline: { positions: positions, width: 5, material: new Cesium.PolylineGlowMaterialProperty({ glowPower: 0.1, color: Cesium.Color.YELLOW }) }});viewer.clock.onTick.addEventListener(function() { ... // 其它操作 positions进行更新操作 polylineEntity.polyline.positions = positions;});
但是我使用这种方法的话,虽然代码层面并不会报错,但是不要说轨迹线的绘制了,整个模型的动画都会卡死。
于是开始转变使用primitive对轨迹线进行绘制,总体思路跟entity保持不变,唯一改变的就是我暂时还没找到像polylineEntity.polyline.positions = positions;这样的一句代码,能够直接改变线的位置和经过的点。
所以我采取了比较笨的方法:每一次添加线之前先将前面一条删去,然后再添加一条。听起来似乎对性能要求更高了,但由于primitive使用更底层的方法进行绘制,就算这样进行绘制,对性能的要求也要远远低于之前使用entity的那种方法。至少我现在可以让我的轨迹线正常绘制,只是在距离比较长后还是有一点点的卡帧,不过也还处在可接受的范围内。
代码如下:
// 动态绘制飞机的轨迹线updatePolyLine(positions, viewer) { // 最开始的时候没有线,后面点肯定就不止2个,所以也可以正常移除。 if (positions.length>=2) { viewer.scene.primitives.remove(window.line); } if (positions.length < 2) { // 这个地方我是为了在刚开始的时候不要报错,因为primitive绘制线要求至少有两个点 positions = [ new Cesium.Cartesian3.fromDegrees( 108.89080568, 34.22720682, 9997.06879914 ), new Cesium.Cartesian3.fromDegrees( 108.86996023, 34.22265071, 9994.60869058 ), ]; } let LineInstanceArr = []; //定义折线几何 let polyline = new Cesium.PolylineGeometry({ positions: positions, width: 5.0, vertexFormat: Cesium.PolylineColorAppearance.VERTEX_FORMAT, }); var LineInstance = new Cesium.GeometryInstance({ geometry: polyline, attributes: { color: Cesium.ColorGeometryInstanceAttribute.fromColor( Cesium.Color.RED ), }, }); LineInstanceArr.push(LineInstance); // 这里使用window.line的原因是我不想让vue组件对我的cesium绘制的任何实体进行监控,以免出现效率问题,这在我的另外一篇博客中有提到 window.line = new Cesium.Primitive({ geometryInstances: LineInstanceArr, //折线外观 appearance: new Cesium.PolylineColorAppearance({ translucent: false, }), asynchronous: false, }); viewer.scene.primitives.add(line);},
positions就是跟之前entity的positions一个意思,也就是一个列表,里面存放了所有的点的经纬度。
下面演示一下绘制效果: