【问题标题】:Calculating window dragging and skewing in JavaScript在 JavaScript 中计算窗口拖动和倾斜
【发布时间】:2011-03-11 11:42:09
【问题描述】:

我正在使用 JavaScript 并试图对 div 产生倾斜效果。

首先,看一下这个视频:http://www.youtube.com/watch?v=ny5Uy81smpE(0:40-0:60 应该足够了)。当您移动窗口时,视频显示了一些不错的转换(倾斜)。我想做的是同样的事情:在我移动 div 时倾斜它。

目前我只有一个简单的 div:

<div id="a" style="background: #0f0; position: absolute; left: 0px; top: 0px;"></div>

我使用 CSS3 的 transform 属性做了一个简单的倾斜变换,但我的实现有问题。是否有很好的教程或数学网站或资源来描述这背后的逻辑?如果我只知道逻辑和数学,我对 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);
};

目前我的拖动系统是错误的和简单的。我需要更多关于我应该应用的逻辑的信息。

【问题讨论】:

    标签: javascript math user-interface draggable effect


    【解决方案1】:

    哇,这个想法摇滚。 :) 我已经清理了你的代码,并解决了初始化问题。现在它在 Firefox 和 Chrome 上对我来说可以正常工作(即使你说不应该)。

    几点说明:

    • 您需要在初始化期间获取起始topleft 位置(getBoundingClientRect
    • 存储 this.dragDataelement.style 等引用以缩短执行速度并加快执行速度
    • dragData 可以初始化为空对象。在javascript中很好。您可以稍后添加属性。
    • options 应该有条件地初始化为一个空对象,这样你就可以取零选项
    • moveddragData.occuring 因为事件管理而完全没用
    • 需要preventDefault,以便在拖动过程中不选择文本
    • 您可能希望跟踪 z-indexes 成为始终可见的活动元素

    玩得开心!

    代码 [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);
    };
    

    【讨论】:

    • 我认为“精湛”可能是在这里使用的词。他要了一杯酒,得到了一口井!每个人都赢了。
    • 非常感谢,但有一个错误。尝试快速移动红黑窗口,然后按住按钮停止鼠标。发生的情况是,即使您不再移动窗口,偏斜也会保持/保持。简而言之:如果您一直按住鼠标左键并做出快速移动,则偏斜将保持不变。如果您找到解决此问题的方法,我将非常乐意接受您的回答;)。
    • 任务完成,陛下! :)
    • 我在 IE8/Win7 上看不到它的运行情况 :(
    • 检查 jsbin.com/aviyi3/38/edit#javascript,html 我编辑添加支持...并查看 ie9 或 ie10
    猜你喜欢
    • 2017-09-15
    • 1970-01-01
    • 2012-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多