soiz1 commited on
Commit
56f29a6
·
verified ·
1 Parent(s): e4d61e9

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +680 -299
index.html CHANGED
@@ -359,6 +359,96 @@
359
  border-radius: 4px;
360
  box-shadow: inset 0 0 5px rgba(0, 200, 255, 0.5);
361
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362
  </style>
363
  </head>
364
 
@@ -377,11 +467,17 @@
377
 
378
  <div class="container mx-auto px-4">
379
  <div class="flex flex-wrap mb-4">
380
- <button id="edit-next-marker" class="hacker-btn secondary">
381
  <span class="glow-text">次のマーカーを編集</span>
382
  </button>
383
- <button onclick="if(confirm('すべてのデータが消去されます。いいですか?')){if(confirm('この操作は取り消せません。')){localStorage.removeItem('leafletMap');location.reload()}}" class="hacker-btn danger">
384
- <span class="glow-text">すべてリセット</span>
 
 
 
 
 
 
385
  </button>
386
  </div>
387
 
@@ -447,392 +543,677 @@
447
  </div>
448
  </div>
449
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
450
  <script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"></script>
451
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/mono-blue.min.css">
452
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js"></script>
453
  <script>
 
 
 
 
 
 
 
 
 
454
  window.onload = function() {
455
  const loading = document.getElementById('loading');
456
  loading.style.opacity = '0';
457
  setTimeout(() => {
458
  loading.style.display = 'none';
459
- loadMapFromStorage();
 
460
  }, 1000);
 
 
 
461
  };
462
 
