Применить Отменить Повторить к элементам, которые можно перетаскивать (перетаскивание) - PullRequest
0 голосов
/ 11 апреля 2011

Я хочу реализовать функциональность svgElements, которую можно перетаскивать с помощью javascript, как я могу это сделать ...

Я реализовал это с помощью мыши вверх

Когда происходит движение вверх, я сохраняю координаты x и y, идентификатор объекта, тип объекта (круг, прямоугольник и т. Д.)

Может кто-нибудь сказать ... это хороший способ реализации?

Ответы [ 5 ]

2 голосов
/ 08 ноября 2011

Я вижу небольшую проблему в примере, иногда вы забываете это.

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 голос
/ 27 ноября 2014

Я нашел лучшую структуру без проблем со счетчиком, смещением индекса или лимитной обработкой.Просто 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;
    };
};
1 голос
/ 12 апреля 2011

cwolves описывает хорошую структуру для функций отмены / возврата.

Вы правы, что при наведении мыши вы захотите сохранить историю, но вы также захотите сохранить исходное местоположение объекта (ов), которым манипулировали при наведении мыши, так что вы получите имейте это, когда вы отменяете движение.

Если в конечном итоге вы сделаете еще один шаг и разрешите масштабирование, тогда вы захотите сохранить полное исходное преобразование, например «translate (10,10) scale (1.2,1.2) rotate (90)», для истории, но также для того, чтобы у вас была базовая линия для применения действия масштабирования с перетаскиванием.

1 голос
/ 11 апреля 2011

Если вы спрашиваете, как реализовать функцию отмены / возврата в целом, это довольно просто: у вас есть массив действий и счетчик.Вы помещаете новые элементы в массив, когда выполняются действия, и переходите назад, когда люди нажимают отмену.

Очень базовая реализация:

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 в случае отмены, но все это зависит от приложения.

0 голосов
/ 01 июля 2015

Есть некоторые проблемы с вышеуказанными кодами.Я попытался использовать их и обнаружил, что сначала мне пришлось дважды нажать «Отменить», прежде чем он начал спускаться по массиву.

Итак, скажем, я сделал [0] сделано [1] сделано [2].done [2] был просто сохранен в массив.Если я нажму "Отменить", это вернет.Вы этого не хотите.Он заменяет то, что уже есть.Но снова нажмите «Отменить», затем вы получите свой предыдущий код.

Мой, так как у меня есть редактор перетаскивания с различными режимами редактирования.Перетащите элементы.Редактировать элементы HTML / Картинки.Сортировка элементов.

$ ("# neoContentContainer") содержит все редакторы html.И вы можете вызывать editor_add по щелчкам, mousedowns и т. Д., Видя, что это функция, которую вы можете легко вызвать.

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

Вы не хотитеочищайте повторы до тех пор, пока вы не пройдете через массив.

(угадайте, что вход в систему до редактирования помогает!)

...