|
|
|
|
|
<!DOCTYPE html> |
|
|
<html lang="ja"> |
|
|
<head> |
|
|
<link rel="preconnect" href="https://fonts.googleapis.com"> |
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
|
|
<link href="https://fonts.googleapis.com/css2?family=Yomogi&display=swap" rel="stylesheet"> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|
|
<title>マーカー編集機能付きのLeafletマップ</title> |
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" /> |
|
|
<style> |
|
|
body{ |
|
|
font-family: "Yomogi", cursive; |
|
|
font-weight: 400; |
|
|
font-style: normal; |
|
|
background-repeat: repeat; background-image:url("https://lh3.googleusercontent.com/d/1MpGi0bdyjKZNYgKQyMWpIZM0R0q1i4rD"); |
|
|
background-attachment: fixed; |
|
|
|
|
|
} |
|
|
#map { height: 600px; width: 100%; } |
|
|
#marker-editor { display: none; position: absolute; top: 10px; left: 10px; background: #fff; padding: 15px; border-radius: 5px; box-shadow: 0 0 15px rgba(0, 0, 0, .3); z-index: 1000; cursor: move; } |
|
|
#marker-editor input, #marker-editor textarea { display: block; width: 100%; margin-bottom: 10px; } |
|
|
#marker-editor button { width: 100%; padding: 10px; border: none; background-color: #007bff; color: #fff; font-size: 16px; border-radius: 4px; cursor: pointer; } |
|
|
#marker-editor button:hover { background-color: #0056b3; } |
|
|
input[type=file] { color: #1f2937; cursor: pointer; border: 1px solid #bfc2c7; border-radius: .375rem; padding-right: .5rem; width: 24rem; } |
|
|
::-webkit-file-upload-button, ::file-selector-button { background-color: #d1d5db; color: #1f2937; border: none; cursor: pointer; border-right: 1px solid #bfc2c7; padding: .25rem 1rem; margin-right: 1rem; } |
|
|
#icon-preview { display: none; margin-top: 10px; max-width: 100%; } |
|
|
#icon-settings { display: none; margin-top: 10px; } |
|
|
#icon-settings label { display: block; margin-bottom: 5px; } |
|
|
|
|
|
body::-webkit-scrollbar { |
|
|
width: 5px; |
|
|
background-color: #c9d8f5; |
|
|
} |
|
|
body::-webkit-scrollbar-thumb { |
|
|
background: #67b9e6; |
|
|
width: 5px; |
|
|
border-radius: 5px; |
|
|
} |
|
|
#loading { |
|
|
position: fixed; |
|
|
top: 0; |
|
|
left: 0; |
|
|
width: 100%; |
|
|
height: 100%; |
|
|
background-color: rgba(255, 255, 255, 0.8); |
|
|
display: flex; |
|
|
align-items: center; |
|
|
justify-content: center; |
|
|
font-size: 24px; |
|
|
z-index: 9999; |
|
|
opacity: 1; |
|
|
transition: opacity 0.5s ease; |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
<div id="loading">Loading...</div> |
|
|
<img src="https://lh3.googleusercontent.com/d/1Wo9oLj4D6JEsT_MWUZ4VyaIy10uLN3q0" /> |
|
|
<button id="edit-next-marker" style="font-family: inherit; font-weight: 700; font-style: normal;">次のマーカーを編集</button> |
|
|
<div id="map" style="width:90%; margin:5%;"></div> |
|
|
<div id="marker-editor"> |
|
|
<h3>マーカーを編集</h3> |
|
|
<label for="marker-lat">緯度:</label> |
|
|
<input type="text" id="marker-lat"> |
|
|
<hr> |
|
|
<label for="marker-lng">経度:</label> |
|
|
<input type="text" id="marker-lng"> |
|
|
<hr> |
|
|
<a href="javascript:window.open('/marker.html');">アイコン</a> |
|
|
<input type="radio" name="icon-source" value="upload" checked>アップロードから |
|
|
<input type="radio" name="icon-source" value="url">URLから読み込む |
|
|
<div id="icon-upload-input" style="display: block; margin-bottom: 20px;"> |
|
|
<label for="marker-icon-upload">マーカーのアイコンをアップロード:</label> |
|
|
<input type="file" id="marker-icon-upload" accept="image/*"> |
|
|
</div> |
|
|
<div id="icon-url-input" style="display: none; margin-bottom: 20px;"> |
|
|
<label for="marker-icon-url">マーカーのアイコンURL:</label> |
|
|
<input type="text" id="marker-icon-url" value="https://unpkg.com/leaflet@1.9.3/dist/images/marker-icon-2x.png"> |
|
|
<button id="load-icon-url">画像を編集</button> |
|
|
</div> |
|
|
<img id="icon-preview" src="" alt="アイコンプレビュー"> |
|
|
<div id="icon-settings"> |
|
|
<label for="icon-width">アイコンの幅:</label> |
|
|
<input type="range" id="icon-width" min="10" max="100" value="25"> |
|
|
<span id="icon-width-value">25</span>px |
|
|
<label for="icon-height">アイコンの高さ:</label> |
|
|
<input type="range" id="icon-height" min="10" max="100" value="41"> |
|
|
<span id="icon-height-value">41</span>px |
|
|
</div> |
|
|
<label for="marker-popup">ポップアップHTML:</label> |
|
|
<textarea id="marker-popup" rows="4"></textarea> |
|
|
<label for="marker-tooltip">ツールチップHTML:</label> |
|
|
<textarea id="marker-tooltip" rows="4"></textarea> |
|
|
<button id="save-marker" style="font-family: inherit; font-weight: 800; font-style: normal;">OK</button> |
|
|
</div> |
|
|
<textarea id="output-html" rows="20" cols="100" readonly hidden></textarea><div id="output-code" style="word-break: break-all;">ここに生成されたHTMLが表示されます。</div><button id="copyButton" style="font-family: inherit; font-weight: 700; font-style: normal;">コードをコピー</button><br> |
|
|
<button id="generate-html" style="width: 50%; padding: 10px; border: none; background-color: #007bff; color: #fff; font-size: 16px; border-radius: 4px; cursor: pointer; margin: 20px; font-family: inherit; font-weight: 800; font-style: normal;">HTMLを生成</button> |
|
|
|
|
|
|
|
|
|
|
|
<script> |
|
|
const output = document.getElementById('output-code'); |
|
|
output.innerHTML = hljs.highlight('html', "ここに生成されたHTMLが表示されます。").value; |
|
|
output.classList.add('hljs');</script> |
|
|
<script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"></script> |
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/mono-blue.min.css"> |
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js"></script> |
|
|
|
|
|
<script> |
|
|
window.onload = function() { |
|
|
const loading = document.getElementById('loading'); |
|
|
loading.style.opacity = '0'; |
|
|
setTimeout(() => { |
|
|
loading.style.display = 'none'; |
|
|
loadMapFromStorage(); |
|
|
}, 500); |
|
|
}; |
|
|
</script> |
|
|
|
|
|
|
|
|
<script> |
|
|
|
|
|
function saveMapToStorage() { |
|
|
const markers = []; |
|
|
map.eachLayer((layer) => { |
|
|
if (layer instanceof L.Marker) { |
|
|
const marker = layer; |
|
|
const icon = marker.options.icon; |
|
|
const { lat, lng } = marker.getLatLng(); |
|
|
markers.push({ |
|
|
lat: lat, |
|
|
lng: lng, |
|
|
iconUrl: icon.options.iconUrl, |
|
|
iconSize: icon.options.iconSize, |
|
|
popupContent: marker.getPopup() ? marker.getPopup().getContent() : '', |
|
|
tooltipContent: marker.getTooltip() ? marker.getTooltip().getContent() : '', |
|
|
}); |
|
|
} |
|
|
}); |
|
|
localStorage.setItem('leafletMap', JSON.stringify(markers)); |
|
|
} |
|
|
|
|
|
function loadMapFromStorage() { |
|
|
const storedMarkers = JSON.parse(localStorage.getItem('leafletMap')); |
|
|
if (!storedMarkers) { |
|
|
console.warn('No markers found in local storage.'); |
|
|
return; |
|
|
} |
|
|
|
|
|
if (!map) { |
|
|
console.error('Map is not initialized.'); |
|
|
return; |
|
|
} |
|
|
|
|
|
storedMarkers.forEach((data) => { |
|
|
if (!data.iconUrl || !data.iconSize) { |
|
|
console.error('Icon data is incomplete.'); |
|
|
return; |
|
|
} |
|
|
|
|
|
const icon = L.icon({ |
|
|
iconUrl: data.iconUrl, |
|
|
iconSize: data.iconSize, |
|
|
iconAnchor: [data.iconSize[0] / 2, data.iconSize[1]], |
|
|
popupAnchor: [0, -data.iconSize[1]], |
|
|
tooltipAnchor: [data.iconSize[0] / 2, -data.iconSize[1] / 2], |
|
|
}); |
|
|
const marker = L.marker([data.lat, data.lng], { icon: icon }).addTo(map); |
|
|
if (data.popupContent) marker.bindPopup(data.popupContent); |
|
|
if (data.tooltipContent) marker.bindTooltip(data.tooltipContent); |
|
|
|
|
|
// ⭐ここから追加⭐ |
|
|
marker.on("mouseover", function() { |
|
|
hoveredMarker = marker; |
|
|
console.log("Marker hovered:", marker); |
|
|
}); |
|
|
marker.on("mouseout", function() { |
|
|
if (hoveredMarker === marker) { |
|
|
hoveredMarker = null; |
|
|
console.log("Marker no longer hovered"); |
|
|
} |
|
|
}); |
|
|
// ⭐ここまで追加⭐ |
|
|
|
|
|
}); |
|
|
} |
|
|
|
|
|
function updatePreviewSize() { |
|
|
var e = document.getElementById("icon-width").value; |
|
|
var t = document.getElementById("icon-height").value; |
|
|
var n = document.getElementById("icon-preview"); |
|
|
n.style.width = e + "px"; |
|
|
n.style.height = t + "px"; |
|
|
document.getElementById("icon-width-value").textContent = e; |
|
|
document.getElementById("icon-height-value").textContent = t; |
|
|
if (editingMarker) { |
|
|
var o = document.querySelector('input[name="icon-source"]:checked').value === "url" ? document.getElementById("marker-icon-url").value : n.src; |
|
|
var i = L.icon({ |
|
|
iconUrl: o, |
|
|
iconSize: [e, t], |
|
|
iconAnchor: [e / 2, t], |
|
|
popupAnchor: [0, -t], |
|
|
tooltipAnchor: [e / 2, -t / 2] |
|
|
}); |
|
|
editingMarker.setIcon(i); |
|
|
saveMapToStorage(); |
|
|
} |
|
|
} |
|
|
|
|
|
function openEditor(e) { |
|
|
const t = e.getLatLng(); |
|
|
document.getElementById("marker-lat").value = t.lat; |
|
|
document.getElementById("marker-lng").value = t.lng; |
|
|
document.getElementById("marker-popup").value = e.getPopup() ? e.getPopup().getContent() : ""; |
|
|
document.getElementById("marker-tooltip").value = e.getTooltip() ? e.getTooltip().getContent() : ""; |
|
|
document.getElementById("marker-editor").style.display = "block"; |
|
|
editingMarker = e; |
|
|
|
|
|
// ここから追加 |
|
|
const icon = e.options.icon; |
|
|
if (icon && icon.options) { |
|
|
if (icon.options.iconUrl) { |
|
|
// URLから読み込むラジオボタンを選択 |
|
|
document.querySelector('input[name="icon-source"][value="url"]').checked = true; |
|
|
document.getElementById("icon-url-input").style.display = "block"; |
|
|
document.getElementById("icon-upload-input").style.display = "none"; |
|
|
document.getElementById("marker-icon-url").value = icon.options.iconUrl; |
|
|
document.getElementById("icon-preview").src = icon.options.iconUrl; |
|
|
document.getElementById("icon-preview").style.display = 'block'; |
|
|
// 高さと幅の設定を表示 |
|
|
document.getElementById("icon-settings").style.display = "block"; |
|
|
} else { |
|
|
// URLから読み込むラジオボタンを選択 |
|
|
document.querySelector('input[name="icon-source"][value="upload"]').checked = true; |
|
|
document.getElementById("icon-url-input").style.display = "none"; |
|
|
document.getElementById("icon-upload-input").style.display = "block"; |
|
|
document.getElementById("marker-icon-url").value = icon.options.iconUrl; |
|
|
document.getElementById("icon-preview").src = icon.options.iconUrl; |
|
|
document.getElementById("icon-preview").style.display = 'block'; |
|
|
// 高さと幅の設定を表示 |
|
|
document.getElementById("icon-settings").style.display = "block"; |
|
|
} |
|
|
document.getElementById("icon-width").value = icon.options.iconSize[0]; |
|
|
document.getElementById("icon-height").value = icon.options.iconSize[1]; |
|
|
document.getElementById("icon-width-value").textContent = icon.options.iconSize[0]; |
|
|
document.getElementById("icon-height-value").textContent = icon.options.iconSize[1]; |
|
|
} |
|
|
// ここまで追加 |
|
|
|
|
|
updatePreviewSize(); |
|
|
} |
|
|
|
|
|
function generateMapHTML() { |
|
|
const e = []; |
|
|
map.eachLayer((function(t) { |
|
|
if (t instanceof L.Marker) { |
|
|
const n = t; |
|
|
const o = n.options.icon; |
|
|
const i = o.options.iconUrl; |
|
|
const r = o.options.iconSize; |
|
|
const c = n.getLatLng(); |
|
|
const l = n.getPopup() ? n.getPopup().getContent() : ""; |
|
|
const a = n.getTooltip() ? n.getTooltip().getContent() : ""; |
|
|
e.push({ |
|
|
lat: c.lat, |
|
|
lng: c.lng, |
|
|
iconUrl: i, |
|
|
iconWidth: r[0], |
|
|
iconHeight: r[1], |
|
|
popupContent: l, |
|
|
tooltipContent: a |
|
|
}); |
|
|
} |
|
|
})); |
|
|
const t = map.getCenter(); |
|
|
const n = map.getZoom(); |
|
|
let o = ` |
|
|
<div id="map" style="height: 600px; width: 100%;"></div> |
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" /> |
|
|
<script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"><\/script> |
|
|
<script> |
|
|
var map = L.map('map').setView([${t.lat}, ${t.lng}], ${n}); |
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { |
|
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' |
|
|
}).addTo(map); |
|
|
|
|
|
${e.map(e => ` |
|
|
var icon = L.icon({ |
|
|
iconUrl: '${e.iconUrl}', |
|
|
iconSize: [${e.iconWidth}, ${e.iconHeight}], |
|
|
iconAnchor: [${e.iconWidth} / 2, ${e.iconHeight}], |
|
|
popupAnchor: [0, -${e.iconHeight}], |
|
|
tooltipAnchor: [${e.iconWidth} / 2, -${e.iconHeight} / 2] |
|
|
}); |
|
|
|
|
|
var marker = L.marker([${e.lat}, ${e.lng}], { |
|
|
icon: icon, |
|
|
zIndexOffset: 1000 |
|
|
}).addTo(map); |
|
|
|
|
|
${e.popupContent ? `marker.bindPopup('${e.popupContent.replace(/'/g, "\\'").replace(/<\/script>/g, "<\\/script>")}');` : ""} |
|
|
${e.tooltipContent ? `marker.bindTooltip('${e.tooltipContent.replace(/'/g, "\\'").replace(/<\/script>/g, "<\\/script>")}');` : ""} |
|
|
`).join("\n")} |
|
|
<\/script> |
|
|
`; |
|
|
o = o.replace(/iconUrl: 'marker-icon\.png'/g, `iconUrl: '${location.origin}/marker-icon.png'`); |
|
|
document.getElementById("output-html").value = o; |
|
|
const input = document.getElementById('output-html').value; |
|
|
const output = document.getElementById('output-code'); |
|
|
output.innerHTML = hljs.highlight('html', input).value; |
|
|
output.classList.add('hljs'); |
|
|
} |
|
|
|
|
|
function resizeImage(e, t, n, o) { |
|
|
const i = new FileReader(); |
|
|
i.onload = function(e) { |
|
|
const i = new Image(); |
|
|
i.onload = function() { |
|
|
const e = document.createElement("canvas"); |
|
|
e.width = t; |
|
|
e.height = n; |
|
|
e.getContext("2d").drawImage(i, 0, 0, t, n); |
|
|
o(e.toDataURL()); |
|
|
}; |
|
|
i.src = e.target.result; |
|
|
}; |
|
|
i.readAsDataURL(e); |
|
|
} |
|
|
|
|
|
document.getElementById("marker-icon-upload").addEventListener("change", function() { |
|
|
const e = this.files[0]; |
|
|
const t = document.getElementById("icon-preview"); |
|
|
if (e) { |
|
|
resizeImage(e, parseInt(document.getElementById("icon-width").value), parseInt(document.getElementById("icon-height").value), function(imageDataUrl) { |
|
|
t.src = imageDataUrl; |
|
|
t.style.display = "block"; |
|
|
document.getElementById("icon-settings").style.display = "block"; // 高さと幅の設定を表示 |
|
|
updatePreviewSize(); |
|
|
}); |
|
|
} else { |
|
|
t.style.display = "none"; |
|
|
document.getElementById("icon-settings").style.display = "none"; // アップロードされていない場合は非表示 |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
document.getElementById("load-icon-url").addEventListener("click", function() { |
|
|
const e = document.getElementById("marker-icon-url").value; |
|
|
const t = document.getElementById("icon-preview"); |
|
|
if (e) { |
|
|
t.src = e; |
|
|
t.onload = function() { |
|
|
t.style.display = "block"; |
|
|
document.getElementById("icon-settings").style.display = "block"; |
|
|
updatePreviewSize(); |
|
|
}; |
|
|
t.onerror = function() { |
|
|
alert("画像の読み込みに失敗しました。URLを確認してください。"); |
|
|
t.style.display = "none"; |
|
|
document.getElementById("icon-settings").style.display = "none"; |
|
|
}; |
|
|
} else { |
|
|
t.style.display = "none"; |
|
|
document.getElementById("icon-settings").style.display = "none"; |
|
|
} |
|
|
}); |
|
|
|
|
|
document.getElementById("icon-width").addEventListener("input", updatePreviewSize); |
|
|
document.getElementById("icon-height").addEventListener("input", updatePreviewSize); |
|
|
|
|
|
const map = L.map("map").setView([33.321797711641395, 130.52061378343208], 16); |
|
|
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' }).addTo(map); |
|
|
|
|
|
let editingMarker = null; |
|
|
let hoveredMarker = null; |
|
|
|
|
|
map.on("click", function(e) { |
|
|
if (editingMarker) { |
|
|
const t = e.latlng; |
|
|
editingMarker.setLatLng([t.lat, t.lng]); |
|
|
document.getElementById("marker-lat").value = t.lat; |
|
|
document.getElementById("marker-lng").value = t.lng; |
|
|
updatePreviewSize(); |
|
|
saveMapToStorage(); |
|
|
} else { |
|
|
const t = e.latlng; |
|
|
const n = L.marker(t).addTo(map); |
|
|
n.bindPopup("新しいマーカー"); |
|
|
n.bindTooltip("新しいマーカーのツールチップ"); |
|
|
n.on("mouseover", function() { |
|
|
hoveredMarker = n; |
|
|
console.log("Marker hovered:", n); |
|
|
}); |
|
|
n.on("mouseout", function() { |
|
|
hoveredMarker === n && (hoveredMarker = null, console.log("Marker no longer hovered")); |
|
|
}); |
|
|
openEditor(n); |
|
|
} |
|
|
}); |
|
|
|
|
|
document.querySelectorAll('input[name="icon-source"]').forEach(function(e) { |
|
|
e.addEventListener("change", function() { |
|
|
const value = this.value; |
|
|
if (value === "url") { |
|
|
document.getElementById("icon-url-input").style.display = "block"; |
|
|
document.getElementById("icon-upload-input").style.display = "none"; |
|
|
} else { |
|
|
document.getElementById("icon-url-input").style.display = "none"; |
|
|
document.getElementById("icon-upload-input").style.display = "block"; |
|
|
} |
|
|
updatePreviewSize(); |
|
|
}); |
|
|
}); |
|
|
|
|
|
document.getElementById("save-marker").addEventListener("click", function() { |
|
|
if (editingMarker) { |
|
|
const lat = parseFloat(document.getElementById("marker-lat").value); |
|
|
const lng = parseFloat(document.getElementById("marker-lng").value); |
|
|
const popupContent = document.getElementById("marker-popup").value; |
|
|
const tooltipContent = document.getElementById("marker-tooltip").value; |
|
|
|
|
|
const iconSource = document.querySelector('input[name="icon-source"]:checked').value; |
|
|
let iconUrl = ""; |
|
|
|
|
|
if (iconSource === "url") { |
|
|
iconUrl = document.getElementById("marker-icon-url").value; |
|
|
} else if (iconSource === "upload") { |
|
|
const file = document.getElementById("marker-icon-upload").files[0]; |
|
|
if (file) { |
|
|
// Blob URLからData URLに変換する処理 |
|
|
resizeImage(file, parseInt(document.getElementById("icon-width").value), parseInt(document.getElementById("icon-height").value), function(dataUrl) { |
|
|
iconUrl = dataUrl; |
|
|
applyIconAndSaveMarker(lat, lng, popupContent, tooltipContent, iconUrl); |
|
|
}); |
|
|
saveMapToStorage(); |
|
|
return; // 非同期処理が完了するまで待つためここでリターン |
|
|
} |
|
|
} |
|
|
|
|
|
// URLの場合や、アップロードファイルがない場合の処理 |
|
|
applyIconAndSaveMarker(lat, lng, popupContent, tooltipContent, iconUrl); |
|
|
} |
|
|
}); |
|
|
|
|
|
function applyIconAndSaveMarker(lat, lng, popupContent, tooltipContent, iconUrl) { |
|
|
const iconWidth = parseInt(document.getElementById("icon-width").value); |
|
|
const iconHeight = parseInt(document.getElementById("icon-height").value); |
|
|
|
|
|
editingMarker.setLatLng([lat, lng]); |
|
|
if (iconUrl) { |
|
|
const icon = L.icon({ |
|
|
iconUrl: iconUrl, |
|
|
iconSize: [iconWidth, iconHeight], |
|
|
iconAnchor: [iconWidth / 2, iconHeight], |
|
|
popupAnchor: [0, -iconHeight], |
|
|
tooltipAnchor: [iconWidth / 2, -iconHeight / 2] |
|
|
}); |
|
|
editingMarker.setIcon(icon); |
|
|
} |
|
|
|
|
|
editingMarker.bindPopup(popupContent); |
|
|
editingMarker.bindTooltip(tooltipContent); |
|
|
|
|
|
document.getElementById("marker-editor").style.display = "none"; |
|
|
editingMarker = null; |
|
|
saveMapToStorage(); |
|
|
} |
|
|
|
|
|
|
|
|
document.addEventListener("keydown", function(e) { |
|
|
if (e.key === "e" && hoveredMarker) { |
|
|
openEditor(hoveredMarker); |
|
|
} |
|
|
}); |
|
|
|
|
|
(function() { |
|
|
const e = document.getElementById("marker-editor"); |
|
|
let t, n, o = false; |
|
|
e.addEventListener("mousedown", function(i) { |
|
|
if (!i.target.closest("input, textarea, button")) { |
|
|
t = i.clientX - e.getBoundingClientRect().left; |
|
|
n = i.clientY - e.getBoundingClientRect().top; |
|
|
o = true; |
|
|
} |
|
|
}); |
|
|
document.addEventListener("mousemove", function(i) { |
|
|
if (o) { |
|
|
e.style.left = i.clientX - t + "px"; |
|
|
e.style.top = i.clientY - n + "px"; |
|
|
} |
|
|
}); |
|
|
document.addEventListener("mouseup", function() { |
|
|
o = false; |
|
|
}); |
|
|
})(); |
|
|
document.getElementById("copyButton").onclick = function() { |
|
|
const textToCopy = document.getElementById("output-code").innerText; |
|
|
navigator.clipboard.writeText(textToCopy).then(() => { |
|
|
alert("テキストがコピーされました!"); |
|
|
}).catch(err => { |
|
|
console.error('コピーに失敗しました:', err); |
|
|
}); |
|
|
}; |
|
|
|
|
|
document.getElementById("generate-html").addEventListener("click", generateMapHTML); |
|
|
|
|
|
let nextMarkerEdit = null; |
|
|
|
|
|
document.getElementById("edit-next-marker").addEventListener("click", function() { |
|
|
nextMarkerEdit = true; |
|
|
alert("次にクリックするマーカーを編集します。"); |
|
|
}); |
|
|
|
|
|
map.on("click", function(e) { |
|
|
if (nextMarkerEdit) { |
|
|
const clickedMarkers = []; |
|
|
map.eachLayer(function (layer) { |
|
|
if (layer instanceof L.Marker) { |
|
|
const distance = map.distance(e.latlng, layer.getLatLng()); |
|
|
if (distance < 20) { |
|
|
clickedMarkers.push(layer); |
|
|
} |
|
|
} |
|
|
}); |
|
|
|
|
|
if (clickedMarkers.length > 0) { |
|
|
openEditor(clickedMarkers[0]); |
|
|
} |
|
|
nextMarkerEdit = false; |
|
|
} else { |
|
|
// 既存のクリックイベント処理 |
|
|
if (editingMarker) { |
|
|
const t = e.latlng; |
|
|
editingMarker.setLatLng([t.lat, t.lng]); |
|
|
document.getElementById("marker-lat").value = t.lat; |
|
|
document.getElementById("marker-lng").value = t.lng; |
|
|
updatePreviewSize(); |
|
|
saveMapToStorage(); |
|
|
} else { |
|
|
const t = e.latlng; |
|
|
const n = L.marker(t).addTo(map); |
|
|
n.bindPopup("新しいマーカー"); |
|
|
n.bindTooltip("新しいマーカーのツールチップ"); |
|
|
n.on("mouseover", function() { |
|
|
hoveredMarker = n; |
|
|
}); |
|
|
n.on("mouseout", function() { |
|
|
hoveredMarker === n && (hoveredMarker = null); |
|
|
}); |
|
|
document.GetelementById("marker-icon-url").value = "https://unpkg.com/leaflet@1.9.3/dist/images/marker-icon-2x.png"; |
|
|
openEditor(n); |
|
|
saveMapToStorage(); |
|
|
document.GetelementById("marker-icon-url").value = "https://unpkg.com/leaflet@1.9.3/dist/images/marker-icon-2x.png"; |
|
|
} |
|
|
} |
|
|
}); |
|
|
|
|
|
// マーカー移動時にも保存 |
|
|
map.on("markerdragend", function(e) { |
|
|
saveMapToStorage(); // マーカー移動後に保存 |
|
|
}); |
|
|
|
|
|
map.on("contextmenu", function (e) { |
|
|
const clickedMarkers = []; |
|
|
|
|
|
// クリックされた位置と既存のマーカーの距離を計算 |
|
|
map.eachLayer(function (layer) { |
|
|
if (layer instanceof L.Marker) { |
|
|
const distance = map.distance(e.latlng, layer.getLatLng()); |
|
|
if (distance < 20) { // 近い距離(ピクセル相当の距離)内のマーカーを検出 |
|
|
clickedMarkers.push(layer); |
|
|
} |
|
|
} |
|
|
}); |
|
|
|
|
|
// クリックされたマーカーがあれば、最初の1つに対して編集を開く |
|
|
if (clickedMarkers.length > 0) { |
|
|
openEditor(clickedMarkers[0]); |
|
|
} |
|
|
}); |
|
|
|
|
|
// マップが動いたときに保存 |
|
|
</script> |
|
|
</body> |
|
|
</html> |