463
- function saveMapToStorage() {
464
- const markers = [];
465
- map.eachLayer((layer) => {
466
- if (layer instanceof L.Marker) {
467
- const marker = layer;
468
- const icon = marker.options.icon;
469
- const { lat, lng } = marker.getLatLng();
470
- markers.push({
471
- lat: lat,
472
- lng: lng,
473
- iconUrl: icon.options.iconUrl,
474
- iconSize: icon.options.iconSize,
475
- popupContent: marker.getPopup() ? marker.getPopup().getContent() : '',
476
- tooltipContent: marker.getTooltip() ? marker.getTooltip().getContent() : '',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
477
  });
 
 
 
 
478
  }
479
  });
480
- localStorage.setItem('leafletMap', JSON.stringify(markers));
481
- }
482
-
483
- function loadMapFromStorage() {
484
- const storedMarkers = JSON.parse(localStorage.getItem('leafletMap'));
485
-
486
- if (!map) {
487
- console.error('マップが見つかりません。再読み込みしてください。');
488
- return;
489
- }
490
-
491
- storedMarkers.forEach((data) => {
492
- if (!data.iconUrl || !data.iconSize) {
493
- console.error('アイコンのデータがありません。データが破損している可能性があります。');
494
- return;
495
  }
496
-
497
- const icon = L.icon({
498
- iconUrl: data.iconUrl,
499
- iconSize: data.iconSize,
500
- iconAnchor: [data.iconSize[0] / 2, data.iconSize[1]],
501
- popupAnchor: [0, -data.iconSize[1]],
502
- tooltipAnchor: [data.iconSize[0] / 2, -data.iconSize[1] / 2],
503
- });
504
- const marker = L.marker([data.lat, data.lng], { icon: icon }).addTo(map);
505
- if (data.popupContent) marker.bindPopup(data.popupContent);
506
- if (data.tooltipContent) marker.bindTooltip(data.tooltipContent);
507
-
508
- marker.on("mouseover", function() {
509
- hoveredMarker = marker;
510
- });
511
- marker.on("mouseout", function() {
512
- if (hoveredMarker === marker) {
513
- hoveredMarker = null;
514
- }
515
- });
516
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
517
  }
518
-
519
- function updatePreviewSize() {
520
- var e = document.getElementById("icon-width").value;
521
- var t = document.getElementById("icon-height").value;
522
- var n = document.getElementById("icon-preview");
523
- n.style.width = e + "px";
524
- n.style.height = t + "px";
525
- document.getElementById("icon-width-value").textContent = e;
526
- document.getElementById("icon-height-value").textContent = t;
527
- if (editingMarker) {
528
- var o = n.src;
529
- var i = L.icon({
530
- iconUrl: o,
531
- iconSize: [e, t],
532
- iconAnchor: [e / 2, t],
533
- popupAnchor: [0, -t],
534
- tooltipAnchor: [e / 2, -t / 2]
535
- });
536
- editingMarker.setIcon(i);
537
- saveMapToStorage();
538
  }
539
  }
540
-
541
- function openEditor(e) {
542
- const t = e.getLatLng();
543
- document.getElementById("marker-lat").value = t.lat;
544
- document.getElementById("marker-lng").value = t.lng;
545
- document.getElementById("marker-popup").value = e.getPopup() ? e.getPopup().getContent() : "";
546
- document.getElementById("marker-tooltip").value = e.getTooltip() ? e.getTooltip().getContent() : "";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
547
  document.getElementById("marker-editor").style.display = "block";
548
- editingMarker = e;
549
-
550
- const icon = e.options.icon;
551
  if (icon && icon.options) {
552
  if (icon.options.iconUrl) {
553
  document.getElementById("marker-icon-url").value = icon.options.iconUrl;
554
  document.getElementById("icon-preview").src = icon.options.iconUrl;
555
  document.getElementById("icon-preview").style.display = 'block';
556
  document.getElementById("icon-settings").style.display = "block";
557
- } else {
558
- document.getElementById("marker-icon-url").value = icon.options.iconUrl;
559
- document.getElementById("icon-preview").src = icon.options.iconUrl;
560
- document.getElementById("icon-preview").style.display = 'block';
561
- document.getElementById("icon-settings").style.display = "block";
562
  }
563
  document.getElementById("icon-width").value = icon.options.iconSize[0];
564
  document.getElementById("icon-height").value = icon.options.iconSize[1];
565
  document.getElementById("icon-width-value").textContent = icon.options.iconSize[0];
566
  document.getElementById("icon-height-value").textContent = icon.options.iconSize[1];
567
  }
568
-
569
  updatePreviewSize();
570
  }
571
-
572
- function generateMapHTML() {
573
- const e = [];
574
- map.eachLayer((function(t) {
575
- if (t instanceof L.Marker) {
576
- const n = t;
577
- const o = n.options.icon;
578
- const i = o.options.iconUrl;
579
- const r = o.options.iconSize;
580
- const c = n.getLatLng();
581
- const l = n.getPopup() ? n.getPopup().getContent() : "";
582
- const a = n.getTooltip() ? n.getTooltip().getContent() : "";
583
- e.push({
584
- lat: c.lat,
585
- lng: c.lng,
586
- iconUrl: i,
587
- iconWidth: r[0],
588
- iconHeight: r[1],
589
- popupContent: l,
590
- tooltipContent: a
591
- });
592
- }
593
- }));
594
- const t = map.getCenter();
595
- const n = map.getZoom();
596
- let o = `<div id="map" style="height: 600px; width: 100%;">
597
- <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" />
598
- <script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"><\/script>
599
- <script>
600
- var map = L.map('map').setView([${t.lat}, ${t.lng}], ${n});
601
- L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
602
- attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap contributors'
603
- }).addTo(map);
604
-
605
- ${e.map(e => `
606
- var icon = L.icon({
607
- iconUrl: '${e.iconUrl}',
608
- iconSize: [${e.iconWidth}, ${e.iconHeight}],
609
- iconAnchor: [${e.iconWidth} / 2, ${e.iconHeight}],
610
- popupAnchor: [0, -${e.iconHeight}],
611
- tooltipAnchor: [${e.iconWidth} / 2, -${e.iconHeight} / 2]
612
- });
613
-
614
- var marker = L.marker([${e.lat}, ${e.lng}], {
615
- icon: icon,
616
- zIndexOffset: 1000
617
- }).addTo(map);
618
-
619
- ${e.popupContent ? `marker.bindPopup('${e.popupContent.replace(/'/g, "\\'").replace(/<\/script>/g, "<\\/script>")}');` : ""}
620
- ${e.tooltipContent ? `marker.bindTooltip('${e.tooltipContent.replace(/'/g, "\\'").replace(/<\/script>/g, "<\\/script>")}');` : ""}
621
- `).join("\n")}
622
- <\/script>
623
- `;
624
- o = o.replace(/iconUrl: 'marker-icon\.png'/g, `iconUrl: '${location.origin}/marker-icon.png'`);
625
- document.getElementById("output-html").value = o;
626
- const input = document.getElementById('output-html').value;
627
- const output = document.getElementById('output-html');
628
- output.innerHTML = hljs.highlight('html', input).value;
629
- output.classList.add('hljs');
630
  }
631
-
632
- function resizeImage(e, t, n, o) {
633
- const i = new FileReader();
634
- i.onload = function(e) {
635
- const i = new Image();
636
- i.onload = function() {
637
- const e = document.createElement("canvas");
638
- e.width = t;
639
- e.height = n;
640
- e.getContext("2d").drawImage(i, 0, 0, t, n);
641
- o(e.toDataURL());
642
- };
643
- i.src = e.target.result;
644
- };
645
- i.readAsDataURL(e);
 
 
 
 
 
 
 
 
646
  }
647
-
648
- document.getElementById("marker-icon-upload").addEventListener("change", function() {
649
- const e = this.files[0];
650
- const t = document.getElementById("icon-preview");
651
- if (e) {
652
- resizeImage(e, parseInt(document.getElementById("icon-width").value), parseInt(document.getElementById("icon-height").value), function(imageDataUrl) {
653
- t.src = imageDataUrl;
654
- t.style.display = "block";
 
 
 
 
 
 
 
 
 
 
 
 
655
  document.getElementById("icon-settings").style.display = "block";
656
  updatePreviewSize();
657
  });
658
  } else {
659
- t.style.display = "none";
660
  document.getElementById("icon-settings").style.display = "none";
661
  }
662
- });
663
-
664
- document.getElementById("load-icon-url").addEventListener("click", function() {
665
- const e = document.getElementById("marker-icon-url").value;
666
- const t = document.getElementById("icon-preview");
667
- if (e) {
668
- t.src = e;
669
- t.onload = function() {
670
- t.style.display = "block";
 
671
  document.getElementById("icon-settings").style.display = "block";
672
  updatePreviewSize();
673
  };
674
- t.onerror = function() {
675
  alert("IMAGE LOAD FAILED. CHECK URL.");
676
- t.style.display = "none";
677
  document.getElementById("icon-settings").style.display = "none";
678
  };
679
  } else {
680
- t.style.display = "none";
681
  document.getElementById("icon-settings").style.display = "none";
682
  }
683
- });
684
-
685
- document.getElementById("icon-width").addEventListener("input", syncWidth);
686
- document.getElementById("icon-width-input").addEventListener("input", syncWidth);
687
- document.getElementById("icon-height").addEventListener("input", syncHeight);
688
- document.getElementById("icon-height-input").addEventListener("input", syncHeight);
689
-
 
 
 
 
 
 
 
 
 
 
 
 
 
690
  function syncWidth(event) {
691
  let value = event.target.value;
692
  document.getElementById("icon-width").value = value;
693
  document.getElementById("icon-width-input").value = value;
694
  updatePreviewSize();
695
  }
696
-
 
697
  function syncHeight(event) {
698
  let value = event.target.value;
699
  document.getElementById("icon-height").value = value;
700
  document.getElementById("icon-height-input").value = value;
701
  updatePreviewSize();
702
  }
703
-
704
- const map = L.map("map").setView([33.321797711641395, 130.52061378343208], 16);
705
- L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap contributors' }).addTo(map);
706
-
707
- let editingMarker = null;
708
- let hoveredMarker = null;
709
-
710
- map.on("click", function(e) {
711
- if (nextMarkerEdit) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
712
  return;
713
  }
714
-
715
- if (editingMarker) {
716
- const t = e.latlng;
717
- editingMarker.setLatLng([t.lat, t.lng]);
718
- document.getElementById("marker-lat").value = t.lat;
719
- document.getElementById("marker-lng").value = t.lng;
720
- updatePreviewSize();
721
- saveMapToStorage();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
722
  } else {
723
- const t = e.latlng;
724
- const n = L.marker(t).addTo(map);
725
- n.bindPopup("新しいマーカーのポップアップ");
726
- n.bindTooltip("新しいマーカーのツールチップ");
727
- n.on("mouseover", function() {
728
- hoveredMarker = n;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
729
  });
730
- n.on("mouseout", function() {
731
- hoveredMarker === n && (hoveredMarker = null);
 
 
 
 
 
732
  });
733
- document.getElementById("marker-icon-url").value = "https://unpkg.com/leaflet@1.9.3/dist/images/marker-icon-2x.png";
734
- openEditor(n);
735
- saveMapToStorage();
736
  }
737
- });
738
-
739
- document.getElementById("save-marker").addEventListener("click", function() {
740
- if (editingMarker) {
741
- const lat = parseFloat(document.getElementById("marker-lat").value);
742
- const lng = parseFloat(document.getElementById("marker-lng").value);
743
- const popupContent = document.getElementById("marker-popup").value;
744
- const tooltipContent = document.getElementById("marker-tooltip").value;
745
-
746
- iconUrl = document.getElementById("icon-preview").src;
747
-
748
- applyIconAndSaveMarker(lat, lng, popupContent, tooltipContent, iconUrl);
 
 
 
 
 
749
  }
750
- });
751
-
752
- function applyIconAndSaveMarker(lat, lng, popupContent, tooltipContent, iconUrl) {
753
- const iconWidth = parseInt(document.getElementById("icon-width").value);
754
- const iconHeight = parseInt(document.getElementById("icon-height").value);
755
-
756
- editingMarker.setLatLng([lat, lng]);
757
- if (iconUrl) {
 
758
  const icon = L.icon({
759
- iconUrl: iconUrl,
760
- iconSize: [iconWidth, iconHeight],
761
- iconAnchor: [iconWidth / 2, iconHeight],
762
- popupAnchor: [0, -iconHeight],
763
- tooltipAnchor: [iconWidth / 2, -iconHeight / 2]
764
  });
765
- editingMarker.setIcon(icon);
766
- }
767
-
768
- editingMarker.bindPopup(popupContent);
769
- editingMarker.bindTooltip(tooltipContent);
770
-
771
- document.getElementById("marker-editor").style.display = "none";
772
- editingMarker = null;
773
- saveMapToStorage();
 
 
 
 
 
 
 
 
 
 
774
  }
775
-
776
- document.addEventListener("keydown", function(e) {
777
- if (e.key === "e" && hoveredMarker) {
778
- openEditor(hoveredMarker);
 
 
 
 
 
779
  }
780
- });
781
-
782
- (function() {
783
- const e = document.getElementById("marker-editor");
784
- let t, n, o = false;
785
- e.addEventListener("mousedown", function(i) {
786
- if (!i.target.closest("input, textarea, button")) {
787
- t = i.clientX - e.getBoundingClientRect().left;
788
- n = i.clientY - e.getBoundingClientRect().top;
789
- o = true;
790
  }
791
  });
792
- document.addEventListener("mousemove", function(i) {
793
- if (o) {
794
- e.style.left = i.clientX - t + "px";
795
- e.style.top = i.clientY - n + "px";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
796
  }
797
  });
798
- document.addEventListener("mouseup", function() {
799
- o = false;
800
- });
801
- })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
802
 
803
- document.getElementById("copyButton").onclick = function() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
804
  const textToCopy = document.getElementById("output-html").innerText;
805
  navigator.clipboard.writeText(textToCopy).then(() => {
806
  alert("コピーしました。");
807
  }).catch(err => {
808
  console.error('コピーに失敗しました:', err);
809
  });
810
- };
811
-
812
- document.getElementById("generate-html").addEventListener("click", generateMapHTML);
813
-
814
- let nextMarkerEdit = false;
815
-
816
- document.getElementById("edit-next-marker").addEventListener("click", function () {
817
- nextMarkerEdit = true;
818
- alert("クリックして次のマーカーを編集します。");
819
- });
820
-
821
- map.on('popupopen', function (e) {
822
  const marker = e.popup._source;
823
  if (nextMarkerEdit) {
824
  openEditor(marker);
825
  nextMarkerEdit = false;
826
- alert("マーカーを編集します。");
827
- }
828
- });
829
-
830
- document.getElementById("delete-marker").addEventListener("click", function() {
831
- if (confirm("削除していいですか?")) {
832
- map.removeLayer(editingMarker);
833
- editingMarker=false;
834
- document.getElementById("marker-editor").style.display = "none";
835
- saveMapToStorage();
836
  }
837
  });
