Image viewer component for vue, supports rotation, scale, zoom and so on, based on viewer.js

Overview

v-viewer

Image viewer component for vue, supports rotation, scale, zoom and so on, based on viewer.js

npm version language

npm version language

npm download license

v-viewer for vue3

Live demo

Examples

中文文档

Migration from 0.x

  • The only change you have to make is to manually import the .css file:
import 'viewerjs/dist/viewer.css'

Installation

Install from NPM

npm install v-viewer

Usage

To use v-viewer, simply import it and the css file, and call Vue.use() to install.

">
<template>
  <div>
    
    <div class="images" v-viewer>
      <img v-for="src in images" :key="src" :src="src">
    div>
    
    <viewer :images="images">
      <img v-for="src in images" :key="src" :src="src">
    viewer>
    
    <button type="button" @click="show">Click to showbutton>
  div>
template>
<script>
  import 'viewerjs/dist/viewer.css'
  import VueViewer from 'v-viewer'
  import Vue from 'vue'
  Vue.use(VueViewer)
  export default {
    data() {
      return {
        images: [
          "https://picsum.photos/200/200",
          "https://picsum.photos/300/200",
          "https://picsum.photos/250/200"
        ]
      };
    },
    methods: {
      show() {
        this.$viewerApi({
          images: this.images,
        })
      },
    },
  }
script>

Support UMD

Browser

">
<link href="//unpkg.com/viewerjs/dist/viewer.css" rel="stylesheet">
<script src="//unpkg.com/vue/dist/vue.js">script>
<script src="//unpkg.com/viewerjs/dist/viewer.js">script>
<script src="//unpkg.com/v-viewer/dist/v-viewer.js">script>
<script>
  Vue.use(VueViewer.default)
script>

CommonJS

var VueViewer = require('VueViewer')

AMD

require(['VueViewer'], function (VueViewer) {});

Usage of directive

Just add the directive v-viewer to any element, then all img elements in it will be handled by viewer.

You can set the options like this: v-viewer="{inline: true}"

Get the element by selector and then use el.$viewer to get the viewer instance if you need.

">
<template>
  <div>
    <div class="images" v-viewer="{movable: false}">
      <img v-for="src in images" :src="src" :key="src">
    div>
    <button type="button" @click="show">Showbutton>
  div>
template>
<script>
  import 'viewerjs/dist/viewer.css'
  import VueViewer from 'v-viewer'
  import Vue from 'vue'
  Vue.use(VueViewer)
  export default {
    data() {
      return {
        images: [
          "https://picsum.photos/200/200",
          "https://picsum.photos/300/200",
          "https://picsum.photos/250/200"
        ]
      };
    },
    methods: {
      show () {
        const viewer = this.$el.querySelector('.images').$viewer
        viewer.show()
      }
    }
  }
script>

Directive modifiers

static

The viewer instance will be created only once after the directive binded.

If you're sure the images inside this element won't change again, use it to avoid unnecessary re-render.

">
<div class="images" v-viewer.static="{inline: true}">
  <img v-for="src in images" :src="src" :key="src">
div>
rebuild

The viewer instance will be updated by update method when the source images changed (added, removed or sorted) by default.

If you encounter any display problems, try rebuilding instead of updating.

">
<div class="images" v-viewer.rebuild="{inline: true}">
  <img v-for="src in images" :src="src" :key="src">
div>

Usage of component

You can simply import the component and register it locally too.

Use scoped slot to customize the presentation of your images.

">
<template>
  <div>
    <viewer :options="options" :images="images"
            @inited="inited"
            class="viewer" ref="viewer"
    >
      <template #default="scope">
        <img v-for="src in scope.images" :src="src" :key="src">
        {{scope.options}}
      template>
    viewer>
    <button type="button" @click="show">Showbutton>
  div>
