// o---------------------------------------------------------------------------------o // | This file is part of the RGraph package - you can learn more at: | // | | // | https://www.rgraph.net/license.html | // | | // | RGraph is dual-licensed under the Open Source GPL license. That means that it's | // | free to use and there are no restrictions on what you can use RGraph for! | // | If the GPL license does not suit you however, then there's an inexpensive | // | commercial license option available. See the URL above for more details. | // o---------------------------------------------------------------------------------o RGraph = window.RGraph || {isrgraph:true,isRGraph:true,rgraph:true}; RGraph.SVG = RGraph.SVG || {}; // Module pattern (function (win, doc, undefined) { // // Adds a zoom function to the chart // RGraph.SVG.addZoom = function (obj) { var state = {}; state.mousedown = false; obj.svg.onmousedown = function (e) { if (e.button !== 0) { return; } var mouseXY = RGraph.SVG.getMouseXY(e); state.startXY = mouseXY; state.mousedown = true; // Get the initial viewbox coords - used for // moving the zoom around if (obj.svg.getAttribute('viewBox')) { String(obj.svg.getAttribute('viewBox')).match(/([-\d.]+) ([-\d.]+) ([-\d.]+) ([-\d.]+)/); state.initialViewbox = [ Number(RegExp.$1), Number(RegExp.$2), Number(RegExp.$3), Number(RegExp.$4) ]; } // If an outline exists already - remove it if (state.outline) { removeOutline(); } if (!state.isZoomed) { state.outline = RGraph.SVG.create({ svg: obj.svg, type: 'rect', parent: obj.svgAllGroup, attr: { x: mouseXY[0], y: mouseXY[1], width: 0, height: 0, stroke: 'black', fill: 'rgba(255,0,0,0.25)', 'stroke-width': 2, 'stroke-dasharray': '3 3' } }); } else { // Move the zoomed in SVG around // Nada } }; obj.svg.onmousemove = function (e) { var mouseXY = RGraph.SVG.getMouseXY(e); if (state.mousedown && !state.isZoomed) { state.endXY = mouseXY; // Update the width and height of the outline // rectangle state.outline.setAttribute( 'width', state.endXY[0] - state.startXY[0] ); state.outline.setAttribute( 'height', (obj.height / obj.width) * (state.endXY[0] - state.startXY[0]) ); clearSelection(); // // This facilitates moving the zoom around // } else if (state.isZoomed && state.mousedown) { var currentXY = RGraph.SVG.getMouseXY(e); var diffXY = [ currentXY[0] - state.startXY[0], currentXY[1] - state.startXY[1] ] // Get the existing viewBox coords obj.svg.getAttribute('viewBox').match(/^([-\d.]+) ([-\d.]+) ([-\d.]+) ([-\d.]+)$/) // Set the new coordinates for the viewBox on the SVG tag obj.svg.setAttribute( 'viewBox', vb = '{1} {2} {3} {4}'.format( state.initialViewbox[0] + diffXY[0] * -1, state.initialViewbox[1] + diffXY[1] * -1, Number(RegExp.$3), Number(RegExp.$4) ) ); clearSelection(); } }; window.onmouseup = function (e) { state.mousedown = false; if (!state.isZoomed) { // Set the viewbox attribute on the SVG tag obj.svg.setAttribute( 'viewBox', '{1} {2} {3} {4}'.format( state.outline.getAttribute('x'), state.outline.getAttribute('y'), state.outline.getAttribute('width'), state.outline.getAttribute('height') ) ); // Get rid of the outline removeOutline(); // Note that we're now zoomed state.isZoomed = true; // Clear any remaining selection clearSelection(); } }; obj.svg.onwheel = function (e) { if (state.isZoomed) { obj.svg.getAttribute('viewBox').match(/^([-\d.]+) ([-\d.]+) ([-\d.]+) ([-\d.]+)$/); var viewbox = [ parseInt(RegExp.$1), parseInt(RegExp.$2), parseInt(RegExp.$3), parseInt(RegExp.$4) ] var step = e.deltaY < 0 ? 3 : -3; if (step === -1) { viewbox = [ viewbox[0] + step, viewbox[1] + step, viewbox[2] + (step * -2), viewbox[3] + (step * -2) ]; } else { viewbox = [ viewbox[0] + step, viewbox[1] + step, viewbox[2] + (step * -2), viewbox[3] + (step * -2) ]; } // Set the new viewbox on the SVG obj.svg.setAttribute('viewBox', "{1} {2} {3} {4}".format( viewbox[0], viewbox[1], viewbox[2], viewbox[3] )); e.preventDefault(); } }; window.addEventListener('keydown', function (e) { if (e.keyCode === 27) { resetZoom(); removeOutline(); } }); function resetZoom () { obj.svg.setAttribute('viewBox', '0 0 {1} {2}'.format(obj.width, obj.height)); state.isZoomed = false; clearSelection(); removeOutline(); } function removeOutline () { if (state.outline) { state.outline.parentNode.removeChild(state.outline); state.outline = null; } } function clearSelection () { if (window.getSelection) { window.getSelection().removeAllRanges(); } else if (document.selection) { document.selection.empty(); } } }; // End module pattern })(window, document);