838
  </script>
 
359
  border-radius: 4px;
360
  box-shadow: inset 0 0 5px rgba(0, 200, 255, 0.5);
361
  }
362
+
363
+ /* ギャラリー用スタイル */
364
+ #gallery-container {
365
+ display: none;
366
+ position: fixed;
367
+ top: 0;
368
+ left: 0;
369
+ width: 100%;
370
+ height: 100%;
371
+ background-color: rgba(0, 10, 20, 0.95);
372
+ z-index: 2000;
373
+ overflow-y: auto;
374
+ padding: 2rem;
375
+ }
376
+
377
+ .gallery-map-item {
378
+ background: rgba(0, 20, 40, 0.8);
379
+ border: 1px solid var(--hacker-border);
380
+ padding: 1rem;
381
+ margin-bottom: 1rem;
382
+ transition: all 0.3s ease;
383
+ }
384
+
385
+ .gallery-map-item:hover {
386
+ background: rgba(0, 40, 80, 0.8);
387
+ box-shadow: 0 0 15px rgba(0, 200, 255, 0.4);
388
+ }
389
+
390
+ .gallery-map-title {
391
+ color: var(--hacker-primary);
392
+ font-weight: bold;
393
+ margin-bottom: 0.5rem;
394
+ }
395
+
396
+ .gallery-map-preview {
397
+ height: 150px;
398
+ background-color: rgba(0, 30, 60, 0.5);
399
+ margin-bottom: 0.5rem;
400
+ display: flex;
401
+ align-items: center;
402
+ justify-content: center;
403
+ color: var(--hacker-secondary);
404
+ font-size: 0.9rem;
405
+ }
406
+
407
+ .gallery-map-actions {
408
+ display: flex;
409
+ gap: 0.5rem;
410
+ }
411
+
412
+ .gallery-btn {
413
+ flex: 1;
414
+ padding: 0.5rem;
415
+ font-size: 0.8rem;
416
+ }
417
+
418
+ #save-map-modal {
419
+ display: none;
420
+ position: fixed;
421
+ top: 50%;
422
+ left: 50%;
423
+ transform: translate(-50%, -50%);
424
+ background: rgba(0, 20, 40, 0.95);
425
+ border: 1px solid var(--hacker-border);
426
+ padding: 2rem;
427
+ z-index: 2001;
428
+ width: 80%;
429
+ max-width: 500px;
430
+ }
431
+
432
+ #save-map-modal h3 {
433
+ color: var(--hacker-primary);
434
+ margin-bottom: 1rem;
435
+ text-align: center;
436
+ }
437
+
438
+ #save-map-name {
439
+ width: 100%;
440
+ margin-bottom: 1rem;
441
+ background: rgba(0, 10, 20, 0.8);
442
+ border: 1px solid var(--hacker-border);
443
+ color: var(--hacker-text);
444
+ padding: 0.5rem;
445
+ }
446
+
447
+ .disabled {
448
+ opacity: 0.5;
449
+ pointer-events: none;
450
+ cursor: not-allowed;
451
+ }
452
  </style>
