对可以拖动的元素应用撤消重做(拖放)

时间:2011-04-11 06:16:31

标签: javascript svg undo-redo

我想在svgElements上实现可以用javascript拖动的功能我该怎么做...

我用鼠标实现了这个

当鼠标出现时,我保存x和y位置,对象id,对象类型(圆形,矩形等)

任何人都可以告诉......这是实施的好方法吗?

5 个答案:

答案 0 :(得分:2)

我在示例中看到一个小问题,有时候你会忘记这一点。

var history = {
    stack   : [],
    counter : -1,
    add     : function(item){
        this.stack[++this.counter] = item;
        this.doSomethingWith(item);

        // delete anything forward of the counter
        this.stack.splice(this.counter+1);
    },
    undo : function(){
        this.doSomethingWith(this.stack[--this.counter]);
    },
    redo : function(){
        this.doSomethingWith(this.stack[++this.counter]);
    },
    doSomethingWith : function(item){
        // show item
    }
};

答案 1 :(得分:1)

如果您一直在询问如何实现撤消/重做功能,那么它非常简单:您有一系列操作和一个计数器。您可以在操作发生时将新元素推送到数组上,并在人们点击撤消时向后推进。

非常基本的实施:

var history = {
    stack   : [],
    counter : -1,
    add     : function(item){
        this.stack[++counter] = item;
        this.doSomethingWith(item);

        // delete anything forward of the counter
        this.stack.splice(this.counter+1);
    },
    undo : function(){
        this.doSomethingWith(this.stack[--counter]);
    },
    redo : function(){
        this.doSomethingWith(this.stack[++counter]);
    },
    doSomethingWith : function(item){
        // show item
    }
};

请注意,应该进行基本的错误检查,以确定计数器不会超出边界,并且您可能希望在撤消的情况下将“撤消”信息传递到doSomethingWith,但所有这些都是应用具体

答案 2 :(得分:1)

cwolves描述了撤销/重做功能的良好结构。

你是对的,在鼠标操作期间,你会想要存储历史记录,但你也想要存储在鼠标按下期间被操纵的对象的原始位置,这样你就有了当你撤消移动时拥有它。

如果您最后更进一步,并允许缩放,那么您将需要存储完整的原始变换,例如“translate(10,10)scale(1.2,1.2)rotate(90)”,对于历史记录,还要有一个基线来应用拖动缩放操作。

答案 3 :(得分:1)

我找到了一个更好的结构,没有计数器,索引转换或限制处理问题。 只需2个堆叠即可完成平衡的“完成”和“恢复”操作。

var history = function() {
    this.done = this.reverted = [];
    var self = this;

    this.add = function(item) {
        self.done.push(item);

        // delete anything forward
        self.reverted = [];
    };

    this.undo = function() {
        var item = self.done.pop();

        if (item) {
            self.reverted.push(item);
        }

        return item;
    };

    this.redo = function() {
        var item = self.reverted.pop();

        if (item) {
            self.done.push(item);
        }

        return item;
    };
};

答案 4 :(得分:0)

上述代码存在一些问题。 我试图使用它们,并发现我必须在它开始向下运行数组之前先进行两次撤销。

所以说我做过[0]完成[1]完成[2]。 完成[2]刚刚保存到数组中。如果我点击撤消,它会返回。你不想要那个。它正在取代现有的东西。但是再次点击撤消,然后你得到你以前的代码。

我的,因为我有一个具有不同编辑模式的拖放编辑器。拖放元素。编辑元素HTML /图片。排序元素。

$(“#neoContentContainer”)包含所有编辑器html。 您可以通过点击,mousedow等调用editor_add ...看到它是一个您可以轻松调用的函数。

function editor_add(){
    undo.push($("#neoContentContainer").html());
    update_buttons();
}
function editor_undo(){
    var item = undo.pop();
    // prevent undo/redo from undoing to the same HTML currently shown. 
    if(item == $("#neoContentContainer").html()){
        redo.push(item);
        item = undo.pop();
    }
    if(item){
        redo.push(item);
        $("#neoContentContainer").html(item);
    }
    update_buttons();
}
function editor_redo(){
    var item = redo.pop();
    if(item == $("#neoContentContainer").html()){
        undo.push(item);
        item = redo.pop();
    }
    if(item){
        undo.push(item);
        $("#neoContentContainer").html(item);
    }
    update_buttons();
}
function update_buttons(){
    if(undo.length == 0){
        $('button[data-id="undo"]').attr('disabled',true);
    } else {
        $('button[data-id="undo"]').attr('disabled',false);
    }

    if(redo.length == 0){
        $('button[data-id="redo"]').attr('disabled',true);
    } else {
        $('button[data-id="redo"]').attr('disabled',false);
    }
}

https://jsfiddle.net/s1L6vv5y/

不完美,但得到它的主旨。 (仍然想知道什么时候我们可以获得一线爆炸!!!!设备在STACKOVERFLOW !!:)

所以当我的页面加载时,我运行:editor_add(); 因为当他们做某事时,需要撤消某些事情!

现在,每当他们放弃某些东西时,我会对我运行的东西进行排序:editor_add();花了我一整天,现在意识到这对我来说非常简单。

所以这个很好......

var history = function() {
    this.done = this.reverted = [];
    var self = this;

    this.add = function(item) {
        self.done.push(item);
    };

    this.undo = function() {
        if(done.length >= 3){
            var undo_item = self.done.pop();
            self.reverted.push(undo_item);
        }

        var item = self.done.pop(); 
        if (item) {
            self.reverted.push(item);
        }

        return item;
    };

    this.redo = function() {
        if(reverted.length >= 3){
            var revert_item = self.reverted.pop();
            self.done.push(revert_item);
        }
        var item = self.reverted.pop();
        if (item) {
            self.done.push(item);
        }

        return item;
    };
};

在遍历数组之前,您不想清除重做。

(猜测在编辑之前登录有帮助!)