I try to place a marker over an image (floor plan) that will stick to that coordinates regardless if user zooms in or out, drags the image in zoom mode. I have tried but with little success to create a semi functional code that uses the click and touch events.
One can double click or double tap to add a marker over a floor plan and then should zoom or not the marker needs to remain in the same position. Imagine you want to have a marker where the light bulb should be, you add a marker at that exact position and then you can zoom the floor plan but the marker should remain where it was added, unless the user double taps / clicks once more.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Image Zoom and Marker</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<style>
#image-container {
position: relative;
width: 100%;
max-width: 600px;
height: 400px; /* Specify a fixed height for better control */
overflow: hidden;
}
#image-container img {
width: 100%;
transform-origin: top left;
transition: transform 0.25s ease;
cursor: grab;
}
.marker {
position: absolute;
color: red;
pointer-events: none; /* Prevent marker from capturing click events */
font-size: 1.5em; /* Smaller marker size */
transform-origin: center;
}
#zoom-button {
position: absolute;
top: 10px;
right: 10px;
background: rgba(0, 0, 0, 0.5); /* Dark transparent background */
border: none;
cursor: pointer;
z-index: 10;
padding: 5px;
border-radius: 10px; /* Rounded corners */
}
#zoom-button i {
font-size: 2em;
color: white;
}
</style>
</head>
<body>
<div id="image-container">
<img id="zoom-image" src="C:877bd8f8386ae50ec097e8c7a6d4a29.jpg" alt="Zoomable Image">
<button id="zoom-button">
<i class="fas fa-search"></i>
</button>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-zoom/1.7.21/jquery.zoom.min.js"></script>
<script src="https://hammerjs.github.io/dist/hammer.min.js"></script>
<script>
$(document).ready(function() {
let scale = 1;
const maxScale = 5; // Maximum zoom level
const minScale = 1;
const scaleStep = 1;
let isDragging = false;
let startX, startY;
let imgX = 0, imgY = 0;
let pinX, pinY;
let existingPin = null;
// Handle zoom button click
$('#zoom-button').on('click', function() {
if (scale < maxScale) {
scale += scaleStep;
} else {
scale = minScale; // Reset to original size
}
updateZoom();
updateMarkers();
});
// Handle double click/tap for marker placement
$('#image-container').on('dblclick', function(e) {
if ($(e.target).is('#zoom-button, #zoom-button *')) {
return; // Prevent placing marker when clicking the zoom button
}
const image = $('#zoom-image');
const offsetX = e.pageX - image.offset().left;
const offsetY = e.pageY - image.offset().top;
const x = offsetX / scale;
const y = offsetY / scale;
// Remove existing pin
if (existingPin) {
existingPin.remove();
}
pinX = x;
pinY = y;
const marker = $('<i class="fas fa-map-marker fa-2x marker"></i>'); // Adjusted size
marker.css({
top: pinY * scale + 'px', // Relative to image
left: pinX * scale + 'px', // Relative to image
transform: `scale(${1 / scale})` // Ensure marker size stays consistent
});
existingPin = marker;
image.after(marker);
});
// Enable dragging
$('#zoom-image').on('mousedown touchstart', function(e) {
isDragging = true;
const event = e.type === 'mousedown' ? e : e.touches[0];
startX = event.pageX - imgX;
startY = event.pageY - imgY;
$('#zoom-image').css('cursor', 'grabbing');
e.preventDefault(); // Prevent default touch actions
});
$(document).on('mousemove touchmove', function(e) {
if (isDragging) {
const event = e.type === 'mousemove' ? e : e.touches[0];
imgX = event.pageX - startX;
imgY = event.pageY - startY;
// Limit dragging within image boundaries
const image = $('#zoom-image');
const maxX = (image.width() * scale - image.width()) / 2;
const maxY = (image.height() * scale - image.height()) / 2;
imgX = Math.max(-maxX, Math.min(imgX, maxX));
imgY = Math.max(-maxY, Math.min(imgY, maxY));
$('#zoom-image').css('transform', 'scale(' + scale + ') translate(' + imgX + 'px, ' + imgY + 'px)');
updateMarkers();
}
});
$(document).on('mouseup touchend', function() {
isDragging = false;
$('#zoom-image').css('cursor', 'grab');
});
// Update marker positions based on the current scale
function updateMarkers() {
if (existingPin) {
existingPin.css({
top: pinY * scale + 'px', // Relative to image
left: pinX * scale + 'px', // Relative to image
transform: `scale(${1 / scale})` // Ensure marker size stays consistent
});
}
}
// Update image zoom level
function updateZoom() {
$('#zoom-image').css('transform', 'scale(' + scale + ') translate(' + imgX + 'px, ' + imgY + 'px)');
}
});
</script>
</body>
</html>
On zoom, the pointer will not stick to the current click coordinates and it will also not display the pointer when zooming. The funny fact is that it will increase / decrease the pointer height on zooming in or out.
Could someone show me where I am doing something stupid?
Thank you!