├── .browserslistrc ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── babel.config.js ├── build └── rollup.config.js ├── dist ├── vue-panzoom.esm.js ├── vue-panzoom.min.js └── vue-panzoom.umd.js ├── package-lock.json ├── package.json ├── postcss.config.js ├── src ├── components │ └── pan-zoom │ │ ├── component.vue │ │ ├── script.js │ │ └── template.html └── main.js └── vue.config.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not ie <= 8 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | public 4 | dist/*.gz 5 | dist/*.map 6 | coverage 7 | docs/.vuepress/dist 8 | 9 | # local env files 10 | .env.local 11 | .env.*.local 12 | 13 | # related test files 14 | /tests/e2e/reports 15 | /tests/e2e/videos 16 | /tests/e2e/screenshots 17 | 18 | # editor directories and files 19 | .idea 20 | .vscode 21 | *.suo 22 | *.ntvs* 23 | *.njsproj 24 | *.sln 25 | *.sw* 26 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | // TODO: release log here ... 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Isa Frimpong <mistabiggx@gmail.com> 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-panzoom 2 | 3 | This is a [Vue.js](https://vuejs.org/) port of [panzoom](https://github.com/anvaka/panzoom), an extensible, mobile friendly pan and zoom framework (supports DOM and SVG). 4 | 5 | # Demo 6 | 7 | * [Regular DOM object](https://anvaka.github.io/panzoom/demo/dom.html) 8 | * [Standalone page](https://anvaka.github.io/panzoom/demo/index.html) - this repository 9 | * [YASIV](http://www.yasiv.com/#/Search?q=algorithms&category=Books&lang=US) - my hobby project 10 | * [SVG Tiger](https://jsfiddle.net/uwxcmbyg/609/) - js fiddle 11 | 12 | # Installation 13 | 14 | Using npm 15 | 16 | ``` 17 | npm install vue-panzoom --save 18 | ``` 19 | 20 | Using yarn 21 | 22 | ``` 23 | yarn add vue-panzoom 24 | ``` 25 | 26 | # Usage 27 | 28 | *main.js* 29 | ``` js 30 | // import Vuejs 31 | import Vue from 'vue' 32 | import App from './App.vue' 33 | 34 | // import vue-panzoom 35 | import panZoom from 'vue-panzoom' 36 | 37 | // install plugin 38 | Vue.use(panZoom); 39 | 40 | new Vue({ 41 | render: h => h(App), 42 | }).$mount('#app') 43 | ``` 44 | 45 | *App.vue* 46 | ``` html 47 | 69 | ``` 70 | 71 | ## Changing the component's name 72 | 73 | If you wish to change the name of the vue component from the default panZoom, you pass an option to the plugin like so: 74 | ``` js 75 | Vue.use(panZoom, {componentName: 'yourPanZoom'}); 76 | ``` 77 | 78 | and then use in your vue template like so: 79 | ``` html 80 | 81 | ``` 82 | 83 | # Attributes 84 | ### selector 85 | Use this to specify an element within the scope of vue-panzoom component instance, to apply panZoom to. Default is the first root element of the vue-panzoom component. It accepts standard css selector specification. 86 | ``` html 87 | 88 |
I cannot be zoomed and panned
89 |
I can be zoomed and panned
90 |
91 | ``` 92 | 93 | # Options 94 | The *options* prop is used to define [panzoom](https://github.com/anvaka/panzoom) options. All panzoom options are supported 95 | ``` html 96 | 97 | ``` 98 | 99 | # Events 100 | You can listen to specific events in the lifecycle of a vue-panzoom instance. For example, in the code below the function *onPanStart* will be called when pan begins 101 | ``` html 102 | 103 | ``` 104 | 105 | Another way to listen to events within the *init* event's callback, when you know for sure everything is ready and the panzoom instance is available. For example 106 | ``` html 107 | 108 | ``` 109 | ``` js 110 | onInit: function(panzoomInstance, id) { 111 | panzoomInstance.on('panstart', function(e){ 112 | console.log(e); 113 | }); 114 | } 115 | ``` 116 | 117 | ## init event 118 | This event is fired when the vue-panzoom instance has been initialized successfully. For example: 119 | ``` html 120 | 121 | ``` 122 | 123 | ## [panzoom](https://github.com/anvaka/panzoom) events 124 | All events supported by [panzoom](https://github.com/anvaka/panzoom) are also supported here. 125 | 126 | # upgrading from 1.1.3 to 1.1.4 127 | Version 1.1.4 uses `"rollup-plugin-vue": "^6.0.0"`, which requires Vue 3. For projects using Vue 2, downgrade to 1.1.3, e.g.: 128 | ```sh 129 | npm install vue-panzoom@1.1.3 130 | ``` 131 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /build/rollup.config.js: -------------------------------------------------------------------------------- 1 | import vue from 'rollup-plugin-vue'; 2 | import buble from 'rollup-plugin-buble'; 3 | import commonjs from 'rollup-plugin-commonjs'; 4 | 5 | export default { 6 | input: 'src/main.js', 7 | output: { 8 | name: 'VuePanZoom', 9 | exports: 'auto', 10 | }, 11 | plugins: [ 12 | vue({ 13 | css: true, 14 | compileTemplate: true, 15 | }), 16 | buble(), 17 | commonjs(), 18 | ], 19 | external: ['panzoom'] 20 | }; -------------------------------------------------------------------------------- /dist/vue-panzoom.esm.js: -------------------------------------------------------------------------------- 1 | import panZoom from 'panzoom'; 2 | import { openBlock, createBlock, createVNode, renderSlot } from 'vue'; 3 | 4 | var PanZoomComponent = { 5 | name: 'panZoom', 6 | props: { 7 | options: Object, 8 | selector: String, 9 | }, 10 | data: function data() { 11 | return { 12 | $panZoomInstance: null, 13 | instanceId: null, 14 | defaultOptions: { 15 | autocenter: true, 16 | bounds: true, 17 | transformOrigin: { 18 | x: 0.5, 19 | y: 0.5, 20 | } 21 | } 22 | } 23 | }, 24 | created: function created() { 25 | this.instanceId = this.generateRandomId(20); 26 | }, 27 | mounted: function mounted() { 28 | if (this.scene) { 29 | var _options = Object.assign({}, this.defaultOptions, this.options); 30 | this.$panZoomInstance = this.$panZoom(this.scene, _options); 31 | this.$panZoomInstanceId = this.instanceId; 32 | this.attachEvents(); 33 | } 34 | }, 35 | computed: { 36 | scene: function scene() { 37 | var el; 38 | var _wrapper = this.$el.querySelector('.vue-pan-zoom-scene'); 39 | if (this.selector) { 40 | el = _wrapper.querySelector(this.selector); 41 | } 42 | else { 43 | el = _wrapper.querySelector('svg, object, embed'); 44 | if (!el) { 45 | el = _wrapper.firstChild; 46 | } 47 | } 48 | return el; 49 | }, 50 | }, 51 | methods: { 52 | generateRandomId: function generateRandomId(l) { 53 | l = l || 16; 54 | var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 55 | var charsLength = chars.length; 56 | var a = []; 57 | 58 | for(var i=0; i=0.1.4" 28 | }, 29 | "description": "Vue plugin to zoom/pan dom elements", 30 | "main": "dist/vue-panzoom.umd.js", 31 | "module": "dist/vue-panzoom.esm.js", 32 | "unpkg": "dist/vue-panzoom.min.js", 33 | "browser": { 34 | "./sfc": "src/main.js" 35 | }, 36 | "repository": { 37 | "type": "git", 38 | "url": "git+https://github.com/thecodealer/vue-panzoom.git" 39 | }, 40 | "keywords": [ 41 | "vue", 42 | "zoom", 43 | "pan" 44 | ], 45 | "author": "Isa Frimpong ", 46 | "license": "MIT", 47 | "bugs": { 48 | "url": "https://github.com/thecodealer/vue-panzoom/issues" 49 | }, 50 | "homepage": "https://github.com/thecodealer/vue-panzoom#readme" 51 | } 52 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/components/pan-zoom/component.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/components/pan-zoom/script.js: -------------------------------------------------------------------------------- 1 | const PanZoomComponent = { 2 | name: 'panZoom', 3 | props: { 4 | options: Object, 5 | selector: String, 6 | }, 7 | data() { 8 | return { 9 | $panZoomInstance: null, 10 | instanceId: null, 11 | defaultOptions: { 12 | autocenter: true, 13 | bounds: true, 14 | transformOrigin: { 15 | x: 0.5, 16 | y: 0.5, 17 | } 18 | } 19 | } 20 | }, 21 | created() { 22 | this.instanceId = this.generateRandomId(20); 23 | }, 24 | mounted() { 25 | if (this.scene) { 26 | var _options = Object.assign({}, this.defaultOptions, this.options); 27 | this.$panZoomInstance = this.$panZoom(this.scene, _options); 28 | this.$panZoomInstanceId = this.instanceId; 29 | this.attachEvents(); 30 | } 31 | }, 32 | computed: { 33 | scene() { 34 | var el; 35 | var _wrapper = this.$el.querySelector('.vue-pan-zoom-scene'); 36 | if (this.selector) { 37 | el = _wrapper.querySelector(this.selector); 38 | } 39 | else { 40 | el = _wrapper.querySelector('svg, object, embed'); 41 | if (!el) { 42 | el = _wrapper.firstChild; 43 | } 44 | } 45 | return el; 46 | }, 47 | }, 48 | methods: { 49 | generateRandomId(l) { 50 | l = l || 16; 51 | var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 52 | var charsLength = chars.length; 53 | var a = []; 54 | 55 | for(var i=0; i { 64 | this.$emit('panstart', e); 65 | }); 66 | 67 | this.$panZoomInstance.on('panend', (e) => { 68 | this.$emit('panend', e); 69 | }); 70 | 71 | this.$panZoomInstance.on('pan', (e) => { 72 | this.$emit('pan', e); 73 | }); 74 | 75 | this.$panZoomInstance.on('zoom', (e) => { 76 | this.$emit('zoom', e); 77 | }); 78 | 79 | this.$panZoomInstance.on('transform', (e) => { 80 | this.$emit('transform', e); 81 | }); 82 | 83 | this.$panZoomInstance.on('zoomend', (e) => { 84 | this.$emit('zoomend', e); 85 | }); 86 | }, 87 | isPaused() { 88 | return this.$panZoomInstance.isPaused(); 89 | }, 90 | pause() { 91 | this.$panZoomInstance.pause(); 92 | }, 93 | resume() { 94 | this.$panZoomInstance.resume(); 95 | } 96 | } 97 | } 98 | 99 | export default PanZoomComponent; 100 | -------------------------------------------------------------------------------- /src/components/pan-zoom/template.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
-------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import panZoom from 'panzoom'; 2 | import PanZoomComponent from './components/pan-zoom/component.vue'; 3 | 4 | const PanZoomPlugin = { 5 | install(app, options) { 6 | var _name = options && options.componentName ? options.componentName : PanZoomComponent.name; 7 | app.component(_name, PanZoomComponent); 8 | if (app.hasOwnProperty('config') && app.config.hasOwnProperty('globalProperties')) { 9 | app.config.globalProperties.$panZoom = panZoom; 10 | } 11 | else { 12 | app.prototype.$panZoom = panZoom; 13 | } 14 | } 15 | }; 16 | 17 | export default PanZoomPlugin; 18 | 19 | if (typeof window !== 'undefined' && window.Vue) { 20 | window.Vue.use(PanZoomPlugin); 21 | } -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | productionSourceMap: false, 3 | filenameHashing: false, 4 | chainWebpack: config => { 5 | config.plugins.delete('html'); 6 | config.plugins.delete('preload'); 7 | config.plugins.delete('prefetch'); 8 | }, 9 | configureWebpack: { 10 | output: { 11 | filename: 'vue-panzoom.js' 12 | }, 13 | optimization: { 14 | splitChunks: false, 15 | }, 16 | }, 17 | } 18 | --------------------------------------------------------------------------------