0.0.3 • Published 1 month ago

@beoe/pan-zoom v0.0.3

Weekly downloads
-
License
MIT
Repository
github
Last release
1 month ago

@beoe/pan-zoom

Small JS library to add pan and zoom functionality to SVG (inline or image). It supports gestures for all types of devices:

intentionmousetrackpad/touchpadtouchscren
panclik + moveclick + movetwo finger drag
zoomCtrl + wheelpinchpinch
resetdouble clickdouble clickdouble tap
scrollwheeltwo finger dragone finger drag

Pay attention:

  • gestures intentionally selected to not interfere with the system's default scroll gestures, to avoid "scroll traps"
  • all actions are available through gestures, so it works without UI. You can add UI, though. Library exposes methods for this, like pan(dx, dy) and zoom(scale)

Demo

TODO: update demo - this is an old one

Netlify Status

pan-zoom demo

Usage

There are two flavors:

  • Headless - without UI
  • Default UI

Headless

If you have container element in HTML:

import { PanZoom } from "@beoe/pan-zoom";

document.querySelectorAll(".beoe").forEach((container) => {
  const element = container.querySelector("svg, img[src$='.svg' i]");
  if (!element) return;
  new PanZoom({ element, container }).on();
});

If you don't have container element in HTML:

import { PanZoom } from "@beoe/pan-zoom";

document.querySelectorAll("svg, img[src$='.svg' i]").forEach((element) => {
  if (element.parentElement?.tagName === "PICTURE") {
    element = element.parentElement;
  }
  const container = document.createElement("div");
  container.className = "beoe";
  element.replaceWith(container);
  container.append(element);
  new PanZoom({ element, container }).on();
});

Additionally following CSS is required:

.beoe {
  overflow: hidden;
  touch-action: pan-x pan-y;
  user-select: none;
  cursor: grab;
}

.beoe svg,
.beoe img {
  /* need to center smaller images to fix bug in zoom functionality */
  margin: auto;
  display: block;
  /* need to fit bigger images */
  max-width: 100%;
  height: auto;
}

.beoe img {
  pointer-events: none;
}

Instance methods:

  • on() - adds event listeners
  • off() - removes event listeners
  • pan(dx, dy) - pans image
  • zoom(scale) - zooms image
  • reset() - resets pan and zoom values

Default UI

import "@beoe/pan-zoom/css/PanZoomUi.css";
import { PanZoomUi } from "@beoe/pan-zoom";

document.querySelectorAll(".beoe").forEach((container) => {
  const element = container.firstElementChild;
  if (!element) return;
  new PanZoomUi({ element, container }).on();
});

Additionally, CSS to style UI required (for example with Tailwind):

.beoe .buttons {
  @apply inline-flex;
}
.beoe .zoom-in {
  @apply bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded-l;
}
.beoe .reset {
  @apply bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4;
}
.beoe .zoom-out {
  @apply bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded-r;
}

You can configure HTML classes used by UI:

const classes = {
  zoomIn: "zoom-in",
  reset: "reset",
  zoomOut: "zoom-out",
  buttons: "buttons",
  tsWarning: "touchscreen-warning",
  tsWarningActive: "active",
};

new PanZoomUi({ element, container, classes });

and message with instructions for the touchscreen:

const message = "Use two fingers to pan and zoom";

new PanZoomUi({ element, container, message });

Pixelation in Safari

Be aware that some CSS will cause pixelation of SVG on zoom (bug in Safari), for example:

  • will-change: transform;
  • transform: matrix3d(...);
  • transition-property: transform; (it setles after animation, though)

Alternatives

There are a lot of solutions for this task:

Logo

spread by Tomas Knopp from Noun Project (CC BY 3.0)

0.0.3

1 month ago