0.0.2 • Published 2 months ago

svg-pan-zoom-gesture v0.0.2

Weekly downloads
-
License
MIT
Repository
-
Last release
2 months ago

svg-pan-zoom-gesture

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

Netlify Status

svg-pan-zoom demo

Usage

There are two flavors:

  • Headless - without UI
  • Default UI

Headless

If you have container element in HTML:

import { SvgPanZoom } from "svg-pan-zoom-gesture";

document.querySelectorAll(".svg-pan-zoom").forEach((container) => {
  const element = container.querySelector("svg,img");
  if (!element) return;
  new SvgPanZoom({ element, container }).on();
});

If you don't have container element in HTML:

import { SvgPanZoom } from "svg-pan-zoom-gesture";

document.querySelectorAll("svg").forEach((element) => {
  const container = document.createElement("div");
  container.className = "svg-pan-zoom";
  element.replaceWith(container);
  container.append(element);
  new SvgPanZoom({ element, container }).on();
});

Additionally following CSS is required:

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

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

.svg-pan-zoom 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 "svg-pan-zoom-gesture/css/SvgPanZoomUi.css";
import { SvgPanZoomUi } from "svg-pan-zoom-gesture";

document.querySelectorAll(".svg-pan-zoom").forEach((container) => {
  const element = container.querySelector("svg,img");
  if (!element) return;
  new SvgPanZoomUi({ element, container }).on();
});

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

.svg-pan-zoom .buttons {
  @apply inline-flex;
}
.svg-pan-zoom .zoom-in {
  @apply bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded-l;
}
.svg-pan-zoom .reset {
  @apply bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4;
}
.svg-pan-zoom .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 SvgPanZoomUi({ element, container, classes });

and message with instructions for the touchscreen:

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

new SvgPanZoomUi({ 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:

0.0.2

2 months ago

0.0.1

2 months ago