2

I want to scale my group (image and something).

group.setScale(zoom, zoom);

http://jsfiddle.net/K8nK3/

But when i scale my group, I think it's not scale from center of my group. i think it like this
enter image description here
I want it scale from center like
enter image description here

I try more but it's not success. How can i do that, thanks.

DeLe
  • 2,442
  • 19
  • 88
  • 133
  • 1
    Not sure about kinetic but with fabric.js, you would just change originX/originY properties to center/center (from left/top). – kangax Apr 06 '13 at 21:26
  • u have any example with fabric library like my example thanks – DeLe Apr 07 '13 at 01:38

4 Answers4

2

[Edited to better fit questioner's needs]

Here’s how to scale a Kinetic group from the centerpoint

First we store the centerX and centerY of the original group so we can keep the group centered there:

      group.cx=group.getX()+group.getWidth()/2;
      group.cy=group.getY()+group.getHeight()/2;

Then we write a custom scaling method that both scales the group and re-centers it:

      group.scale=function(x,y){
          group.setScale(x,y);
          group.setPosition(
              group.cx-group.getWidth()/2*group.getScale().x,
              group.cy-group.getHeight()/2*group.getScale().y);
          group.draw();
      }

Here’s code and a Fiddle: http://jsfiddle.net/m1erickson/dVGGz/

<!DOCTYPE HTML>
<html>
  <head></head>
  <body>
    <button id="larger">Larger</button>
    <div id="container"></div>
    <script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.4.0.min.js"></script>
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    <script>
    $(function(){
      var stage = new Kinetic.Stage({
        container: 'container',
        width: 400,
        height: 400
      });
      var layer = new Kinetic.Layer();

      // Be sure to set width and height
      // They are required for this method to work
      var group = new Kinetic.Group({
        x: 100,
        y: 100,
        width:100,
        height:100
      });
      // store the original group center
      // so we can center the group there
      group.cx=group.getX()+group.getWidth()/2;
      group.cy=group.getY()+group.getHeight()/2;
      // custom scale function to both
      // scale the group and center the results
      group.scale=function(x,y){
          group.setScale(x,y);
          group.setPosition(
              group.cx-group.getWidth()/2*group.getScale().x,
              group.cy-group.getHeight()/2*group.getScale().y);
          group.draw();
      }

      var box1 = new Kinetic.Rect({
        x: 0,
        y: 0,
        width: 50,
        height: 50,
        fill: "blue",
        stroke: 'black',
        strokeWidth: 4
      });
      group.add(box1);

      var box2 = new Kinetic.Rect({
        x: 50,
        y: 50,
        width: 50,
        height: 50,
        fill: "green",
        stroke: 'black',
        strokeWidth: 4
      });
      group.add(box2);

      layer.add(group);
      stage.add(layer);

      var scaleFactor=1;
      $("#larger").click(function(){
          scaleFactor+=0.10;
          group.scale(scaleFactor,scaleFactor);
          console.log(scaleFactor);
      });

});

    </script>
  </body>
</html>
markE
  • 102,905
  • 11
  • 164
  • 176
  • i have some objects on my group. i can't do this way. u have other way? – DeLe Apr 06 '13 at 17:32
  • Yes, see my edited answer which should meet your needs to scale a group from the center. – markE Apr 07 '13 at 05:07
  • It's not working in my context. in my context, the group not hold objects (it hasn't width and height), and group can drag (execute point center again when i drag). i think 'scale point' is offset. Can u try again with my project. – DeLe Apr 07 '13 at 07:25
  • Yes, you are entirely correct about how you customize this proof-of-concept into something that fits your needs exactly. If you are dragging then you will want to recomputed the group.cx and group.cy after the drag (or at least before the next scaling). If you don't have an initial width and a height for your group, you will have to declare an arbitrary "centerpoint" around which you want to scale. – markE Apr 07 '13 at 14:12
  • How to declare a centerpoint around which the scale will be done? – user1499220 Aug 02 '13 at 20:26
0

Have you tried to use offset property? i.e. offset: [width/2, height/2]

0

Problem #1: I need to scale a group from its center. Problem #2: Kinetic JS group.getWidth() and group.getHeight() don't work unless you explicitly set the width at creation. Problem #3: I don't know the width and height, I'm dynamically changing the shapes.

This means in order to try your code out, I'll have to write my own getWidth and getHeight functions. Then I can use the method you propose.

Solution below.

(There may be a better way, but this is my level of programming right now . . . if anyone can add recursion to this to look through groups that contain groups that contain groups etc, that would be great.)

var results = getGroupMinsAndMaxes(myKineticGroup);
console.log('results: '+ results.groupMinX, results.groupMaxX, 
     results.groupMinY, results.groupMaxY);



function getGroupMinsAndMaxes( group ) {

   // note this does not handle children that are groups, 
   // it expects children to be shapes

   var item;
   var groupMinX = 99999;
   var groupMaxX = -99999;
   var groupMinY = 99999;
   var groupMaxY = -99999;
   var shapeFunctionDefinition = '';
   var bounds = {};

   for (var i = 0; i < group.children.length; i++ ) {

       item = group.children[ i ];
       if ( item.getType() !== 'Shape' ) {

            alert('The getGroupMinsAndMaxes function is not designed to handle groups that contain groups.');
            break;

       } else {

            shapeFunctionDefinition = item.attrs.drawFunc.toString();

            bounds = getShapeMinsAndMaxes( shapeFunctionDefinition );

            if ( bounds.shapeMinX < groupMinX ) { groupMinX = bounds.shapeMinX; }
            if ( bounds.shapeMaxX > groupMaxX ) { groupMaxX = bounds.shapeMaxX; }
            if ( bounds.shapeMinY < groupMinY ) { groupMinY = bounds.shapeMinY; }
            if ( bounds.shapeMaxY > groupMaxY ) { groupMaxY = bounds.shapeMaxY; }

        }
   }

    return {
            groupMinX: groupMinX,
            groupMaxX: groupMaxX,
            groupMinY: groupMinY,
            groupMaxY: groupMaxY
        };

}

function getShapeMinsAndMaxes( shape ) {

   // the shape definition is passed as a string

    var regex = /[+-]?\d+\.\d+/g;

    var floats = shape.match(regex).map(function (v) {
        return parseFloat(v);
    });

   // preset some unrealistically large numbers which 
   // we will never encounter

    var shapeMinX = 99999;
    var shapeMaxX = -99999;
    var shapeMinY = 99999;
    var shapeMaxY = -99999;


    for (var i = 0; i < floats.length; i++) {

        if (isOdd(i)) {

            // Check Y values
            if (floats[i] < shapeMinY) {
                shapeMinY = floats[i];
            }
            if (floats[i] > shapeMaxY) {
                shapeMaxY = floats[i];
            }

        } else {

            // Check X values
            if (floats[i] < shapeMinX) {
                shapeMinX = floats[i];
            }
            if (floats[i] > shapeMaxX) {
                shapeMaxX = floats[i];
            }

        }
    }

    return {
            shapeMinX: shapeMinX,
            shapeMaxX: shapeMaxX,
            shapeMinY: shapeMinY,
            shapeMaxY: shapeMaxY
        };

}


function isOdd(num) {
    return num % 2;
}
JSdc
  • 121
  • 1
  • 8
0

the easiest way would be to reposition / center the offset. all scaling and moving will be based on your new offset position.

group.offset( { x: group.width() * .5, y: group.height() * .5 } );

http://kineticjs.com/docs/Kinetic.Group.html