Вычисление перетаскивания окна и скоса в JavaScript

Я использую JavaScript и пытаюсь сделать скошенный эффект на отделение.

Во-первых, смотрите на это видео: http://www.youtube.com/watch?v=ny5Uy81smpE (0:40-0:60 должен быть достаточно). Видео показывает некоторые хорошие преобразования (скос) при перемещении окна. То, что я хочу сделать, является тем же самым: скашивать отделение, когда я перемещаю его.

В настоящее время у меня просто есть простое простое отделение:

Я сделал простое скошенное преобразование с помощью свойства преобразования CSS3, но моя реализация является багги. Есть ли хорошие учебные руководства или сайты математики или ресурсы, которые описывают логику позади этого? Я знаю, что JavaScript и CSS достаточно хорошо реализуют, если я просто знал логику и математику. Я пытался читать исходный код FreeWins, но я не хорош в C.

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

/**
 * The draggable object.
 */
Draggable = function(targetElement, options) {
    this.targetElement = targetElement;

    // Initialize drag data.
    this.dragData = {
        startX: null,
        startY: null,
        lastX: null,
        lastY: null,
        offsetX: null,
        offsetY: null,
        lastTime: null,
        occuring: false
    };

    // Set the cursor style.
    targetElement.style.cursor = 'move';

    // The element to move.
    this.applyTo = options.applyTo || targetElement;

    // Event methods for "mouse down", "up" and "move".
    // Mouse up and move are binded to window.
    // We can attach and deattach "move" and "up" events as needed.
    var me = this;

    targetElement.addEventListener('mousedown', function(event) {
        me.onMouseDown.call(me, event);
    }, false);

    this.mouseUp = function(event) {
        me.onMouseUp.call(me, event);
    };

    this.mouseMove = function(event) {
        me.onMouseMove.call(me, event);
    };
};

/**
 * The mouse down event.
 * @param {Object} event
 */
Draggable.prototype.onMouseDown = function(event) {
    // New drag event.
    if (this.dragData.occuring === false) {
        this.dragData.occuring = true;

        this.dragData.startX = this.dragData.lastX = event.clientX;
        this.dragData.startY = this.dragData.lastY = event.clientY;
        this.dragData.offsetX = parseInt(this.applyTo.style.left, 10) - event.clientX;
        this.dragData.offsetY = parseInt(this.applyTo.style.top, 10) - event.clientY;
        this.dragData.lastTime = (new Date()).getTime();

        // Mouse up and move events.
        var me = this;
        window.addEventListener('mousemove', this.mouseMove, false);
        window.addEventListener('mouseup', this.mouseUp, false);
    }
};

/**
 * The mouse movement event.
 * @param {Object} event
 */
Draggable.prototype.onMouseMove = function(event) {
    if (this.dragData.occuring === true) {
        // He is dragging me now, we move if there is need for that.
        var moved = (this.dragData.lastX !== event.clientX || this.dragData.lastY !== event.clientY);

        if (moved === true) {
            var element = this.applyTo;

            // The skew animation. :)
            var skew = (this.dragData.lastX - event.clientX) * 1;
            var limit = 25;
            if (Math.abs(skew) > limit) {
                skew = limit * (skew > 0 ? 1 : -1);
            }

            var transform = 'translateX(' + (event.clientX + this.dragData.offsetX - parseInt(element.style.left, 10)) + 'px)';
            transform += 'translateY(' + (event.clientY + this.dragData.offsetY - parseInt(element.style.top, 10)) + 'px)';
            transform += 'skew(' + skew + 'deg)';
            element.style.MozTransform = transform;
            element.style.webkitTransform = transform;

            this.dragData.lastX = event.clientX;
            this.dragData.lastY = event.clientY;

            this.dragData.lastTime = (new Date()).getTime();
        }
    }
};

/**
 * The mouse up event.
 * @param {Object} event
 */
Draggable.prototype.onMouseUp = function(event) {
    this.dragData.occuring = false;
    var element = this.applyTo;

    // Reset transformations.
    element.style.MozTransform = '';
    element.style.webkitTransform = '';

    // Save the new position.
    element.style.left = (this.dragData.lastX + this.dragData.offsetX) + 'px';
    element.style.top = (this.dragData.lastY + this.dragData.offsetY) + 'px';

    // Remove useless events.
    window.removeEventListener('mousemove', this.mouseMove, false);
    window.removeEventListener('mousemove', this.mouseUp, false);
};

В настоящее время моя система перетаскивания является багги и простой. Мне нужно больше информации о логике, которую я должен применять.

18
задан gblazex 13 July 2010 в 13:43
поделиться

1 ответ

Вау, идея потрясающая. :) Я немного почистил ваш код и решил проблемы с инициализацией. Теперь он отлично работает в Firefox и Chrome (хотя вы говорили, что не должен).

