該項目用於高速公路監管。高速公路監管包括:高速公路的設備運行狀況,設備維護狀況,道路維護狀況;交通流量分析,交通擁堵分析,擁堵溯源;事故分析,事件信息發佈等。數組
該項目目前主要是一個預演形式的項目,因此設計圖層面主要仍是用了客戶提供的圖片。 咱們的設計團隊參與的並很少。下面是客戶的設計圖紙:bash
公路的實際效果仍是比較複雜的,好比公路上面有各類線(斑馬線,黃線,白線,實線,虛線等等)。可是這些在本系統不是最重要的要素,所以考慮忽略。所以咱們使用帶邊線效果的路徑進行模擬,效果以下所示:app
繪製的邏輯其實也很簡單,首先用較大的線寬繪製路徑,而後改成較小的線寬和不一樣顏色在繪製一次路徑。 大體的繪製邏輯以下:echarts
ctx.save();
ctx.beginPath();
ctx.lineJoin = 'round';
// ctx.lineCap = 'round';
points.forEach(({
x,
y
}, index) => {
ctx[index ? 'lineTo' : 'moveTo'](x, y);
})
ctx.lineWidth = width;
ctx.strokeStyle = sideColor;
ctx.stroke();
ctx.shadowBlur = 0;
ctx.globalCompositeOperation = 'source-over';
ctx.lineWidth = width * 0.5;
ctx.strokeStyle = midColor;
ctx.stroke();
複製代碼
在編輯器中,增長一個公路組件,點擊下公路組件,即可以開始繪製公路:編輯器
經過打點編輯路徑,便可以對公路的走向進行編輯。 須要注意的是,技術上使用了自動平滑的技術,本來的尖銳的角都會變成平滑的效果。ide
export function createSmoothCurvePoints(
points,
tension = 0.5,
closed = false,
numberOfSegments = 16
) {
if (points.length < 2) {
return points;
}
// 展開數組
points = expandPointArr(points);
let ps = points.slice(0), // clone array so we don't change the original result = [], // result points x, y, // our x,y coords t1x, t2x, t1y, t2y, // tension vectors c1, c2, c3, c4, // cardinal points st, t, i; // steps based on number of segments // The algorithm require a previous and next point to the actual point array. // Check if we will draw closed or open curve. // If closed, copy end points to beginning and first points to end // If open, duplicate first points to befinning, end points to end if (closed) { ps.unshift(points[points.length - 1]); ps.unshift(points[points.length - 2]); ps.unshift(points[points.length - 1]); ps.unshift(points[points.length - 2]); ps.push(points[0]); ps.push(points[1]); } else { ps.unshift(points[1]); // copy 1st point and insert at beginning ps.unshift(points[0]); ps.push(points[points.length - 2]); // copy last point and append ps.push(points[points.length - 1]); } // 1. loop goes through point array // 2. loop goes through each segment between the 2 points + 1e point before and after for (i = 2; i < ps.length - 4; i += 2) { // calculate tension vectors t1x = (ps[i + 2] - ps[i - 2]) * tension; t2x = (ps[i + 4] - ps[i - 0]) * tension; t1y = (ps[i + 3] - ps[i - 1]) * tension; t2y = (ps[i + 5] - ps[i + 1]) * tension; for (t = 0; t <= numberOfSegments; t++) { // calculate step st = t / numberOfSegments; // calculate cardinals c1 = 2 * Math.pow(st, 3) - 3 * Math.pow(st, 2) + 1; c2 = -(2 * Math.pow(st, 3)) + 3 * Math.pow(st, 2); c3 = Math.pow(st, 3) - 2 * Math.pow(st, 2) + st; c4 = Math.pow(st, 3) - Math.pow(st, 2); // calculate x and y cords with common control vectors x = c1 * ps[i] + c2 * ps[i + 2] + c3 * t1x + c4 * t2x; y = c1 * ps[i + 1] + c2 * ps[i + 3] + c3 * t1y + c4 * t2y; //store points in array result.push(x); result.push(y); } } return contractPointArr(result); 複製代碼
門架的最終效果以下圖所示:oop
能夠看出門架是由幾個立方體組合而成的。咱們只須要理解立方體的繪製邏輯,即可以很輕鬆理解門架的繪製邏輯。ui
編輯器中自己也存在立方體組件:this
其顯示效果以下:spa
繪製立方體的思路並不複雜,只是藉助了一些三維的思路。首先借助了三維的投影變換的思路,固然此處使用的是正投影:
/**
* 3d座標轉2d座標
*
* @param {Object} point - 3d座標
* @param {Object} offset - 一點偏移
* @returns {Object} - 2d座標
*/
getProjectionPoint(point) {
const network = this._network,
p = vec3.create(),
itMat = network.getMVMatrix();
vec3.transformMat4(
p,
[point.x, point.y, point.z],
itMat
);
const {
x,
y
} = this.getLocation()
return {
x: p[0] + x,
y: -p[1] + y
};
}
複製代碼
對立方體的8個頂點計算出其在平面上的位置,並計算出其如今在外面的三個面(注意:最多隻會有三個面顯示在外面)。 而後把三個面繪製值出來:
drawSide(ctx, points, isFill = false, color = "#00ccff") {
ctx.save();
ctx[isFill ? 'fillStyle' : 'strokeStyle'] = color;
ctx.lineWidth = 1;
ctx.beginPath();
points.forEach(({
x,
y
}, index) => {
ctx[index ? 'lineTo' : 'moveTo'](x, y);
})
ctx.closePath();
ctx[isFill ? 'fill' : 'stroke']();
ctx.restore();
}
複製代碼
最終繪製的效果如上圖所示。
門架的繪製,就是多個立方體的組合的繪製。須要注意的一點就是,要注意多個立方體繪製的順序,這會涉及到遮擋關係的正確性。
在編輯器中,能夠經過調整其長寬高和y軸旋轉角度來改變其顯示形態:
標誌牌是公路上面常見的對象。 用於各類提示,在本系統,標誌牌顯示效果以下:
其繪製思路其實和前面的門架相似,都是經過立方體組合而成的。所以此處再也不贅述。
因爲山是比較複雜的模型,所以程序直接使用了設計人員的設計的圖形。以下圖所示:
使用設計人員設計的圖片做爲網元的圖片,直接拖拽進入場景便可。
編輯器中集成了經常使用的echarts圖表和擴展的圖表。應此能夠直接拖拽到場景之中,好比下圖截出了部分的圖表,包括柱狀圖、餅圖、曲線圖:
把圖表直接拖到場景中便可生成圖表效果,以下圖所示:
並能夠在屬性框配置圖表的數據,此處爲了演示,使用的是靜態數據;也能夠對接動態的數據上倆。
綜合上述全部的效果,最終編輯出來了一個演示頁面,以下圖所示:
有興趣獲取demo的,請發郵件到:
terry.tan@servasoft.com
另歡迎關注我的公衆號 「ITman彪叔」