【问题标题】:KineticJS Canvas - Scale group from center pointKineticJS Canvas - 从中​​心点缩放组
【发布时间】:2013-03-29 00:45:21
【问题描述】:

我想扩展我的组(图像和其他内容)。

group.setScale(zoom, zoom);

http://jsfiddle.net/K8nK3/

但是当我扩展我的组时,我认为它不是从我的组中心扩展的。我觉得是这样

我希望它从中心缩放,例如

我尝试了更多,但没有成功。我该怎么做呢,谢谢。

【问题讨论】:

  • 不确定动力学,但使用 fabric.js,您只需将 originX/originY 属性更改为中心/中心(从左/上)。
  • 你有任何织物库的例子,比如我的例子,谢谢

标签: javascript canvas html5-canvas kineticjs


【解决方案1】:

[编辑以更好地满足提问者的需求]

以下是从中心点缩放 Kinetic 组的方法

首先我们存储原始组的 centerX 和 centerY 以便我们可以保持组居中:

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

然后我们编写一个自定义缩放方法来缩放组并重新居中:

      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();
      }

这是代码和小提琴: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>

【讨论】:

  • 我的组中有一些对象。我不能这样做。你有别的办法吗?
  • 是的,请参阅我编辑的答案,它应该可以满足您从中心扩展组的需要。
  • 它在我的上下文中不起作用。在我的上下文中,组不包含对象(它没有宽度和高度),并且组可以拖动(当我拖动时再次执行点中心)。我认为“比例点”是偏移的。你能用我的项目再试一次吗?
  • 是的,关于如何将此概念验证自定义为完全符合您需求的东西,您是完全正确的。如果您正在拖动,那么您将需要在拖动之后(或至少在下一次缩放之前)重新计算 group.cx 和 group.cy。如果您没有组的初始宽度和高度,则必须声明要围绕其缩放的任意“中心点”。
  • 如何声明一个中心点,围绕该中心点进行缩放?
【解决方案2】:

您是否尝试过使用偏移属性?即偏移量:[width/2, height/2]

【讨论】:

    【解决方案3】:

    问题 #1:我需要从中心缩放一个组。 问题 #2:Kinetic JS group.getWidth() 和 group.getHeight() 不起作用,除非您在创建时明确设置宽度。 问题 #3:我不知道宽度和高度,我正在动态更改形状。

    这意味着为了试用您的代码,我必须编写自己的 getWidth 和 getHeight 函数。那我就可以用你建议的方法了。

    下面的解决方案。

    (可能有更好的方法,但这是我现在的编程水平......如果有人可以为此添加递归以查看包含包含组的组等的组,那就太好了。)

    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;
    }
    

    【讨论】:

      【解决方案4】:

      最简单的方法是重新定位/居中偏移。所有缩放和移动都将基于您的新偏移位置。

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

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

      【讨论】:

        猜你喜欢
        • 2020-07-24
        • 1970-01-01
        • 2013-08-04
        • 2012-09-04
        • 1970-01-01
        • 2012-09-28
        • 1970-01-01
        • 2018-02-04
        • 2014-05-28
        相关资源
        最近更新 更多