template>
<script>
  import 'viewerjs/dist/viewer.css'
  import Viewer from "v-viewer/src/component.vue"
  export default {
    components: {
      Viewer
    },
    data() {
      return {
        images: [
          "https://picsum.photos/200/200",
          "https://picsum.photos/300/200",
          "https://picsum.photos/250/200"
        ]
      };
    },
    methods: {
      inited (viewer) {
        this.$viewer = viewer
      },
      show () {
        this.$viewer.show()
      }
    }
  }
script>

Component props

images
trigger

You can replace images with trigger, to accept any type of prop. when the trigger changes, the component will re-render the viewer.

">
<viewer :trigger="externallyGeneratedHtmlWithImages">
  <div v-html="externallyGeneratedHtmlWithImages"/>
viewer>
rebuild

The viewer instance will be updated by update method when the source images changed (added, removed or sorted) by default.

If you encounter any display problems, try rebuilding instead of updating.

">
<viewer
  ref="viewer"
  :options="options"
  :images="images"
  rebuild
  class="viewer"
  @inited="inited"
>
  <template #default="scope">
    <img v-for="src in scope.images" :src="src" :key="src">
    {{scope.options}}
  template>
viewer>

Component events

inited

Listen for the inited event to get the viewer instance, or use this.refs.xxx.$viewer.

Usage of api

Only available in modal mode.

You can call the function: this.$viewerApi({options: {}, images: []}) to show gallery without rendering the img elements yourself.

The function returns the current viewer instance.

URL Array
">
<template>
  <div>
    <button type="button" class="button" @click="previewURL">URL Arraybutton>
    <button type="button" class="button" @click="previewImgObject">Img-Object Arraybutton>
  div>
template>
<script>
  import 'viewerjs/dist/viewer.css'
  import { api as viewerApi } from "v-viewer"
  export default {
    data() {
      sourceImageURLs: [
        'https://picsum.photos/200/200?random=1',
        'https://picsum.photos/200/200?random=2',
      ],
      sourceImageObjects: [
        {
          'src':'https://picsum.photos/200/200?random=3',
          'data-source':'https://picsum.photos/800/800?random=3'
        },
        {
          'src':'https://picsum.photos/200/200?random=4',
          'data-source':'https://picsum.photos/800/800?random=4'
        }
      ]
    },
    methods: {
      previewURL () {
        // If you use the `app.use` full installation, you can use `this.$viewerApi` directly like this
        const $viewer = this.$viewerApi({
          images: this.sourceImageURLs
        })
      },
      previewImgObject () {
        // Or you can just import the api method and call it.
        const $viewer = viewerApi({
          options: {
            toolbar: true,
            url: 'data-source',
            initialViewIndex: 1
          },
          images: this.sourceImageObjects
        })
      }
    }
  }
script>

Options & Methods of Viewer

Refer to viewer.js.

Plugin options

name

If you need to avoid name conflict, you can import it like this:

">
<template>
  <div>
    
    <div class="images" v-vuer="{movable: false}">
      <img v-for="src in images" :src="src" :key="src">
    div>
    <button type="button" @click="show">Showbutton>
    
    <vuer :images="images">
      <img v-for="src in images" :src="src" :key="src">
    vuer>
  div>
template>
<script>
  import 'viewerjs/dist/viewer.css'
  import Vuer from 'v-viewer'
  import Vue from 'vue'
  Vue.use(Vuer, {name: 'vuer'})
  export default {
    data() {
      return {
        images: [
          "https://picsum.photos/200/200",
          "https://picsum.photos/300/200",
          "https://picsum.photos/250/200"
        ]
      };
    },
    methods: {
      show () {
        // viewerjs instance name
        const vuer = this.$el.querySelector('.images').$vuer
        vuer.show()
        // api name
        this.$vuerApi({
          images: this.images
        })
      }
    }
  }
script>

defaultOptions

If you need to set the viewer default options, you can import it like this:

import VueViewer from 'v-viewer'
import Vue from 'vue'
Vue.use(VueViewer, {
  defaultOptions: {
    zIndex: 9999
  }
})

And you can reset the default options at any other time:

