1

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

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

4

2 回答 2

1

好吧......这是你的问题的黑客代码 - 小提琴

那么我本质上做了什么?我更改了绘图函数的一部分Kinetic.Image,现在如下所示:(您可以从此处下载修改后的 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,我用他的小提琴作为起点

于 2013-08-17T00:15:35.707 回答
-2

您确定要从组中删除该节点吗?您最好使用该.hide()功能隐藏它。

有关示例,请参见jsfiddle

无论哪种方式,只要您不使用.destroy(). 您只需要找出一种方法来访问已删除隐藏的节点。

如果您决定使用hide

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()他们。

于 2013-08-16T13:43:17.340 回答