Adding mapbox-gl branch
This commit is contained in:
@@ -0,0 +1,425 @@
|
||||
/**
|
||||
* SVGPan library 1.2.2
|
||||
* ======================
|
||||
*
|
||||
* Given an unique existing element with a given id (or by default, the first
|
||||
* g-element), including the library into any SVG adds the following
|
||||
* capabilities:
|
||||
*
|
||||
* - Mouse panning
|
||||
* - Mouse zooming (using the wheel)
|
||||
* - Object dragging
|
||||
*
|
||||
* You can configure the behaviour of the pan/zoom/drag via setOptions().
|
||||
*
|
||||
* Known issues:
|
||||
*
|
||||
* - Zooming (while panning) on Safari has still some issues
|
||||
*
|
||||
* Releases:
|
||||
*
|
||||
* 1.2.2, Tue Aug 30 17:21:56 CEST 2011, Andrea Leofreddi
|
||||
* - Fixed viewBox on root tag (#7)
|
||||
* - Improved zoom speed (#2)
|
||||
*
|
||||
* 1.2.1, Mon Jul 4 00:33:18 CEST 2011, Andrea Leofreddi
|
||||
* - Fixed a regression with mouse wheel (now working on Firefox 5)
|
||||
* - Working with viewBox attribute (#4)
|
||||
* - Added "use strict;" and fixed resulting warnings (#5)
|
||||
* - Added configuration variables, dragging is disabled by default (#3)
|
||||
*
|
||||
* 1.2, Sat Mar 20 08:42:50 GMT 2010, Zeng Xiaohui
|
||||
* Fixed a bug with browser mouse handler interaction
|
||||
*
|
||||
* 1.1, Wed Feb 3 17:39:33 GMT 2010, Zeng Xiaohui
|
||||
* Updated the zoom code to support the mouse wheel on Safari/Chrome
|
||||
*
|
||||
* 1.0, Andrea Leofreddi
|
||||
* First release
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license
|
||||
* This code is licensed under the following BSD license:
|
||||
* Copyright 2009-2010 Andrea Leofreddi <a.leofreddi@itcharm.com>. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Andrea Leofreddi ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL Andrea Leofreddi OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are
|
||||
* those of the authors and should not be interpreted as representing official
|
||||
* policies, either expressed or implied, of Andrea Leofreddi.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('svgpan.SvgPan');
|
||||
|
||||
goog.require('goog.Disposable');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.events.MouseWheelHandler');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates an SvgPan object.
|
||||
* @param {string=} opt_graphElementId The id of the graph element.
|
||||
* @param {Element=} opt_root An optional document root.
|
||||
* @constructor
|
||||
* @extends {goog.Disposable}
|
||||
*/
|
||||
svgpan.SvgPan = function(opt_graphElementId, opt_root) {
|
||||
svgpan.SvgPan.base(this, 'constructor');
|
||||
|
||||
/** @private {Element} */
|
||||
this.root_ = opt_root || document.documentElement;
|
||||
|
||||
/** @private {?string} */
|
||||
this.graphElementId_ = opt_graphElementId || null;
|
||||
|
||||
/** @private {boolean} */
|
||||
this.cancelNextClick_ = false;
|
||||
|
||||
/** @private {boolean} */
|
||||
this.enablePan_ = true;
|
||||
|
||||
/** @private {boolean} */
|
||||
this.enableZoom_ = true;
|
||||
|
||||
/** @private {boolean} */
|
||||
this.enableDrag_ = false;
|
||||
|
||||
/** @private {number} */
|
||||
this.zoomScale_ = 0.4;
|
||||
|
||||
/** @private {svgpan.SvgPan.State} */
|
||||
this.state_ = svgpan.SvgPan.State.NONE;
|
||||
|
||||
/** @private {Element} */
|
||||
this.svgRoot_ = null;
|
||||
|
||||
/** @private {Element} */
|
||||
this.stateTarget_ = null;
|
||||
|
||||
/** @private {SVGPoint} */
|
||||
this.stateOrigin_ = null;
|
||||
|
||||
/** @private {SVGMatrix} */
|
||||
this.stateTf_ = null;
|
||||
|
||||
/** @private {goog.events.MouseWheelHandler} */
|
||||
this.mouseWheelHandler_ = null;
|
||||
|
||||
this.setupHandlers_();
|
||||
};
|
||||
goog.inherits(svgpan.SvgPan, goog.Disposable);
|
||||
|
||||
|
||||
/** @override */
|
||||
svgpan.SvgPan.prototype.disposeInternal = function() {
|
||||
svgpan.SvgPan.base(this, 'disposeInternal');
|
||||
goog.events.removeAll(this.root_);
|
||||
this.mouseWheelHandler_.dispose();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
svgpan.SvgPan.State = {
|
||||
NONE: 'none',
|
||||
PAN: 'pan',
|
||||
DRAG: 'drag'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Enables/disables panning the entire SVG (default = true).
|
||||
* @param {boolean} enabled Whether or not to allow panning.
|
||||
*/
|
||||
svgpan.SvgPan.prototype.setPanEnabled = function(enabled) {
|
||||
this.enablePan_ = enabled;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Enables/disables zooming (default = true).
|
||||
* @param {boolean} enabled Whether or not to allow zooming (default = true).
|
||||
*/
|
||||
svgpan.SvgPan.prototype.setZoomEnabled = function(enabled) {
|
||||
this.enableZoom_ = enabled;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Enables/disables dragging individual SVG objects (default = false).
|
||||
* @param {boolean} enabled Whether or not to allow dragging of objects.
|
||||
*/
|
||||
svgpan.SvgPan.prototype.setDragEnabled = function(enabled) {
|
||||
this.enableDrag_ = enabled;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the sensitivity of mousewheel zooming (default = 0.4).
|
||||
* @param {number} scale The new zoom scale.
|
||||
*/
|
||||
svgpan.SvgPan.prototype.setZoomScale = function(scale) {
|
||||
this.zoomScale_ = scale;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Registers mouse event handlers.
|
||||
* @private
|
||||
*/
|
||||
svgpan.SvgPan.prototype.setupHandlers_ = function() {
|
||||
goog.events.listen(this.root_, goog.events.EventType.CLICK,
|
||||
goog.bind(this.handleMouseClick_, this));
|
||||
goog.events.listen(this.root_, goog.events.EventType.MOUSEUP,
|
||||
goog.bind(this.handleMouseUp_, this));
|
||||
goog.events.listen(this.root_, goog.events.EventType.MOUSEDOWN,
|
||||
goog.bind(this.handleMouseDown_, this));
|
||||
goog.events.listen(this.root_, goog.events.EventType.MOUSEMOVE,
|
||||
goog.bind(this.handleMouseMove_, this));
|
||||
this.mouseWheelHandler_ = new goog.events.MouseWheelHandler(this.root_);
|
||||
goog.events.listen(this.mouseWheelHandler_,
|
||||
goog.events.MouseWheelHandler.EventType.MOUSEWHEEL,
|
||||
goog.bind(this.handleMouseWheel_, this));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the root element for SVG manipulation. The element is then cached.
|
||||
* @param {Document} svgDoc The document.
|
||||
* @return {Element} The svg root.
|
||||
* @private
|
||||
*/
|
||||
svgpan.SvgPan.prototype.getRoot_ = function(svgDoc) {
|
||||
if (!this.svgRoot_) {
|
||||
var r = this.graphElementId_ ?
|
||||
svgDoc.getElementById(this.graphElementId_) : svgDoc.documentElement;
|
||||
var t = r;
|
||||
while (t != svgDoc) {
|
||||
if (t.getAttribute('viewBox')) {
|
||||
this.setCtm_(r, r.getCTM());
|
||||
t.removeAttribute('viewBox');
|
||||
}
|
||||
t = t.parentNode;
|
||||
}
|
||||
this.svgRoot_ = r;
|
||||
}
|
||||
return this.svgRoot_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates an SVGPoint object with given event coordinates.
|
||||
* @param {!goog.events.Event} evt The event with coordinates.
|
||||
* @return {SVGPoint} The created point.
|
||||
* @private
|
||||
*/
|
||||
svgpan.SvgPan.prototype.getEventPoint_ = function(evt) {
|
||||
return this.newPoint_(evt.clientX, evt.clientY);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates an SVGPoint object with given coordinates.
|
||||
* @param {number} x The x coordinate.
|
||||
* @param {number} y The y coordinate.
|
||||
* @return {SVGPoint} The created point.
|
||||
* @private
|
||||
*/
|
||||
svgpan.SvgPan.prototype.newPoint_ = function(x, y) {
|
||||
var p = this.root_.createSVGPoint();
|
||||
p.x = x;
|
||||
p.y = y;
|
||||
return p;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the current transform matrix of an element.
|
||||
* @param {Element} element The element.
|
||||
* @param {SVGMatrix} matrix The transform matrix.
|
||||
* @private
|
||||
*/
|
||||
svgpan.SvgPan.prototype.setCtm_ = function(element, matrix) {
|
||||
var s = 'matrix(' + matrix.a + ',' + matrix.b + ',' + matrix.c + ',' +
|
||||
matrix.d + ',' + matrix.e + ',' + matrix.f + ')';
|
||||
element.setAttribute('transform', s);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle mouse wheel event.
|
||||
* @param {!goog.events.Event} evt The event.
|
||||
* @private
|
||||
*/
|
||||
svgpan.SvgPan.prototype.handleMouseWheel_ = function(evt) {
|
||||
if (!this.enableZoom_)
|
||||
return;
|
||||
|
||||
// Prevents scrolling.
|
||||
evt.preventDefault();
|
||||
|
||||
var svgDoc = evt.target.ownerDocument;
|
||||
|
||||
var delta = evt.deltaY / -9;
|
||||
var z = Math.pow(1 + this.zoomScale_, delta);
|
||||
var g = this.getRoot_(svgDoc);
|
||||
var p = this.getEventPoint_(evt);
|
||||
p = p.matrixTransform(g.getCTM().inverse());
|
||||
|
||||
// Compute new scale matrix in current mouse position
|
||||
var k = this.root_.createSVGMatrix().translate(
|
||||
p.x, p.y).scale(z).translate(-p.x, -p.y);
|
||||
this.setCtm_(g, g.getCTM().multiply(k));
|
||||
|
||||
if (typeof(this.stateTf_) == 'undefined') {
|
||||
this.stateTf_ = g.getCTM().inverse();
|
||||
}
|
||||
this.stateTf_ =
|
||||
this.stateTf_ ? this.stateTf_.multiply(k.inverse()) : this.stateTf_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle mouse move event.
|
||||
* @param {!goog.events.Event} evt The event.
|
||||
* @private
|
||||
*/
|
||||
svgpan.SvgPan.prototype.handleMouseMove_ = function(evt) {
|
||||
if (evt.button != 0) {
|
||||
return;
|
||||
}
|
||||
this.handleMove(evt.clientX, evt.clientY, evt.target.ownerDocument);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles mouse motion for the given coordinates.
|
||||
* @param {number} x The x coordinate.
|
||||
* @param {number} y The y coordinate.
|
||||
* @param {Document} svgDoc The svg document.
|
||||
*/
|
||||
svgpan.SvgPan.prototype.handleMove = function(x, y, svgDoc) {
|
||||
var g = this.getRoot_(svgDoc);
|
||||
if (this.state_ == svgpan.SvgPan.State.PAN && this.enablePan_) {
|
||||
// Pan mode
|
||||
var p = this.newPoint_(x, y).matrixTransform(
|
||||
/** @type {!SVGMatrix} */ (this.stateTf_));
|
||||
this.setCtm_(g, this.stateTf_.inverse().translate(
|
||||
p.x - this.stateOrigin_.x, p.y - this.stateOrigin_.y));
|
||||
this.cancelNextClick_ = true;
|
||||
} else if (this.state_ == svgpan.SvgPan.State.DRAG && this.enableDrag_) {
|
||||
// Drag mode
|
||||
var p = this.newPoint_(x, y).matrixTransform(g.getCTM().inverse());
|
||||
this.setCtm_(this.stateTarget_, this.root_.createSVGMatrix().translate(
|
||||
p.x - this.stateOrigin_.x, p.y - this.stateOrigin_.y).multiply(
|
||||
g.getCTM().inverse()).multiply(this.stateTarget_.getCTM()));
|
||||
this.stateOrigin_ = p;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle click event.
|
||||
* @param {!goog.events.Event} evt The event.
|
||||
* @private
|
||||
*/
|
||||
svgpan.SvgPan.prototype.handleMouseDown_ = function(evt) {
|
||||
if (evt.button != 0) {
|
||||
return;
|
||||
}
|
||||
// Prevent selection while dragging.
|
||||
evt.preventDefault();
|
||||
var svgDoc = evt.target.ownerDocument;
|
||||
|
||||
var g = this.getRoot_(svgDoc);
|
||||
|
||||
if (evt.target.tagName == 'svg' || !this.enableDrag_) {
|
||||
// Pan mode
|
||||
this.state_ = svgpan.SvgPan.State.PAN;
|
||||
this.stateTf_ = g.getCTM().inverse();
|
||||
this.stateOrigin_ = this.getEventPoint_(evt).matrixTransform(this.stateTf_);
|
||||
} else {
|
||||
// Drag mode
|
||||
this.state_ = svgpan.SvgPan.State.DRAG;
|
||||
this.stateTarget_ = /** @type {Element} */ (evt.target);
|
||||
this.stateTf_ = g.getCTM().inverse();
|
||||
this.stateOrigin_ = this.getEventPoint_(evt).matrixTransform(this.stateTf_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle mouse button release event.
|
||||
* @param {!goog.events.Event} evt The event.
|
||||
* @private
|
||||
*/
|
||||
svgpan.SvgPan.prototype.handleMouseUp_ = function(evt) {
|
||||
if (this.state_ != svgpan.SvgPan.State.NONE) {
|
||||
this.endPanOrDrag();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Ends pan/drag mode.
|
||||
*/
|
||||
svgpan.SvgPan.prototype.endPanOrDrag = function() {
|
||||
if (this.state_ != svgpan.SvgPan.State.NONE) {
|
||||
this.state_ = svgpan.SvgPan.State.NONE;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle mouse clicks.
|
||||
* @param {!goog.events.Event} evt The event.
|
||||
* @private
|
||||
*/
|
||||
svgpan.SvgPan.prototype.handleMouseClick_ = function(evt) {
|
||||
// We only set cancelNextClick_ after panning occurred, and use it to prevent
|
||||
// the default action that would otherwise take place when clicking on the
|
||||
// element (for instance, navigation on clickable links, but also any click
|
||||
// handler that may be set on an SVG element, in the case of active SVG
|
||||
// content)
|
||||
if (this.cancelNextClick_) {
|
||||
// Cancel potential click handler on active SVG content.
|
||||
evt.stopPropagation();
|
||||
// Cancel navigation when panning on clickable links.
|
||||
evt.preventDefault();
|
||||
}
|
||||
this.cancelNextClick_ = false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the current state.
|
||||
* @return {!svgpan.SvgPan.State}
|
||||
*/
|
||||
svgpan.SvgPan.prototype.getState = function() {
|
||||
return this.state_;
|
||||
};
|
||||
Reference in New Issue
Block a user