canvas在拖拽的畫布中繪制geojson地圖數(shù)據(jù)

image.png
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <canvas id="myCanvas" width="1680" height="830"></canvas>
</body>

</html>
<script src="mapJson.js"></script>
<script>
    // 當前 canvas 的 0 0 坐標襟齿,我們設(shè)置 canvas 左上角頂點為 0 0,向右??和向下??是 X Y 軸正方向盹兢,0,0 為 pageSlicePos 初始值
    const pageSlicePos = {  // 坐標系的原點
        x: 0,
        y: 0,
    };
    var scale = 10; // 縮放比例
    var mapScale = 10; // 調(diào)整地圖的默認的縮放大小
    // ----------- pageSlicePos, scale 這兩個值是重點------------------

    const solidColor = '#ccc'; // 實線顏色
    const dashedColor = '#f0f0f0'; // 虛線顏色
    const zeroColor = '#358bf3'; // 0 點坐標系顏色
    const GRIDSIZE = 5;  // 一個正方形網(wǎng)格的寬高大小, 一個GRIDSIZE視為一個單位

    const myCanvas = document.querySelector('#myCanvas');
    const ctx = myCanvas.getContext('2d'); // 獲取canvas上下文
    myCanvas.addEventListener("mousedown", mouseDown);
    myCanvas.addEventListener("mousewheel", mouseWheel);
    myCanvas.addEventListener("mousemove", mouseMove);

    const curMousePos = {
        x: 0,
        y: 0
    }

    const arrX = []
    const arrY = []
    map.features.forEach(item => {
        let coordinates = item.geometry.coordinates;
        coordinates.forEach(data => {
            data.forEach(data1 => {
                if (data1.length > 2) {
                    data1.forEach((data2, i) => {
                        arrX.push(data2[0]);
                        arrY.push(data2[1]);
                    });
                }
            });
        });
    });
    const left = Math.min(...arrX);
    const right = Math.max(...arrX);
    const topp = Math.min(...arrY);
    const bottom = Math.max(...arrY);
    let mapH = topp + bottom;
    let mapW = left + right;
    let mapCenterPos = [mapW / 2, mapH / 2];

    /**
     * 繪制網(wǎng)格
     * @param scaleVal 縮放倍數(shù)
     */
    var drawLineGrid = (scaleVal = scale) => {
        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        /*獲取繪圖工具*/
        // 設(shè)置網(wǎng)格大小
        var girdSize = getPixelSize(GRIDSIZE);
        // 獲取Canvas的width、height
        var CanvasWidth = ctx.canvas.width;
        var CanvasHeight = ctx.canvas.height;

        // 在 pageSlicePos 的 x,y 點位畫一個 10 * 10 的紅色標記用來表示當前頁面的 0 0 坐標
        ctx.fillStyle = 'red';
        ctx.fillRect(pageSlicePos.x - 5, pageSlicePos.y - 5, 10, 10); // 效果圖紅色小方塊

        const canvasXHeight = CanvasHeight - pageSlicePos.y;
        const canvasYWidth = CanvasWidth - pageSlicePos.x;
        // 從 pageSlicePos.y 處開始往 Y 軸正方向畫 X 軸網(wǎng)格
        const xPageSliceTotal = Math.ceil(canvasXHeight / girdSize);   // 每隔一個單位畫一條線
        for (let i = 0; i < xPageSliceTotal; i++) {
            ctx.beginPath(); // 開啟路徑,設(shè)置不同的樣式
            ctx.moveTo(0, pageSlicePos.y + girdSize * i);
            ctx.lineTo(CanvasWidth, pageSlicePos.y + girdSize * i);
            ctx.strokeStyle = i === 0 ? zeroColor : (i % 5 === 0 ? solidColor : dashedColor); // 如果為 0 則用藍色標記,取余 5 為實線铐望,其余為比較淡的線
            ctx.stroke();
        }

        // 從 pageSlicePos.y 處開始往 Y 軸負方向畫 X 軸網(wǎng)格
        const xRemaining = pageSlicePos.y;
        const xRemainingTotal = Math.ceil(xRemaining / girdSize);
        for (let i = 0; i < xRemainingTotal; i++) {
            if (i === 0) continue;
            ctx.beginPath(); // 開啟路徑,設(shè)置不同的樣式
            ctx.moveTo(0, pageSlicePos.y - girdSize * i); // -0.5是為了解決像素模糊問題
            ctx.lineTo(CanvasWidth, pageSlicePos.y - girdSize * i);
            ctx.strokeStyle = i === 0 ? zeroColor : (i % 5 === 0 ? solidColor : dashedColor);// 如果為 0 則用藍色標記茂附,取余 5 為實線正蛙,其余為比較淡的線
            ctx.stroke();
        }

        // 從 pageSlicePos.x 處開始往 X 軸正方向畫 Y 軸網(wǎng)格
        const yPageSliceTotal = Math.ceil(canvasYWidth / girdSize); // 計算需要繪畫y軸的條數(shù)
        for (let j = 0; j < yPageSliceTotal; j++) {
            ctx.beginPath(); // 開啟路徑,設(shè)置不同的樣式
            ctx.moveTo(pageSlicePos.x + girdSize * j, 0);
            ctx.lineTo(pageSlicePos.x + girdSize * j, CanvasHeight);
            ctx.strokeStyle = j === 0 ? zeroColor : (j % 5 === 0 ? solidColor : dashedColor);// 如果為 0 則用藍色標記何之,取余 5 為實線跟畅,其余為比較淡的線
            ctx.stroke();
        }

        // 從 pageSlicePos.x 處開始往 X 軸負方向畫 Y 軸網(wǎng)格
        const yRemaining = pageSlicePos.x;
        const yRemainingTotal = Math.ceil(yRemaining / girdSize);
        for (let j = 0; j < yRemainingTotal; j++) {
            if (j === 0) continue;
            ctx.beginPath(); // 開啟路徑,設(shè)置不同的樣式
            ctx.moveTo(pageSlicePos.x - girdSize * j, 0);
            ctx.lineTo(pageSlicePos.x - girdSize * j, CanvasHeight);
            ctx.strokeStyle = j === 0 ? zeroColor : (j % 5 === 0 ? solidColor : dashedColor);// 如果為 0 則用藍色標記溶推,取余 5 為實線徊件,其余為比較淡的線
            ctx.stroke();
        }

        ctx.strokeStyle = "black";
        map.features.forEach(item => {
            console.log(item.properties, "item");
            let coordinates = item.geometry.coordinates;
            if (item.properties.center && item.properties.center.length == 2) {
                let cp = item.properties.center;
                let mapX = (cp[0] - mapCenterPos[0]);
                let mapY = mapH - (cp[1] + mapCenterPos[1]);
                let center = getPixelPos({ x: mapX * mapScale, y: mapY * mapScale });
                ctx.fillStyle = "#000"
                ctx.fillText(item.properties.name, center.x, center.y);
            }
            coordinates.forEach(data => {
                data.forEach(data1 => {
                    if (data1.length > 2) {
                        ctx.beginPath();
                        data1.forEach((data2, i) => {
                            let mapX = (data2[0] - mapCenterPos[0]);
                            let mapY = mapH - (data2[1] + mapCenterPos[1]);
                            let point = getPixelPos({ x: mapX * mapScale, y: mapY * mapScale });
                            if (i === 0) {
                                ctx.moveTo(point.x, point.y);
                            }
                            ctx.lineTo(point.x, point.y);
                        });
                        ctx.stroke();
                        let isPointIn = ctx.isPointInPath(curMousePos.x, curMousePos.y);
                        if (isPointIn) {
                            ctx.fillStyle = "red";
                            ctx.fill();
                        }
                    }
                });
            });
        });
    };

    function mouseMove(e) {
        curMousePos.x = e.clientX;
        curMousePos.y = e.clientY;
    }

    function getPixelPos(point) {
        return {
            x: pageSlicePos.x + (point.x / GRIDSIZE) * scale,
            y: pageSlicePos.y + (point.y / GRIDSIZE) * scale,
        };
    }

    function getRelativePos(point) {
        return {
            x: ((point.x - pageSlicePos.x) / scale) * GRIDSIZE,
            y: ((point.y - pageSlicePos.y) / scale) * GRIDSIZE,
        };
    }

    function getPixelSize(size) {
        return size * scale;
    }

    function getRelativeSize(size) {
        return size / scale;
    }

    /**
     * 滾輪縮放倍數(shù)
     */
    function mouseWheel(e) {
        if (e.wheelDelta > 0) {
            if (scale < 20) {
                scale++;
            }
        } else {
            if (scale > 1) {
                scale--;
            }
        }
    }

    /**
     * 拖動 canvas 動態(tài)渲染,拖動時蒜危,動態(tài)設(shè)置 pageSlicePos 的值
     * @param e Event
     */
    function mouseDown(e) {
        const downX = e.clientX;
        const downY = e.clientY;
        const { x, y } = pageSlicePos;
        myCanvas.onmousemove = (ev) => {
            const moveX = ev.clientX;
            const moveY = ev.clientY;
            pageSlicePos.x = x + (moveX - downX);
            pageSlicePos.y = y + (moveY - downY);
            myCanvas.onmouseup = (en) => {
                myCanvas.onmousemove = null;
                myCanvas.onmouseup = null;
            };
        }
        myCanvas.onmouseup = (en) => {
            myCanvas.onmousemove = null;
            myCanvas.onmouseup = null;
        };
    }

    (function main() {
        drawLineGrid();
        requestAnimationFrame(main);
    })()

