//自定義繪製圖形,支持 點,線,面,矩形,圓,標識,可自定義繪製過程當中的和繪製完的預覽 this.drawGraphic = function(view,_mode,_callback,_GraphicProperty){ //清空全部可能的監聽和畫到一半的圖形 if(handler){ handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE); handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK); } if(activeShapePoints||activeShape||floatingPoint||boundaryPoints.length>0||returnGraphic){ if(floatingPoint){ view.entities.remove(floatingPoint); floatingPoint = undefined; } if(activeShape){ view.entities.remove(activeShape); activeShape = undefined; } activeShapePoints = []; if(boundaryPoints.length>0){ for(let i=0;i<boundaryPoints.length;i++){ view.entities.remove(boundaryPoints[i]); } } } //配置 var drawingMode = _mode; var GraphicProperty; if(_GraphicProperty===null||_GraphicProperty===""||_GraphicProperty===undefined){ GraphicProperty = {} }else{ GraphicProperty=_GraphicProperty } //監聽左鍵點擊事件 function listenClick(_view,_callback) { handler = new Cesium.ScreenSpaceEventHandler(view.scene.canvas); handler.setInputAction(function(movement) { let position = view.scene.pickPosition(movement.position); let screenPosition = movement.position; let callbackObj = {}; callbackObj.cartesian3=position; callbackObj.movement=movement; callbackObj.screenPosition=screenPosition; _callback(callbackObj,handler); },Cesium.ScreenSpaceEventType.LEFT_CLICK); } //模式判斷 if(drawingMode==='point'){ listenClick(_view, function(callbackObj, handler) { let position = callbackObj.cartesian3; let Point; //構造實體 if(GraphicProperty.style&&GraphicProperty.style.point){ Point = view.entities.add({ id:GraphicProperty.id||null, description:GraphicProperty.description||'', name:GraphicProperty.name||'', position:position, point:GraphicProperty.style.point }); }else{ Point = view.entities.add({ type:'Selection tool', position:position, point:{ color: Cesium.Color.WHITE, pixelSize: 10, outlineColor: Cesium.Color.BLACK, outlineWidth: 0, show: true, } }); } //回調產生的點 if(_callback){ _callback(Point); } //銷燬左鍵監聽 handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE); handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK); }); } else if(drawingMode==='marker'){ if(GraphicProperty.style&&GraphicProperty.style.billboard){ listenClick(_view, function(callbackObj, handler) { //此時場景中的點 let position = callbackObj.cartesian3; //賦值,構造點實體Entity let Marker = view.entities.add({ id:GraphicProperty.id||null, description:GraphicProperty.description||null, name:GraphicProperty.name||'', type:'Selection tool', show:GraphicProperty.show||true, position:position, billboard:GraphicProperty.style.billboard }); //回調構造的點 if(_callback){ _callback(Marker); } //銷燬 handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE); handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK); }); }else{ listenClick(_view, function(callbackObj, handler) { //此時場景中的點 let position = callbackObj.cartesian3; //賦值,構造點實體Entity let Marker = view.entities.add({ type:'Selection tool', show: true, position:position, point:{ color: Cesium.Color.WHITE, pixelSize: 10, outlineColor: Cesium.Color.BLACK, outlineWidth: 0, show: true, } }); //回調構造的點 if(_callback){ _callback(Marker); } //銷燬 handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE); handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK); }); } } else{ handler = new Cesium.ScreenSpaceEventHandler(view.canvas); //取消自帶的雙擊放大監聽 view.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); //構造點,例如在活動的提示點 function createPoint(worldPosition) { var point = view.entities.add({ position : worldPosition, point : { color : Cesium.Color.WHITE, pixelSize : 5, } }); return point; } //繪製圖形 function drawShape(positionData) { var shape; if (drawingMode === 'polyline') { if(GraphicProperty.style&&GraphicProperty.style.polyline){ GraphicProperty.style.polyline.positions=positionData; shape = view.entities.add({ id:GraphicProperty.id||null, name:GraphicProperty.name||'', description:GraphicProperty.description||'', polyline : GraphicProperty.style.polyline }); }else{ shape = view.entities.add({ polyline : { positions : positionData, width : 3 } }); } } else if (drawingMode === 'polygon') { if(GraphicProperty.style&&GraphicProperty.style.polygon){ GraphicProperty.style.polygon.hierarchy=positionData; GraphicProperty.style.polygon.perPositionHeight=true; shape = view.entities.add({ id:GraphicProperty.id||null, name:GraphicProperty.name||'', description:GraphicProperty.description||'', polygon:GraphicProperty.style.polygon }); }else{ shape = view.entities.add({ polygon: { hierarchy: positionData, material: new Cesium.ColorMaterialProperty(Cesium.Color.WHITE.withAlpha(0.7)), perPositionHeight:true } }); } } else if (drawingMode === 'circle'){ //當positionData爲數組時繪製最終圖,若是爲function則繪製動態圖 let xyz = new Cesium.Cartesian3(activeShapePoints[0].x, activeShapePoints[0].y, activeShapePoints[0].z); //轉WGS84 let wgs84 = view.scene.globe.ellipsoid.cartesianToCartographic(xyz); let height = wgs84.height; let value = typeof positionData.getValue === 'function' ? positionData.getValue(0) : positionData; if(GraphicProperty.style&&GraphicProperty.style.ellipse){ GraphicProperty.style.ellipse.semiMinorAxis=new Cesium.CallbackProperty(function () { //半徑 兩點間距離 var r = Math.sqrt(Math.pow(value[0].x - value[value.length - 1].x, 2) + Math.pow(value[0].y - value[value.length - 1].y, 2)); return r ? r : r + 1; }, false); GraphicProperty.style.ellipse.semiMajorAxis=new Cesium.CallbackProperty(function () { var r = Math.sqrt(Math.pow(value[0].x - value[value.length - 1].x, 2) + Math.pow(value[0].y - value[value.length - 1].y, 2)); return r ? r : r + 1; }, false); GraphicProperty.style.ellipse.height=height; shape = view.entities.add({ position: activeShapePoints[0], id:GraphicProperty.id||null, name:GraphicProperty.name||'', description:GraphicProperty.description||'', ellipse:GraphicProperty.style.ellipse }); } else{ shape = view.entities.add({ position: activeShapePoints[0], ellipse: { semiMinorAxis: new Cesium.CallbackProperty(function () { //半徑 兩點間距離 var r = Math.sqrt(Math.pow(value[0].x - value[value.length - 1].x, 2) + Math.pow(value[0].y - value[value.length - 1].y, 2)); return r ? r : r + 1; }, false), semiMajorAxis: new Cesium.CallbackProperty(function () { var r = Math.sqrt(Math.pow(value[0].x - value[value.length - 1].x, 2) + Math.pow(value[0].y - value[value.length - 1].y, 2)); return r ? r : r + 1; }, false), material: GraphicProperty.material||Cesium.Color.BLUE.withAlpha(0.5), height:height, outline: true } }); } } else if (drawingMode === 'rectangle'){ let xyz = new Cesium.Cartesian3(activeShapePoints[0].x, activeShapePoints[0].y, activeShapePoints[0].z); //轉WGS84 let wgs84 = view.scene.globe.ellipsoid.cartesianToCartographic(xyz); let height = wgs84.height; //當positionData爲數組時繪製最終圖,若是爲function則繪製動態圖 let arr = typeof positionData.getValue === 'function' ? positionData.getValue(0) : positionData; if(GraphicProperty.style&&GraphicProperty.style.rectangle){ GraphicProperty.style.rectangle.coordinates=new Cesium.CallbackProperty(function () { return Cesium.Rectangle.fromCartesianArray(arr); }, false); GraphicProperty.style.rectangle.height=height; shape = view.entities.add({ id:GraphicProperty.id||null, name:GraphicProperty.name||'', description:GraphicProperty.description||'', rectangle : GraphicProperty.style.rectangle }); }else{ shape = view.entities.add({ rectangle : { coordinates : new Cesium.CallbackProperty(function () { return Cesium.Rectangle.fromCartesianArray(arr); }, false), material : Cesium.Color.GREEN.withAlpha(0.5), height:height } }); } } return shape; } //左鍵監聽,每一次繪製都要留下記錄 handler.setInputAction(function(event) { //在場景中使用深度拾取scene.pickPosition globe的pick還有camera的pick在場景中拾取不許確 var earthPosition = view.scene.pickPosition(event.position); //當鼠標不在地表時,earthPosition切成未定義undefined if (Cesium.defined(earthPosition)) { if (activeShapePoints.length === 0) { floatingPoint = createPoint(earthPosition); activeShapePoints.push(earthPosition); var dynamicPositions = new Cesium.CallbackProperty(function () { if (drawingMode === 'polygon') { return new Cesium.PolygonHierarchy(activeShapePoints); } return activeShapePoints; }, false); activeShape = drawShape(dynamicPositions); } activeShapePoints.push(earthPosition); let boundaryPoint=createPoint(earthPosition); boundaryPoints.push(boundaryPoint); } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); //鼠標移動的監聽 handler.setInputAction(function(event) { if (Cesium.defined(floatingPoint)) { var newPosition = view.scene.pickPosition(event.endPosition); if (Cesium.defined(newPosition)) { floatingPoint.position.setValue(newPosition); activeShapePoints.pop(); activeShapePoints.push(newPosition); } } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); //重置圖形,造成最終形態,把動態過程當中的圖形所有去掉 function terminateShape() { activeShapePoints.pop(); let final_Entity; if(activeShapePoints.length){ final_Entity = drawShape(activeShapePoints);//繪製最終圖 } view.entities.remove(floatingPoint); view.entities.remove(activeShape); floatingPoint = undefined; activeShape = undefined; activeShapePoints = []; for(let i=0;i<boundaryPoints.length;i++){ view.entities.remove(boundaryPoints[i]); } return final_Entity; } //右鍵監聽,結束畫圖 handler.setInputAction(function(event) { returnGraphic = terminateShape(); if(_callback){ _callback(returnGraphic); } handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE); handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK); }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); } };
點、標註、面、線、圓、矩形的style式樣構造按照Cesium本身的那個graphic來構造
//構造polygon屬性 function constructPolygon(_param){ if(!_param){ _param={}; } let PolygonlEntity = {}; PolygonlEntity.polygon = { hierarchy: _param.hierarchy||null, show:_param.show||true, fill:_param.fill||true, outline: _param.outline || false, outlineWidth: _param.maximumHeights || null, outlineColor: _param.show || true, distanceDisplayCondition: _param.distanceDisplayCondition || undefined, material:_param.material||Cesium.Color.WHITE, perPositionHeight:_param.perPositionHeight||true //這個屬性是false時會始終貼在地表,不會變成空間性的面 }; return PolygonlEntity; }; //構造polyline屬性 function constructPolyline(_param) { if(!_param){ _param={}; } let PolylineEntity = {}; PolylineEntity.polyline = { width: _param.width || 1.0, positions: _param.positions||null, show: _param.show || true, material: _param.material || Cesium.Color.WHITE, distanceDisplayCondition: _param.distanceDisplayCondition || undefined }; return PolylineEntity; }; //構造rectangle屬性 function constructRectangle(_param) { if(!_param){ _param={}; } let RectangleEntity = {}; RectangleEntity.rectangle = { coordinates: _param.coordinates||null, show: _param.show || true, fill: _param.fill || true, material: _param.material || Cesium.Color.WHITE, distanceDisplayCondition: _param.distanceDisplayCondition || undefined }; return RectangleEntity; }; //構造point屬性 function constructPoint(_param) { let PointEntity = {}; if (!_param) { _param = {} } PointEntity.point = { color: _param.color || Cesium.Color.WHITE, pixelSize: _param.pixelSize || 1, outlineColor: _param.outlineColor || Cesium.Color.BLACK, outlineWidth: _param.outlineWidth || 0, show: _param.show || true, scaleByDistance: _param.scaleByDistance || null, translucencyByDistance: _param.translucencyByDistance || null, heightReference: _param.heightReference || Cesium.HeightReference.NONE, distanceDisplayCondition: _param.distanceDisplayCondition || undefined, }; return PointEntity; }; //構造marker(billboard)屬性 function constructBillboard(_param) { if(!_param){ _param={}; } let BillboardEntity = {}; BillboardEntity.billboard = { image: _param.image||null, show: _param.show || true, scale: _param.scale || 1.0, eyeOffset: _param.eyeOffset || Cesium.Cartesian3.ZERO, pixelOffset: _param.pixelOffset || Cesium.Cartesian2.ZERO, // sizeInMeters:_param.sizeInMeters||true, horizontalOrigin: _param.horizontalOrigin || Cesium.HorizontalOrigin.CENTER, //水平方向 中心 verticalOrigin: _param.verticalOrigin || Cesium.VerticalOrigin.CENTER, //垂直方向 底部 rotation: _param.rotation || 0, heightReference: _param.heightReference || Cesium.HeightReference.NONE, distanceDisplayCondition:_param.distanceDisplayCondition ||undefined // pixelOffsetScaleByDistance:_param.pixelOffsetScaleByDistance }; return BillboardEntity }; //構造circle(ellipse)的屬性 function constructEllipse(_param) { if(!_param){ _param={}; } let EllipseEntity = {}; EllipseEntity.ellipse = { semiMinorAxis: _param.semiMinorAxis || 2000, semiMajorAxis: _param.semiMajorAxis || 2000, height: _param.height || 0, material: _param.material || Cesium.Color.WHITE, }; return EllipseEntity; };
繪製canvas
let pointStyle = { style: constructPoint({ color: Cesium.Color.RED, pixelSize: 10, outlineColor: Cesium.Color.BLACK, outlineWidth: 0, show: true, distanceDisplayCondition: camera.DistanceDisplayCondition(0.1, 2500.0) }) }; let markerStyle = { style: constructBillboard({ image: 'images/pic.png', scale: 0.3, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: coordinates.createCatesian2(0, -20), }) }; let rectangleStyle = { style: constructRectangle({ material:style.setColorWithAlpha(Cesium.Color.GREEN,0.5) }) }; let circleStyle = { style: constructEllipse({ material:style.setColorWithAlpha(Cesium.Color.DARKGOLDENROD,0.5) }) }; //繪製 let drawarr = []; function draW(e) { switch (e) { case 'point': drawGraphic(view,'point',function (_entity) { drawarr.push(_entity); },pointStyle); break; case 'polyline': drawGraphic(view,'polyline',function (_entity) { drawarr.push(_entity); },polylineStyle); break; case 'polygon': drawGraphic(view,'polygon',function (_entity) { drawarr.push(_entity); },polygonStyle); break; case 'marker': drawGraphic(view,'marker',function (_entity) { drawarr.push(_entity); },markerStyle); break; case 'circle': drawGraphic(view,'circle',function (_entity) { drawarr.push(_entity); },circleStyle); break; case 'rectangle': drawGraphic(view,'rectangle',function (_entity) { drawarr.push(_entity); },rectangleStyle); break; } }
最終效果: