Calculating window dragging and skewing in JavaScript Calculating window dragging and skewing in JavaScript javascript javascript

Calculating window dragging and skewing in JavaScript


Wow, the idea rocks. :) I've cleaned your code a bit, and solved the problems with initialization. Now it works fine for me on Firefox and Chrome (even though you said it shouldn't).

A few notes:

  • you need to grab the starting top and left positions during initialization (getBoundingClientRect)
  • store references like this.dragData and element.style for shortness and faster execution
  • dragData can be initialized as an empty object. It's fine in javascript. You can add properties later.
  • options should be conditionally initialized as an empty object, so that you can take zero options
  • moved and dragData.occuring were totally useless because of the event management
  • preventDefault is needed in order not to select text during dragging
  • you may want to keep track of z-indexes to be the active element always visible

Have fun!

Code [See it in action]

/** * 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);};