圓形方形繪製

範例展示

原始碼

copy
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>圓形方形繪製 - Map8 Platform Documentation</title>
    <link rel="stylesheet" href="https://api.map8.zone/css/gomp.css?key=[YOUR_KEY_HERE]" />
    <style>
        #map{
            height: 400px; 
            width: 100%;
        }
        .map-wrap {
          width: 100%;
          height: 400px;
          position: relative;
        }

        #map {
          width: 100%;
          height: 100%;
        }

        .myCanvas {
          position: absolute;
          top: 0;
          left: 0;
        }
    </style>
</head>
<body>
    <div class="map-wrap">
      <div id="map"></div>
    </div>
    <button id="circleOn" class="btn">圓形on</button>
    <button id="rectOn" class="btn">矩形on</button>
    <button id="paintOn" class="btn">繪製on</button>
    <button id="circleOff" class="btn" disabled>圓形off</button>
    <button id="rectOff" class="btn" disabled>矩形off</button>
    <button id="paintOff" class="btn" disabled>繪製off</button>
    
    <script type="text/javascript" src="https://api.map8.zone/maps/js/gomp.js?key=[YOUR_KEY_HERE]"></script>
    <script src="https://code.jquery.com/jquery-3.7.1.js" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" crossorigin="anonymous"></script>
    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/Turf.js/5.1.5/turf.min.js"></script>
    <script type="text/javascript">
        gomp.accessToken = '[YOUR_KEY_HERE]';
        var map = new gomp.Map({
            container: 'map', // 地圖容器 ID
            style: 'https://api.map8.zone/styles/go-life-maps-tw-style-std/style.json', // 地圖樣式檔案位置
            maxBounds: [[105, 15], [138.45858, 33.4]], // 台灣地圖區域
            center: [121.54885, 25.037853], // 初始中心座標,格式為 [lng, lat]
            zoom: 16, // 初始 ZOOM LEVEL; [0-20, 0 為最小 (遠), 20 ;最大 (近)]
            minZoom: 6, // 限制地圖可縮放之最小等級, 可省略, [0-19.99]
            maxZoom: 19.99, // 限制地圖可縮放之最大等級, 可省略 [0-19.99]
            speedLoad: false,
            attributionControl: false
        }).addControl(new gomp.AttributionControl({
            compact: false
        }));
