2013-08-16 15 views
1

我的情况是,我的形状(图像)的父母是某个组。形状,群体和其他可能的父母可能对他们有各种各样的立场和转变。当我从组中删除形状并将其添加到其图层时,是否有一种简单的方法可以将所有形状再次应用于形状,使其看起来像屏幕上没有变化?在Kineticjs中将其从父项中移除后保持形状外观

我所做的是使用getAbsolutePosition来保存位置,但我需要转换,例如旋转也要跟着。在文档中,我看到了getAbsoluteTransform,但我没有看到将该变换应用于形状。

回答

1

好吧......这里是你的问题被黑客入侵的代码 - fiddle

所以我基本上是做? 我改变了Kinetic.Image的绘图函数的一部分,现在读取如下:(你可以下载修改后的KineticJS4.6。0here

 drawFunc: function(canvas) { 
     if(this.overrideTransform){ 
      var m2 = this.getAttr('OverrideTransform').getMatrix(); 
      canvas.context.setTransform(m2[0], m2[1], m2[2], m2[3], m2[4], m2[5]); 
     } 
     var width = this.getWidth(), 
     ... 

,然后设置参数overrideTransform为true与设置属性OverrideTransform包含来自组移动到层...这样

document.getElementById('a2').addEventListener('click', function() { 
     var yoda = yodaGroup.get('#yoda')[0]; 
     if (typeof yoda != 'undefined') { 
      var currT = yoda.getAbsoluteTransform(); 
      yoda.moveTo(layer); 
      yoda.overrideTransform = true; 
      yoda.setAttr('OverrideTransform',currT); 
     } 
     layer.draw(); 
    }); 

及以下之前的绝对变换沿是完整的代码。

function loadImages(sources, callback) { 
    var images = {}; 
    var loadedImages = 0; 
    var numImages = 0; 
    for (var src in sources) { 
     numImages++; 
    } 
    for (var src in sources) { 
     images[src] = new Image(); 
     images[src].onload = function() { 
      if (++loadedImages >= numImages) { 
       callback(images); 
      } 
     }; 
     images[src].src = sources[src]; 
    } 
} 

function initStage(images) { 
    var stage = new Kinetic.Stage({ 
     container: 'container', 
     width: 578, 
     height: 400 
    }); 
    var darthVaderGroup = new Kinetic.Group({ 
     x: 270, 
     y: 100, 
     draggable: true 
    }); 
    var yodaGroup = new Kinetic.Group({ 
     x: 100, 
     y: 110, 
     draggable: true 
    }); 
    var layer = new Kinetic.Layer({ 
     x: 0, 
     y: 0, 
    }); 

    layer.add(darthVaderGroup); 
    layer.add(yodaGroup); 
    stage.add(layer); 

    // darth vader 
    var darthVaderImg = new Kinetic.Image({ 
     x: 0, 
     y: 0, 
     image: images.darthVader, 
     width: 200, 
     height: 138, 
     name: 'image', 
     id: 'vader' 
    }); 

    yodaGroup.add(darthVaderImg); 
    // yoda 
    var yodaImg = new Kinetic.Image({ 
     x: 10, 
     y: 10, 
     image: images.yoda, 
     width: 93, 
     height: 104, 
     name: 'image', 
     id: 'yoda' 
    }); 

    yodaGroup.add(yodaImg); 
    stage.draw(); 

    document.getElementById('a2').addEventListener('click', function() { 
     var yoda = yodaGroup.get('#yoda')[0]; 
     if (typeof yoda != 'undefined') { 
      var currT = yoda.getAbsoluteTransform(); 
      yoda.moveTo(layer); 
      yoda.overrideTransform = true; 
      yoda.setAttr('OverrideTransform',currT); 
     } 
     layer.draw(); 
    }); 

    document.getElementById('c').addEventListener('click', function() { 
     yodaGroup.rotateDeg(90); 
     layer.draw(); 
    });  
} 

var sources = { 
    darthVader: 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg', 
    yoda: 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg' 
}; 
loadImages(sources, initStage); 

我喜欢这个工作的挑战!还要感谢@projeqht,我用他的小提琴作为起点

+1

对于代表OP所需的代码。但是,这不会将#yoda从其正常的动态变换命令中断开 - 例如后续的yoda.rotate(Math.PI/8)?我会提到,篡改一个库的基本代码可能会有问题维护...但我已经做到了这一点,我不能抱怨 - 他内疚地说) – markE

+0

你有没有在动力学中找到过一个位置API可以让你“合法地”设置/重置节点的变换矩阵 - 我不能。几个.getAbsoluteTransform加上一些矩阵乘法加上一个final.setTransform将解决这个任务。如果您觉得这样做的话,我会在github上向KineticJS提出拉取请求,让Eric添加合法的node.setTransformMatrix()。 – markE

+1

@markE在上面的黑客攻击中,我只是为了图像而做的,但是提交给Eric的人适用于所有的Kinetic.Shape()。至于合法的方式,有一种方法_setTransform()可以复制矩阵,但不幸的是,在绘制形状时不考虑它。因为我的第一次尝试是颠倒当前(移动后)变换并乘以绝对变换并设置在这里,但它不起作用。 – Ani

-2

您确定要删除该组的节点?使用.hide()函数隐藏它可能会更好。

查看jsfiddle的例子。

无论哪种方式,只要您不使用.destroy(),形状将保留其数据,外观和转换。你只需要找出一种方法去除或隐藏的节点。

如果你决定隐藏去:

var yodaImg = new Kinetic.Image({ 
     x: 0, 
     y: 0, 
     image: images.yoda, 
     width: 93, 
     height: 104, 
     name: 'image', 
     id: 'yoda' 
    }); 

document.getElementById('a').addEventListener('click', function() { 
    var yoda = layer.get('#yoda')[0]; 
    (yoda.isVisible()) ? yoda.hide() : yoda.show(); 
    layer.draw(); 
}); 

你可以简单地使用ID重新选择节点的问题,然后用.show()再次显示图像,到底在哪里。

如果你决定删除去:

阶段初始化:

var secretLayer = new Kinetic.Layer(); 
stage.add(secretLayer); 
secretLayer.hide(); 

删除(或者更确切地说,移动)图像到新的隐藏secretLayer:

document.getElementById('a2').addEventListener('click', function() { 
    var yoda = layer.get('#yoda')[0]; 
    var yoda2 = secretLayer.get('#yoda')[0]; 
    if (typeof yoda != 'undefined') yoda.moveTo(secretLayer); 
    if (typeof yoda2 != 'undefined') yoda2.moveTo(yodaGroup); 
    layer.draw(); 
}); 

secretLayer作为介质以从给定图层中移除对象,但仍然会为您提供便利的功能,使用.get()Kinetic.Container#get

如果您不想使用另一个图层只是删除/移动对象并隐藏它们,那么您需要使用自己的数据结构来访问已删除的节点。就像删除它们并将它们追加到数组中以在稍后调用它们时进行访问。

无论哪种方式,节点将保持其转换,直到你destroy()他们。