Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pinch zoom in responsive layout HTML5

Tags:

html

css

I have an HTML file with the following responsive definition:

<html>
<head>
  <meta name="viewport" content="width=device-width, user-scalable=no">
</head>
<body>
  <img class="img"
    src="https://stmed.net/sites/default/files/cube-wallpapers-25187-9698686.jpg" />
</body>
</html>

With this CSS:

body {
  margin: 0;
  padding: 0;
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column

}
.img {
  width: 80vw;
  margin: 10px auto;
}

Full working example in: jsfiddle.

In my scenario the user cannot apply zoom to my page, which is good.

However, I want to allow the user to use a "pinch zoom" only in my image tag.

To be clear, I want that the size of the box of the image stays the same but the image get zoom. Of course part of the image will be hidden by the box (like overflow auto does).

Can I achieve that with only HTML and CSS (preferably without js)?

like image 478
Jonny Piazzi Avatar asked Nov 01 '25 04:11

Jonny Piazzi


1 Answers

This is impossible without Javascript. Even with Javascript it's pretty hard to figure out how to do it! If you google "pinch zoom mdn" it will take you to Pinch Zoom Gestures which tries to use pointerdown, pointermove and pointerup to implement pinch to zoom itself in Javascript. Their example is here and if you have a play with it you will find that it doesn't work at all.

The issue is that it tries to implement pinch to zoom itself, rather than having the browser/OS do it properly, and send the zoom result to the web page, which is obviously the sane way to do it.

In the end I couldn't find any answers about people doing this at all, so I looked at how Google Maps does it - they simply use the wheel event!

It turns out when browsers detect a two finger pan they send it as a wheel event (with deltaX and deltaY). And if they detect a pinch zoom they send a wheel event with event.ctrlKey and deltaY set.

Here's an example (I know this isn't exactly what you're looking for but if I ask a different question it will just get closed as a duplicate of this one, sorry).

let x = 250;
let y = 250;
let s = 10;

function redraw() {
  const c = document.getElementById("can");
  const ctx = c.getContext("2d");
  ctx.fillStyle = 'grey';
  ctx.fillRect(0, 0, c.width, c.height);
  ctx.fillStyle = 'red';
  ctx.fillRect(x-s, y-s, 2*s, 2*s);
}

function init() {
  const c = document.getElementById("can");
  c.addEventListener("wheel", (event) => {
    // preventDefault() is necessary to stop the browser zooming.
    event.preventDefault();
    if (event.ctrlKey) {
      s -= event.deltaY;
      s = Math.min(Math.max(s, 5), 100);
    } else {
      x += event.deltaX;
      y += event.deltaY;
      x = Math.min(Math.max(x, 10), 490);
      y = Math.min(Math.max(y, 10), 490);
    }
    redraw();
  });
  redraw();
}

init();
<canvas width="500" height="500" id="can"></canvas>
like image 70
Timmmm Avatar answered Nov 03 '25 20:11

Timmmm



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!