453
  </head>
454
 
 
467
 
468
  <div class="container mx-auto px-4">
469
  <div class="flex flex-wrap mb-4">
470
+ <button id="edit-next-marker" class="hacker-btn secondary disabled">
471
  <span class="glow-text">次のマーカーを編集</span>
472
  </button>
473
+ <button id="save-map-btn" class="hacker-btn secondary">
474
+ <span class="glow-text">マップを保存</span>
475
+ </button>
476
+ <button id="load-map-btn" class="hacker-btn secondary">
477
+ <span class="glow-text">マップを読み込み</span>
478
+ </button>
479
+ <button onclick="if(confirm('現在のマップのすべてのデータが消去されます。いいですか?')){clearCurrentMap()}" class="hacker-btn danger">
480
+ <span class="glow-text">現在のマップをリセット</span>
481
  </button>
482
  </div>
483
 
 
543
  </div>
544
  </div>
545
 
546
+ <!-- マップ保存モーダル -->
547
+ <div id="save-map-modal">
548
+ <h3>マップを保存</h3>
549
+ <input type="text" id="save-map-name" placeholder="マップ名を入力">
550
+ <button id="confirm-save-map" class="hacker-btn">
551
+ <span class="glow-text">保存</span>
552
+ </button>
553
+ <button id="cancel-save-map" class="hacker-btn danger">
554
+ <span class="glow-text">キャンセル</span>
555
+ </button>
556
+ </div>
557
+
558
+ <!-- マップギャラリー -->
559
+ <div id="gallery-container">
560
+ <div class="container mx-auto">
561
+ <h2 class="hacker-title text-center">保存されたマップ</h2>
562
+ <div id="gallery-map-list" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"></div>
563
+ <div class="text-center mt-4">
564
+ <button id="close-gallery" class="hacker-btn danger">
565
+ <span class="glow-text">閉じる</span>
566
+ </button>
567
+ </div>
568
+ </div>
569
+ </div>
570
+
571
  <script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"></script>
572
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/mono-blue.min.css">
573
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js"></script>
574
  <script>
575
+ // グローバル変数
576
+ let map;
577
+ let editingMarker = null;
578
+ let hoveredMarker = null;
579
+ let nextMarkerEdit = false;
580
+ let markers = [];
581
+ let currentMapName = '';
582
+
583
+ // 初期化処理
584
  window.onload = function() {
585
  const loading = document.getElementById('loading');
586
  loading.style.opacity = '0';
587
  setTimeout(() => {
588
  loading.style.display = 'none';
589
+ initMap();
590
+ updateEditNextMarkerButton();
591
  }, 1000);
592
+
593
+ // イベントリスナーの設定
594
+ setupEventListeners();
595
  };
596
 
597
+ // マップ初期化
598
+ function initMap() {
599
+ map = L.map("map").setView([33.321797711641395, 130.52061378343208], 16);
600
+ L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
601
+ attribution: <a href="https://www.openstreetmap.org/copyright">OpenStreetMap contributors'
602
+ }).addTo(map);
603
+
604
+ // マーカーイベントの設定
605
+ map.on("click", function(e) {
606
+ if (nextMarkerEdit) {
607
+ return;
608
+ }
609
+
610
+ if (editingMarker) {
611
+ const latlng = e.latlng;
612
+ editingMarker.setLatLng([latlng.lat, latlng.lng]);
613
+ document.getElementById("marker-lat").value = latlng.lat;
614
+ document.getElementById("marker-lng").value = latlng.lng;
615
+ updatePreviewSize();
616
+ saveCurrentMapToStorage();
617
+ } else {
618
+ const latlng = e.latlng;
619
+ const marker = L.marker(latlng).addTo(map);
620
+ marker.bindPopup("新しいマーカーのポップアップ");
621
+ marker.bindTooltip("新しいマーカーのツールチップ");
622
+
623
+ marker.on("mouseover", function() {
624
+ hoveredMarker = marker;
625
+ });
626
+
627
+ marker.on("mouseout", function() {
628
+ if (hoveredMarker === marker) {
629
+ hoveredMarker = null;
630
+ }
631
  });
632
+
633
+ document.getElementById("marker-icon-url").value = "https://unpkg.com/leaflet@1.9.3/dist/images/marker-icon-2x.png";
634
+ openEditor(marker);
635
+ saveCurrentMapToStorage();
636
  }
637
  });
