|
|
|
const canvasContainer = document.getElementById('canvas-container');
|
|
|
|
let zoomLevel = 0.15
|
|
|
|
let stageX = 0
|
|
|
|
let stageY = 0
|
|
|
|
let myWindow
|
|
|
|
|
|
|
|
// Create a Konva stage, which will be the entire w x h of the screen
|
|
|
|
const stage = new Konva.Stage({
|
|
|
|
container: 'canvas-container',
|
|
|
|
width: window.innerWidth,
|
|
|
|
height: window.innerHeight,
|
|
|
|
draggable: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
// Create a Konva layer
|
|
|
|
// This acts as a layer to add various shapes, images, groups to
|
|
|
|
const layer = new Konva.Layer();
|
|
|
|
|
|
|
|
// Create a Konva image
|
|
|
|
const image = new Konva.Image({
|
|
|
|
draggable: false,
|
|
|
|
shadowColor: 'rgba(0, 0, 0, 0.5)', // Shadow color
|
|
|
|
shadowBlur: 20, // Blur radius
|
|
|
|
shadowOffset: { x: 0, y: 0 }, // Offset of the shadow
|
|
|
|
shadowOpacity: 0, // Shadow opacity
|
|
|
|
});
|
|
|
|
|
|
|
|
// Load the PNG image
|
|
|
|
const imageURL = 'map.png'; // Replace with the path to your PNG image
|
|
|
|
const imageObj = new Image();
|
|
|
|
|
|
|
|
imageObj.onload = function () {
|
|
|
|
// Set the image dimensions and center it in the stage
|
|
|
|
image.width(imageObj.width);
|
|
|
|
image.height(imageObj.height);
|
|
|
|
|
|
|
|
// Set the image source
|
|
|
|
image.image(imageObj);
|
|
|
|
|
|
|
|
// Add the image to the layer
|
|
|
|
layer.add(image);
|
|
|
|
|
|
|
|
// Fetch JSON data asynchronously
|
|
|
|
fetch('./links.json')
|
|
|
|
.then(response => response.json())
|
|
|
|
.then(jsonData => {
|
|
|
|
// Process the JSON data and create rectangles
|
|
|
|
const layer = new Konva.Layer();
|
|
|
|
|
|
|
|
jsonData.sections.forEach(section => {
|
|
|
|
section.links.forEach(link => {
|
|
|
|
const clickableRect = new Konva.Rect({
|
|
|
|
id: link.id,
|
|
|
|
x: link.x,
|
|
|
|
y: link.y,
|
|
|
|
width: link.width,
|
|
|
|
height: link.height,
|
|
|
|
fill: 'rgba(255, 0, 0, 0.0)',
|
|
|
|
draggable: false,
|
|
|
|
shadowColor: 'rgba(0, 0, 0, 0)',
|
|
|
|
shadowBlur: 20,
|
|
|
|
shadowOffset: { x: 0, y: 0 },
|
|
|
|
shadowOpacity: 1,
|
|
|
|
});
|
|
|
|
|
|
|
|
clickableRect.on('click', () => {
|
|
|
|
let linkName = link.url
|
|
|
|
// Check if the window is already open
|
|
|
|
if (myWindow && !myWindow.closed) {
|
|
|
|
// Reuse the existing window
|
|
|
|
myWindow.location.href = 'http://localhost:3000/' + linkName;
|
|
|
|
} else {
|
|
|
|
// Open a new window and assign a unique name
|
|
|
|
myWindow = window.open('http://localhost:3000/' + linkName, 'myWindow', 'width=600,height=400');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
clickableRect.on('mouseenter', () => {
|
|
|
|
document.body.style.cursor = 'pointer';
|
|
|
|
});
|
|
|
|
|
|
|
|
clickableRect.on('mouseleave', () => {
|
|
|
|
document.body.style.cursor = 'default';
|
|
|
|
});
|
|
|
|
|
|
|
|
layer.add(clickableRect);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
stage.add(layer);
|
|
|
|
})
|
|
|
|
.catch(error => console.error('Error fetching JSON:', error));
|
|
|
|
|
|
|
|
stage.x((stage.width()/2) - (image.width()/2) * 0.15)
|
|
|
|
stage.y((stage.height()/2) - (image.height()/2) * 0.15)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stageX = stage.x()
|
|
|
|
stageY = stage.y()
|
|
|
|
|
|
|
|
stage.scaleX(0.15)
|
|
|
|
stage.scaleY(0.15)
|
|
|
|
|
|
|
|
// Add the layer to the stage
|
|
|
|
stage.add(layer);
|
|
|
|
|
|
|
|
layer.batchDraw();
|
|
|
|
};
|
|
|
|
|
|
|
|
imageObj.src = imageURL;
|
|
|
|
|
|
|
|
// Add the image to the layer
|
|
|
|
layer.add(image);
|
|
|
|
|
|
|
|
// Add the layer to the stage
|
|
|
|
stage.add(layer);
|
|
|
|
|
|
|
|
|
|
|
|
// Handle zoom in and zoom out
|
|
|
|
window.addEventListener('wheel', (e) => {
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
const oldScale = stage.scaleX();
|
|
|
|
|
|
|
|
// Calculate the new scale based on the wheel delta
|
|
|
|
zoomLevel += e.deltaY * -0.001;
|
|
|
|
zoomLevel = Math.max(0.15, Math.min(0.8, zoomLevel));
|
|
|
|
|
|
|
|
// Calculate the new scale factor
|
|
|
|
const scale = zoomLevel / oldScale;
|
|
|
|
|
|
|
|
// Calculate the cursor position relative to the stage
|
|
|
|
const pointer = stage.getPointerPosition();
|
|
|
|
const pointerX = pointer.x - stageX;
|
|
|
|
const pointerY = pointer.y - stageY;
|
|
|
|
|
|
|
|
// Adjust the stage position to zoom around the cursor
|
|
|
|
stageX -= pointerX * (scale - 1);
|
|
|
|
stageY -= pointerY * (scale - 1);
|
|
|
|
|
|
|
|
// Set the new scale and position of the stage
|
|
|
|
stage.scaleX(zoomLevel);
|
|
|
|
stage.scaleY(zoomLevel);
|
|
|
|
stage.x(stageX);
|
|
|
|
stage.y(stageY);
|
|
|
|
|
|
|
|
layer.batchDraw();
|
|
|
|
}, { passive: false });
|
|
|
|
|
|
|
|
// Slow down dragging based on the current scale
|
|
|
|
const dragSpeedFactor = 0.5; // Adjust this value to control the drag speed
|
|
|
|
|
|
|
|
// Reset stage position on drag
|
|
|
|
stage.on('dragstart', () => {
|
|
|
|
stageX = stage.x();
|
|
|
|
stageY = stage.y();
|
|
|
|
});
|
|
|
|
|
|
|
|
stage.on('dragmove', (e) => {
|
|
|
|
// Calculate drag speed factor based on scale
|
|
|
|
|
|
|
|
const dragSpeedFactor = 0.5 + (1-stage.scaleX()) * 1; // Adjust the multiplier as needed
|
|
|
|
|
|
|
|
const offsetX = e.evt.movementX * dragSpeedFactor * stage.scaleX();
|
|
|
|
const offsetY = e.evt.movementY * dragSpeedFactor * stage.scaleY();
|
|
|
|
|
|
|
|
stageX += offsetX;
|
|
|
|
stageY += offsetY;
|
|
|
|
|
|
|
|
stage.x(stageX);
|
|
|
|
stage.y(stageY);
|
|
|
|
|
|
|
|
layer.batchDraw();
|
|
|
|
});
|
|
|
|
|
|
|
|
stage.on('dragend', () => {
|
|
|
|
stageX = stage.x();
|
|
|
|
stageY = stage.y();
|
|
|
|
});
|
|
|
|
|
|
|
|
document.addEventListener('contextmenu', event => {
|
|
|
|
event.preventDefault();
|
|
|
|
});
|