Search code examples
javascripthtmlanimationscalekineticjs

How to scale a shape from its center as origin?


I have the following, code, that works perfectly fine, except that it scales the shape from top left corner as origin, but I want it to scale from its center as origin. How should do that in away, the animation will start to scale up from center of the shape when moused over, and scale down to original size again from center as origin?

    <div id="hex-menu"></div>
    <script src="js/kinetic.min.js" charset="utf-8"></script>
    <script defer="defer" type="text/javascript">
        function makeHex(x, y, fill) {
            var hex = new Kinetic.Shape({
                x: x,
                y: y,
                fill: fill,
                // a Kinetic.Canvas renderer is passed into the drawFunc function
                drawFunc: function (canvas) {
                    var context = canvas.getContext();
                    context.save();
                    context.translate(x, y);
                    context.beginPath();
                    context.moveTo(0.1, 51.9);
                    context.bezierCurveTo(0.1, 43.6, 4.6, 35.8, 11.9, 31.6);
                    context.lineTo(61.0, 3.3);
                    context.bezierCurveTo(68.2, -0.9, 77.2, -0.9, 84.4, 3.3);
                    context.lineTo(133.6, 31.6);
                    context.bezierCurveTo(140.8, 35.8, 145.3, 43.6, 145.3, 52.0);
                    context.lineTo(145.3, 108.7);
                    context.bezierCurveTo(145.3, 117.1, 140.8, 124.8, 133.6, 129.0);
                    context.lineTo(84.4, 157.4);
                    context.bezierCurveTo(77.2, 161.5, 68.2, 161.5, 61.0, 157.4);
                    context.lineTo(11.9, 129.0);
                    context.bezierCurveTo(4.6, 124.8, 0.1, 117.0, 0.1, 108.7);
                    context.lineTo(0.1, 51.9);
                    context.closePath();
                    canvas.fillStroke(this);
                    context.restore();
                }
            });
            return hex;
        }
        function Zoom(node) {
            var tween = new Kinetic.Tween({
                node: node,
                duration: 0.5,
                scaleX: 1.2,
                scaleY: 1.2
            });
        return tween;
        }
        function AddAnimation(node, tween) {
            node.on('mouseover', function() {
                tween.play();
            });
            node.on('mouseleave', function() {
                tween.reverse();
            });
        }
        var stage = new Kinetic.Stage({
            container: 'hex-menu',
            width: 513,
            height: 484
        });
        var shapesLayer = new Kinetic.Layer();
        var home = makeHex(80, 90, 'rgb(19, 217, 209)', 50);
        shapesLayer.add(home);
        stage.add(shapesLayer);
        var zoomHome = Zoom(home);
        AddAnimation(home, zoomHome);
    </script>

Solution

  • You need to set the offset property to the centre of the shape using some trigonometry. By default Kinetic.Circle and Kinetic.Ellipse are offset in the centre, while the rest of the shapes are offset on the top left.

    In this example I'm setting the offset to half of the width and height (50 and 25), but you'll need to do some calculations on your hex object to get the centre point.

    var rect = new Kinetic.Rect({
      x: 239,
      y: 75,
      width: 100,
      height: 50,
      fill: 'green',
      stroke: 'black',
      strokeWidth: 4,
      offset: {x: 50, y: 25}
    });
    

    Or you can use the methods getOffset() and setOffset()

    http://kineticjs.com/docs/Kinetic.Shape.html#getOffset http://kineticjs.com/docs/Kinetic.Shape.html#setOffset

    JSFIDDLE