// 設置初始位置和半徑
      var startX,
        startY,
        endX,
        endY,
        radius,
        width,
        height,
        canvas,
        context,
        circleFeature,
        rectFeature,
        polygonFeature;
      var point_1, point_2;
      // 拖曳使用的變數
      let isDragging = false;
      let paintCoordinates = [];

      $('#circleOn').click(() => {
        $('#circleOn').attr('disabled', true);
        $('#circleOff').attr('disabled', false);
        $('#rectOn').attr('disabled', true);
        $('#paintOn').attr('disabled', true);
        [canvas, context] = makeCanvas(
          map._canvas.clientWidth,
          map._canvas.clientHeight
        );
        canvas.classList.add('myCanvas');
        $('.map-wrap')[0].append(canvas);
        canvas.addEventListener('mousedown', circleMouseDown);
        canvas.addEventListener('mousemove', circleMouseMove);
        canvas.addEventListener('mouseup', circleMouseUp);
        canvas.addEventListener('touchstart', circleMouseDown);
        canvas.addEventListener('touchmove', circleMouseMove);
        canvas.addEventListener('touchend', circleMouseUp);
      });
      $('#circleOff').click(() => {
        $('#circleOn').attr('disabled', false);
        $('#circleOff').attr('disabled', true);
        $('#rectOn').attr('disabled', false);
        $('#paintOn').attr('disabled', false);
        if (map.getLayer('circle-layer')) {
          map.removeLayer('circle-layer');
          map.removeSource('circle-source');
        }
        canvas.removeEventListener('mousedown', circleMouseDown);
        canvas.removeEventListener('mousemove', circleMouseMove);
        canvas.removeEventListener('mouseup', circleMouseUp);
        canvas.removeEventListener('touchstart', circleMouseDown);
        canvas.removeEventListener('touchmove', circleMouseMove);
        canvas.removeEventListener('touchend', circleMouseUp);
        myCanvasRemove();
      });
      $('#rectOn').click(() => {
        $('#rectOn').attr('disabled', true);
        $('#rectOff').attr('disabled', false);
        $('#circleOn').attr('disabled', true);
        $('#paintOn').attr('disabled', true);
        [canvas, context] = makeCanvas(
          map._canvas.clientWidth,
          map._canvas.clientHeight
        );
        canvas.classList.add('myCanvas');
        $('.map-wrap')[0].append(canvas);
        canvas.addEventListener('mousedown', rectMouseDown);
        canvas.addEventListener('mousemove', rectMouseMove);
        canvas.addEventListener('mouseup', rectMouseUp);
        canvas.addEventListener('touchstart', rectMouseDown);
        canvas.addEventListener('touchmove', rectMouseMove);
        canvas.addEventListener('touchend', rectMouseUp);
      });
      $('#rectOff').click(() => {
        $('#rectOn').attr('disabled', false);
        $('#rectOff').attr('disabled', true);
        $('#circleOn').attr('disabled', false);
        $('#paintOn').attr('disabled', false);
        if (map.getLayer('rect-layer')) {
          map.removeLayer('rect-layer');
          map.removeSource('rect-source');
        }
        canvas.removeEventListener('mousedown', rectMouseDown);
        canvas.removeEventListener('mousemove', rectMouseMove);
        canvas.removeEventListener('mouseup', rectMouseUp);
        canvas.removeEventListener('touchstart', rectMouseDown);
        canvas.removeEventListener('touchmove', rectMouseMove);
        canvas.removeEventListener('touchend', rectMouseUp);
        myCanvasRemove();
      });
      $('#paintOn').click(() => {
        $('#paintOn').attr('disabled', true);
        $('#paintOff').attr('disabled', false);
        $('#circleOn').attr('disabled', true);
        $('#rectOn').attr('disabled', true);
        [canvas, context] = makeCanvas(
          map._canvas.clientWidth,
          map._canvas.clientHeight
        );
        canvas.classList.add('myCanvas');
        $('.map-wrap')[0].append(canvas);
        canvas.addEventListener('mousedown', paintMouseDown);
        canvas.addEventListener('mousemove', paintMouseMove);
        canvas.addEventListener('mouseup', paintMouseUp);
        canvas.addEventListener('touchstart', paintMouseDown);
        canvas.addEventListener('touchmove', paintMouseMove);
        canvas.addEventListener('touchend', paintMouseUp);
      });
      $('#paintOff').click(() => {
        $('#paintOn').attr('disabled', false);
        $('#paintOff').attr('disabled', true);
        $('#circleOn').attr('disabled', false);
        $('#rectOn').attr('disabled', false);
        if (map.getLayer('polygon-layer')) {
          map.removeLayer('polygon-layer');
          map.removeSource('polygon-source');
        }
        paintCoordinates = [];
        canvas.removeEventListener('mousedown', paintMouseDown);
        canvas.removeEventListener('mousemove', paintMouseMove);
        canvas.removeEventListener('mouseup', paintMouseUp);
        canvas.removeEventListener('touchstart', paintMouseDown);
        canvas.removeEventListener('touchmove', paintMouseMove);
        canvas.removeEventListener('touchend', paintMouseUp);
        myCanvasRemove();
      });

      // 圓形
      function circleMouseDown(event) {
        event.preventDefault();
        var rect = canvas.getBoundingClientRect();
        if (event.type.startsWith('mouse')) {
          startX = event.clientX - rect.left;
          startY = event.clientY - rect.top;
          point_1 = screenToLngLat(startX, startY);
        } else {
          startX = event.touches[0].clientX - rect.left;
          startY = event.touches[0].clientY - rect.top;
          point_1 = screenToLngLat(startX, startY);
        }
      }
      function circleMouseMove(event) {
        event.preventDefault();
        if (startX && startY) {
          var rect = canvas.getBoundingClientRect();
          let currentX, currentY;
          if (event.type.startsWith('mouse')) {
            currentX = event.clientX - rect.left;
            currentY = event.clientY - rect.top;
          } else {
            currentX = event.touches[0].clientX - rect.left;
            currentY = event.touches[0].clientY - rect.top;
          }
          radius = Math.sqrt(
            Math.pow(currentX - startX, 2) + Math.pow(currentY - startY, 2)
          );
          context.clearRect(0, 0, canvas.width, canvas.height);
          context.beginPath();
          context.arc(startX, startY, radius, 0, 2 * Math.PI);
          context.stroke();
        }
      }
      function circleMouseUp(event) {
        event.preventDefault();
        var rect = canvas.getBoundingClientRect();
        if (event.type.startsWith('mouse')) {
          endX = event.clientX - rect.left;
          endY = event.clientY - rect.top;
          point_2 = screenToLngLat(endX, endY);
        } else {
          endX = event.changedTouches[0].clientX - rect.left;
          endY = event.changedTouches[0].clientY - rect.top;
          point_2 = screenToLngLat(endX, endY);
        }
        const distance = turf.distance(point_1, point_2);
        circleFeature = makeCircleLayer(point_1, distance);
        map.addSource('circle-source', {
          type: 'geojson',
          data: circleFeature,
        });
        map.addLayer({
          id: 'circle-layer',
          type: 'fill',
          source: 'circle-source',
          layout: {},
          paint: {
            'fill-color': '#ff0000',
            'fill-opacity': 0.5,
          },
        });
        canvas.remove();
        startX = null;
        startY = null;
        radius = null;
      }
      // 矩形
      function rectMouseDown(event) {
        event.preventDefault();
        var rect = canvas.getBoundingClientRect();
        if (event.type.startsWith('mouse')) {
          startX = event.clientX - rect.left;
          startY = event.clientY - rect.top;
          point_1 = screenToLngLat(startX, startY);
        } else {
          startX = event.touches[0].clientX - rect.left;
          startY = event.touches[0].clientY - rect.top;
          point_1 = screenToLngLat(startX, startY);
        }
      }
      function rectMouseMove(event) {
        event.preventDefault();
        if (startX && startY) {
          var rect = canvas.getBoundingClientRect();
          let currentX, currentY;
          if (event.type.startsWith('mouse')) {
            currentX = event.clientX - rect.left;
            currentY = event.clientY - rect.top;
          } else {
            currentX = event.touches[0].clientX - rect.left;
            currentY = event.touches[0].clientY - rect.top;
          }
          width = currentX - startX;
          height = currentY - startY;
          context.clearRect(0, 0, canvas.width, canvas.height);
          context.strokeRect(startX, startY, width, height);
        }
      }
      function rectMouseUp(event) {
        event.preventDefault();
        var rect = canvas.getBoundingClientRect();
        if (event.type.startsWith('mouse')) {
          endX = event.clientX - rect.left;
          endY = event.clientY - rect.top;
          point_2 = screenToLngLat(endX, endY);
        } else {
          endX = event.changedTouches[0].clientX - rect.left;
          endY = event.changedTouches[0].clientY - rect.top;
          point_2 = screenToLngLat(endX, endY);
        }
        rectFeature = makeRectLayer(point_1, point_2);
        map.addSource('rect-source', {
          type: 'geojson',
          data: rectFeature,
        });
        map.addLayer({
          id: 'rect-layer',
          type: 'fill',
          source: 'rect-source',
          layout: {},
          paint: {
            'fill-color': '#ff0000',
            'fill-opacity': 0.5,
          },
        });
        canvas.remove();
        startX = null;
        startY = null;
        width = null;
        height = null;
      }
      // 繪製
      function paintMouseDown(event) {
        event.preventDefault();
        var rect = canvas.getBoundingClientRect();
        if (event.type.startsWith('mouse')) {
          startX = event.clientX - rect.left;
          startY = event.clientY - rect.top;
          point_1 = screenToLngLat(startX, startY);
          paintCoordinates.push(point_1);
          context.beginPath();
          context.moveTo(startX, startY);
        } else {
          startX = event.touches[0].clientX - rect.left;
          startY = event.touches[0].clientY - rect.top;
          point_1 = screenToLngLat(startX, startY);
          paintCoordinates.push(point_1);
          context.beginPath();
          context.moveTo(startX, startY);
        }
      }
      function paintMouseMove(event) {
        event.preventDefault();
        if (startX && startY) {
          var rect = canvas.getBoundingClientRect();
          if (event.type.startsWith('mouse')) {
            var currentX = event.clientX - rect.left;
            var currentY = event.clientY - rect.top;
            let movePoint = screenToLngLat(currentX, currentY);
            paintCoordinates.push(movePoint);
            context.lineTo(currentX, currentY);
            context.stroke();
          } else {
            var currentX = event.touches[0].clientX - rect.left;
            var currentY = event.touches[0].clientY - rect.top;
            let movePoint = screenToLngLat(currentX, currentY);
            paintCoordinates.push(movePoint);
            context.lineTo(currentX, currentY);
            context.stroke();
          }
        }
      }
      function paintMouseUp(event) {
        event.preventDefault();
        var rect = canvas.getBoundingClientRect();
        if (event.type.startsWith('mouse')) {
          endX = event.clientX - rect.left;
          endY = event.clientY - rect.top;
        } else {
          endX = event.changedTouches[0].clientX - rect.left;
          endY = event.changedTouches[0].clientY - rect.top;
        }
        point_2 = screenToLngLat(endX, endY);
        paintCoordinates.push(point_2);
        paintCoordinates.push(point_1); // 加回第一個點形成完整的polygon陣列格式
        if (paintCoordinates.length > 10) {
          polygonFeature = makePolygonLayer(paintCoordinates);
          map.addSource('polygon-source', {
            type: 'geojson',
            data: polygonFeature,
          });
          map.addLayer({
            id: 'polygon-layer',
            type: 'fill',
            source: 'polygon-source',
            layout: {},
            paint: {
              'fill-color': '#ff0000',
              'fill-opacity': 0.5,
            },
          });
        } else {
          alert('請重新繪製');
          $('#paintOff')[0].click();
        }
        canvas.remove();
        startX = null;
        startY = null;
        width = null;
        height = null;
      }
      // 及時 canvas 畫布生成
      function makeCanvas(width, height) {
        const canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
        canvas.style.cursor = 'crosshair';
        return [canvas, canvas.getContext('2d')];
      }
      // turf 生成 circle 圖層
      function makeCircleLayer(start, radius) {
        const center = turf.point(start);
        const circle = turf.circle(center, radius);
        return circle;
      }
      // turf 生成 rect 圖層
      function makeRectLayer(start, end) {
        const polygon = turf.polygon([
          [
            [start[0], start[1]],
            [start[0], end[1]],
            [end[0], end[1]],
            [end[0], start[1]],
            [start[0], start[1]],
          ],
        ]);
        return polygon;
      }
      // turf 生成 自定義polygon 圖層
      function makePolygonLayer(polygonCoordinates) {
        const polygon = turf.polygon([polygonCoordinates]);
        return polygon;
      }
      function isLatLngInPolygon(latLng, polygonCoordinates) {
        const point = turf.point(latLng);
        const polygon = turf.polygon([polygonCoordinates]);
        return turf.booleanPointInPolygon(point, polygon);
      }
      // 座標點取得地圖經緯度
      function screenToLngLat(x, y) {
        var lngLat = map.unproject([x, y]);
        return [lngLat.lng, lngLat.lat];
      }
      function myCanvasRemove() {
        let canvas = document.getElementsByClassName('myCanvas')[0];
        if (canvas) {
          let parent = canvas.parentNode;
          parent.removeChild(canvas);
        }
      }
    </script>
</body>
</html>