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

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 GitHub via 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 id="app">
    <!-- directive -->
    <div class="images" v-viewer>
      <img src="1.jpg">
      <img src="2.jpg">
      ...
    </div>
    <!-- component -->
    <viewer :images="images">
      <img v-for="src in images" :src="src" :key="src">
    </viewer>
  </div>
</template>
<script>
  import 'viewerjs/dist/viewer.css'
  import Viewer from 'v-viewer'
  import Vue from 'vue'
  Vue.use(Viewer)
  export default {
    data() {
      images: ['1.jpg', '2.jpg']
    }
  }
</script>

Support UMD

Browser

<link href="//path/viewer.css" rel="stylesheet">
<script src="//path/vue.js"></script>
<script src="//path/viewer.js"></script>
<script src="//path/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 id="app">
    <div class="images" v-viewer="{movable: false}">
      <img v-for="src in images" :src="src" :key="src">
    </div>
    <button type="button" @click="show">Show</button>
  </div>
</template>
<script>
  import 'viewerjs/dist/viewer.css'
  import Viewer from 'v-viewer'
  import Vue from 'vue'
  Vue.use(Viewer)
  export default {
    data() {
      images: ['1.jpg', '2.jpg']
    },
    methods: {
      show () {
        const viewer = this.$el.querySelector('.images').$viewer
        viewer.show()
      }
    }
  }
</script>

Direcitve 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 id="app">
    <viewer :options="options" :images="images"
            @inited="inited"
            class="viewer" ref="viewer"
    >
      <template slot-scope="scope">
        <img v-for="src in scope.images" :src="src" :key="src">
        {{scope.options}}
      </template>
    </viewer>
    <button type="button" @click="show">Show</button>
  </div>
</template>
<script>
  import 'viewerjs/dist/viewer.css'
  import Viewer from "v-viewer/src/component.vue"
  export default {
    components: {
      Viewer
    },
    data() {
      images: ['1.jpg', '2.jpg']
    },
    methods: {
      inited (viewer) {
        this.$viewer = viewer
      },
      show () {
        this.$viewer.show()
      }
    }
  }
</script>

Component props

images
  • Type: Array
trigger
  • Type: Array

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
  • Type: Boolean
  • Default: false

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 slot-scope="scope">
    <img v-for="src in scope.images" :src="src" :key="src">
    {{scope.options}}
  </template>
</viewer>

Component events

inited
  • viewer: Viewer

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

Options & Methods of Viewer

Refer to viewer.js.

Plugin options

name

  • Type: String
  • Default: viewer

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

<template>
  <div id="app">
    <div class="images" v-vuer="{movable: false}">
      <img v-for="src in images" :src="src" :key="src">
    </div>
    <button type="button" @click="show">Show</button>
  </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() {
      images: ['1.jpg', '2.jpg']
    },
    methods: {
      show () {
        const vuer = this.$el.querySelector('.images').$vuer
        vuer.show()
      }
    }
  }
</script>

defaultOptions

  • Type: Object
  • Default: undefined

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

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

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

import Viewer from 'v-viewer'
import Vue from 'vue'
Vue.use(Viewer)
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)
:camera: Responsive and customizable image and video gallery, carousel and lightbox, optimized for both mobile and desktop web browsers.

vue-gallery ?? VueJS responsive and customizable image and video gallery, carousel and lightbox, optimized for both mobile and desktop web browsers. E

Igor Ognichenko 433 Nov 26, 2022
A Vue component to display an image gallery lightbox

vue-image-lightbox A simple image/video lightbox component for Vuejs NPM Package I use CSS style from react-images Demo! Development (NPM / Yarn) npm

Dũng Nguyễn Thiện 322 Jan 5, 2023
A simple image / (YouTube) video lightbox component for Vue.js.

Vue It Bigger! A simple image / (YouTube) video lightbox component for Vue.js. Based on vue-image-lightbox. Click on the screenshot above for a demo.

 haiafara.ro 182 Dec 28, 2022
🖼 Lightweight and responsive image gallery for Vue.js

vue-gallery-slideshow Lightweight and responsive image gallery for Vue.js. Live Demo https://jsfiddle.net/headione/szk73x45/show/ Installation By CDN

null 168 Dec 24, 2022
A light vue dialog plugin with loading animation and image preview

vue-dialog-loading A light vue dialog plugin with loading animation and image preview View the Demo and its source for more. Install npm install --sav

lisper 9 Sep 23, 2021
A vue plugin that can help you display image in correct orientation.

Vue Img Orientation Changer English | 简体中文 A vue directive that fixes your jpeg jpg tiff files orientation. TIPS: This can really help you stay away f

Li Wenyan 38 Aug 23, 2022
v-img - Easy to install image gallery.

v-img is a plugin for Vue.js that allows you to show images in full-screen gallery by adding only one directive to the <img> tag. Demonstration page B

Crowdbotics Corporation 419 Dec 28, 2022
Vue-modally - a component based vue modal library

vue-modally is a component based vue modal library, in a simpler term, it lets you use any vue component as asynchronous/synchronous modal programmatically

Sulaiman Adewale 3 Jul 3, 2022
A simple Vue.js component for fullscreen, based on screenfull.js

A simple Vue.js component for fullscreen, based on screenfull.js

mirari 404 Dec 17, 2022
A Vue.js popover component based on PopperJS

A Vue.js popover component based on PopperJS

Valgeir Björnsson 168 Dec 23, 2022
A lightweight, promise based alert, prompt and confirm dialog

Vuejs Dialog Plugin A lightweight, promise based alert, prompt and confirm dialog. Demo https://godofbrowser.github.io/vuejs-dialog/ Important updates

Emeke Ajeh 352 Dec 14, 2022
Backend management system based on 2.6+ with Ts

Vue2.6-Typescript Backend management system based on Vue2.6+ with Ts Project setup yarn install Compiles and hot-reloads for development yarn serve

阿威十八式 0 Feb 27, 2022
Vuetify Dialog Loader Component (with SnackBar) component that can be used locally or globally

VuetifyDialogLoader Vuetify Dialog Loader Component (with SnackBar) component that can be used locally or globally This component use the Vuetify Dial

Myles McNamara 8 Feb 23, 2021
Simple and intuitive, highly customizable modal component for Vue.js.

Transform Vue.js 2.0+ component into modal with powerful layout and transition support

Yuqiao Chen 9 Nov 15, 2022
A simple and lightweight Vue (v2) modal component.

@burhanahmeed/vue-modal-2 A simple and lightweight Vue modal component for Vue 2.x. Documentation Docs: https://initbase.github.io/vue-modal-2/ Demo d

Initbase Labs 6 Dec 4, 2022
Pixabay-gallery-in-vue-and-buefy - A gallery application in Vue and Buefy which uses pixabay API

PixaBay Gallery in Vue and Buefy Project Briefing This is a carousel based galle

Lightning Bolt 2 Aug 17, 2022
A simple and clean instructional dialog plugin for Vue2, dialog type including Modal, Alert, Mask and Toast

v-dialogs · A simple and clean instructional dialog plugin for Vue2, dialog type including Modal, Alert, Mask and Toast Examples and Documentation Exp

Terry Zeng 126 Sep 25, 2022
vue-ya-semantic-modal - Yet another semantic-ui modal component for Vue2 without Jquery but with Vue transition

vue-ya-semantic-modal Yet another semantic-ui modal component for Vue2 without Jquery but with pure Vue transition This component only provide a frame

null 20 Jan 20, 2022
🍕Vue Final Modal is a tiny, renderless, mobile-friendly, feature-rich modal component for Vue.js.

Vue Final Modal Looking for a Vue 3 version? It's over here ?? Documentation ?? Examples Introduction Vue Final Modal is a renderless component! You c

Vue Final 521 Dec 30, 2022