Based on other SO questions (see credits at the bottom), I came up with a way to animate the "zoom to cursor" effect with KineticJS.
Here is a fiddle.
The relevant section is here :
zoom: function(event) {
    event.preventDefault();
    var evt = event.originalEvent,
        mx = evt.clientX - ui.stage.getX(),
        my = evt.clientY - ui.stage.getY(),
        zoom = (ui.zoomFactor - (evt.wheelDelta < 0 ? 0.4 : -0.4)),
        newscale = ui.scale * zoom;
    ui.origin.x = mx / ui.scale + ui.origin.x - mx / newscale;
    ui.origin.y = my / ui.scale + ui.origin.y - my / newscale;
    zoomTween = new Kinetic.Tween({
        node: ui.layer, 
        duration: 0.8,
        offsetX: ui.origin.x,
        offsetY: ui.origin.y,
        scaleX: newscale,
        scaleY: newscale
    });
    zoomTween.play();
    ui.scale *= zoom;
}
What should I change in my code to avoid the "bouncing" effect, especially when zooming in/out fast ?
My code is a fork of this jsfiddle (attached to this answer) with 3 minor modifications :
- uses KineticJS 5.1.0
 - uses a Tween to animate the offset and scale properties
 - layer is being offseted/scaled instead of stage because stage wasn't playing well with Tween
 
Other credits :
- Zoom Canvas to Mouse Cursor : excellent canvas-only solution
 - https://stackoverflow.com/a/13663169/4066116 : KineticJS version