【问题标题】:Apply Undo Redo on elements that can dragable (drag and drop)对可拖动的元素应用撤消重做(拖放)
【发布时间】:2011-04-11 06:16:31
【问题描述】:

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

我已经用鼠标向上实现了这个

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

谁能告诉...这是实施的好方法吗?

【问题讨论】:

    标签: javascript svg undo-redo


    【解决方案1】:

    如果您要问如何实现一般的撤消/重做功能,这很简单:您有一组动作和一个计数器。当动作发生时你将新元素推入数组,当人们点击撤消时后退。

    非常基本的实现:

    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,但所有这些都是特定于应用程序的。

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

      • 感谢 josh pearce,onmousedown 如果我保存位置,它将节省两次(因为它也保存在 mouseup 上)我已经完成了几乎......但问题是它保存最后一个位置 2 次。 . 当我按下撤消按钮 2 次然后对象撤消(去它的最后一个位置)
      【解决方案3】:

      我找到了一个更好的结构,没有计数器、索引移位或限制处理问题。 只需 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] 完成[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/

        不完美,但要了解它的要点。 (仍然想知道我们什么时候可以得到 ONE LINE LINE BREAKS!!!! 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;
            };
        };
        

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-09-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多