在Kineticjs中将其从父母中移除后保持形状的外观

时间:2013-08-16 12:09:05

标签: kineticjs

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

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

2 个答案:

答案 0 :(得分:1)

好吧......这是你问题的黑客代码 - fiddle

那么我基本上做了什么? 我更改了Kinetic.Image的绘图功能的一部分,现在如下所示:(您可以从here下载修改后的KineticJS4.6.0

        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 :(得分:-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()为止。