Well, I turned on the Zynga Scroller functionality with the KineticJS framework to get what I wanted.
Code in action
Let the step take a look at the code, which is the union of the things that I found on the Internet and wrote myself.
First, we create the canvas using KineticJS:
var width = 700; var height = 700; var stage = new Kinetic.Stage({ container: 'container', width: width, height: height }); var layer = new Kinetic.Layer({}); stage.add(layer);
Then we define some events that trigger when you drag something onto the layer. We will use them to populate a global variable called somethingIsBeingDraggedInKinetic . We will use this variable in the Zynga Scroller pan code so that the whole scene does not move when you drag the KineticJS form.
var somethingIsBeingDraggedInKinetic = false; layer.on('dragstart', function(evt) { // get the thing that is being dragged var thing = evt.targetNode; if( thing ) somethingIsBeingDraggedInKinetic = true; }); layer.on('dragend', function(evt) { // get the thing that is being dragged var thing = evt.targetNode; if( thing ) somethingIsBeingDraggedInKinetic = false; });
Next is the Zynga Scroller initialization code. Zynga Scroller code processes input and transformation, and then passes three values ββto the rendering function: top , left and zoom . These values ββare ideal for moving to the KineticJS infrastructure:
// Canvas renderer var render = function(left, top, zoom) { // Constrain the stage from going too far to the right if( (left + (width / zoom)) > width ) left = width - (width / zoom ); // Constrain the stage from going too far to the left if( (top + (height / zoom)) > height ) top = height - (height / zoom ); stage.setOffset(left, top); stage.setScale(zoom); stage.draw(); }; // Initialize Scroller this.scroller = new Scroller(render, { zooming: true, animating: false, bouncing: false, locking: false, minZoom: 1 });
After that, we need to properly place the Zynga Scroller. I admit that this part is a little black for me. I copied the rest of the code from the file "asset / ui.js".
var container = document.getElementById("container"); var rect = container.getBoundingClientRect(); scroller.setPosition(rect.left + container.clientLeft, rect.top + container.clientTop); scroller.setDimensions(700, 700, width, height);
Finally, I also copied the pan code and added code that checks that the KineticJS framework is moving something:
var mousedown = false; container.addEventListener("mousedown", function(e) { if (e.target.tagName.match(/input|textarea|select/i)) { return; } scroller.doTouchStart([{ pageX: e.pageX, pageY: e.pageY }], e.timeStamp); mousedown = true; }, false); document.addEventListener("mousemove", function(e) { if (somethingIsBeingDraggedInKinetic) return; if (!mousedown) { return; } scroller.doTouchMove([{ pageX: e.pageX, pageY: e.pageY }], e.timeStamp); mousedown = true; }, false); document.addEventListener("mouseup", function(e) { if (!mousedown) { return; } scroller.doTouchEnd(e.timeStamp); mousedown = false; }, false);
Oh and the scaling handler.
container.addEventListener(navigator.userAgent.indexOf("Firefox") > -1 ? "DOMMouseScroll" : "mousewheel", function(e) { scroller.doMouseZoom(e.detail ? (e.detail * -120) : e.wheelDelta, e.timeStamp, e.pageX, e.pageY); }, false);
This is perfect for a scalable map!