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

发布于 2024-10-31 09:30:36 字数 168 浏览 2 评论 0原文

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

我已经用鼠标向上实现了

当鼠标向上发生时,我保存 x 和 y 位置、对象 ID、对象类型(圆、直等)

谁能告诉...这是一种很好的实施方式吗?

I want to implement functionality on the svgElements that can be dragged with javascript how could I do this...

I have implemented this with mouse up

When mouse up occurs, I save the x and y position, object id, object type (circle, rect, etc.)

Can any one tell...is this good way to implement?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

满意归宿 2024-11-07 09:30:36

如果您询问如何实现一般撤消/重做功能,那么这相当简单:您有一组操作和一个计数器。当操作发生时,您将新元素推送到数组中;当人们点击撤消时,您将向后退一步。

非常基本的实现:

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
    }
};

请注意,应该进行基本的错误检查,以确保计数器没有超出范围,并且在撤消的情况下,您可能希望将“撤消”信息传递到 doSomethingWith 中,但是所有这些都是特定于应用程序的。

If you're asking how to implement undo/redo functionality in general, it's fairly simple: you have an array of actions and a counter. You push new elements onto the array when actions occur and step backwards when people hit undo.

Very basic implementation:

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
    }
};

Note that there should be basic error checking to see that counter doesn't go beyond bounds and that you may want to pass 'undo' info into doSomethingWith in the case of an undo, but all that is app specific.

淡淡離愁欲言轉身 2024-11-07 09:30:36

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

您是对的,在鼠标松开期间,您需要存储历史记录,但您还需要存储在鼠标按下期间操作的对象的原始位置,这样您就可以在您撤消该移动。

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

cwolves describes a good structure for the undo/redo functionality.

You are correct, that during mouse-up, you'll want to store the history, but you'll also want to store the original location of the object(s) being manipulated during mouse-down so you'll have have it when you undo the move.

If you end up taking it a step further, and allowing scaling, then you'll want to store the complete original transform e.g. "translate(10,10) scale(1.2,1.2) rotate(90)", for history, but also so that you'll have a baseline to apply the drag-scaling action to.

余生共白头 2024-11-07 09:30:36

我发现了一个更好的结构,没有计数器、索引移位或限制处理问题。
只需 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;
    };
};

I found a better structure without counter, index shift or limit handling problems.
Simply 2 stack for "done" and "reverted" action that are balancing.

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;
    };
};
南渊 2024-11-07 09:30:36

上述代码存在一些问题。
我尝试使用它们,发现在它开始沿着阵列向下移动之前,我最初必须点击撤消两次。

所以说我已经完成[0]完成[1]完成[2]。
done[2] 刚刚保存到数组中。如果我点击撤消,它就会返回该内容。你不想要这样。它正在取代现有的东西。但再次点击撤消,然后你就得到了以前的代码。

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

$("#neoContentContainer") 包含所有编辑器 html。
你可以在点击、鼠标按下等时调用 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/

并不完美,但了解其要点。 (仍然想知道我们什么时候可以得到一行换行符!!!!DEVS AT 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;
    };
};

在运行完数组之前,您不想清除重做。

(猜测编辑前登录会有所帮助!)

There are some issues with the above codes.
I attempted to use those and found out that I had to hit undo twice initially before it started going down the array.

So say I have done[0] done[1] done[2].
done[2] was just saved into the array. If I hit undo, it returns that. You dont want that. It is replacing what is already there. But hitting undo again, THEN you get your previous code.

Mine, as I have a drag and drop editor with different modes of edits. Drag and Drop Elements. Edit Elements HTML/Pictures. Sorting elements.

$("#neoContentContainer") contains all editor html.
And you can call editor_add on clicks, mousedowns ect... seeing it is a function you can easily call.

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/

Not perfect, but get the jist of it. (Still wondering when we can get ONE LINE LINE BREAKS!!!! DEVS AT STACKOVERFLOW!! :)

So when my page loads, I run: editor_add();
Because when they do something, it needs to undo to something!

Now every time they drop something, sort things I run editor_add(); Took me all day, now realizing how simple it was this works very well for me.

So with this one, which is good....

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;
    };
};

You do not want to clear the redos until you ran through the array.

(Guess logging in before editing helps!)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文