diff --git a/src/SvgPanZoomThumbnail.vue b/src/SvgPanZoomThumbnail.vue new file mode 100644 index 0000000..275d40a --- /dev/null +++ b/src/SvgPanZoomThumbnail.vue @@ -0,0 +1,42 @@ + + + + + diff --git a/src/index.vue b/src/index.vue index 5990dff..b20c80c 100644 --- a/src/index.vue +++ b/src/index.vue @@ -1,12 +1,20 @@ diff --git a/src/thumbnail.stories.vue b/src/thumbnail.stories.vue index 50cdda4..87586dc 100644 --- a/src/thumbnail.stories.vue +++ b/src/thumbnail.stories.vue @@ -3,6 +3,10 @@ style="width: 300px; height: 500px; border:1px solid black; " > + @@ -11,8 +15,10 @@ import { SvgPanZoom, SvgPanZoomThumbnail } from './index.vue'; import RawTiger from './RawTiger.vue'; +console.log(SvgPanZoomThumbnail); + export default { - components: { SvgPanZoom, RawTiger }, + components: { SvgPanZoom, RawTiger, SvgPanZoomThumbnail }, }; diff --git a/src/thumbnailViewer.js b/src/thumbnailViewer.js new file mode 100644 index 0000000..74da633 --- /dev/null +++ b/src/thumbnailViewer.js @@ -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); +}; +