import VueViewer from 'v-viewer'
import Vue from 'vue'
Vue.use(VueViewer)
Viewer.setDefaults({
  zIndexInline: 2017
})
Comments
  • Component method not working!

    Component method not working!

    <viewer :images="this.awardData.files">
              <img v-for="src in this.awardData.files" :src="'src'" :key="src">
            </viewer>
    

    Hey, above is my code. I tried using component method. But nothing is shown in the browser.

    Is that I should use directive method also or any of the methods(component, directives) is fine?

    opened by harishankards 9
  • 作者你好, 在项目中使用v-viewer遇到问题无法解决(附在线BUG复现链接)。

    作者你好, 在项目中使用v-viewer遇到问题无法解决(附在线BUG复现链接)。

    给viewer设置容器, 并在容器外放置一个兄弟元素。 兄弟元素显示内容为vue data中的数据初始值为空对象。 在viewed()方法中获取图片数据对数据赋值时viewer预览图像发生了闪退, 浏览器中的元素也消失了。 附在线链接https://codepen.io/aohongjie/pen/vYdRdaJ

    opened by AoHongJie 8
  • How to handle when an image is unavailable?

    How to handle when an image is unavailable?

    I am finding then if my gallery a single image that is unavailable (due to 403 or 404 error when the browser attempts to load it), the entire viewer will not function.

    Is this intentional? Is there a way to handle these errors gracefully so the viewer will still work for the other images?

    I am using viewer with the inline option and it simply never appears if there is an error loading one out of 200 images.

    opened by flyingL123 8
  • Remove unused 'images' attribute

    Remove unused 'images' attribute

    Currently, <viewer> component takes the non-optional images attribute but then does nothing good with it (in particular, it does not render images from it). This is not only useless but deceitful.

    For example:

      <viewer :images="images">
        <!-- images is ignored! -->
        <img src="https://picsum.photos/200/200">
        <img src="https://picsum.photos/300/200">
        <img src="https://picsum.photos/250/200">
      </viewer>
    

    Whatever is passed to images is not used, although it is required to pass an Array value there.

    images will be passed as a slot scope argument however this serves no purpose either, because the slot code has direct access to containing component data, for example:

    <template>
      <viewer>
        <slot>
          <!-- no need to pull images from slot scope, it is already available: -->
          <img v-for="image in images" :src="image">
        </slot>
      </viewer>
    </template>
    
    <script>
    export default {
      data () {
        return {
          images: [ ... ]
        }
      }
    }
    </script>
    

    Codepen demonstrating both problems: https://codepen.io/ilya-semenov/pen/KRKXLv

    This PR removes image attribute. It also replaces scope with slot-scope in the example, as the former is deprecated in Vue 2.5.

    opened by IlyaSemenov 8
  • 使用 Vite + Vue3 + Ts 重构,新加 API 调用方式。

    使用 Vite + Vue3 + Ts 重构,新加 API 调用方式。

    你好,感谢作者提供的插件之前我也一直在使用。

    周末准备用 Vue3 重构的此项目,重构完之后发现您已在 cli3 分支开发(还以为是脚手架呢,就没注意)。本来不打算写了,我看了您的实现方式思路和我不太一样,觉得可以讨论一下比较好的方案。

    完整的代码地址

    https://github.com/haiweilian/v-viewer/tree/next

    删除指令的功能

    我不太清楚作者之前是什么原因添加指令功能的,使用指令监听子元素的变化的方式会造成很多意外的问题,我也没再使用。在现在的版本有些不方便的是,不能自定义标签名、或者有时造成多余的层级嵌套、没有 API 调用的方式。

    我想有其他的办法可以解决,比如指令使用 v-is,它也会保留原始标签的属性。

    <section v-is="'viewer'" :images="reactiveImages.asyncImages">
      <img v-for="item of reactiveImages.asyncImages" :key="item" :src="item" width="200" height="200" />
    </section>
    

    组件使用函数

    使用 render 函数,控制标签的标签名添加 tag 属性实现、还比较容易扩展。

    return () =>
      h(props.tag, { ref: $root }, slots.default && slots.default({ ...props })
    );
    

    这将渲染 section 标签。

    <viewer tag="section">
      <img v-for="item of reactiveImages.syncImages" :key="item" :src="item" width="200" height="200" />
    </viewer>
    

    API 调用的方式

    使用 API 的方式,会很方便的处理某些问题,比如点击一个按钮然后预览图片,之前使用图片隐藏的方式太过麻烦也不太优雅。

    期望调用方式如下,然后返回组件实例。

    viewerInstance = ViewerPreview({
      images: Images,
      options: Options,
    });
    
    nextTick(() => {
      viewerInstance.$viewer().view(1);
    });
    

    render 函数去渲染 component 组件,再返回组件实例。

    function ViewerPreview(options: ViewerPreviewOptions) {
      // ....
      const vm = h(
        ViewerComponent,
        options,
        options.images.map((src) => {
          return typeof src === "string"
            ? h("img", { src })
            : h("img", { src: src.src });
        })
      );
      // ...
    }
    

    整体的方案

    我还没有做过多的测试,或者是否有其他更好的方式去实现。如果觉得可行,我将提交一个新分支。

    opened by haiweilian 6
  • 请问vue3项目里使用的时候报错,是不能在vue3里使用吗

    请问vue3项目里使用的时候报错,是不能在vue3里使用吗

    Uncaught (in promise) TypeError: Cannot read property '_c' of undefined at Proxy.render (v-viewer.js?6944:583) at renderComponentRoot (runtime-core.esm-bundler.js?5c40:732) at componentEffect (runtime-core.esm-bundler.js?5c40:4225) at reactiveEffect (reactivity.esm-bundler.js?a1e9:42) at effect (reactivity.esm-bundler.js?a1e9:17) at setupRenderEffect (runtime-core.esm-bundler.js?5c40:4208) at mountComponent (runtime-core.esm-bundler.js?5c40:4167) at processComponent (runtime-core.esm-bundler.js?5c40:4127) at patch (runtime-core.esm-bundler.js?5c40:3745) at mountChildren (runtime-core.esm-bundler.js?5c40:3927)

    • [ ]
    opened by shikunping 5
  • 您好,请问一下为什么我按指令方式调用后,能打开图片了,但下边的ToolBar却只有一张图片,不是全部呢?

    您好,请问一下为什么我按指令方式调用后,能打开图片了,但下边的ToolBar却只有一张图片,不是全部呢?

    export default { directives: { viewer: viewer({ debug: true, }), }, options: { toolbar: true, images: this.images, movable: false } }
    opened by visatest 1
  • 编译后出现 Uncaught SyntaxError: Unexpected token '...'

    编译后出现 Uncaught SyntaxError: Unexpected token '...'

    esbuild 中配置了 pure, 移除了所有 console.log 后, 会出现错误信息:

    Uncaught SyntaxError: Unexpected token '...'
    

    找到原因,是因为这个文件 https://github.com/mirari/v-viewer/blob/v3/src/directive.ts 98行 log 方法里 console.log(...args), 被 esbuild 去除了 console.log 后, 代码变成了:

    debug && ...args
    

    有什么办法能解决这个问题呢?

    opened by cnhuye 5
