var thumbnailViewer = function(options) {
var getSVGDocument = function(objectElem) {
var svgDoc = objectElem.contentDocument;
if (!svgDoc) {
if (typeof objectElem.getSVGDocument === "function") {
svgDoc = objectElem.getSVGDocument();
}
}
return svgDoc;
}
var bindThumbnail = function(main, thumb, scopeContainerId) {
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() {
// TODO: Parametrizar estas varibales id del html
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, scopeContainerId) {
if (evt.which == 0 && evt.button == 0) {
return false;
}
var scopeContainer = document.getElementById(scopeContainerId);
_updateMainViewPan(evt.clientX, evt.clientY, scopeContainer, window.main, window.thumb);
}
var scopeContainer = document.getElementById(scopeContainerId);
scopeContainer.addEventListener('click', function(evt) {
updateMainViewPan(evt, scopeContainerId);
});
scopeContainer.addEventListener('mousemove', function(evt) {
updateMainViewPan(evt, scopeContainerId);
});
};
var initMainView = 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);
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.mainSVGId, {
zoomEnabled: true,
controlIconsEnabled: true,
fit: true,
center: true,
beforePan: beforePan,
});
bindThumbnail(main, undefined, options.scopeContainerId);
if (options.onMainViewShown) {
options.onMainViewShown(mainViewSVGDoc, main);
}
};
var mainViewObjectElem = document.getElementById(options.mainSVGId);
mainViewObjectElem.addEventListener("load", function() {
initMainView();
}, false);
var initThumbView = function() {
var thumbViewSVGDoc = getSVGDocument(thumbViewObjectElem);
if (options.onThumbnailSVGLoaded) {
options.onThumbnailSVGLoaded(thumbViewSVGDoc);
}
var thumb = svgPanZoom('#' + options.thumbSVGId, {
fit: true,
zoomEnabled: false,
panEnabled: false,
controlIconsEnabled: false,
dblClickZoomEnabled: false,
preventMouseEventsDefault: true,
});
bindThumbnail(undefined, thumb, options.scopeContainerId);
if (options.onThumbnailShown) {
options.onThumbnailShown(thumbViewSVGDoc, thumb);
}
};
var thumbViewObjectElem = document.getElementById(options.thumbSVGId);
thumbViewObjectElem.addEventListener("load", function() {
initThumbView();
}, false);
// Se inicializan los controles
initThumbView();
initMainView();
};
body {
background: #f5f5f5;
}
html,
body {
width: 100%;
height: 100%;
}
#mainViewContainer {
width: 95%;
height: 95%;
border: 1px solid black;
margin: 10px;
padding: 3px;
overflow: hidden;
}
#mainView {
width: 100%;
height: 100%;
min-height: 100%;
display: inline;
}
.thumbViewClass {
border: 1px solid black;
position: absolute;
bottom: 5px;
left: 5px;
width: 20%;
height: 30%;
margin: 3px;
padding: 3px;
overflow: hidden;
}
#thumbSVG,
#mainSVG {
height: 100%;
width: 100%;
}
#thumbView {
z-index: 110;
background: white;
}
#scopeContainer {
z-index: 120;
}
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Meta -->
<meta charset="UTF-8">
<title>My New Project!</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="http://ariutta.github.io/svg-pan-zoom/dist/svg-pan-zoom.js"></script>
</head>
<body>
<div id="mainViewContainer">
<div id="mainView">
<svg id="mainSVG" style="display: inline; width: inherit; min-width: inherit; max-width: inherit; height: inherit; min-height: inherit; max-height: inherit; " xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<linearGradient id="linear-gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(56,121,217);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(138,192,7);stop-opacity:1" />
</linearGradient>
</defs>
<g fill="none">
<g stroke="#000" fill="#FFF">
<rect x="10" y="10" width="120" height="120" fill="url(#linear-gradient)"/>
<path d="M 10 10 L 130 130 Z"/>
</g>
</g>
</svg>
</div>
</div>
<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>
<div id="thumbView" class="thumbViewClass">
<svg id="thumbSVG" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<linearGradient id="linear-gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(56,121,217);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(138,192,7);stop-opacity:1" />
</linearGradient>
</defs>
<g fill="none">
<g stroke="#000" fill="#FFF">
<rect x="10" y="10" width="120" height="120" fill="url(#linear-gradient)"/>
<path d="M 10 10 L 130 130 Z"/>
</g>
</g>
</svg>
</div>
</div>
<!-- Scripts -->
<script>
window.onload = function() {
thumbnailViewer({
mainSVGId: 'mainSVG',
thumbSVGId: 'thumbSVG',
scopeContainerId: 'scopeContainer'
});
}
</script>
</body>
</html>