该计划借鉴了多个大佬的,把代码理了一遍再整合了一下做了个汇合(算是一个练手的demo)重点这里初始化地球的时候留神下这个参数requestRenderMode(缩小Cesium渲染新帧总工夫并缩小Cesium在应用程序中总体CPU使用率),如果你开启了,那么流线材质就会动一下就不动了,切记!!!!上面是vue组件代码https://segmentfault.com/u/yo...
<template> <div class="tole"> <div id="cesiumContainer" style="height: 100%;width: 100%"> </div> </div></template><script>import * as Cesium from 'cesium/Cesium'import widget from 'cesium/Widgets/widgets.css'var viewer = nullexport default { data(){ return{ viewer:null } }, mounted(){ console.log(widget); Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJlZGMwM2M2OC02ZGYwLTQ5NzQtYjBkOS1lYTM0MmYxNTZlZTkiLCJpZCI6NjEwNTMsImlhdCI6MTYyNTY0ODgzN30.9B76dtOIBsNmX3laJ5VXFOqt2NlBT-n16j4ppUF8IYA' // viewer = new Cesium.CesiumWidget('cesiumContainer') viewer = new Cesium.Viewer("cesiumContainer",{ animation: false, // 暗藏动画控件 baseLayerPicker: false, // 暗藏图层抉择控件 fullscreenButton: false, // 暗藏全屏按钮 vrButton: false, // 暗藏VR按钮,默认false geocoder: false, // 暗藏地名查找控件 homeButton: false, // 暗藏Home按钮 infoBox: false, // 暗藏点击因素之后显示的信息窗口 sceneModePicker: false, // 暗藏场景模式抉择控件 selectionIndicator: true, // 显示实体对象抉择框,默认true timeline: false, // 暗藏工夫线控件 navigationHelpButton: false, // 暗藏帮忙按钮 scene3DOnly: true, // 每个几何实例将只在3D中出现,以节俭GPU内存 shouldAnimate: true, // 开启动画自动播放 sceneMode: 3, // 初始场景模式 1:2D 2:2D循环 3:3D,默认3 requestRenderMode: false, // 缩小Cesium渲染新帧总工夫并缩小Cesium在应用程序中总体CPU使用率 // 如场景中的元素没有随仿真工夫变动,请思考将设置maximumRenderTimeChange为较高的值,例如Infinity maximumRenderTimeChange: Infinity, //天地图影像 // imageryProvider: new Cesium.WebMapTileServiceImageryProvider({ // url: "http://t0.tianditu.com/vec_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=vec&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=39ca2b2b8dc2f3e1e9c3de07f4d4de57", // layer: "tdtBasicLayer", // style: "default", // format: "tiles", // tileMatrixSetID: "GoogleMapsCompatible", // show: true, // maximumLevel: 18 // }) }) this.viewer = viewer //增加天地图标注 // viewer.imageryLayers.addImageryProvider(new Cesium.WebMapTileServiceImageryProvider({ // url: "http://t0.tianditu.com/cia_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cia&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default.jpg&tk=39ca2b2b8dc2f3e1e9c3de07f4d4de57", // layer: "tdtAnnoLayer", // style: "default", // format: "tiles", // tileMatrixSetID: "GoogleMapsCompatible", // show: true // })); viewer.cesiumWidget.creditContainer.style.display = "none" //增加线 // var orangeOutlined = viewer.entities.add({ // name: // "Orange line with black outline at height and following the surface", // polyline: { // positions: Cesium.Cartesian3.fromDegreesArrayHeights([ // -75, // 39, // 0, // -125, // 39, // 0, // ]), // width: 5, // material: new Cesium.PolylineOutlineMaterialProperty({ // color: Cesium.Color.ORANGE, // outlineWidth: 2, // outlineColor: Cesium.Color.BLACK, // }), // }, // }); // console.log(orangeOutlined); //增加点位 var entity = viewer.entities.add({ position: Cesium.Cartesian3.fromDegrees(120.9677706,30.7985748,2.61), point: { color: Cesium.Color.RED, //点位色彩 pixelSize: 10 //像素点大小 }, label : { text : '测试名称', font : '14pt Source Han Sans CN', //字体款式 fillColor:Cesium.Color.BLACK, //字体色彩 backgroundColor:Cesium.Color.AQUA, //背景色彩 showBackground:true, //是否显示背景色彩 style: Cesium.LabelStyle.FILL, //label款式 outlineWidth : 2, verticalOrigin : Cesium.VerticalOrigin.CENTER,//垂直地位 horizontalOrigin :Cesium.HorizontalOrigin.LEFT,//程度地位 pixelOffset:new Cesium.Cartesian2(10,0) //偏移 } }); console.log(entity); //这里通过算法失去曲线 let mm = this.parabola([-75,39,-175,39]) var polyline = new Cesium.PolylineGeometry({ positions: mm, width : 2 }); const instance = new Cesium.GeometryInstance({ geometry: polyline, id: 'flyline', }) //增加至场景 this.viewer.scene.primitives.add( new Cesium.Primitive({ geometryInstances: [instance], appearance: this.getFlylineMaterial(), releaseGeometryInstances: false, compressVertices: false, }) ) }, methods:{ computeFlyline( point1 = [-75, 39], point2 = [-175,39], h = 500000 ) { let flyline = getBSRxyz(...point1, ...point2, h) return flyline // 将数据转换为cesium polyline positions格局 function getBSRxyz(x1, y1, x2, y2, h) { let arr3d = getBSRPoints(x1, y1, x2, y2, h) let arrAll = [] for (let ite of arr3d) { arrAll.push(ite[0]) arrAll.push(ite[1]) arrAll.push(ite[2]) } return Cesium.Cartesian3.fromDegreesArrayHeights(arrAll) } function getBSRPoints(x1, y1, x2, y2, h) { let point1 = [y1, 0] let point2 = [(y2 + y1) / 2, h] let point3 = [y2, 0] let arr = getBSR(point1, point2, point3) let arr3d = [] for (let i = 0; i< arr.length; i++) { let x = ((x2 - x1) * (arr[i][0] - y1)) / (y2 - y1) + x1 arr3d.push([x, arr[i][0], arr[i][1]]) } return arr3d } // 生成贝塞尔曲线 function getBSR(point1, point2, point3) { var ps = [ { x: point1[0], y: point1[1] }, { x: point2[0], y: point2[1] }, { x: point3[0], y: point3[1] } ] // 100 每条线由100个点组成 let guijipoints = CreateBezierPoints(ps, 100) return guijipoints } // 贝赛尔曲线算法 // 参数: // anchorpoints: [{ x: 116.30, y: 39.60 }, { x: 37.50, y: 40.25 }, { x: 39.51, y: 36.25 }] function CreateBezierPoints(anchorpoints, pointsAmount) { var points = [] for (var i = 0; i < pointsAmount; i++) { var point = MultiPointBezier(anchorpoints, i / pointsAmount) points.push([point.x, point.y]) } return points } function MultiPointBezier(points, t) { var len = points.length var x = 0, y = 0 var erxiangshi = function(start, end) { var cs = 1, bcs = 1 while (end > 0) { cs *= start bcs *= end start-- end-- } return cs / bcs } for (var i = 0; i < len; i++) { var point = points[i] x += point.x * Math.pow(1 - t, len - 1 - i) * Math.pow(t, i) * erxiangshi(len - 1, i) y += point.y * Math.pow(1 - t, len - 1 - i) * Math.pow(t, i) * erxiangshi(len - 1, i) } return { x: x, y: y } } }, parabola(twoPoints) { //抛物线绘制 let s = [] let startPoint = [twoPoints[0],twoPoints[1],0]; //终点的经度、纬度 s = s.concat(startPoint) let step = 80; //线的多少,越多则越平滑(但过多浏览器缓存也会占用越多) let heightProportion = 0.125; //最高点和总间隔的比值 let dLon = (twoPoints[2] - startPoint[0])/step; //经度差值 let dLat = (twoPoints[3] - startPoint[1])/step; //纬度差值 let deltaLon = dLon * Math.abs(111000*Math.cos(twoPoints[1])); //经度差(米级) let deltaLat = dLat * 111000; //纬度差(米),1纬度相差约111000米 let endPoint = [0,0,0]; //定义一个端点(前面将进行startPoint和endPoint两点画线) let heigh = (step * Math.sqrt(deltaLon*deltaLon+deltaLat*deltaLat) * heightProportion).toFixed(0)*2; let x2 = (10000*Math.sqrt(dLon*dLon+dLat*dLat)); //小数点扩充10000倍,进步精确度 let a = (heigh/(x2*x2)); function y(x,height) { return height - a*x*x; } for(var i = 1;i <= step; i++){ //逐“帧”画线 endPoint[0] = startPoint[0] + dLon; //更新end点经度 endPoint[1] = startPoint[1] + dLat; //更新end点纬度 let x = x2*(2*i/step-1); //求抛物线函数x endPoint[2] = (y(x,heigh)).toFixed(0)*1; //求end点高度 s = s.concat(endPoint) // end点变为start点 startPoint[0] = endPoint[0]; startPoint[1] = endPoint[1]; startPoint[2] = endPoint[2]; } return Cesium.Cartesian3.fromDegreesArrayHeights(s) }, getFlylineMaterial(){ // 创立材质,在MaterialAppearance中若不增加根底材质,模型将会通明 var material = new Cesium.Material.fromType('Color') material.uniforms.color = Cesium.Color.ORANGE // 飞线成果-飞线距离,宽度2 let fragmentShaderSource = ` varying vec2 v_st; varying float v_width; varying float v_polylineAngle; varying vec4 v_positionEC; varying vec3 v_normalEC; void main() { vec2 st = v_st; // 箭头飞线,宽度 8 float xx = fract(st.s*10.0 + st.t - czm_frameNumber/60.0); if (st.t<0.5) { xx = fract(st.s*10.0 - st.t - czm_frameNumber/60.0); } float r = 0.0; float g = xx; float b = xx; float a = xx; // 飞线边框 if (st.t>0.8||st.t<0.2) { g = 1.0; b = 1.0; a = 0.4; } gl_FragColor = vec4(r,g,b,a); } ` // 自定义材质 const aper = new Cesium.PolylineMaterialAppearance({ material: material, translucent: true, vertexShaderSource: ` #define CLIP_POLYLINE void clipLineSegmentToNearPlane( vec3 p0, vec3 p1, out vec4 positionWC, out bool clipped, out bool culledByNearPlane, out vec4 clippedPositionEC) { culledByNearPlane = false; clipped = false; vec3 p0ToP1 = p1 - p0; float magnitude = length(p0ToP1); vec3 direction = normalize(p0ToP1); float endPoint0Distance = czm_currentFrustum.x + p0.z; float denominator = -direction.z; if (endPoint0Distance > 0.0 && abs(denominator) < czm_epsilon7) { culledByNearPlane = true; } else if (endPoint0Distance > 0.0) { float t = endPoint0Distance / denominator; if (t < 0.0 || t > magnitude) { culledByNearPlane = true; } else { p0 = p0 + t * direction; p0.z = min(p0.z, -czm_currentFrustum.x); clipped = true; } } clippedPositionEC = vec4(p0, 1.0); positionWC = czm_eyeToWindowCoordinates(clippedPositionEC); } vec4 getPolylineWindowCoordinatesEC(vec4 positionEC, vec4 prevEC, vec4 nextEC, float expandDirection, float width, bool usePrevious, out float angle) { #ifdef POLYLINE_DASH vec4 positionWindow = czm_eyeToWindowCoordinates(positionEC); vec4 previousWindow = czm_eyeToWindowCoordinates(prevEC); vec4 nextWindow = czm_eyeToWindowCoordinates(nextEC); vec2 lineDir; if (usePrevious) { lineDir = normalize(positionWindow.xy - previousWindow.xy); } else { lineDir = normalize(nextWindow.xy - positionWindow.xy); } angle = atan(lineDir.x, lineDir.y) - 1.570796327; angle = floor(angle / czm_piOverFour + 0.5) * czm_piOverFour; #endif vec4 clippedPrevWC, clippedPrevEC; bool prevSegmentClipped, prevSegmentCulled; clipLineSegmentToNearPlane(prevEC.xyz, positionEC.xyz, clippedPrevWC, prevSegmentClipped, prevSegmentCulled, clippedPrevEC); vec4 clippedNextWC, clippedNextEC; bool nextSegmentClipped, nextSegmentCulled; clipLineSegmentToNearPlane(nextEC.xyz, positionEC.xyz, clippedNextWC, nextSegmentClipped, nextSegmentCulled, clippedNextEC); bool segmentClipped, segmentCulled; vec4 clippedPositionWC, clippedPositionEC; clipLineSegmentToNearPlane(positionEC.xyz, usePrevious ? prevEC.xyz : nextEC.xyz, clippedPositionWC, segmentClipped, segmentCulled, clippedPositionEC); if (segmentCulled) { return vec4(0.0, 0.0, 0.0, 1.0); } vec2 directionToPrevWC = normalize(clippedPrevWC.xy - clippedPositionWC.xy); vec2 directionToNextWC = normalize(clippedNextWC.xy - clippedPositionWC.xy); if (prevSegmentCulled) { directionToPrevWC = -directionToNextWC; } else if (nextSegmentCulled) { directionToNextWC = -directionToPrevWC; } vec2 thisSegmentForwardWC, otherSegmentForwardWC; if (usePrevious) { thisSegmentForwardWC = -directionToPrevWC; otherSegmentForwardWC = directionToNextWC; } else { thisSegmentForwardWC = directionToNextWC; otherSegmentForwardWC = -directionToPrevWC; } vec2 thisSegmentLeftWC = vec2(-thisSegmentForwardWC.y, thisSegmentForwardWC.x); vec2 leftWC = thisSegmentLeftWC; float expandWidth = width * 0.5; if (!czm_equalsEpsilon(prevEC.xyz - positionEC.xyz, vec3(0.0), czm_epsilon1) && !czm_equalsEpsilon(nextEC.xyz - positionEC.xyz, vec3(0.0), czm_epsilon1)) { vec2 otherSegmentLeftWC = vec2(-otherSegmentForwardWC.y, otherSegmentForwardWC.x); vec2 leftSumWC = thisSegmentLeftWC + otherSegmentLeftWC; float leftSumLength = length(leftSumWC); leftWC = leftSumLength < czm_epsilon6 ? thisSegmentLeftWC : (leftSumWC / leftSumLength); vec2 u = -thisSegmentForwardWC; vec2 v = leftWC; float sinAngle = abs(u.x * v.y - u.y * v.x); expandWidth = clamp(expandWidth / sinAngle, 0.0, width * 2.0); } vec2 offset = leftWC * expandDirection * expandWidth * czm_pixelRatio; return vec4(clippedPositionWC.xy + offset, -clippedPositionWC.z, 1.0) * (czm_projection * clippedPositionEC).w; } vec4 getPolylineWindowCoordinates(vec4 position, vec4 previous, vec4 next, float expandDirection, float width, bool usePrevious, out float angle) { vec4 positionEC = czm_modelViewRelativeToEye * position; vec4 prevEC = czm_modelViewRelativeToEye * previous; vec4 nextEC = czm_modelViewRelativeToEye * next; return getPolylineWindowCoordinatesEC(positionEC, prevEC, nextEC, expandDirection, width, usePrevious, angle); } attribute vec3 position3DHigh; attribute vec3 position3DLow; attribute vec3 prevPosition3DHigh; attribute vec3 prevPosition3DLow; attribute vec3 nextPosition3DHigh; attribute vec3 nextPosition3DLow; attribute vec2 expandAndWidth; attribute vec2 st; attribute float batchId; varying float v_width; varying vec2 v_st; varying float v_polylineAngle; varying vec4 v_positionEC; varying vec3 v_normalEC; void main() { float expandDir = expandAndWidth.x; float width = abs(expandAndWidth.y) + 0.5; bool usePrev = expandAndWidth.y < 0.0; vec4 p = czm_computePosition(); vec4 prev = czm_computePrevPosition(); vec4 next = czm_computeNextPosition(); float angle; vec4 positionWC = getPolylineWindowCoordinates(p, prev, next, expandDir, width, usePrev, angle); gl_Position = czm_viewportOrthographic * positionWC; v_width = width; v_st.s = st.s; v_st.t = st.t; // v_st.t = czm_writeNonPerspective(st.t, gl_Position.w); v_polylineAngle = angle; vec4 eyePosition = czm_modelViewRelativeToEye * p; v_positionEC = czm_inverseModelView * eyePosition; // position in eye coordinates //v_normalEC = czm_normal * normal; // normal in eye coordinates } `, fragmentShaderSource: fragmentShaderSource }) return aper; }, }}</script><style scope lang="scss">.tole{ width: 100%; height: 100%;}</style>这里有两个曲线算法computeFlyline和parabola,任选其一即可其中一个来自于https://www.cnblogs.com/s3131...另一个忘了(原作者能够分割我)
...