Releases(v1.6.4)
Image viewer component for vue 3.x, supports rotation, scale, zoom and so on, based on viewer.js

v-viewer Image viewer component for vue, supports rotation, scale, zoom and so on, based on viewer.js v-viewer for vue2 Live demo Quick Example direct

mirari 14 Oct 29, 2022
A Vue.js 3.0 image lightbox component with Zoom / Drag / Rotate / Switch .

A Vue.js 3.0 image lightbox component with Zoom / Drag / Rotate / Switch .

XiongAmao 272 Jan 3, 2023
Lightweight responsive image zoom component for Vue.js 2

Vue Image Zoomer Lightweight responsive image zoom component for Vue.js 2, that also works on touch devices. Perfect for zooming on product images on

Sam Jones 40 Dec 24, 2022
🔍 Vue image zoom component

vue-magnifier This is a Vue 3 adaptation of react-magnifier, which is the original version. Someone else made a Svelte version, called svelte-magnifie

Website Beaver 3 Aug 9, 2022
Vue Prettybox - a tool dependency that allows you to open or zoom image just by click it

Vue Prettybox - a tool dependency that allows you to open or zoom image just by click it. It helps you to view the image to have a better look of it without making zoom in on your browser.

Israel De Castro A. 2 Aug 7, 2022
Image comparison slider. Compare images before and after. Supports React, Vue, Angular.