638
+
639
+ // マーカーが変更されたらボタンの状態を更新
640
+ map.on('layeradd layerremove', function() {
641
+ updateEditNextMarkerButton();
642
+ });
643
+ }
644
+
645
+ // イベントリスナーの設定
646
+ function setupEventListeners() {
647
+ // マーカー編集関連
648
+ document.getElementById("save-marker").addEventListener("click", saveMarker);
649
+ document.getElementById("delete-marker").addEventListener("click", deleteMarker);
650
+ document.addEventListener("keydown", function(e) {
651
+ if (e.key === "e" && hoveredMarker) {
652
+ openEditor(hoveredMarker);
653
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
654
  });
655
+
656
+ // アイコン設定関連
657
+ document.getElementById("marker-icon-upload").addEventListener("change", handleIconUpload);
658
+ document.getElementById("load-icon-url").addEventListener("click", loadIconFromUrl);
659
+ document.getElementById("icon-width").addEventListener("input", syncWidth);
660
+ document.getElementById("icon-width-input").addEventListener("input", syncWidth);
661
+ document.getElementById("icon-height").addEventListener("input", syncHeight);
662
+ document.getElementById("icon-height-input").addEventListener("input", syncHeight);
663
+
664
+ // マーカー編集モード関連
665
+ document.getElementById("edit-next-marker").addEventListener("click", toggleEditNextMarkerMode);
666
+
667
+ // マップ保存/読み込み関連
668
+ document.getElementById("save-map-btn").addEventListener("click", showSaveMapModal);
669
+ document.getElementById("load-map-btn").addEventListener("click", showGallery);
670
+ document.getElementById("confirm-save-map").addEventListener("click", saveCurrentMapWithName);
671
+ document.getElementById("cancel-save-map").addEventListener("click", hideSaveMapModal);
672
+ document.getElementById("close-gallery").addEventListener("click", hideGallery);
673
+
674
+ // マーカーエディタのドラッグ移動
675
+ setupEditorDrag();
676
+
677
+ // HTML生成関連
678
+ document.getElementById("generate-html").addEventListener("click", generateMapHTML);
679
+ document.getElementById("copyButton").onclick = copyHTMLToClipboard;
680
  }
681
+
682
+ // マーカー編集モードのトグル
683
+ function toggleEditNextMarkerMode() {
684
+ if (nextMarkerEdit) {
685
+ // 編集モードをキャンセル
686
+ nextMarkerEdit = false;
687
+ document.getElementById("edit-next-marker").textContent = "次のマーカーを編集";
688
+ document.getElementById("edit-next-marker").classList.remove("danger");
689
+ document.getElementById("edit-next-marker").classList.add("secondary");
690
+ alert("編集モードをキャンセルしました。");
691
+ } else {
692
+ // 編集モードを開始
693
+ nextMarkerEdit = true;
694
+ document.getElementById("edit-next-marker").textContent = "編集をキャンセル";
695
+ document.getElementById("edit-next-marker").classList.remove("secondary");
696
+ document.getElementById("edit-next-marker").classList.add("danger");
697
+ alert("クリックして次のマーカーを編集します。");
 
 
 
698
  }
699
  }
700
+
701
+ // マーカーが存在するかどうかでボタンの状態を更新
702
+ function updateEditNextMarkerButton() {
703
+ const hasMarkers = mapHasMarkers();
704
+ const editBtn = document.getElementById("edit-next-marker");
705
+
706
+ if (hasMarkers) {
707
+ editBtn.classList.remove("disabled");
708
+ } else {
709
+ editBtn.classList.add("disabled");
710
+ // マーカーがない場合、編集モードをキャンセル
711
+ if (nextMarkerEdit) {
712
+ nextMarkerEdit = false;
713
+ editBtn.textContent = "次のマーカーを編集";
714
+ editBtn.classList.remove("danger");
715
+ editBtn.classList.add("secondary");
716
+ }
717
+ }
718
+ }
719
+
720
+ // マップにマーカーが存在するかチェック
721
+ function mapHasMarkers() {
722
+ let hasMarkers = false;
723
+ map.eachLayer((layer) => {
724
+ if (layer instanceof L.Marker) {
725
+ hasMarkers = true;
726
+ }
727
+ });
728
+ return hasMarkers;
729
+ }
730
+
731
+ // マーカーエディタを開く
732
+ function openEditor(marker) {
733
+ const latlng = marker.getLatLng();
734
+ document.getElementById("marker-lat").value = latlng.lat;
735
+ document.getElementById("marker-lng").value = latlng.lng;
736
+ document.getElementById("marker-popup").value = marker.getPopup() ? marker.getPopup().getContent() : "";
737
+ document.getElementById("marker-tooltip").value = marker.getTooltip() ? marker.getTooltip().getContent() : "";
738
  document.getElementById("marker-editor").style.display = "block";
739
+ editingMarker = marker;
740
+
741
+ const icon = marker.options.icon;
742
  if (icon && icon.options) {
743
  if (icon.options.iconUrl) {
744
  document.getElementById("marker-icon-url").value = icon.options.iconUrl;
745
  document.getElementById("icon-preview").src = icon.options.iconUrl;
746
  document.getElementById("icon-preview").style.display = 'block';
747
  document.getElementById("icon-settings").style.display = "block";
 
 
 
 
 
748
  }
749
  document.getElementById("icon-width").value = icon.options.iconSize[0];
750
  document.getElementById("icon-height").value = icon.options.iconSize[1];
751
  document.getElementById("icon-width-value").textContent = icon.options.iconSize[0];
752
  document.getElementById("icon-height-value").textContent = icon.options.iconSize[1];
753
  }
754
+
755
  updatePreviewSize();
756
  }
757
+
758
+ // マーカーを保存
759
+ function saveMarker() {
760
+ if (editingMarker) {
761
+ const lat = parseFloat(document.getElementById("marker-lat").value);
762
+ const lng = parseFloat(document.getElementById("marker-lng").value);
763
+ const popupContent = document.getElementById("marker-popup").value;
764
+ const tooltipContent = document.getElementById("marker-tooltip").value;
765
+ const iconUrl = document.getElementById("icon-preview").src;
766
+
767
+ applyIconAndSaveMarker(lat, lng, popupContent, tooltipContent, iconUrl);
768
+ saveCurrentMapToStorage();
769
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
770
  }
771
+
772
+ // アイコンを適用してマーカーを保存
773
+ function applyIconAndSaveMarker(lat, lng, popupContent, tooltipContent, iconUrl) {
774
+ const iconWidth = parseInt(document.getElementById("icon-width").value);
775
+ const iconHeight = parseInt(document.getElementById("icon-height").value);
776
+
777
+ editingMarker.setLatLng([lat, lng]);
778
+ if (iconUrl) {
779
+ const icon = L.icon({
780
+ iconUrl: iconUrl,
781
+ iconSize: [iconWidth, iconHeight],
782
+ iconAnchor: [iconWidth / 2, iconHeight],
783
+ popupAnchor: [0, -iconHeight],
784
+ tooltipAnchor: [iconWidth / 2, -iconHeight / 2]
785
+ });
786
+ editingMarker.setIcon(icon);
787
+ }
788
+
789
+ editingMarker.bindPopup(popupContent);
790
+ editingMarker.bindTooltip(tooltipContent);
791
+
792
+ document.getElementById("marker-editor").style.display = "none";
793
+ editingMarker = null;
794
  }
795
+
796
+ // マーカーを削除
797
+ function deleteMarker() {
798
+ if (confirm("削除していいですか?")) {
799
+ map.removeLayer(editingMarker);
800
+ document.getElementById("marker-editor").style.display = "none";
801
+ editingMarker = null;
802
+ saveCurrentMapToStorage();
803
+ updateEditNextMarkerButton();
804
+ }
805
+ }
806
+
807
+ // アイコンをアップロード
808
+ function handleIconUpload() {
809
+ const file = this.files[0];
810
+ const preview = document.getElementById("icon-preview");
811
+ if (file) {
812
+ resizeImage(file, parseInt(document.getElementById("icon-width").value), parseInt(document.getElementById("icon-height").value), function(imageDataUrl) {
813
+ preview.src = imageDataUrl;
814
+ preview.style.display = "block";
815
  document.getElementById("icon-settings").style.display = "block";
816
  updatePreviewSize();
817
  });
818
  } else {
819
+ preview.style.display = "none";
820
  document.getElementById("icon-settings").style.display = "none";
821
  }
822
+ }
823
+
824
+ // URLからアイコンを読み込み
825
+ function loadIconFromUrl() {
826
+ const url = document.getElementById("marker-icon-url").value;
827
+ const preview = document.getElementById("icon-preview");
828
+ if (url) {
829
+ preview.src = url;
830
+ preview.onload = function() {
831
+ preview.style.display = "block";
832
  document.getElementById("icon-settings").style.display = "block";
833
  updatePreviewSize();
834
  };
835
+ preview.onerror = function() {
836
  alert("IMAGE LOAD FAILED. CHECK URL.");
837
+ preview.style.display = "none";
838
  document.getElementById("icon-settings").style.display = "none";
839
  };
840
  } else {
841
+ preview.style.display = "none";
842
  document.getElementById("icon-settings").style.display = "none";
843
  }
844
+ }
845
+
846
+ // 画像をリサイズ
847
+ function resizeImage(file, width, height, callback) {
848
+ const reader = new FileReader();
849
+ reader.onload = function(e) {
850
+ const img = new Image();
851
+ img.onload = function() {
852
+ const canvas = document.createElement("canvas");
853
+ canvas.width = width;
854
+ canvas.height = height;
855
+ canvas.getContext("2d").drawImage(img, 0, 0, width, height);
856
+ callback(canvas.toDataURL());
857
+ };
858
+ img.src = e.target.result;
859
+ };
860
+ reader.readAsDataURL(file);
861
+ }
862
+
863
+ // 幅の同期
864
  function syncWidth(event) {
865
  let value = event.target.value;
866
  document.getElementById("icon-width").value = value;
867
  document.getElementById("icon-width-input").value = value;
868
  updatePreviewSize();
869
  }
870
+
871
+ // 高さの同期
872
  function syncHeight(event) {
873
  let value = event.target.value;
874
  document.getElementById("icon-height").value = value;
875
  document.getElementById("icon-height-input").value = value;
876
  updatePreviewSize();
877
  }
878
+
879
+ // プレビューサイズを更新
880
+ function updatePreviewSize() {
881
+ var width = document.getElementById("icon-width").value;
882
+ var height = document.getElementById("icon-height").value;
883
+ var preview = document.getElementById("icon-preview");
884
+ preview.style.width = width + "px";
885
+ preview.style.height = height + "px";
886
+ document.getElementById("icon-width-value").textContent = width;
887
+ document.getElementById("icon-height-value").textContent = height;
888
+ if (editingMarker) {
889
+ var iconUrl = preview.src;
890
+ var icon = L.icon({
891
+ iconUrl: iconUrl,
892
+ iconSize: [width, height],
893
+ iconAnchor: [width / 2, height],
894
+ popupAnchor: [0, -height],
895
+ tooltipAnchor: [width / 2, -height / 2]
896
+ });
897
+ editingMarker.setIcon(icon);
898
+ saveCurrentMapToStorage();
899
+ }
900
+ }
901
+
902
+ // マーカーエディタのドラッグ移動を設定
903
+ function setupEditorDrag() {
904
+ const editor = document.getElementById("marker-editor");
905
+ let isDragging = false;
906
+ let offsetX, offsetY;
907
+
908
+ editor.addEventListener("mousedown", function(e) {
909
+ if (!e.target.closest("input, textarea, button")) {
910
+ isDragging = true;
911
+ offsetX = e.clientX - editor.getBoundingClientRect().left;
912
+ offsetY = e.clientY - editor.getBoundingClientRect().top;
913
+ }
914
+ });
915
+
916
+ document.addEventListener("mousemove", function(e) {
917
+ if (isDragging) {
918
+ editor.style.left = (e.clientX - offsetX) + "px";
919
+ editor.style.top = (e.clientY - offsetY) + "px";
920
+ }
921
+ });
922
+
923
+ document.addEventListener("mouseup", function() {
924
+ isDragging = false;
925
+ });
926
+ }
927
+
928
+ // 現在のマップを保存
929
+ function saveCurrentMapToStorage() {
930
+ const mapData = {
931
+ center: map.getCenter(),
932
+ zoom: map.getZoom(),
933
+ markers: []
934
+ };
935
+
936
+ map.eachLayer((layer) => {
937
+ if (layer instanceof L.Marker) {
938
+ const marker = layer;
939
+ const icon = marker.options.icon;
940
+ const { lat, lng } = marker.getLatLng();
941
+ mapData.markers.push({
942
+ lat: lat,
943
+ lng: lng,
944
+ iconUrl: icon.options.iconUrl,
945
+ iconSize: icon.options.iconSize,
946
+ popupContent: marker.getPopup() ? marker.getPopup().getContent() : '',
947
+ tooltipContent: marker.getTooltip() ? marker.getTooltip().getContent() : '',
948
+ });
949
+ }
950
+ });
951
+
952
+ if (currentMapName) {
953
+ // 既存のマップを更新
954
+ const savedMaps = JSON.parse(localStorage.getItem('savedMaps')) || {};
955
+ savedMaps[currentMapName] = mapData;
956
+ localStorage.setItem('savedMaps', JSON.stringify(savedMaps));
957
+ }
958
+ }
959
+
960
+ // マップ保存モーダルを表示
961
+ function showSaveMapModal() {
962
+ document.getElementById("save-map-modal").style.display = "block";
963
+ }
964
+
965
+ // マップ保存モーダルを非表示
966
+ function hideSaveMapModal() {
967
+ document.getElementById("save-map-modal").style.display = "none";
968
+ }
969
+
970
+ // マップ名を付けて保存
971
+ function saveCurrentMapWithName() {
972
+ const mapName = document.getElementById("save-map-name").value.trim();
973
+ if (!mapName) {
974
+ alert("マップ名を入力してください");
975
  return;
976
  }
977
+
978
+ const mapData = {
979
+ center: map.getCenter(),
980
+ zoom: map.getZoom(),
981
+ markers: []
982
+ };
983
+
984
+ map.eachLayer((layer) => {
985
+ if (layer instanceof L.Marker) {
986
+ const marker = layer;
987
+ const icon = marker.options.icon;
988
+ const { lat, lng } = marker.getLatLng();
989
+ mapData.markers.push({
990
+ lat: lat,
991
+ lng: lng,
992
+ iconUrl: icon.options.iconUrl,
993
+ iconSize: icon.options.iconSize,
994
+ popupContent: marker.getPopup() ? marker.getPopup().getContent() : '',
995
+ tooltipContent: marker.getTooltip() ? marker.getTooltip().getContent() : '',
996
+ });
997
+ }
998
+ });
999
+
1000
+ const savedMaps = JSON.parse(localStorage.getItem('savedMaps')) || {};
1001
+ savedMaps[mapName] = mapData;
1002
+ localStorage.setItem('savedMaps', JSON.stringify(savedMaps));
1003
+
1004
+ currentMapName = mapName;
1005
+ document.getElementById("save-map-name").value = "";
1006
+ hideSaveMapModal();
1007
+ alert(`マップ「${mapName}」を保存しました`);
1008
+ }
1009
+
1010
+ // マップギャラリーを表示
1011
+ function showGallery() {
1012
+ const gallery = document.getElementById("gallery-container");
1013
+ const mapList = document.getElementById("gallery-map-list");
1014
+ mapList.innerHTML = "";
1015
+
1016
+ const savedMaps = JSON.parse(localStorage.getItem('savedMaps')) || {};
1017
+
1018
+ if (Object.keys(savedMaps).length === 0) {
1019
+ mapList.innerHTML = '<div class="text-center py-4">保存されたマップはありません</div>';
1020
  } else {
1021
+ for (const [name, data] of Object.entries(savedMaps)) {
1022
+ const mapItem = document.createElement("div");
1023
+ mapItem.className = "gallery-map-item";
1024
+
1025
+ mapItem.innerHTML = `
1026
+ <div class="gallery-map-title">${name}</div>
1027
+ <div class="gallery-map-preview">
1028
+ マーカー数: ${data.markers.length}<br>
1029
+ 中心座標: ${data.center.lat.toFixed(4)}, ${data.center.lng.toFixed(4)}<br>
1030
+ ズームレベル: ${data.zoom}
1031
+ </div>
1032
+ <div class="gallery-map-actions">
1033
+ <button class="hacker-btn gallery-btn load-map-btn" data-name="${name}">読み込み</button>
1034
+ <button class="hacker-btn gallery-btn danger delete-map-btn" data-name="${name}">削除</button>
1035
+ </div>
1036
+ `;
1037
+
1038
+ mapList.appendChild(mapItem);
1039
+ }
1040
+
1041
+ // イベントリスナーを追加
1042
+ document.querySelectorAll('.load-map-btn').forEach(btn => {
1043
+ btn.addEventListener('click', function() {
1044
+ loadMapFromGallery(this.dataset.name);
1045
+ });
1046
  });
1047
+
1048
+ document.querySelectorAll('.delete-map-btn').forEach(btn => {
1049
+ btn.addEventListener('click', function() {
1050
+ if (confirm(`マップ「${this.dataset.name}」を削除しますか?`)) {
1051
+ deleteMapFromGallery(this.dataset.name);
1052
+ }
1053
+ });
1054
  });
 
 
 
1055
  }
1056
+
1057
+ gallery.style.display = "block";
1058
+ }
1059
+
1060
+ // マップギャラリーを非表示
1061
+ function hideGallery() {
1062
+ document.getElementById("gallery-container").style.display = "none";
1063
+ }
1064
+
1065
+ // ギャラリーからマップを読み込み
1066
+ function loadMapFromGallery(mapName) {
1067
+ const savedMaps = JSON.parse(localStorage.getItem('savedMaps')) || {};
1068
+ const mapData = savedMaps[mapName];
1069
+
1070
+ if (!mapData) {
1071
+ alert("マップデータが見つかりません");
1072
+ return;
1073
  }
1074
+
1075
+ // 現在のマップをクリア
1076
+ clearCurrentMap();
1077
+
1078
+ // 新しいマップを読み込み
1079
+ map.setView(mapData.center, mapData.zoom);
1080
+ currentMapName = mapName;
1081
+
1082
+ mapData.markers.forEach((markerData) => {
1083
  const icon = L.icon({
1084
+ iconUrl: markerData.iconUrl,
1085
+ iconSize: markerData.iconSize,
1086
+ iconAnchor: [markerData.iconSize[0] / 2, markerData.iconSize[1]],
1087
+ popupAnchor: [0, -markerData.iconSize[1]],
1088
+ tooltipAnchor: [markerData.iconSize[0] / 2, -markerData.iconSize[1] / 2],
1089
  });
1090
+
1091
+ const marker = L.marker([markerData.lat, markerData.lng], { icon: icon }).addTo(map);
1092
+ if (markerData.popupContent) marker.bindPopup(markerData.popupContent);
1093
+ if (markerData.tooltipContent) marker.bindTooltip(markerData.tooltipContent);
1094
+
1095
+ marker.on("mouseover", function() {
1096
+ hoveredMarker = marker;
1097
+ });
1098
+
1099
+ marker.on("mouseout", function() {
1100
+ if (hoveredMarker === marker) {
1101
+ hoveredMarker = null;
1102
+ }
1103
+ });
1104
+ });
1105
+
1106
+ hideGallery();
1107
+ updateEditNextMarkerButton();
1108
+ alert(`マップ「${mapName}」を読み込みました`);
1109
  }
1110
+
1111
+ // ギャラリーからマップを削除
1112
+ function deleteMapFromGallery(mapName) {
1113
+ const savedMaps = JSON.parse(localStorage.getItem('savedMaps')) || {};
1114
+ delete savedMaps[mapName];
1115
+ localStorage.setItem('savedMaps', JSON.stringify(savedMaps));
1116
+
1117
+ if (currentMapName === mapName) {
1118
+ currentMapName = '';
1119
  }
1120
+
1121
+ showGallery(); // ギャラリーを更新
1122
+ }
1123
+
1124
+ // 現在のマップをクリア
1125
+ function clearCurrentMap() {
1126
+ map.eachLayer(layer => {
1127
+ if (layer instanceof L.Marker) {
1128
+ map.removeLayer(layer);
 
1129
  }
1130
  });
1131
+ currentMapName = '';
1132
+ updateEditNextMarkerButton();
1133
+ }
1134
+
1135
+ // HTMLを生成
1136
+ function generateMapHTML() {
1137
+ const markers = [];
1138
+ map.eachLayer((layer) => {
1139
+ if (layer instanceof L.Marker) {
1140
+ const marker = layer;
1141
+ const icon = marker.options.icon;
1142
+ const iconUrl = icon.options.iconUrl;
1143
+ const iconSize = icon.options.iconSize;
1144
+ const latlng = marker.getLatLng();
1145
+ const popupContent = marker.getPopup() ? marker.getPopup().getContent() : "";
1146
+ const tooltipContent = marker.getTooltip() ? marker.getTooltip().getContent() : "";
1147
+ markers.push({
1148
+ lat: latlng.lat,
1149
+ lng: latlng.lng,
1150
+ iconUrl: iconUrl,
1151
+ iconWidth: iconSize[0],
1152
+ iconHeight: iconSize[1],
1153
+ popupContent: popupContent,
1154
+ tooltipContent: tooltipContent
1155
+ });
1156
  }
1157
  });
1158
+
1159
+ const center = map.getCenter();
1160
+ const zoom = map.getZoom();
1161
+ let html = `<div id="map" style="height: 600px; width: 100%;">
1162
+ <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" />
1163
+ <script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"><\/script>
1164
+ <script>
1165
+ var map = L.map('map').setView([${center.lat}, ${center.lng}], ${zoom});
1166
+ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
1167
+ attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap contributors'
1168
+ }).addTo(map);
1169
+
1170
+ ${markers.map(marker => `
1171
+ var icon = L.icon({
1172
+ iconUrl: '${marker.iconUrl}',
1173
+ iconSize: [${marker.iconWidth}, ${marker.iconHeight}],
1174
+ iconAnchor: [${marker.iconWidth} / 2, ${marker.iconHeight}],
1175
+ popupAnchor: [0, -${marker.iconHeight}],
1176
+ tooltipAnchor: [${marker.iconWidth} / 2, -${marker.iconHeight} / 2]
1177
+ });
1178
+
1179
+ var marker = L.marker([${marker.lat}, ${marker.lng}], {
1180
+ icon: icon,
1181
+ zIndexOffset: 1000
1182
+ }).addTo(map);
1183
 
1184
+ ${marker.popupContent ? `marker.bindPopup('${marker.popupContent.replace(/'/g, "\\'").replace(/<\/script>/g, "<\\/script>")}');` : ""}
1185
+ ${marker.tooltipContent ? `marker.bindTooltip('${marker.tooltipContent.replace(/'/g, "\\'").replace(/<\/script>/g, "<\\/script>")}');` : ""}
1186
+ `).join("\n")}
1187
+ <\/script>
1188
+ `;
1189
+
1190
+ html = html.replace(/iconUrl: 'marker-icon\.png'/g, `iconUrl: '${location.origin}/marker-icon.png'`);
1191
+ document.getElementById("output-html").value = html;
1192
+ const input = document.getElementById('output-html').value;
1193
+ const output = document.getElementById('output-html');
1194
+ output.innerHTML = hljs.highlight('html', input).value;
1195
+ output.classList.add('hljs');
1196
+ }
1197
+
1198
+ // HTMLをクリップボードにコピー
1199
+ function copyHTMLToClipboard() {
1200
  const textToCopy = document.getElementById("output-html").innerText;
1201
  navigator.clipboard.writeText(textToCopy).then(() => {
1202
  alert("コピーしました。");
1203
  }).catch(err => {
1204
  console.error('コピーに失敗しました:', err);
1205
  });
1206
+ }
1207
+
1208
+ // ポップアップが開いた時の処理
1209
+ map.on('popupopen', function(e) {
 
 
 
 
 
 
 
 
1210
  const marker = e.popup._source;
1211
  if (nextMarkerEdit) {
1212
  openEditor(marker);
1213
  nextMarkerEdit = false;
1214
+ document.getElementById("edit-next-marker").textContent = "次のマーカーを編集";
1215
+ document.getElementById("edit-next-marker").classList.remove("danger");
1216
+ document.getElementById("edit-next-marker").classList.add("secondary");
 
 
 
 
 
 
 
1217
  }
1218
  });
1219
  </script>