Merge branch 'alessiocarrafa-master'

zoom
Yanick Champoux 2019-09-27 17:17:32 -04:00
commit 7c932d7810
10 changed files with 2604 additions and 2367 deletions

9
.editorconfig Normal file
View File

@ -0,0 +1,9 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

View File

@ -1,5 +1,9 @@
Release history for vue-svg-pan-zoom
$NEXT
- exposes some of svg-pan-zoom api. (alessiocarrafa, GH#7)
v1.0.1 2019-05-26
- corrects the thumbnail docs in the README. (GH#6)

4607
dist/index.js vendored

File diff suppressed because it is too large Load Diff

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -14,25 +14,25 @@
"url": "https://github.com/yanick/vue-svg-pan-zoom/issues"
},
"devDependencies": {
"@babel/cli": "^7.4.3",
"@babel/core": "^7.4.3",
"@babel/preset-env": "^7.4.3",
"@storybook/addon-actions": "^5.0.10",
"@storybook/addon-knobs": "^5.0.10",
"@storybook/addons": "^5.0.10",
"@storybook/vue": "^5.0.10",
"babel-loader": "^8.0.5",
"babel-preset-vue": "^2.0.2",
"poi": "^12.6.6",
"vue": "^2.5.13",
"vue-loader": "^15.7.0",
"vue-template-compiler": "^2.5.13"
"@babel/cli": "7.4.3",
"@babel/core": "7.4.3",
"@babel/preset-env": "7.4.3",
"@storybook/addon-actions": "5.0.10",
"@storybook/addon-knobs": "5.0.10",
"@storybook/addons": "5.0.10",
"@storybook/vue": "5.0.10",
"babel-loader": "8.0.5",
"babel-preset-vue": "2.0.2",
"poi": "12.6.6",
"vue": "2.5.13",
"vue-loader": "15.7.0",
"vue-template-compiler": "2.5.13"
},
"dependencies": {
"svg-pan-zoom": "^3.6.0"
"svg-pan-zoom": "3.6.0"
},
"scripts": {
"build": "poi src/index.js --format cjs -d dist/ --target node",
"build": "poi src/index.js --format cjs -d dist/",
"storybook": "start-storybook -p 9009 -s public",
"build-storybook": "build-storybook -s public"
}

View File

@ -1,12 +1,33 @@
<template>
<svg class="thumbViewClass" @click="updateMainViewPan" @mousemove="updateMainViewPan">
<rect class="scope" :x="x" :y="y" :width="width" :height="height"/>
</svg>
<svg class="thumbViewClass" @click="updateMainViewPan" @mousemove="updateMainViewPan">
<rect class="scope" :x="x" :y="y" :width="width" :height="height"/>
</svg>
</template>
<script>
<style scoped>
.scope {
fill: red;
fill-opacity: 0.1;
stroke: red;
stroke-width: 2px;
}
function updateScope(){
svg.thumbViewClass {
border: 1px solid black;
position: absolute;
bottom: 5px;
left: 5px;
width: 20%;
height: 30%;
margin: 3px;
padding: 3px;
overflow: hidden;
z-index: 120;
}
</style>
<script>
function updateScope(){
let main = this.mainSPZ;
let thumb = this.thumbnailSPZ;
@ -32,12 +53,12 @@ function updateScope(){
this.y = scopeY + 1;
this.width = scopeWidth - 2;
this.height = scopeHeight - 2;
};
};
function updateMainViewPan(evt){
function updateMainViewPan(evt){
if(evt.which == 0 && evt.button == 0){
return false;
return false;
}
let main = this.mainSPZ;
@ -56,46 +77,22 @@ function updateMainViewPan(evt){
var mainPanX = - thumbPanX * mainZoom / thumbZoom;
var mainPanY = - thumbPanY * mainZoom / thumbZoom;
main.pan({x:mainPanX, y:mainPanY});
}
}
export default {
export default {
props: [ 'bus', 'mainSPZ', 'thumbnailSPZ' ],
data: () => ({ x: 0, y: 0, width: 0, height: 0 }),
watch: {
mainSPZ() { updateScope.call(this) },
thumbnailSPZ() { updateScope.call(this) },
mainSPZ() { updateScope.call(this) },
thumbnailSPZ() { updateScope.call(this) },
},
mounted() {
const up = updateScope.bind(this);
[ 'mainZoom', 'mainPan', 'thumbnailCreated' ].forEach( event => this.bus.$on( event, up )
);
up();
const up = updateScope.bind(this);
[ 'mainZoom', 'mainPan', 'thumbnailCreated' ].forEach( event => this.bus.$on( event, up ) );
up();
},
methods: {
updateMainViewPan
updateMainViewPan
}
};
};
</script>
<style scoped>
.scope {
fill: red;
fill-opacity: 0.1;
stroke: red;
stroke-width: 2px;
}
svg.thumbViewClass {
border: 1px solid black;
position: absolute;
bottom: 5px;
left: 5px;
width: 20%;
height: 30%;
margin: 3px;
padding: 3px;
overflow: hidden;
z-index: 120;
}
</style>

View File

@ -23,43 +23,56 @@ import { EventBus } from './EventBus';
import SvgPanZoomThumbnail from './SvgPanZoomThumbnail.vue';
import { SvgPanZoomApi } from './SvgPanZoomApi';
export default {
props,
components: { SvgPanZoomThumbnail },
computed: {
has_thumbnail: function() { return this.$slots.thumbnail },
options: function() {
let options = {};
components: { SvgPanZoomThumbnail },
props,
computed: {
has_thumbnail: function() { return this.$slots.thumbnail },
options: function() {
let options = {};
const is_defined = k => this[k] !== undefined;
const is_defined = k => this[k] !== undefined;
Object.keys(props)
.filter( is_defined )
.forEach( k => options[k] = this[k] );
Object.keys(props)
.filter( is_defined )
.forEach( k => options[k] = this[k] );
return options;
}
return options;
}
},
data: () => ({
spz: null,
bus: EventBus()
}),
mounted: function() {
let options = {};
Object.keys(props).filter( k => this[k] !== undefined ).forEach( k => options[k] = this[k] );
options.onZoom = (...args) => {
this.bus.$emit( 'mainZoom' );
if( this.onZoom ) this.onZoom(args);
};
options.onPan = (...args) => {
this.bus.$emit( 'mainPan' );
if( this.onPan ) this.onPan(args);
};
this.spz = svg_pan_zoom( this.$slots.default[0].elm , options );
this.$emit( 'svgpanzoom', this.spz );
},
methods: {
zoom: function( v ){
this.spz.zoom( v );
},
mounted: function() {
let options = {};
Object.keys(props).filter( k => this[k] !== undefined ).forEach( k => options[k] = this[k] );
options.onZoom = (...args) => {
this.bus.$emit( 'mainZoom' );
if( this.onZoom ) this.onZoom(args);
};
options.onPan = (...args) => {
this.bus.$emit( 'mainPan' );
if( this.onPan ) this.onPan(args);
};
this.spz = svg_pan_zoom( this.$slots.default[0].elm , options );
this.$emit( 'svgpanzoom', this.spz );
},
data: () => ({ spz: null, bus: EventBus() }),
zoomBy: function( v ){
this.spz.zoomBy( v );
}
}
};
</script>

6
src/SvgPanZoomApi.js Normal file
View File

@ -0,0 +1,6 @@
export const SvgPanZoomApi = ( SvgPanZoomInstance ) => ({
zoom: function( v ){
SvgPanZoomInstance.zoom( v );
},
zoomBy: ( v ) => SvgPanZoomInstance.zoomBy( v )
});

View File

@ -1,69 +1,66 @@
<template>
<div v-on:wheel="zoomMain">
<SPZ class="thumbnail"
:zoomEnabled="false"
:panEnabled="false"
:controlIconsEnabled="false"
:dblClickZoomEnabled="false"
:preventMouseEventsDefault="true"
v-on:svgpanzoom="thumbnailSPZcreated"
>
<slot class="thumbnail" />
</SPZ>
<Scope :bus="bus" :mainSPZ="mainSPZ" :thumbnailSPZ="thumbnailSPZ" />
</div>
<div v-on:wheel="zoomMain">
<SPZ class="thumbnail"
:zoomEnabled="false"
:panEnabled="false"
:controlIconsEnabled="false"
:dblClickZoomEnabled="false"
:preventMouseEventsDefault="true"
v-on:svgpanzoom="thumbnailSPZcreated"
>
<slot class="thumbnail" />
</SPZ>
<Scope :bus="bus" :mainSPZ="mainSPZ" :thumbnailSPZ="thumbnailSPZ" />
</div>
</template>
<style>
.thumbView {
z-index: 110;
background: white;
}
.thumbnail {
position: absolute;
bottom: 5px;
left: 5px;
width: 20%;
height: 30%;
margin: 3px;
padding: 3px;
overflow: hidden;
z-index: 120;
}
.thumbnail svg {
width: 100% !important;
height: 100% !important;
}
</style>
<script>
import Scope from './Scope.vue';
export default {
props: [ 'onThumbnailShown', 'mainSPZ', 'bus' ],
beforeCreate: function () {
this.$options.components.SPZ = require('./SvgPanZoom.vue').default
components: { Scope },
props: [ 'onThumbnailShown', 'mainSPZ', 'bus' ],
data: () => ({ thumbnailSPZ: null }),
beforeCreate: function () {
this.$options.components.SPZ = require('./SvgPanZoom.vue').default
},
methods: {
zoomMain(evt) {
this.mainSPZ[ event.deltaY < 0 ? 'zoomIn' : 'zoomOut' ]();
},
methods: {
zoomMain(evt) {
this.mainSPZ[ event.deltaY < 0 ? 'zoomIn' : 'zoomOut' ]();
},
thumbnailSPZcreated(spz) {
this.thumbnailSPZ = spz;
this.bus.$emit( 'thumbnailCreated', spz );
},
thumbnailSPZcreated(spz) {
this.thumbnailSPZ = spz;
this.bus.$emit( 'thumbnailCreated', spz );
},
mounted() {
if( this.onThumbnailShown ) {
this.onThumbnailShown();
}
},
components: { Scope },
data: () => ({ thumbnailSPZ: null })
},
mounted() {
if( this.onThumbnailShown ) {
this.onThumbnailShown();
}
}
};
</script>
<style>
.thumbView {
z-index: 110;
background: white;
}
.thumbnail {
position: absolute;
bottom: 5px;
left: 5px;
width: 20%;
height: 30%;
margin: 3px;
padding: 3px;
overflow: hidden;
z-index: 120;
}
.thumbnail svg {
width: 100% !important;
height: 100% !important;
}
</style>

View File

@ -1,25 +1,25 @@
export default {
'zoomEnabled': { type: Boolean, default: true },
'controlIconsEnabled': { type: Boolean, default: false },
'fit': { type: Boolean, default: true },
'panEnabled': { type: Boolean, default: true },
'dblClickZoomEnabled': { type: Boolean, default: true },
'mouseWheelZoomEnabled': { type: Boolean, default: true },
'preventMouseEventsDefault': { type: Boolean, default: true },
'contain': { type: Boolean, default: false },
'center': { type: Boolean, default: true },
viewportSelector: { default: '.svg-pan-zoom_viewport' }
, zoomScaleSensitivity: { default: 0.2}
, minZoom: { default: 0.5}
, maxZoom: { default: 10}
, refreshRate: { default: 'auto'}
, beforeZoom: { }
, onZoom: { }
, beforePan: { }
, onPan: { }
, onUpdatedCTM: { }
, customEventsHandler: { }
, eventsListenerElement: { },
onThumbnailShown: { },
zoomEnabled: { type: Boolean, default: true },
controlIconsEnabled: { type: Boolean, default: false },
fit: { type: Boolean, default: true },
panEnabled: { type: Boolean, default: true },
dblClickZoomEnabled: { type: Boolean, default: true },
mouseWheelZoomEnabled: { type: Boolean, default: true },
preventMouseEventsDefault: { type: Boolean, default: true },
contain: { type: Boolean, default: false },
center: { type: Boolean, default: true },
viewportSelector: { default: '.svg-pan-zoom_viewport' },
zoomScaleSensitivity: { default: 0.2 },
minZoom: { default: 0.5 },
maxZoom: { default: 10 },
refreshRate: { default: 'auto' },
beforeZoom: { },
onZoom: { },
beforePan: { },
onPan: { },
onUpdatedCTM: { },
customEventsHandler: { },
eventsListenerElement: { },
onThumbnailShown: { },
};