Image comparison slider. Compare images before and after. Supports React, Vue, Angular.

Dmitry Snisarenko 267 Dec 18, 2022
Vue-cool-lightbox is a pretty Vue.js lightbox component, inspired by fancybox with zoom, swipe, captions and videos supported

Vue-cool-lightbox is a pretty Vue.js lightbox component, inspired by fancybox with zoom, swipe, captions and videos supported.

Lucas Pulliese 327 Jan 1, 2023
vue zoom component

vue zoom component

Alexander Vysotsky 2 Oct 11, 2021
An Mobile-First image viewer for Vue2 / 一个移动端优先的 Vue2 图片预览插件

img-vuer An Mobile-First image viewer for Vue2 中文 README ??‍♀️ Easy to use ?? Swipe gesture ?? Zoom gesture V0.11.0 Now you can use thumbnail~ V0.13.0

DJJo 260 Sep 20, 2022
JavaScript image viewer.

Viewer.js JavaScript image viewer. Website jquery-viewer - A jQuery plugin wrapper for Viewer.js. Table of contents Features Main Getting started Keyb

Fengyuan Chen 6.9k Jan 5, 2023
KéMeet is a Simple, beautiful, fast and secured Open-source zoom alternative, 100% FREE forever!

KéMeet is a Simple, beautiful, fast and secured Open-source zoom alternative, 100% FREE forever! Simply enter a meeting room ID and connect to anyone else in that room! You can even share your screen if you are on desktop!

fotiecodes 31 Jul 6, 2022
A Vue component for showing loader during image loading https://john015.github.io/vue-load-image/

English | 한국어 Vue-load-image Vue-load-image is 1KB(gzipped size) minimalist Vue component that display loader during image loading and display alterna

Sangwon Lee 60 Dec 7, 2022
🌈 A Vue image component. Simple realization of image shadow.

?? vue-image-shadow A Vue image component. Simple realization of image shadow. ?? Example Online: https://image-component.github.io/vue-image-shadow/

null 21 Aug 13, 2022
vue-image-markup will provide you to edit uploaded image easily and save it.

Markup Image with Vue.js (customizable) vue-image-markup will provide you to edit uploaded image easily and save it. Installation npm i vue-image-mark

Lionix 92 Dec 9, 2022
Build a web-based 3D viewer workshop

This repo is a part of the "Build a web-based 3D viewer workshop" conducted as part of AECTech2021. The workshop walks participants through the proces

CORE studio 19 Jun 7, 2022
Vue-image-loader: image loader for vue js with prevue

Vue-image-loader: image loader for vue js with prevue

null 0 Feb 1, 2020
A Directive for setting fall back image in a vue js application if in case image is not loaded

vue-fall-back-image-directive A Directive for setting fall back image in a vue js application. Installation npm install Run npm install --save vue-fal

Arun sivan 1 Oct 15, 2019
A Simple and Beautiful 360° Product Viewer built on Vue.js

vue-360 A Simple and Beautiful 360° Product Viewer built on Vue.js Click here for React Version Demo Demo | Documentation Features 360° View Zoom Pan

Rajeev 88 Dec 5, 2022
Millicast viewer plugin for Vue framework. It uses Vuex store for the plugin state management.

Millicast Vue.js Web Viewer Plugin Vue.js plugin to embed viewer of a Millicast stream. This plugin allows developers to simplify Millicast services i

Millicast, Inc. 3 Oct 18, 2022