圓形方形繪製
範例展示
原始碼
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>