OpenLayers.Kinetic = OpenLayers.Class({ /** * Property: threshold * In most cases changing the threshold isn't needed. * In px/ms, default to 0. */ threshold: 0, /** * Property: interval * {Integer} Interval in milliseconds between 2 steps in the "kinetic * dragging". Defaults to 10 milliseconds. */ interval: 10, /** * Property: deceleration * {Float} the deseleration in px/ms², default to 0.0035. */ deceleration: 0.0035, /** * Property: nbPoints * {Integer} the number of points we use to calculate the kinetic * initial values. */ nbPoints: 100, /** * Property: delay * {Float} time to consider to calculate the kinetic initial values. * In ms, default to 200. */ delay: 200, /** * Property: points * List of points use to calculate the kinetic initial values. */ points: undefined, /** * Property: timerId * ID of the timer. */ timerId: undefined, /** * Constructor: OpenLayers.Kinetic * * Parameters: * options - {Object} */ initialize: function(options) { OpenLayers.Util.extend(this, options); }, /** * Method: begin * * Begins the dragging. */ begin: function() { clearInterval(this.timerId); this.timerId = undefined; this.points = []; }, /** * Method: update * * Updates during the dragging. */ update: function(xy) { this.points.unshift({xy: xy, tick: new Date().getTime()}); if (this.points.length > this.nbPoints) { this.points.pop(); } }, /** * Method: end * * Ends the dragging, start the kinetic. */ end: function(xy) { var last, now = new Date().getTime(); for (var i = 0, l = this.points.length, point; i < l; i++) { point = this.points[i]; if (now - point.tick > this.delay) { break; } last = point; } if (!last) { return; } var time = new Date().getTime() - last.tick; var dist = Math.sqrt(Math.pow(xy.x - last.xy.x, 2) + Math.pow(xy.y - last.xy.y, 2)); var speed = dist / time; if (speed == 0 || speed < this.threshold) { return; } var theta = Math.asin((xy.y - last.xy.y) / dist); if (last.xy.x <= xy.x) { theta = Math.PI - theta; } return {speed: speed, theta: theta}; }, /** * Method: move * * Launch the kinetic move pan. * * Parameters: * info - {Object} * callback - arguments x, y (values to pan), end (is the last point) */ move: function(info, callback) { var v0 = info.speed; var fx = Math.cos(info.theta); var fy = -Math.sin(info.theta); var time = 0; var initialTime = new Date().getTime(); var lastX = 0; var lastY = 0; var timerCallback = function() { if (this.timerId == null) { return; } time += this.interval; var realTime = new Date().getTime() - initialTime; var t = (time + realTime) / 2.0; var p = (-this.deceleration * Math.pow(t, 2)) / 2.0 + v0 * t; var x = p * fx; var y = p * fy; var args = {}; args.end = false; var v = -this.deceleration * t + v0; if (v <= 0) { clearInterval(this.timerId); this.timerId = null; args.end = true; } args.x = x - lastX; args.y = y - lastY; lastX = x; lastY = y; callback(args.x, args.y, args.end); }; this.timerId = window.setInterval( OpenLayers.Function.bind(timerCallback, this), this.interval); }, CLASS_NAME: "OpenLayers.Kinetic" });