The complete sample I wrote for the project:
- scaling the desktop around the mouse point using scrollwheel
- using scrollwheel crossbrowser including firefox (using jquery.mousewheel.js)
- scaling iPAD using a pinch around the point between the fingers
- support for changing the orientation of the iPad and disabling automatic zoom safari
- scaling of one layer while saving other layers without increasing - OOP javascript class and proxying events to local methods
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.4.min.js"></script> <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script> <script src="https://rawgithub.com/brandonaaron/jquery-mousewheel/master/jquery.mousewheel.js"></script> </head> <body> <div id="container"></div> <script type='text/javascript'> function makePos(x, y) { return { 'x': x, 'y': y }; } function View() { this.init = init; var self = this; var kineticStage, kineticLayer, kineticTextLayer, zoomOrigin = makePos(0, 0), zoomFactor = 1.1, pinchLastDist, pinchStartCenter; init(); function init() { // disable ipad zoom to prevent safari from zooming on orientation change $('head meta[name=viewport]').remove(); $('head').prepend('<meta name="viewport" content="user-scalable=no, width=device-width, minimum-scale=1.0 , initial-scale=1.0, maximum-scale=1.0" />'); // create stage layer and circle kineticStage = new Kinetic.Stage({ container: 'container', width: $(document).width() - 10, height: $(document).height() - 10, }); kineticLayer = new Kinetic.Layer({ draggable: true }); var circle = new Kinetic.Circle({ x: 200, y: 200, radius: 50, fill: '#00D200', stroke: 'black', strokeWidth: 2, }); kineticLayer.add(circle); kineticStage.add(kineticLayer); kineticTextLayer = new Kinetic.Layer({}); kineticStage.add(kineticTextLayer); // register events and proxy to methods $(kineticStage.content).on('mousewheel', function(e) { e.preventDefault(); var evt = e.originalEvent; stageMouseWheel.call(self, evt.deltaY, makePos(evt.clientX, evt.clientY)); }); kineticStage.getContent().addEventListener('touchmove', function(e) { e.preventDefault(); // prevent iPAD panning var touch1 = e.touches[0]; var touch2 = e.touches[1]; if (touch1 && touch2) { touch1.offsetX = touch1.pageX - $(touch1.target).offset().left; touch1.offsetY = touch1.pageY - $(touch1.target).offset().top; touch2.offsetX = touch2.pageX - $(touch2.target).offset().left; touch2.offsetY = touch2.pageY - $(touch2.target).offset().top; stagePinch.call(self, makePos(touch1.offsetX, touch1.offsetY), makePos(touch2.offsetX, touch2.offsetY)); } }, false); kineticStage.getContent().addEventListener('touchend', function(e) { stageTouchEnd.call(self); }, false); $(window).on("orientationchange", function(event) { window.scrollTo(0, 0); // scroll to top left on orientation change }); editTextLayer('scrollwheel/pinch to zoom'); window.scrollTo(0, 0); } function zoom(newscale, center) { // zoom around center var mx = center.x - kineticLayer.getX(), my = center.y - kineticLayer.getY(), oldscale = kineticLayer.getScaleX(); editTextLayer('zoom ' + newscale.toFixed(2) + ' around ' + mx.toFixed(2) + ',' + my.toFixed(2)); zoomOrigin = makePos(mx / oldscale + zoomOrigin.x - mx / newscale, my / oldscale + zoomOrigin.y - my / newscale); kineticLayer.setOffset(zoomOrigin.x, zoomOrigin.y); kineticLayer.setScale(newscale); kineticLayer.draw(); } function stageMouseWheel(factor, p) { var oldscale = kineticLayer.getScaleX(), newscale = oldscale * (zoomFactor - (factor < 0 ? 0.2 : 0)); zoom(newscale, p); } function stagePinch(p1, p2) { var dist = Math.sqrt(Math.pow((p2.x - p1.x), 2) + Math.pow((p2.y - p1.y), 2)); if (!pinchLastDist) pinchLastDist = dist; var newscale = kineticLayer.getScale().x * dist / pinchLastDist; var center = makePos(Math.abs((p1.x + p2.x) / 2), Math.abs((p1.y + p2.y) / 2)); if (!pinchStartCenter) pinchStartCenter = center; zoom(newscale, pinchStartCenter); pinchLastDist = dist; } function stageTouchEnd() { pinchLastDist = pinchStartCenter = 0; } function editTextLayer(text) { var label = new Kinetic.Text({ x: 0, y: 0, text: text, fontSize: 12, fontFamily: 'Calibri', fill: 'black' }); kineticTextLayer.destroyChildren(); kineticTextLayer.add(label); kineticTextLayer.drawScene(); } } $(window).load(function() { var view = new View(); }); </script> </body> </html>
http://jsfiddle.net/45YJH/1/