wip
This commit is contained in:
parent
e2410ecc24
commit
ada3302def
42
src/SvgPanZoomThumbnail.vue
Normal file
42
src/SvgPanZoomThumbnail.vue
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<template>
|
||||||
|
<div id="thumbViewContainer">
|
||||||
|
<svg id="scopeContainer" class="thumbViewClass">
|
||||||
|
<g>
|
||||||
|
<rect id="scope" fill="red" fill-opacity="0.1" stroke="red" stroke-width="2px" x="0" y="0" width="0" height="0"/>
|
||||||
|
<line id="line1" stroke="red" stroke-width="2px" x1="0" y1="0" x2="0" y2="0"/>
|
||||||
|
<line id="line2" stroke="red" stroke-width="2px" x1="0" y1="0" x2="0" y2="0"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export const SvgPanZoomThumbnail = {};
|
||||||
|
export default SvgPanZoomThumbnail;
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.thumbViewClass {
|
||||||
|
border: 1px solid black;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 5px;
|
||||||
|
left: 5px;
|
||||||
|
width: 20%;
|
||||||
|
height: 30%;
|
||||||
|
margin: 3px;
|
||||||
|
padding: 3px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#thumbView {
|
||||||
|
z-index: 110;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#scopeContainer {
|
||||||
|
z-index: 120;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,12 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<slot />
|
<slot />
|
||||||
|
<SvgPanZoomThumbnail v-if="has_thumbnail">
|
||||||
|
<slot name="thumbnail" />
|
||||||
|
</SvgPanZoomThumbnail>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import svg_pan_zoom from 'svg-pan-zoom';
|
import svg_pan_zoom from 'svg-pan-zoom';
|
||||||
|
|
||||||
|
import SvgPanZoomThumbnail from './SvgPanZoomThumbnail.vue';
|
||||||
|
export { SvgPanZoomThumbnail } from './SvgPanZoomThumbnail.vue';
|
||||||
|
|
||||||
|
import thumbnailViewer from './thumbnailViewer';
|
||||||
|
|
||||||
let props = {
|
let props = {
|
||||||
'zoomEnabled': { type: Boolean, default: true },
|
'zoomEnabled': { type: Boolean, default: true },
|
||||||
'controlIconsEnabled': { type: Boolean, default: false },
|
'controlIconsEnabled': { type: Boolean, default: false },
|
||||||
@ -33,17 +41,31 @@ let props = {
|
|||||||
|
|
||||||
export const SvgPanZoom = {
|
export const SvgPanZoom = {
|
||||||
props,
|
props,
|
||||||
|
components: { SvgPanZoomThumbnail },
|
||||||
|
computed: {
|
||||||
|
has_thumbnail: function() { return this.$slots.thumbnail }
|
||||||
|
},
|
||||||
mounted: function() {
|
mounted: function() {
|
||||||
let options = {};
|
let options = {};
|
||||||
|
|
||||||
Object.keys(props).filter( k => this[k] !== undefined ).forEach( k => options[k] = this[k] );
|
Object.keys(props).filter( k => this[k] !== undefined ).forEach( k => options[k] = this[k] );
|
||||||
console.log(options);
|
console.log(options);
|
||||||
svg_pan_zoom( this.$slots.default[0].elm , options );
|
|
||||||
|
if( this.has_thumbnail ) {
|
||||||
|
console.log( this.$slots.default[0].elm.id );
|
||||||
|
console.log( this.$slots.thumbnail );
|
||||||
|
thumbnailViewer({
|
||||||
|
mainViewId: this.$slots.default[0].elm.id,
|
||||||
|
thumbViewId: 'thumbView',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
svg_pan_zoom( this.$slots.default[0].elm , options );
|
||||||
|
}
|
||||||
// svg_pan_zoom( '#mainView', options );
|
// svg_pan_zoom( '#mainView', options );
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SvgPanZoom;
|
export default SvgPanZoom;
|
||||||
|
|
||||||
export const SvgPanZoomThumbnail = {};
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
style="width: 300px; height: 500px; border:1px solid black; "
|
style="width: 300px; height: 500px; border:1px solid black; "
|
||||||
>
|
>
|
||||||
<RawTiger />
|
<RawTiger />
|
||||||
|
<RawTiger slot="thumbnail" id="thumbView" class="thumbViewClass"
|
||||||
|
style="position: absolute; width: 20%; height: 30% bottom: 5px;
|
||||||
|
left: 5px; margin: 3px; padding: 3px;"
|
||||||
|
/>
|
||||||
</SvgPanZoom>
|
</SvgPanZoom>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -11,8 +15,10 @@
|
|||||||
import { SvgPanZoom, SvgPanZoomThumbnail } from './index.vue';
|
import { SvgPanZoom, SvgPanZoomThumbnail } from './index.vue';
|
||||||
import RawTiger from './RawTiger.vue';
|
import RawTiger from './RawTiger.vue';
|
||||||
|
|
||||||
|
console.log(SvgPanZoomThumbnail);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { SvgPanZoom, RawTiger },
|
components: { SvgPanZoom, RawTiger, SvgPanZoomThumbnail },
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
195
src/thumbnailViewer.js
Normal file
195
src/thumbnailViewer.js
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
import svgPanZoom from 'svg-pan-zoom';
|
||||||
|
|
||||||
|
export default function(options){
|
||||||
|
|
||||||
|
var getSVGDocument = function(objectElem){
|
||||||
|
var svgDoc = objectElem.contentDocument;
|
||||||
|
if(! svgDoc){
|
||||||
|
try {
|
||||||
|
svgDoc = objectElem.getSVGDocument();
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
svgDoc = objectElem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return svgDoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bindThumbnail = function(main, thumb){
|
||||||
|
|
||||||
|
if(! window.main && main){
|
||||||
|
window.main = main;
|
||||||
|
}
|
||||||
|
if(! window.thumb && thumb){
|
||||||
|
window.thumb = thumb;
|
||||||
|
}
|
||||||
|
if(! window.main || ! window.thumb){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var resizeTimer;
|
||||||
|
var interval = 300; //msec
|
||||||
|
window.addEventListener('resize', function(event){
|
||||||
|
if (resizeTimer !== false) {
|
||||||
|
clearTimeout(resizeTimer);
|
||||||
|
}
|
||||||
|
resizeTimer = setTimeout(function () {
|
||||||
|
window.main.resize();
|
||||||
|
window.thumb.resize();
|
||||||
|
}, interval);
|
||||||
|
});
|
||||||
|
|
||||||
|
window.main.setOnZoom(function(level){
|
||||||
|
window.thumb.updateThumbScope();
|
||||||
|
if(options.onZoom){
|
||||||
|
options.onZoom(window.main, window.thumb, level);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
window.main.setOnPan(function(point){
|
||||||
|
window.thumb.updateThumbScope();
|
||||||
|
if(options.onPan){
|
||||||
|
options.onPan(window.main, window.thumb, point);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var _updateThumbScope = function (main, thumb, scope, line1, line2){
|
||||||
|
var mainPanX = main.getPan().x
|
||||||
|
, mainPanY = main.getPan().y
|
||||||
|
, mainWidth = main.getSizes().width
|
||||||
|
, mainHeight = main.getSizes().height
|
||||||
|
, mainZoom = main.getSizes().realZoom
|
||||||
|
, thumbPanX = thumb.getPan().x
|
||||||
|
, thumbPanY = thumb.getPan().y
|
||||||
|
, thumbZoom = thumb.getSizes().realZoom;
|
||||||
|
|
||||||
|
var thumByMainZoomRatio = thumbZoom / mainZoom;
|
||||||
|
|
||||||
|
var scopeX = thumbPanX - mainPanX * thumByMainZoomRatio;
|
||||||
|
var scopeY = thumbPanY - mainPanY * thumByMainZoomRatio;
|
||||||
|
var scopeWidth = mainWidth * thumByMainZoomRatio;
|
||||||
|
var scopeHeight = mainHeight * thumByMainZoomRatio;
|
||||||
|
|
||||||
|
scope.setAttribute("x", scopeX + 1);
|
||||||
|
scope.setAttribute("y", scopeY + 1);
|
||||||
|
scope.setAttribute("width", scopeWidth - 2);
|
||||||
|
scope.setAttribute("height", scopeHeight - 2);
|
||||||
|
/*
|
||||||
|
line1.setAttribute("x1", scopeX + 1);
|
||||||
|
line1.setAttribute("y1", scopeY + 1);
|
||||||
|
line1.setAttribute("x2", scopeX + 1 + scopeWidth - 2);
|
||||||
|
line1.setAttribute("y2", scopeY + 1 + scopeHeight - 2);
|
||||||
|
line2.setAttribute("x1", scopeX + 1);
|
||||||
|
line2.setAttribute("y1", scopeY + 1 + scopeHeight - 2);
|
||||||
|
line2.setAttribute("x2", scopeX + 1 + scopeWidth - 2);
|
||||||
|
line2.setAttribute("y2", scopeY + 1);
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
window.thumb.updateThumbScope = function(){
|
||||||
|
var scope = document.getElementById('scope');
|
||||||
|
var line1 = document.getElementById('line1');
|
||||||
|
var line2 = document.getElementById('line2');
|
||||||
|
_updateThumbScope(window.main, window.thumb, scope, line1, line2);
|
||||||
|
}
|
||||||
|
window.thumb.updateThumbScope();
|
||||||
|
|
||||||
|
var _updateMainViewPan = function(clientX, clientY, scopeContainer, main, thumb){
|
||||||
|
var dim = scopeContainer.getBoundingClientRect()
|
||||||
|
, mainWidth = main.getSizes().width
|
||||||
|
, mainHeight = main.getSizes().height
|
||||||
|
, mainZoom = main.getSizes().realZoom
|
||||||
|
, thumbWidth = thumb.getSizes().width
|
||||||
|
, thumbHeight = thumb.getSizes().height
|
||||||
|
, thumbZoom = thumb.getSizes().realZoom;
|
||||||
|
|
||||||
|
var thumbPanX = clientX - dim.left - thumbWidth / 2;
|
||||||
|
var thumbPanY = clientY - dim.top - thumbHeight / 2;
|
||||||
|
var mainPanX = - thumbPanX * mainZoom / thumbZoom;
|
||||||
|
var mainPanY = - thumbPanY * mainZoom / thumbZoom;
|
||||||
|
main.pan({x:mainPanX, y:mainPanY});
|
||||||
|
};
|
||||||
|
|
||||||
|
var updateMainViewPan = function(evt){
|
||||||
|
if(evt.which == 0 && evt.button == 0){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var scopeContainer = document.getElementById('scopeContainer');
|
||||||
|
_updateMainViewPan(evt.clientX, evt.clientY, scopeContainer, window.main, window.thumb);
|
||||||
|
}
|
||||||
|
|
||||||
|
var scopeContainer = document.getElementById('scopeContainer');
|
||||||
|
scopeContainer.addEventListener('click', function(evt){
|
||||||
|
updateMainViewPan(evt);
|
||||||
|
});
|
||||||
|
|
||||||
|
scopeContainer.addEventListener('mousemove', function(evt){
|
||||||
|
updateMainViewPan(evt);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var mainViewObjectElem = document.getElementById(options.mainViewId);
|
||||||
|
console.log(mainViewObjectElem);
|
||||||
|
mainViewObjectElem.addEventListener("load", function(){
|
||||||
|
|
||||||
|
var mainViewSVGDoc = getSVGDocument(mainViewObjectElem);
|
||||||
|
if(options.onMainViewSVGLoaded){
|
||||||
|
options.onMainViewSVGLoaded(mainViewSVGDoc);
|
||||||
|
}
|
||||||
|
|
||||||
|
var beforePan = function(oldPan, newPan){
|
||||||
|
var stopHorizontal = false
|
||||||
|
, stopVertical = false
|
||||||
|
, gutterWidth = 100
|
||||||
|
, gutterHeight = 100
|
||||||
|
// Computed variables
|
||||||
|
, sizes = this.getSizes()
|
||||||
|
, leftLimit = -((sizes.viewBox.x + sizes.viewBox.width) * sizes.realZoom) + gutterWidth
|
||||||
|
, rightLimit = sizes.width - gutterWidth - (sizes.viewBox.x * sizes.realZoom)
|
||||||
|
, topLimit = -((sizes.viewBox.y + sizes.viewBox.height) * sizes.realZoom) + gutterHeight
|
||||||
|
, bottomLimit = sizes.height - gutterHeight - (sizes.viewBox.y * sizes.realZoom);
|
||||||
|
let customPan = {};
|
||||||
|
customPan.x = Math.max(leftLimit, Math.min(rightLimit, newPan.x));
|
||||||
|
customPan.y = Math.max(topLimit, Math.min(bottomLimit, newPan.y));
|
||||||
|
return customPan;
|
||||||
|
};
|
||||||
|
|
||||||
|
var main = svgPanZoom('#'+options.mainViewId, {
|
||||||
|
zoomEnabled: true,
|
||||||
|
controlIconsEnabled: true,
|
||||||
|
fit: false,
|
||||||
|
center: true,
|
||||||
|
beforePan: beforePan
|
||||||
|
});
|
||||||
|
|
||||||
|
bindThumbnail(main, undefined);
|
||||||
|
if(options.onMainViewShown){
|
||||||
|
options.onMainViewShown(mainViewSVGDoc, main);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
var thumbViewObjectElem = document.getElementById(options.thumbViewId);
|
||||||
|
thumbViewObjectElem.addEventListener("load", function(){
|
||||||
|
|
||||||
|
var thumbViewSVGDoc = getSVGDocument(thumbViewObjectElem);
|
||||||
|
if(options.onThumbnailSVGLoaded){
|
||||||
|
options.onThumbnailSVGLoaded(thumbViewSVGDoc);
|
||||||
|
}
|
||||||
|
|
||||||
|
var thumb = svgPanZoom('#'+options.thumbViewId, {
|
||||||
|
zoomEnabled: false,
|
||||||
|
panEnabled: false,
|
||||||
|
controlIconsEnabled: false,
|
||||||
|
dblClickZoomEnabled: false,
|
||||||
|
preventMouseEventsDefault: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
bindThumbnail(undefined, thumb);
|
||||||
|
if(options.onThumbnailShown){
|
||||||
|
options.onThumbnailShown(thumbViewSVGDoc, thumb);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, false);
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user