aboutsummaryrefslogtreecommitdiff
path: root/website/assets/js/SVGPan.js
diff options
context:
space:
mode:
Diffstat (limited to 'website/assets/js/SVGPan.js')
-rw-r--r--website/assets/js/SVGPan.js281
1 files changed, 281 insertions, 0 deletions
diff --git a/website/assets/js/SVGPan.js b/website/assets/js/SVGPan.js
new file mode 100644
index 0000000..e23d05a
--- /dev/null
+++ b/website/assets/js/SVGPan.js
@@ -0,0 +1,281 @@
1/**
2 * SVGPan library 1.2.1
3 * ======================
4 *
5 * Given an unique existing element with id "viewport" (or when missing, the first g
6 * element), including the the library into any SVG adds the following capabilities:
7 *
8 * - Mouse panning
9 * - Mouse zooming (using the wheel)
10 * - Object dragging
11 *
12 * You can configure the behaviour of the pan/zoom/drag with the variables
13 * listed in the CONFIGURATION section of this file.
14 *
15 * Known issues:
16 *
17 * - Zooming (while panning) on Safari has still some issues
18 *
19 * Releases:
20 *
21 * 1.2.1, Mon Jul 4 00:33:18 CEST 2011, Andrea Leofreddi
22 * - Fixed a regression with mouse wheel (now working on Firefox 5)
23 * - Working with viewBox attribute (#4)
24 * - Added "use strict;" and fixed resulting warnings (#5)
25 * - Added configuration variables, dragging is disabled by default (#3)
26 *
27 * 1.2, Sat Mar 20 08:42:50 GMT 2010, Zeng Xiaohui
28 * Fixed a bug with browser mouse handler interaction
29 *
30 * 1.1, Wed Feb 3 17:39:33 GMT 2010, Zeng Xiaohui
31 * Updated the zoom code to support the mouse wheel on Safari/Chrome
32 *
33 * 1.0, Andrea Leofreddi
34 * First release
35 *
36 * This code is licensed under the following BSD license:
37 *
38 * Copyright 2009-2010 Andrea Leofreddi <a.leofreddi@itcharm.com>. All rights reserved.
39 *
40 * Redistribution and use in source and binary forms, with or without modification, are
41 * permitted provided that the following conditions are met:
42 *
43 * 1. Redistributions of source code must retain the above copyright notice, this list of
44 * conditions and the following disclaimer.
45 *
46 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
47 * of conditions and the following disclaimer in the documentation and/or other materials
48 * provided with the distribution.
49 *
50 * THIS SOFTWARE IS PROVIDED BY Andrea Leofreddi ``AS IS'' AND ANY EXPRESS OR IMPLIED
51 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
52 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Andrea Leofreddi OR
53 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
54 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
55 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
56 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
57 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
58 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59 *
60 * The views and conclusions contained in the software and documentation are those of the
61 * authors and should not be interpreted as representing official policies, either expressed
62 * or implied, of Andrea Leofreddi.
63 */
64
65"use strict";
66
67/// CONFIGURATION
68/// ====>
69
70var enablePan = 1; // 1 or 0: enable or disable panning (default enabled)
71var enableZoom = 1; // 1 or 0: enable or disable zooming (default enabled)
72var enableDrag = 0; // 1 or 0: enable or disable dragging (default disabled)
73
74/// <====
75/// END OF CONFIGURATION
76
77var root = document.documentElement;
78
79var state = 'none', svgRoot, stateTarget, stateOrigin, stateTf;
80
81setupHandlers(root);
82
83/**
84 * Register handlers
85 */
86function setupHandlers(root){
87 setAttributes(root, {
88 "onmouseup" : "handleMouseUp(evt)",
89 "onmousedown" : "handleMouseDown(evt)",
90 "onmousemove" : "handleMouseMove(evt)",
91 //"onmouseout" : "handleMouseUp(evt)", // Decomment this to stop the pan functionality when dragging out of the SVG element
92 });
93
94 if(navigator.userAgent.toLowerCase().indexOf('webkit') >= 0)
95 window.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari
96 else
97 window.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others
98}
99
100/**
101 * Retrieves the root element for SVG manipulation. The element is then cached into the svgRoot global variable.
102 */
103function getRoot(root) {
104 if(typeof(svgRoot) == "undefined") {
105 var g = null;
106
107 g = root.getElementById("viewport");
108
109 if(g == null)
110 g = root.getElementsByTagName('g')[0];
111
112 if(g == null)
113 alert('Unable to obtain SVG root element');
114
115 setCTM(g, g.getCTM());
116
117 g.removeAttribute("viewBox");
118
119 svgRoot = g;
120 }
121
122 return svgRoot;
123}
124
125/**
126 * Instance an SVGPoint object with given event coordinates.
127 */
128function getEventPoint(evt) {
129 var p = root.createSVGPoint();
130
131 p.x = evt.clientX;
132 p.y = evt.clientY;
133
134 return p;
135}
136
137/**
138 * Sets the current transform matrix of an element.
139 */
140function setCTM(element, matrix) {
141 var s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")";
142
143 element.setAttribute("transform", s);
144}
145
146/**
147 * Dumps a matrix to a string (useful for debug).
148 */
149function dumpMatrix(matrix) {
150 var s = "[ " + matrix.a + ", " + matrix.c + ", " + matrix.e + "\n " + matrix.b + ", " + matrix.d + ", " + matrix.f + "\n 0, 0, 1 ]";
151
152 return s;
153}
154
155/**
156 * Sets attributes of an element.
157 */
158function setAttributes(element, attributes){
159 for (var i in attributes)
160 element.setAttributeNS(null, i, attributes[i]);
161}
162
163/**
164 * Handle mouse wheel event.
165 */
166function handleMouseWheel(evt) {
167 if(!enableZoom)
168 return;
169
170 if(evt.preventDefault)
171 evt.preventDefault();
172
173 evt.returnValue = false;
174
175 var svgDoc = evt.target.ownerDocument;
176
177 var delta;
178
179 if(evt.wheelDelta)
180 delta = evt.wheelDelta / 3600; // Chrome/Safari
181 else
182 delta = evt.detail / -90; // Mozilla
183
184 var z = 1 + delta; // Zoom factor: 0.9/1.1
185
186 var g = getRoot(svgDoc);
187
188 var p = getEventPoint(evt);
189
190 p = p.matrixTransform(g.getCTM().inverse());
191
192 // Compute new scale matrix in current mouse position
193 var k = root.createSVGMatrix().translate(p.x, p.y).scale(z).translate(-p.x, -p.y);
194
195 setCTM(g, g.getCTM().multiply(k));
196
197 if(typeof(stateTf) == "undefined")
198 stateTf = g.getCTM().inverse();
199
200 stateTf = stateTf.multiply(k.inverse());
201}
202
203/**
204 * Handle mouse move event.
205 */
206function handleMouseMove(evt) {
207 if(evt.preventDefault)
208 evt.preventDefault();
209
210 evt.returnValue = false;
211
212 var svgDoc = evt.target.ownerDocument;
213
214 var g = getRoot(svgDoc);
215
216 if(state == 'pan' && enablePan) {
217 // Pan mode
218 var p = getEventPoint(evt).matrixTransform(stateTf);
219
220 setCTM(g, stateTf.inverse().translate(p.x - stateOrigin.x, p.y - stateOrigin.y));
221 } else if(state == 'drag' && enableDrag) {
222 // Drag mode
223 var p = getEventPoint(evt).matrixTransform(g.getCTM().inverse());
224
225 setCTM(stateTarget, root.createSVGMatrix().translate(p.x - stateOrigin.x, p.y - stateOrigin.y).multiply(g.getCTM().inverse()).multiply(stateTarget.getCTM()));
226
227 stateOrigin = p;
228 }
229}
230
231/**
232 * Handle click event.
233 */
234function handleMouseDown(evt) {
235 if(evt.preventDefault)
236 evt.preventDefault();
237
238 evt.returnValue = false;
239
240 var svgDoc = evt.target.ownerDocument;
241
242 var g = getRoot(svgDoc);
243