added Map and SlimeMap class
This commit is contained in:
+1
-4
@@ -43,10 +43,7 @@
|
|||||||
<div class="border"></div>
|
<div class="border"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="js/locations/nations.js"></script>
|
<script src="js/mapBuilder.js" type="module"></script>
|
||||||
<script src="js/locations/capitals.js"></script>
|
|
||||||
<script src="js/locations/pois.js"></script>
|
|
||||||
<script src="js/mapBuilder.js"></script>
|
|
||||||
<script src="js/tooltip.js"></script>
|
<script src="js/tooltip.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
/**
|
||||||
|
* Map class for creating interactive maps with SVG
|
||||||
|
*/
|
||||||
|
export default class Map {
|
||||||
|
/**
|
||||||
|
* @param {string} svgId - The ID of the SVG element
|
||||||
|
* @param {string} mapImage - The URL of the map image
|
||||||
|
*/
|
||||||
|
constructor(svgId, mapImage) {
|
||||||
|
this.svg = document.getElementById(svgId);
|
||||||
|
this.svg.innerHTML = "";
|
||||||
|
|
||||||
|
this.g = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
||||||
|
this.svg.appendChild(this.g);
|
||||||
|
|
||||||
|
this.g.innerHTML += `<image href="${mapImage}" width="100%"/>`;
|
||||||
|
|
||||||
|
this.isDragging = false;
|
||||||
|
this.startX = 0;
|
||||||
|
this.startY = 0;
|
||||||
|
this.initialTranslateX = 0;
|
||||||
|
this.initialTranslateY = 0;
|
||||||
|
this.initialScale = 1;
|
||||||
|
|
||||||
|
this.dragSensitivity = 2;
|
||||||
|
this.maxScale = 6;
|
||||||
|
this.minScale = 1;
|
||||||
|
|
||||||
|
this.initializeEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeEvents() {
|
||||||
|
this.svg.addEventListener("mousedown", (e) => this.onMouseDown(e));
|
||||||
|
this.svg.addEventListener("mousemove", (e) => this.onMouseMove(e));
|
||||||
|
this.svg.addEventListener("mouseup", () => this.onMouseUp());
|
||||||
|
this.svg.addEventListener("mouseleave", () => this.onMouseUp());
|
||||||
|
this.svg.addEventListener("wheel", (e) => this.onWheel(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the zoom level
|
||||||
|
* @param {number} zoomLevel - The zoom level
|
||||||
|
*/
|
||||||
|
setZoomLevel(zoomLevel) {
|
||||||
|
const svgRect = this.svg.getBoundingClientRect();
|
||||||
|
const centerX = svgRect.width / 2;
|
||||||
|
const centerY = svgRect.height / 2;
|
||||||
|
|
||||||
|
const [translate, scale] = this.parseTransform(this.g.getAttribute("transform") || "translate(0,0) scale(1)");
|
||||||
|
const newScale = Math.min(Math.max(zoomLevel, this.minScale), this.maxScale);
|
||||||
|
|
||||||
|
const svgPoint = this.svg.createSVGPoint();
|
||||||
|
svgPoint.x = centerX;
|
||||||
|
svgPoint.y = centerY;
|
||||||
|
const centerPoint = svgPoint.matrixTransform(this.svg.getScreenCTM().inverse());
|
||||||
|
|
||||||
|
const newTranslateX = translate[0] - (centerPoint.x - translate[0]) * (newScale / scale - 1);
|
||||||
|
const newTranslateY = translate[1] - (centerPoint.y - translate[1]) * (newScale / scale - 1);
|
||||||
|
|
||||||
|
this.g.setAttribute("transform", `translate(${newTranslateX}, ${newTranslateY}) scale(${newScale})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zoom in
|
||||||
|
* @param factor - The zoom factor
|
||||||
|
*/
|
||||||
|
zoomIn(factor = 1.1) {
|
||||||
|
const [translate, scale] = this.parseTransform(this.g.getAttribute("transform") || "translate(0,0) scale(1)");
|
||||||
|
const newScale = Math.min(scale * factor, this.maxScale);
|
||||||
|
this.setZoomLevel(newScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zoom out
|
||||||
|
* @param {number} factor - The zoom factor
|
||||||
|
*/
|
||||||
|
zoomOut(factor = 0.9) {
|
||||||
|
const [translate, scale] = this.parseTransform(this.g.getAttribute("transform") || "translate(0,0) scale(1)");
|
||||||
|
const newScale = Math.max(scale * factor, this.minScale);
|
||||||
|
this.setZoomLevel(newScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMouseDown(e) {
|
||||||
|
if (!this.g.getAttribute("transform") || this.g.getAttribute("transform").includes("scale(1)")) return;
|
||||||
|
this.isDragging = true;
|
||||||
|
this.startX = e.clientX;
|
||||||
|
this.startY = e.clientY;
|
||||||
|
|
||||||
|
const [translate, scale] = this.parseTransform(this.g.getAttribute("transform") || "translate(0,0) scale(1)");
|
||||||
|
this.initialTranslateX = translate[0];
|
||||||
|
this.initialTranslateY = translate[1];
|
||||||
|
this.initialScale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMouseMove(e) {
|
||||||
|
if (!this.isDragging) return;
|
||||||
|
|
||||||
|
const svgRect = this.svg.getBoundingClientRect();
|
||||||
|
const mapRect = this.g.getBBox();
|
||||||
|
|
||||||
|
const deltaX = (e.clientX - this.startX) * this.dragSensitivity;
|
||||||
|
const deltaY = (e.clientY - this.startY) * this.dragSensitivity;
|
||||||
|
|
||||||
|
let newTranslateX = this.initialTranslateX + deltaX;
|
||||||
|
let newTranslateY = this.initialTranslateY + deltaY;
|
||||||
|
|
||||||
|
const scale = this.initialScale;
|
||||||
|
const mapWidth = mapRect.width * scale;
|
||||||
|
const mapHeight = mapRect.height * scale;
|
||||||
|
const svgWidth = svgRect.width;
|
||||||
|
const svgHeight = svgRect.height;
|
||||||
|
|
||||||
|
const minTranslateX = Math.min(0, svgWidth - mapWidth);
|
||||||
|
const minTranslateY = Math.min(0, svgHeight - mapHeight);
|
||||||
|
|
||||||
|
const maxTranslateX = 0;
|
||||||
|
const maxTranslateY = 0;
|
||||||
|
|
||||||
|
newTranslateX = Math.max(minTranslateX, Math.min(maxTranslateX, newTranslateX));
|
||||||
|
newTranslateY = Math.max(minTranslateY, Math.min(maxTranslateY, newTranslateY));
|
||||||
|
|
||||||
|
this.g.setAttribute("transform", `translate(${newTranslateX}, ${newTranslateY}) scale(${scale})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMouseUp() {
|
||||||
|
this.isDragging = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onWheel(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const [translate, scale] = this.parseTransform(this.g.getAttribute("transform") || "translate(0,0) scale(1)");
|
||||||
|
const newScale = Math.min(Math.max(scale * (e.deltaY > 0 ? 0.9 : 1.1), 1), this.maxScale);
|
||||||
|
|
||||||
|
if (newScale === 1) {
|
||||||
|
this.g.setAttribute("transform", `translate(0,0) scale(1)`);
|
||||||
|
} else {
|
||||||
|
const svgPoint = this.svg.createSVGPoint();
|
||||||
|
svgPoint.x = e.clientX;
|
||||||
|
svgPoint.y = e.clientY;
|
||||||
|
const mousePoint = svgPoint.matrixTransform(this.svg.getScreenCTM().inverse());
|
||||||
|
|
||||||
|
const newTranslateX = translate[0] - (mousePoint.x - translate[0]) * (newScale / scale - 1);
|
||||||
|
const newTranslateY = translate[1] - (mousePoint.y - translate[1]) * (newScale / scale - 1);
|
||||||
|
this.g.setAttribute("transform", `translate(${newTranslateX}, ${newTranslateY}) scale(${newScale})`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parseTransform(transform) {
|
||||||
|
const translateMatch = transform.match(/translate\(([^)]+)\)/);
|
||||||
|
const scaleMatch = transform.match(/scale\(([^)]+)\)/);
|
||||||
|
const translate = translateMatch ? translateMatch[1].split(",").map(Number) : [0, 0];
|
||||||
|
const scale = scaleMatch ? parseFloat(scaleMatch[1]) : 1;
|
||||||
|
return [translate, scale];
|
||||||
|
}
|
||||||
|
|
||||||
|
addPolygon(points, attributes = {}) {
|
||||||
|
const polygon = document.createElementNS("http://www.w3.org/2000/svg", "polygon");
|
||||||
|
polygon.setAttribute("points", points);
|
||||||
|
Object.entries(attributes).forEach(([key, value]) => polygon.setAttribute(key, value));
|
||||||
|
this.g.appendChild(polygon);
|
||||||
|
}
|
||||||
|
|
||||||
|
addSVGElement(svgString) {
|
||||||
|
this.g.innerHTML += svgString;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import Map from "./Map.js";
|
||||||
|
|
||||||
|
export default class SlimeMap extends Map {
|
||||||
|
/**
|
||||||
|
* @param {string} svgId - The ID of the SVG element
|
||||||
|
* @param {string} mapImage - The URL of the map image
|
||||||
|
* @param nations
|
||||||
|
* @param capitals
|
||||||
|
* @param pois
|
||||||
|
*/
|
||||||
|
constructor(svgId, mapImage, nations, capitals, pois) {
|
||||||
|
super(svgId, mapImage);
|
||||||
|
this.nations = nations;
|
||||||
|
this.capitals = capitals;
|
||||||
|
this.pois = pois;
|
||||||
|
this.addNations();
|
||||||
|
this.addCapitals();
|
||||||
|
this.addPOIs();
|
||||||
|
}
|
||||||
|
|
||||||
|
addNations() {
|
||||||
|
for (let nation of this.nations) {
|
||||||
|
this.addPolygon(nation.points, {
|
||||||
|
class: "region",
|
||||||
|
fill: "transparent",
|
||||||
|
stroke: "transparent",
|
||||||
|
"stroke-width": "4",
|
||||||
|
"data-name": nation.name,
|
||||||
|
"data-ruler": nation.ruler,
|
||||||
|
"data-capital": nation.capital,
|
||||||
|
"data-population": nation.population,
|
||||||
|
"data-description": nation.description,
|
||||||
|
"data-url": nation.url ?? ""
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addCapitals() {
|
||||||
|
for (let capital of this.capitals) {
|
||||||
|
const svgString = `
|
||||||
|
<g transform="translate(${capital.position.x}, ${capital.position.y}) scale(2.5, 2.5)"
|
||||||
|
class="location"
|
||||||
|
data-name="${capital.name}"
|
||||||
|
data-url="${capital.url ?? ""}"
|
||||||
|
data-description="${capital.description ?? ""}">
|
||||||
|
<rect x="0" y="0" width="24" height="24" fill="transparent" stroke="transparent" stroke-width="4" />
|
||||||
|
<path d="M4.5 14L3 15V21H7M7 21H10M7 21V13L9.5 11V6L12 3L14.5 6V11L17 13V21M10 21H14M10 21V17C10 15.8954 10.8954 15 12 15C13.1046 15 14 15.8954 14 17V21M14 21H17M17 21H21V15L19.5 14"
|
||||||
|
stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
|
</g>`;
|
||||||
|
this.addSVGElement(svgString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addPOIs() {
|
||||||
|
for (let poi of this.pois) {
|
||||||
|
const svgString = `
|
||||||
|
<g transform="translate(${poi.position.x}, ${poi.position.y}) scale(2, 2)"
|
||||||
|
class="location"
|
||||||
|
data-name="${poi.name}"
|
||||||
|
data-description="${poi.description}"
|
||||||
|
data-url="${poi.url ?? ""}">
|
||||||
|
<rect x="-12" y="-12" width="24" height="24" fill="transparent" stroke="transparent" stroke-width="4" />
|
||||||
|
<polygon points="0,-10 3,-3 10,0 3,3 0,10 -3,3 -10,0 -3,-3"
|
||||||
|
fill="white" stroke="black" stroke-width="1" />
|
||||||
|
</g>`;
|
||||||
|
this.addSVGElement(svgString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
/**
|
/**
|
||||||
* @type {[CapitalData]}
|
* @type {[CapitalData]}
|
||||||
*/
|
*/
|
||||||
const capitals = [
|
export const capitals = [
|
||||||
{
|
{
|
||||||
name: "Lune",
|
name: "Lune",
|
||||||
description: "The capital of the Holy Empire Lubelius, home of God Luminous.",
|
description: "The capital of the Holy Empire Lubelius, home of God Luminous.",
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export * from "./pois.js";
|
||||||
|
export * from "./nations.js";
|
||||||
|
export * from "./capitals.js";
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
/**
|
/**
|
||||||
* @type {[NationData]}
|
* @type {[NationData]}
|
||||||
*/
|
*/
|
||||||
const nations = [
|
export const nations = [
|
||||||
{
|
{
|
||||||
name: "Kingdom of Englassia",
|
name: "Kingdom of Englassia",
|
||||||
url: "https://tensura.fandom.com/wiki/Kingdom_of_Englassia",
|
url: "https://tensura.fandom.com/wiki/Kingdom_of_Englassia",
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
/**
|
/**
|
||||||
* @type {[POIData]}
|
* @type {[POIData]}
|
||||||
*/
|
*/
|
||||||
const pois = [
|
export const pois = [
|
||||||
{
|
{
|
||||||
name: "Sealed Cave",
|
name: "Sealed Cave",
|
||||||
description: "The cave where Veldora was sealed and where Rimuru was born.",
|
description: "The cave where Veldora was sealed and where Rimuru was born.",
|
||||||
|
|||||||
+3
-183
@@ -1,184 +1,4 @@
|
|||||||
function drawMap() {
|
import {pois, capitals, nations} from "./locations";
|
||||||
const svg = document.getElementById("map");
|
import SlimeMap from "./SlimeMap.js";
|
||||||
svg.innerHTML = "";
|
|
||||||
|
|
||||||
const g = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
const slimeMap = new SlimeMap("map", "img/map.webp", nations, capitals, pois);
|
||||||
svg.appendChild(g);
|
|
||||||
|
|
||||||
g.innerHTML += `<image href="img/map.webp" width="100%"/>`;
|
|
||||||
|
|
||||||
for (let nation of nations) {
|
|
||||||
addNation(g, nation);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let capital of capitals) {
|
|
||||||
addCapital(g, capital);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let poi of pois) {
|
|
||||||
addPOI(g, poi);
|
|
||||||
}
|
|
||||||
|
|
||||||
let isDragging = false;
|
|
||||||
let startX, startY, initialTranslateX, initialTranslateY, initialScale;
|
|
||||||
|
|
||||||
const dragSensitivity = 2;
|
|
||||||
const maxScale = 6;
|
|
||||||
|
|
||||||
svg.addEventListener("mousedown", (e) => {
|
|
||||||
if (!g.getAttribute("transform") || g.getAttribute("transform").includes("scale(1)")) return;
|
|
||||||
isDragging = true;
|
|
||||||
startX = e.clientX;
|
|
||||||
startY = e.clientY;
|
|
||||||
|
|
||||||
// Get the current transform values, including scale
|
|
||||||
const [translate, scale] = parseTransform(g.getAttribute("transform") || "translate(0,0) scale(1)");
|
|
||||||
initialTranslateX = translate[0];
|
|
||||||
initialTranslateY = translate[1];
|
|
||||||
initialScale = scale;
|
|
||||||
});
|
|
||||||
|
|
||||||
svg.addEventListener("mousemove", (e) => {
|
|
||||||
if (!isDragging) return;
|
|
||||||
|
|
||||||
const svgRect = svg.getBoundingClientRect();
|
|
||||||
const mapRect = g.getBBox(); // Get the bounding box of the map content
|
|
||||||
|
|
||||||
// Calculate how far the mouse has moved
|
|
||||||
const deltaX = (e.clientX - startX) * dragSensitivity;
|
|
||||||
const deltaY = (e.clientY - startY) * dragSensitivity;
|
|
||||||
|
|
||||||
// New translation values
|
|
||||||
let newTranslateX = initialTranslateX + deltaX;
|
|
||||||
let newTranslateY = initialTranslateY + deltaY;
|
|
||||||
|
|
||||||
// Calculate boundaries
|
|
||||||
const scale = initialScale;
|
|
||||||
const mapWidth = mapRect.width * scale;
|
|
||||||
const mapHeight = mapRect.height * scale;
|
|
||||||
const svgWidth = svgRect.width;
|
|
||||||
const svgHeight = svgRect.height;
|
|
||||||
|
|
||||||
// Constrain the translation to prevent dragging out of bounds
|
|
||||||
const minTranslateX = Math.min(0, svgWidth - mapWidth); // Minimum X translation
|
|
||||||
const minTranslateY = Math.min(0, svgHeight - mapHeight); // Minimum Y translation
|
|
||||||
|
|
||||||
const maxTranslateX = 0; // Maximum X translation
|
|
||||||
const maxTranslateY = 0; // Maximum Y translation
|
|
||||||
|
|
||||||
// Apply constraints
|
|
||||||
newTranslateX = Math.max(minTranslateX, Math.min(maxTranslateX, newTranslateX));
|
|
||||||
newTranslateY = Math.max(minTranslateY, Math.min(maxTranslateY, newTranslateY));
|
|
||||||
|
|
||||||
// Apply the movement to the translation, using the stored initialScale
|
|
||||||
g.setAttribute("transform", `translate(${newTranslateX}, ${newTranslateY}) scale(${scale})`);
|
|
||||||
});
|
|
||||||
|
|
||||||
svg.addEventListener("mouseup", () => {
|
|
||||||
isDragging = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
svg.addEventListener("mouseleave", () => {
|
|
||||||
isDragging = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
svg.addEventListener("wheel", (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const [translate, scale] = parseTransform(g.getAttribute("transform") || "translate(0,0) scale(1)");
|
|
||||||
const newScale = Math.min(Math.max(scale * (e.deltaY > 0 ? 0.9 : 1.1), 1), maxScale);
|
|
||||||
|
|
||||||
if (newScale === 1) {
|
|
||||||
// Center the map when zoomed out
|
|
||||||
g.setAttribute("transform", `translate(0,0) scale(1)`);
|
|
||||||
} else {
|
|
||||||
// Convert mouse position to SVG coordinates
|
|
||||||
const svgPoint = svg.createSVGPoint();
|
|
||||||
svgPoint.x = e.clientX;
|
|
||||||
svgPoint.y = e.clientY;
|
|
||||||
const mousePoint = svgPoint.matrixTransform(svg.getScreenCTM().inverse());
|
|
||||||
|
|
||||||
// Adjust translation based on new scale
|
|
||||||
const newTranslateX = translate[0] - (mousePoint.x - translate[0]) * (newScale / scale - 1);
|
|
||||||
const newTranslateY = translate[1] - (mousePoint.y - translate[1]) * (newScale / scale - 1);
|
|
||||||
g.setAttribute("transform", `translate(${newTranslateX}, ${newTranslateY}) scale(${newScale})`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function parseTransform(transform) {
|
|
||||||
const translateMatch = transform.match(/translate\(([^)]+)\)/);
|
|
||||||
const scaleMatch = transform.match(/scale\(([^)]+)\)/);
|
|
||||||
const translate = translateMatch ? translateMatch[1].split(",").map(Number) : [0, 0];
|
|
||||||
const scale = scaleMatch ? parseFloat(scaleMatch[1]) : 1;
|
|
||||||
return [translate, scale];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Element} svg
|
|
||||||
* @param {NationData} nation
|
|
||||||
*/
|
|
||||||
function addNation(svg, nation) {
|
|
||||||
const polygon = document.createElementNS("http://www.w3.org/2000/svg", "polygon");
|
|
||||||
polygon.setAttribute("class", "region");
|
|
||||||
polygon.setAttribute("fill", "transparent");
|
|
||||||
polygon.setAttribute("stroke", "transparent");
|
|
||||||
polygon.setAttribute("stroke-width", "4");
|
|
||||||
polygon.setAttribute("points", nation.points);
|
|
||||||
polygon.setAttribute("data-name", nation.name);
|
|
||||||
polygon.setAttribute("data-ruler", nation.ruler);
|
|
||||||
polygon.setAttribute("data-capital", nation.capital);
|
|
||||||
polygon.setAttribute("data-population", nation.population);
|
|
||||||
polygon.setAttribute("data-description", nation.description);
|
|
||||||
polygon.setAttribute("data-url", nation.url ?? "");
|
|
||||||
svg.appendChild(polygon);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Element} svg
|
|
||||||
* @param {CapitalData} capital
|
|
||||||
*/
|
|
||||||
function addCapital(svg, capital) {
|
|
||||||
const svgString = `
|
|
||||||
<g
|
|
||||||
transform="translate(${capital.position.x}, ${capital.position.y}) scale(2.5, 2.5 )"
|
|
||||||
class="location"
|
|
||||||
data-name="${capital.name}"
|
|
||||||
data-url="${capital.url ?? ""}"
|
|
||||||
data-description="${capital.description ?? ""}"
|
|
||||||
>
|
|
||||||
<rect x="0" y="0" width="24" height="24" fill="transparent" stroke="transparent" stroke-width="4" />
|
|
||||||
<path d="M4.5 14L3 15V21H7M7 21H10M7 21V13L9.5 11V6L12 3L14.5 6V11L17 13V21M10 21H14M10 21V17C10 15.8954 10.8954 15 12 15C13.1046 15 14 15.8954 14 17V21M14 21H17M17 21H21V15L19.5 14"
|
|
||||||
stroke="#ffffff"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round" />
|
|
||||||
</g>
|
|
||||||
`;
|
|
||||||
|
|
||||||
svg.innerHTML += svgString;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Element} svg
|
|
||||||
* @param {POIData} poi
|
|
||||||
*/
|
|
||||||
function addPOI(svg, poi) {
|
|
||||||
const svgString = `
|
|
||||||
<g
|
|
||||||
transform="translate(${poi.position.x}, ${poi.position.y}) scale(2, 2)"
|
|
||||||
class="location"
|
|
||||||
data-name="${poi.name}"
|
|
||||||
data-description="${poi.description}"
|
|
||||||
data-url="${poi.url ?? ""}"
|
|
||||||
>
|
|
||||||
<rect x="-12" y="-12" width="24" height="24" fill="transparent" stroke="transparent" stroke-width="4" />
|
|
||||||
<polygon points="0,-10 3,-3 10,0 3,3 0,10 -3,3 -10,0 -3,-3"
|
|
||||||
fill="white" stroke="black" stroke-width="1" />
|
|
||||||
</g>
|
|
||||||
`;
|
|
||||||
|
|
||||||
svg.innerHTML += svgString;
|
|
||||||
}
|
|
||||||
|
|
||||||
drawMap();
|
|
||||||
@@ -4,6 +4,10 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
let mouseOnTooltipableArea = false;
|
let mouseOnTooltipableArea = false;
|
||||||
let currentTooltipContent = '';
|
let currentTooltipContent = '';
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
console.log("Control is held:", isControlHeld);
|
||||||
|
}, 500)
|
||||||
|
|
||||||
const showTooltip = (content, e) => {
|
const showTooltip = (content, e) => {
|
||||||
mouseOnTooltipableArea = true;
|
mouseOnTooltipableArea = true;
|
||||||
currentTooltipContent = content;
|
currentTooltipContent = content;
|
||||||
|
|||||||
Reference in New Issue
Block a user