</script>
<style>
    body {
        margin: 0;
    }
</style>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末虱痕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子辐赞,更是在濱河造成了極大的恐慌部翘,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件响委,死亡現(xiàn)場離奇詭異新思,居然都是意外死亡,警方通過查閱死者的電腦和手機赘风,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門夹囚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人邀窃,你說我怎么就攤上這事荸哟。” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵鞍历,是天一觀的道長舵抹。 經(jīng)常有香客問我,道長劣砍,這世上最難降的妖魔是什么惧蛹? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮刑枝,結(jié)果婚禮上赊淑,老公的妹妹穿的比我還像新娘。我一直安慰自己仅讽,他們只是感情好,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布钾挟。 她就那樣靜靜地躺著洁灵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪掺出。 梳的紋絲不亂的頭發(fā)上徽千,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機與錄音汤锨,去河邊找鬼双抽。 笑死,一個胖子當著我的面吹牛闲礼,可吹牛的內(nèi)容都是我干的牍汹。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼柬泽,長吁一口氣:“原來是場噩夢啊……” “哼慎菲!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起锨并,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤露该,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后第煮,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體解幼,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年包警,在試婚紗的時候發(fā)現(xiàn)自己被綠了撵摆。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡揽趾,死狀恐怖台汇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤苟呐,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布痒芝,位于F島的核電站,受9級特大地震影響牵素,放射性物質(zhì)發(fā)生泄漏严衬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一笆呆、第九天 我趴在偏房一處隱蔽的房頂上張望请琳。 院中可真熱鬧,春花似錦赠幕、人聲如沸俄精。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽竖慧。三九已至,卻和暖如春逆屡,著一層夾襖步出監(jiān)牢的瞬間圾旨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工魏蔗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留砍的,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓莺治,卻偏偏與公主長得像廓鞠,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子谣旁,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容