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(); });