I do it like this. I'm zooming the whole layer but it works for any image or shape. Just let setPosition do all the work and adjust for the new scale factor. Note1: if the canvas isn't in the top corner of the page, you also need to get the canvas position and remove it from the pageX,Y position. This is what the function getPos() does. I pulled it straight from another stackoverflow topic. Note2: Use the zP point to control where the zooming takes place (i.e. at the mouse click position, or center than zoom, etc.)
The kineticJS part...
layer.on("dblclick",function(ev){
var d=document.getElementById('photoCnvs');
var cnvsPos=getPos(d);
var R={ //(canvas space)
x: ev.pageX,
y: ev.pageY
};
var off0=this.getPosition();
var scl0=this.getScale().x;
var w=stageM.getWidth();
var h=stageM.getHeight();
//desired zoom point (e.g. mouse position, canvas center)
var zP={
//use these first two lines to center the image on the clicked point while zooming
//x: w/2,
//y: h/2
//use these next two lines to zoom the image around the clicked point
x: R.x-cnvsPos.x,
y: R.y-cnvsPos.y
}
//actual pixel value clicked (image space)
var xA={
x:(R.x-off0.x-cnvsPos.x)/scl0,
y:(R.y-off0.y-cnvsPos.y)/scl0
}
//rescale image
var sclf=scl0*1.10;
this.setScale(sclf);
//move clicked pixel to the desired zoom point
var newR={
x: zP.x-sclf*xA.x,
y: zP.y-sclf*xA.y
}
this.setPosition(newR.x, newR.y)
this.draw();
})
Then the canvas position part
function getPos(el) {
for (var lx=0, ly=0;
el != null;
lx += el.offsetLeft, ly += el.offsetTop, el = el.offsetParent);
return {x: lx,y: ly};
}