0

I'm trying to use javascript to place an image overlay over an existing HTML image when the user clicks on it. I have that part working, but am wondering if it is possible to reposition the superimposed images when the window resizes so they maintain their position relative to the base image. I'd also like to scale the inserted images on window resize. I have a little codepen here: https://codepen.io/Matt-Denko/pen/abxLqrR.

window.addEventListener("load", function () {
    document.getElementById('myImg').onclick = function(event) {
        var i = new Image();
        i.src = 'https://picsum.photos/30/30?grayscale';
        i.style.position = "absolute";
        var yOffset = event.clientY;
        var xOffset = event.clientX;
        // Apply offsets for CSS margins etc.
        yOffset -= 148;
        xOffset -= 40;
        // Set image insertion coordinates
        i.style.top = yOffset + 'px';
        i.style.left = xOffset + 'px';
        // Append the image to the DOM
        document.getElementById('map1').appendChild(i); 
    }
});
.responsive {
    position: relative;
    max-width: 1200px;
    width: 100%;
    height: 100%;
}
<div class="container">
    <div style="height: auto; padding: 3px 0 3px 0;">
        <div class="card">
            <div class="card_content">
                <h1>Map PNG Testing</h1>
                <div id="map1" class="responsive">
                    <img src="https://picsum.photos/seed/picsum/200/300" id="myImg" class="responsive">
                </div>
            </div>
        </div>
    </div>
</div>

2 Answers 2

1

I think best would be just to set left and top using % units. You can do the same for the width of the marker.

const rect = document.getElementById('map1').getBoundingClientRect();
const originalWidth = rect.width
const originalHeight = rect.height


window.addEventListener("load", function() {
  document.getElementById('map1').onclick = function(event) {
    const rect = event.target.getBoundingClientRect();
    const x = event.clientX - rect.left;
    const y = event.clientY - rect.top;
    addMarker(x, y, rect.width, rect.height);
  }
});


function resize() {
  document.getElementById('map1').style.width = ((Math.random() * 50) + 50) + "%"
}

function addMarker(x, y, w, h) {
  var i = new Image();
  i.src = 'https://placehold.co/32x32/000000/FFF';
  i.style.position = "absolute";
  i.onload = function() {
    var xOffset = x;
    var yOffset = y;

    // center image on cursor

    xOffset -= i.width / 2;
    yOffset -= i.height / 2;

    // Set image insertion coordinates
    i.style.left = (xOffset / w * 100) + '%';
    i.style.top = (yOffset / h * 100) + '%';

    // optionally: 
    i.style.width = (i.width / originalWidth * 100) + '%'

  }

  // Append the image to the DOM
  document.getElementById('map1').appendChild(i);

}
.responsive {
  position: relative;
  max-width: 1200px;
  width: 100%;
  height: auto;
  border: 1px solid red;
}

.responsive #myImg {
  width: 100%;
  display: block;
}
<div class="container">
  <div style="height: auto; padding: 3px 0 3px 0;">
    <div class="card">
      <div class="card_content">
        <p>click to place markers <button onclick="resize()">random size</button></p>
        <div id="map1" class="responsive">
          <img src="https://picsum.photos/800/300" id="myImg">
        </div>
      </div>
    </div>
  </div>
</div>

Sign up to request clarification or add additional context in comments.

2 Comments

This is working great; thanks! One question - your optional addition to set the width of the image works when the window is resized, but any new images that are added are full size. How would I go about setting the width of the added image on insertion based on the current bounding rectangle width?
in that case you they should be a fraction of the original width. answer edited.
0

To achieve what you're looking for, you need to listen for a few different events.

I'll give you this code snippet I wrote based on your codepen. It detects the events you'll need to look for.

  1. Window Resize
  2. Image Scaling up/down
  3. Extra check: checking if the image itself was resized (if you add the ability later in your code)
document.addEventListener('DOMContentLoaded', function() {
    // Get the reference to the div container
    const mapContainer = document.getElementById('map1');

    // Find the image inside the container
    const imageElement = mapContainer.querySelector('img');

    // Add event listener to window resize event
    window.addEventListener('resize', function() {
        console.log('Window resized');
        // Detect if the image was scaled
        detectImageScaling();
    });

    // Add event listener to image resize event
    const imageResizeObserver = new ResizeObserver(entries => {
        for (let entry of entries) {
            console.log('Image resized');
        }
    });

    // Start observing the image element
    imageResizeObserver.observe(imageElement);

    // Function to detect scaling changes of your map1.img
    function detectImageScaling() {
        const currentWidth = imageElement.clientWidth;
        const currentHeight = imageElement.clientHeight;

        // Check if the width or height has changed since the last check
        if (imageElement.dataset.prevWidth !== currentWidth || imageElement.dataset.prevHeight !== currentHeight) {
            if (imageElement.dataset.prevWidth && imageElement.dataset.prevHeight) {
                const scalingFactorX = currentWidth / imageElement.dataset.prevWidth;
                const scalingFactorY = currentHeight / imageElement.dataset.prevHeight;

                if (scalingFactorX > 1 || scalingFactorY > 1) {
                    console.log('Image scaled up');
                } else if (scalingFactorX < 1 || scalingFactorY < 1) {
                    console.log('Image scaled down');
                }
            }

            // Update previous width and height
            imageElement.dataset.prevWidth = currentWidth;
            imageElement.dataset.prevHeight = currentHeight;
        }

        // Call this function recursively to continue detecting scaling changes
        requestAnimationFrame(detectImageScaling);
    }
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.