一、前言
對於一個地圖GIS場景,繪制點、線、面屬於是基礎功能,無論是二維地圖還是三維地圖場景均是如此,尤其對於三維場景來說比二維應該是更加困難了些。
但是基礎的簡單繪制不用考慮太多,下面我們開始學習在Cesium的三維場景中如何進行基礎繪制的實現。
二、使用原始Cesium的Entity方法繪制
Cesium中封裝了幾何對象的接口,也就是點、線、面、圓柱體、長方體、圓錐體等等,還有特殊的幾何對象:corridor、ellipse、ellipsoid;以及billboard和model。但這次主要是使用點、線、面這三個幾何對象,其他的幾何對象都是類似的,使用方法大同小異,主要是看每個幾何對象自身內部所需要的參數有哪些罷了。
2.1繪制點Entity
首先看看PointGraphics點幾何對象,它需要的參數是點的位置(坐標、最主要的),樣式(顏色、輪廓的寬度、顏色等)。那么我們傳給它這些屬性即可實現繪制點的功能。
核心代碼如下:
1、使用handler構建鼠標事件:
//繪制點 document.getElementById("drawpoint").addEventListener("click", function () { var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); handler.setInputAction(function (movement) { tooltip.style.left = movement.endPosition.x + 10 + "px"; tooltip.style.top = movement.endPosition.y + 20 + "px"; }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); handler.setInputAction(function (movement) { position = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid); let point = drawPoint(position); tempEntities.push(point); }, Cesium.ScreenSpaceEventType.LEFT_CLICK); handler.setInputAction(function () { handler.destroy();//關閉事件句柄 handler = null; }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); handler.setInputAction(function () { handler.destroy();//關閉事件句柄 handler = null; }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); });
2、使用entity添加點:
function drawPoint(position, config) { var config = config ? config : {}; var pointGeometry = viewer.entities.add({ name: "點幾何對象", position: position, point: { color: Cesium.Color.SKYBLUE, pixelSize: 10, outlineColor: Cesium.Color.YELLOW, outlineWidth: 3, disableDepthTestDistance: Number.POSITIVE_INFINITY } }); return pointGeometry; };
3、效果圖:

2.2繪制線Entity
可以看看PolylineGraphics對象中的屬性,兩點連成線,positions屬性就是用來存放各個拐點的;還有線的寬度width,樣式等和點類似。
1、使用handler構建鼠標事件:
//繪制線 document.getElementById("drawline").addEventListener("click", function () { handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); var tempPoints = []; //鼠標移動事件 handler.setInputAction(function (movement) { tooltip.style.left = movement.endPosition.x + 10 + "px"; tooltip.style.top = movement.endPosition.y + 20 + "px"; }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); //左鍵點擊操作 handler.setInputAction(function (click) { //調用獲取位置信息的接口 position = viewer.camera.pickEllipsoid(click.position, viewer.scene.globe.ellipsoid); tempPoints.push(position); let tempLength = tempPoints.length; //調用繪制點的接口 let point = drawPoint(tempPoints[tempPoints.length - 1]); tempEntities.push(point); if (tempLength > 1) { let pointline = drawPolyline([tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1]]); tempEntities.push(pointline); } else { tooltip.innerHTML = "請繪制下一個點,右鍵結束"; } return; }, Cesium.ScreenSpaceEventType.LEFT_CLICK); //右鍵點擊操作 handler.setInputAction(function (click) { tooltip.style.display = "none"; tooltip.innerHTML = "左鍵單擊繪制,右鍵結束繪制"; tempPoints = []; handler.destroy();//關閉事件句柄 handler = null; }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); });
2、使用entity添加線:
function drawPolyline(positions, config) { if (positions.length < 1) return; var config = config ? config : {}; var polylineGeometry = viewer.entities.add({ name: "線幾何對象", polyline: { positions: positions, width: config.width ? config.width : 5.0, material: new Cesium.PolylineGlowMaterialProperty({ color: config.color ? new Cesium.Color.fromCssColorString(config.color) : Cesium.Color.GOLD, }), depthFailMaterial: new Cesium.PolylineGlowMaterialProperty({ color: config.color ? new Cesium.Color.fromCssColorString(config.color) : Cesium.Color.GOLD, }), } }); return polylineGeometry; };
3、效果圖:

2.3繪制面Entity
面幾何對象,我們使用PolygonGraphics來繪制。繪制一個面,我們會繪制多個點、多條線組合成。它的屬性也是類似的,其中positions屬性同線對象是一樣的。
1、使用handler構建鼠標事件:
//繪制面 document.getElementById("drawploy").addEventListener("click", function () { var tempPoints = []; handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); tooltip.style.display = "block"; //鼠標移動事件 handler.setInputAction(function (movement) { tooltip.style.left = movement.endPosition.x + 10 + "px"; tooltip.style.top = movement.endPosition.y + 20 + "px"; }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); //左鍵點擊操作 handler.setInputAction(function (click) { //調用獲取位置信息的接口 position = viewer.camera.pickEllipsoid(click.position, viewer.scene.globe.ellipsoid); tempPoints.push(position); let tempLength = tempPoints.length; //調用繪制點的接口 let point = drawPoint(position); tempEntities.push(point); if (tempLength > 1) { let pointline = drawPolyline([tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1]]); tempEntities.push(pointline); } else { tooltip.innerHTML = "請繪制下一個點,右鍵結束"; } return; }, Cesium.ScreenSpaceEventType.LEFT_CLICK); //右鍵點擊操作 handler.setInputAction(function (click) { let cartesian = viewer.camera.pickEllipsoid(click.position, viewer.scene.globe.ellipsoid); if (cartesian) { let tempLength = tempPoints.length; if (tempLength < 3) { alert('請選擇3個以上的點再執行閉合操作命令'); } else { //閉合最后一條線 let pointline = drawPolyline([tempPoints[tempPoints.length - 1], tempPoints[0]]); tempEntities.push(pointline); drawPolygon(tempPoints); tempEntities.push(tempPoints); handler.destroy();//關閉事件句柄 handler = null; } } }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); });
2、使用entity添加面:
function drawPolygon(positions, config) { if (positions.length < 2) return; var config = config ? config : {}; var polygonGeometry = viewer.entities.add({ name: "線幾何對象", polygon: { height: 0.1, hierarchy: new Cesium.PolygonHierarchy(positions), material: config.color ? new Cesium.Color.fromCssColorString(config.color).withAlpha(.2) : new Cesium.Color.fromCssColorString("#FFD700").withAlpha(.2), perPositionHeight: true, } }); return polygonGeometry; };
3、效果圖:

三、DrawHandler插件
網上有很多大佬們寫了自己的DrawHandler For Ceisum的插件,其中的功能更加豐富,非常適合偷懶者使用(ˇ∀ˇ)。當然也是學習的好資料,其中繪制的方法是不一樣的,我上面的是簡單的繪制,且沒有實時將線繪制出來,面也是,而drawhandler插件實現的方式卻是實時繪制出來的。下面我們來看看。
3.1繪制點

3.2繪制線

3.3繪制面

四、總結
使用自己制作的基礎繪制工具,其優點是方便、快捷,缺點是簡陋,但好方法、好技術都是慢慢積累出來的,這里我只是使用了Cesium的Entity中的點、線、面繪制,Entity中還有很多的幾何對象繪制,可以自行查看API學習,如果之后有時間會考慮再補充。
插件是好東西,對於我們使用來說極其方便,用起來也是好用,但是對於我們理解Cesium來說就少了些內容,如果有時間應當自己去模仿一下插件的實現,或者閱讀其源碼,看看它是如何實現的。