Несколько замечаний:

  • вам нужно захватить начальные top и left позиции при инициализации (getBoundingClientRect)
  • храните ссылки типа this.dragData и element.style для краткости и более быстрого выполнения
  • dragData можно инициализировать как пустой объект. Это нормально в javascript. Вы можете добавить свойства позже.
  • options должен быть условно инициализирован как пустой объект, так что вы можете взять ноль опций
  • moved и dragData.occuring были совершенно бесполезны из-за управления событиями
  • preventDefault нужен для того, чтобы не выделять текст при перетаскивании
  • вы можете захотеть отслеживать z-indexes, чтобы активный элемент всегда был виден

Удачи!

Код [Посмотреть в действии]

/**
 * The draggable object.
 */
Draggable = function(targetElement, options) {
    this.targetElement = targetElement;

    // we can take zero options
    options = options || {};

    // Initialize drag data.

    // @props: startX, startY, lastX, lastY,
    // offsetX, offsetY, lastTime, occuring
    this.dragData = {};

    // Set the cursor style.
    targetElement.style.cursor = 'move';

    // The element to move.
    var el = this.applyTo = options.applyTo || targetElement;

    // Event methods for "mouse down", "up" and "move".
    // Mouse up and move are binded to window.
    // We can attach and deattach "move" and "up" events as needed.
    var me = this;

    targetElement.addEventListener('mousedown', function(event) {
        me.onMouseDown.call(me, event);
    }, false);

    this.mouseUp = function(event) {
        me.onMouseUp.call(me, event);
    };

    this.mouseMove = function(event) {
        me.onMouseMove.call(me, event);
    };

    // initialize position, so it will
    // be smooth even on the first drag
    var position  = el.getBoundingClientRect();
    el.style.left = position.left + "px";
    el.style.top  = position.top  + "px";
    el.style.position = "absolute";
    if (el.style.zIndex > Draggable.zindex)
      Draggable.zindex = el.style.zIndex + 1;
};

Draggable.zindex = 0;

/**
 * Sets the skew and saves the position
 * @param {Number} skew
 */
Draggable.prototype.setSkew = function(skew) {

    var data  = this.dragData;
    var style = this.applyTo.style;

    // Set skew transformations.
    data.skew = skew;
    style.MozTransform    = skew ? 'skew(' + skew + 'deg)' : '';
    style.webkitTransform = skew ? 'skew(' + skew + 'deg)' : '';

    // Save the new position.
    style.left = (data.lastX + data.offsetX) + 'px';
    style.top  = (data.lastY + data.offsetY) + 'px';
}

/**
 * The mouse down event.
 * @param {Object} event
 */
Draggable.prototype.onMouseDown = function(event) {

    var data = this.dragData;

    // New drag event.
    var style = this.applyTo.style;

    data.startX   = data.lastX = event.clientX;
    data.startY   = data.lastY = event.clientY;
    data.offsetX  = parseInt(style.left, 10) - event.clientX;
    data.offsetY  = parseInt(style.top,  10) - event.clientY;
    style.zIndex  = Draggable.zindex++;
    data.lastTime = (new Date()).getTime();

    // Mouse up and move events.
    window.addEventListener('mousemove', this.mouseMove, false);
    window.addEventListener('mouseup', this.mouseUp, false);
    event.preventDefault(); // prevent text selection
};

/**
 * The mouse movement event.
 * @param {Object} event
 */
Draggable.prototype.onMouseMove = function(event) {

    // He is dragging me now
    var me      = this;
    var data    = me.dragData;
    var element = me.applyTo;
    var clientX = event.clientX;
    var clientY = event.clientY;

    data.moving = true;

    // The skew animation. :)
    var skew  = (data.lastX - clientX) * 1;
    var limit = 25;

    if (Math.abs(skew) > limit) {
        skew = limit * (skew > 0 ? 1 : -1);
    }

    var style = element.style;
    var left  = parseInt(style.left, 10);
    var top   = parseInt(style.top,  10);

    var transform =
          'translateX(' + (clientX + data.offsetX - left) + 'px)' +
          'translateY(' + (clientY + data.offsetY - top)  + 'px)' +
          'skew(' + skew + 'deg)';

    style.MozTransform    = transform;
    style.webkitTransform = transform;

    data.lastX = clientX;
    data.lastY = clientY;

    data.lastTime = (new Date()).getTime();

    // here is the cooldown part in order
    // not to stay in disorted state
    var pre = skew > 0 ? 1 : -1;
    clearInterval(data.timer);
    data.timer = setInterval(function() {
      var skew = data.skew - (pre * 10);
      skew = pre * skew < 0 ? 0 : skew;
      me.setSkew(skew);
      if (data.moving || skew === 0)
        clearInterval(data.timer);
   }, 20);  
   data.moving = false;
};

/**
 * The mouse up event.
 * @param {Object} event
 */
Draggable.prototype.onMouseUp = function(event) {

    this.setSkew('');

    // Remove useless events.
    window.removeEventListener('mousemove', this.mouseMove, false);
    window.removeEventListener('mousemove', this.mouseUp, false);
};
32
ответ дан 30 November 2019 в 07:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: