Zoom the image or other thing with mouse or touch using vue.js

In modern web applications, providing an interactive and immersive user experience is crucial. One way to achieve this is by incorporating features like image zooming. In this comprehensive guide, we’ll explore how to implement image zoom functionality using Vue.js. This interactive component will allow users to zoom in and out of images seamlessly, enhancing the overall user experience.

Setting Up the Vue Project:

Start by creating a new Vue project using the Vue CLI. If you haven’t installed it, run:

npm install -g @vue/cli
vue create vue-image-zoom
cd vue-image-zoom

Designing the ZoomableImage Component:

  1. Create a ZoomableImage.vue component:
<template>
  <div class="zoom-container" @wheel.prevent="handleZoom">
    <img
      ref="image"
      :src="imageSrc"
      :style="{ transform: `scale(${zoomScale})`, transformOrigin: zoomOrigin }"
      @mousedown="startDrag"
      @mousemove="handleDrag"
      @mouseup="stopDrag"
      @touchstart="startTouch"
      @touchmove="handleTouch"
      @touchend="stopTouch"
    />
  </div>
</template>

<script>
export default {
  props: {
    imageSrc: String, // Image source URL
    maxZoom: {
      type: Number,
      default: 2,
    },
    minZoom: {
      type: Number,
      default: 0.5,
    },
  },
  data() {
    return {
      zoomScale: 1,
      isDragging: false,
      dragStart: { x: 0, y: 0 },
      dragOffset: { x: 0, y: 0 },
      touchStart: { x: 0, y: 0 },
      touchOffset: { x: 0, y: 0 },
      zoomOrigin: '50% 50%',
    };
  },
  methods: {
    handleZoom(event) {
      // Handle mouse wheel zooming
      const delta = event.deltaY > 0 ? -0.1 : 0.1;
      this.updateZoom(delta);
    },
    startDrag(event) {
      // Start dragging the image
      this.isDragging = true;
      this.dragStart = { x: event.clientX, y: event.clientY };
    },
    handleDrag(event) {
      // Handle dragging the image
      if (this.isDragging) {
        const deltaX = event.clientX - this.dragStart.x;
        const deltaY = event.clientY - this.dragStart.y;
        this.dragOffset = { x: deltaX, y: deltaY };
        this.updateZoom(0);
      }
    },
    stopDrag() {
      // Stop dragging the image
      this.isDragging = false;
      this.dragOffset = { x: 0, y: 0 };
    },
    startTouch(event) {
      // Start touching the image
      this.touchStart = { x: event.touches[0].clientX, y: event.touches[0].clientY };
    },
    handleTouch(event) {
      // Handle touching the image
      const touchDeltaX = event.touches[0].clientX - this.touchStart.x;
      const touchDeltaY = event.touches[0].clientY - this.touchStart.y;
      this.touchOffset = { x: touchDeltaX, y: touchDeltaY };
      this.updateZoom(0);
    },
    stopTouch() {
      // Stop touching the image
      this.touchOffset = { x: 0, y: 0 };
    },
    updateZoom(delta) {
      // Update the zoom scale and origin
      this.zoomScale = Math.min(
        Math.max(this.zoomScale + delta, this.minZoom),
        this.maxZoom
      );
      this.zoomOrigin = `${50 - this.touchOffset.x / 10}% ${50 - this.touchOffset.y / 10}%`;
    },
  },
};
</script>

<style scoped>
.zoom-container {
  overflow: hidden;
  width: 100%;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

img {
  user-drag: none;
  user-select: none;
  max-width: 100%;
  max-height: 100%;
  cursor: grab;
}
</style>

Using the ZoomableImage Component in App.vue:

  1. Update the App.vue component:
<template>
  <div id="app">
    <ZoomableImage
      imageSrc="https://placekitten.com/800/600" <!-- Example image URL -->
      :maxZoom="3"
      :minZoom="0.5"
    />
  </div>
</template>

<script>
import ZoomableImage from './components/ZoomableImage.vue';

export default {
  components: {
    ZoomableImage,
  },
};
</script>

<style>
#app {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: #ecf0f1;
  margin: 0;
}
</style>

Explanation of the ZoomableImage Component:

  1. The ZoomableImage.vue component utilizes mouse and touch events to enable zooming and dragging of the image.
  2. The handleZoom method is triggered by the mouse wheel, adjusting the zoom scale accordingly.
  3. The startDrag, handleDrag, and stopDrag methods handle mouse dragging, updating the image’s position during dragging.
  4. The startTouch, handleTouch, and stopTouch methods manage touch events for mobile devices.
  5. The updateZoom method adjusts the zoom scale and origin based on user interaction.

Running the Application:

Run the following commands to see the image zoom component in action:

npm install
npm run serve

Visit http://localhost:8080 in your browser to interact with the Vue.js image zoom component.

You can implement Zoom the image or other thing with mouse or touch using Vue.js

vue-zoomer

Zoom the image or other thing with mouse or touch

For Vue 3

This library has released a Vue 3 beta version here.

Usage

Install:

npm install vue-zoomer

Import:

import Vue from 'vue'
import VueZoomer from 'vue-zoomer'

Vue.use(VueZoomer)

Single usage:

<v-zoomer style="width: 500px; height: 500px; border: solid 1px silver;">
  <img
    src="./assets/landscape-1.jpg"
    style="object-fit: contain; width: 100%; height: 100%;"
  >
</v-zoomer>

Gallery usage:

<v-zoomer-gallery
  style="width: 100vw; height: 100vh;"
  :list="['a.jpg', 'b.jpg', 'c.jpg']"
  v-model="selIndex"
></v-zoomer-gallery>

API

<v-zoomer> Props

  • maxScale: number – Maximum scale limit, default is 5;
  • minScale: number – Minimum scale limit, default is 1;
  • zoomed: out boolean – Whether zoomed in (scale equals to 1). out means the prop is a child to parent one-way binding. So there must have a .sync modifier.
  • pivot: 'cursor' | 'image-center' – The pivot when zoom the content, default is cursor, can set to be image-center;
  • zoomingElastic: boolean – Whether to use the elastic effect when reaching the max/min zooming bounds, default is true;
  • limitTranslation: boolean – Whether to limit the content into the container, default is true;
  • doubleClickToZoom: boolean – Whether to zoom in/out the content by double click, default is true;
  • mouseWheelToZoom: boolean – Whether to zoom in/out the content by mouse wheel, default is true;

<v-zoomer> Methods

  • reset() – Reset the scale and translate to the initial state.
  • zoomIn(scale=2) – Zoom in.
  • zoomOut(scale=0.5) – Zoom out.

<v-zoomer-gallery> Props

  • list: Array<string> required – Displaying image urls;
  • v-model(value): number required – Index of current showing image;
  • pivot: 'cursor' | 'image-center' – Same as above;
  • zoomingElastic: boolean – Same as above;
  • limitTranslation: boolean – Same as above;
  • doubleClickToZoom: boolean – Same as above;
  • mouseWheelToZoom: boolean – Same as above;

<v-zoomer-gallery> Methods

  • reset() – Reset the scale and translate to the initial state.
  • zoomIn(scale=2) – Zoom in.
  • zoomOut(scale=0.5) – Zoom out.

Leave a Comment