1

I love KineticJS, its speed, marriage with GSAP, but what is making my head spin is there a way to freely transform KineticJS objects like the way in FabricJS? Here is the link reference to what I am trying to say: http://fabricjs.com/customization/ I don't want to use FabricJs as its really slow, and its low performance evident from various unit tests.

I am really looking forward to finding a way to be able to freely transform object in KineticJS as it would make life so much easier.

Is there a way to do it?

Thanks for your help, Praney

4

3 回答 3

6

正如markE 所说, Eric(KineticJS 的创建者)教程网站上的本教程是 KineticJS 中所有自由转换的基础。

我将详细介绍实际的自由变换逻辑,主要有两个功能:

function addAnchor(group, x, y, name) {
  var stage = group.getStage();
  var layer = group.getLayer();

  //Create the anchor shape
  var anchor = new Kinetic.Circle({
    x: x,
    y: y,
    stroke: '#666',
    fill: '#ddd',
    strokeWidth: 2,
    radius: 8,
    name: name,
    draggable: true,
    dragOnTop: false
  });

  //Calls the update function which handles the transform logic
  anchor.on('dragmove', function() {
    update(this);
    layer.draw();
  });
  //When the anchor is selected, we want to turn dragging off for the group
  //This is so that only the anchor is draggable, and we can transform instead of drag
  anchor.on('mousedown touchstart', function() {
    group.setDraggable(false);
    this.moveToTop();
  });
  //Turn back on draggable for the group
  anchor.on('dragend', function() {
    group.setDraggable(true);
    layer.draw();
  });
  // add hover styling
  anchor.on('mouseover', function() {
    var layer = this.getLayer();
    document.body.style.cursor = 'pointer';
    this.setStrokeWidth(4);
    layer.draw();
  });
  anchor.on('mouseout', function() {
    var layer = this.getLayer();
    document.body.style.cursor = 'default';
    this.setStrokeWidth(2);
    layer.draw();
  });

  group.add(anchor);
}

就像名字所说的那样,该addAnchor函数将单个锚点(或自由变换句柄)添加到Kinetic.Group. 默认情况下它使用 aKinetic.Circle但实际上你可以使用任何你想要的形状。

  • group- 要将锚添加到的组
  • x- 锚点的 x 位置
  • y- 锚点的 y 位置
  • name- 锚的名称(通常描述锚所代表的位置,如topLeftbottomRight

您会注意到一堆events附加到新创建的锚点,其中大多数都非常简单,但您要注意的是dragmove事件 - 这个事件是调用处理所有逻辑update的函数的事件转换组/节点。需要注意的update是,对于拖动锚点的每个像素都会调用该函数。

本教程使用 4 个角锚(因此每个组/节点调用 addAnchor 4 次),但如果您想要 8 个锚(4 个角 - 4 个边),那么您只需调整逻辑以正确定位锚并移动锚转换时正确。

顺便说一句,我们将 Anchors 添加到 Group 的原因是因为我们需要它们与相关节点进行分组,并通过拖动和转换来坚持每个节点。

第二种方法是update函数:

function update(activeAnchor) {
  var group = activeAnchor.getParent();

  //Get each anchor inside the group, by name. Keep a standard set of names for every anchor you use and note they have to be names not ids because there will be multiple anchors named .topLeft in your app
  var topLeft = group.get('.topLeft')[0];
  var topRight = group.get('.topRight')[0];
  var bottomRight = group.get('.bottomRight')[0];
  var bottomLeft = group.get('.bottomLeft')[0];
  var image = group.get('.image')[0];

  var anchorX = activeAnchor.getX();
  var anchorY = activeAnchor.getY();

  // update anchor positions
  switch (activeAnchor.getName()) {
    case 'topLeft':
      //When topLeft is being dragged, topRight has to update in the Y-axis
      //And bottomLeft has to update in the X-axis
      topRight.setY(anchorY);
      bottomLeft.setX(anchorX);
      break;
    case 'topRight':
      topLeft.setY(anchorY);
      bottomRight.setX(anchorX);
      break;
    case 'bottomRight':
      bottomLeft.setY(anchorY);
      topRight.setX(anchorX); 
      break;
    case 'bottomLeft':
      bottomRight.setY(anchorY);
      topLeft.setX(anchorX); 
      break;
  }

  image.setPosition(topLeft.getPosition());

  //New height and width are calculated with a little math
  //by calculating the distance between the update anchor positions.
  var width = topRight.getX() - topLeft.getX();
  var height = bottomLeft.getY() - topLeft.getY();
  if(width && height) {
    image.setSize(width, height);
  }
}

update函数只接受一个参数:activeAnchor被拖动的锚点。

之后,它会选择组内的其他锚点(使用您需要为每个节点提供的静态名称并在整个应用程序中保持一致),以便我们可以activeAnchor在拖动时转换它们的位置。

如果您使用 8 个锚点而不是 4 个锚点,switch 语句可能会变得非常大。这是因为您需要考虑在拖动其中一个锚点时翻译几乎所有其他锚点。

以 8 个锚点为例:如果拖动topLeft锚点,则需要更新锚点的y位置、topRight锚点的x位置,bottomLeft对于topMidleftMid锚点,您需要调整x、y值以保持在其他锚。

更新锚位置后,该函数处理调整形状大小的逻辑。请注意,形状是由var image = group.get('.image')[0];但是选择的,您可以做的是使用该get功能按类型选择并执行以下操作:

var shape = group.get('Shape')[0];

显然,如果每组只有 1 个形状(用于变换)+ 4 或 8 个锚点,这将最有效。

如果您有任何其他问题或意见,请告诉我!祝你好运!

于 2013-09-13T14:05:15.547 回答
0

该项目添加了一个转换工具(调整大小)和一些可以用作基础的不错的处理程序: https ://github.com/soloproyectos/jquery.transformtool

于 2014-02-04T11:54:36.540 回答
0

嗨,请参阅我之前对此的回答。只要搜索我的名字。希望它对您有帮助:) 使用 KineticJS 变换(移动/缩放/旋转)形状

我忘了在那里包含 html 标签,所以这里是...... :)``

<!-- INSIDE THE HEAD TAGS -->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- I am using jquery transform tool for kineticjs -->
<script type="text/javascript" src="../lib/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="../lib/jquery.timer-1.0.3.js"></script>
<script type="text/javascript" src="../lib/kinetic-v4.7.4.min.js"></script>
<script type="text/javascript" src="../src/jquery.transformtool-1.0.2.js"></script>
<script type="text/javascript">
                 //PUT THE JAVSCRIPT SNIPPET HERE FROM THE LINK THAT I PROVIDED ABOVE
</script>

//添加 id = 画布的 div 元素和 id = 文件和名称的文件元素 files[] INSIDE THE BODY

于 2014-02-06T09:08:07.323 回答