如何使用拖动使对象旋转,如何获得围绕原点的旋转点使用sin或cos?

时间:2013-01-30 08:39:37

标签: javascript jquery css3 math

我一直在寻找很长时间,但找不到更好的方法来解决我的问题,
使div可拖动,旋转并调整每个句柄的大小,如同这两个示例1 2,现在它可以拖动,但旋转..

关于Prasanth K CChangoYi Jiang ..的回答,这些代码可能不正确,
1。它应该在原点周围有一个旋转点 2.需要考虑半径。
但我不知道如何使用sin或cos来使旋转考虑半径?
任何建议将不胜感激。 http://jsfiddle.net/tBgLh/8/

var dragging = false, target_wp;   
$('.handle').mousedown(function(e) {
    var o_x = e.pageX, o_y = e.pageY; // origin point
    e.preventDefault();
    e.stopPropagation();
    dragging = true;
    target_wp=$(e.target).closest('.draggable_wp');

    $(document).mousemove(function(e) {
        if (dragging) {
            var s_x = e.pageX, s_y = e.pageY; // start rotate point
            if(s_x !== o_x && s_y !== o_y){ //start rotate
                var s_rad = Math.atan2(s_y, s_x);
                var degree = (s_rad * (360 / (2 * Math.PI)));
                target_wp.css('-moz-transform', 'rotate(' + degree + 'deg)');
                target_wp.css('-moz-transform-origin', '50% 50%');
                target_wp.css('-webkit-transform', 'rotate(' + degree + 'deg)');
                target_wp.css('-webkit-transform-origin', '50% 50%');
                target_wp.css('-o-transform', 'rotate(' + degree + 'deg)');
                target_wp.css('-o-transform-origin', '50% 50%');
                target_wp.css('-ms-transform', 'rotate(' + degree + 'deg)');
                target_wp.css('-ms-transform-origin', '50% 50%');
            }
        }
    })
    $(document).mouseup(function() {
        dragging = false
    })
})// end mousemove

HTML

<div class="draggable_wp">
    <div class="el"></div>
    <div class="handle"></div>
</div>

2 个答案:

答案 0 :(得分:21)

您的方法存在两个问题:

  1. 原点不应该是用户点击的位置(即句柄),而是div中的固定点:

    target_wp=$(e.target).closest('.draggable_wp');
    //var o_x = e.pageX, o_y = e.pageY; // origin point
    var o_x = target_wp.offset().left,
        o_y = target_wp.offset().top; // origin point
    

    也会使用点击的点,但是对于其他内容(稍后):

    var h_x = e.pageX, h_y = e.pageY; // clicked point
    

    最后,原点应该是固定的(即不应在旋转之间改变)。一种方法是将其保留为data属性(但还有其他选项):

    if ( !target_wp.data("origin") )
        target_wp.data("origin", { left:target_wp.offset().left,
                                   top:target_wp.offset().top    });
    var o_x = target_wp.data("origin").left, 
        o_y = target_wp.data("origin").top; // origin point
    

    更新:原点的一个好选择是CSS属性transform-origin,如果存在的话 - 它应该确保鼠标尽可能地跟随句柄。然而,这是一个实验性特征,因此实际结果可能会有所不同。附:我不确定将它设置为50% 50%是一个好主意,因为转换本身可能会改变元素的宽度和高度,顶部和左侧。

  2. 要查找角度,您不应仅在鼠标点上调用atan2,因为它只会计算该点与页面左上角之间的角度。您想要该点与原点之间的角度:

    var s_rad = Math.atan2(s_y - o_y, s_x - o_x); // current to origin
    

    那会引导你halfway,但它仍会表现得很奇怪(它会围绕元素原点旋转,但不会像你期望的那样跟随句柄)。要使其跟随手柄,您应该调整相对于单击点的角度 - 这将作为旋转量的基础:

    s_rad -= Math.atan2(h_y - o_y, h_x - o_x); // handle to origin
    

    之后你得到轮换working(至少一次用户迭代)。

  3. 您会注意到手柄没有精确跟随鼠标,原因是原点的选择 - 默认为元素的上/左角。将其调整到元素内部的某个位置(可能使用data-属性),它应该按预期工作。

    但是,如果用户多次与手柄交互,仅仅设置旋转角度是不够的,您必须更新在上次迭代期间的任何内容。所以我添加了last_angle var,它将在第一次点击时设置,然后在拖动过程中添加到最终角度:

    // on mousedown
    last_angle = target_wp.data("last_angle") || 0;
    
    // on mousemove
    s_rad += last_angle; // relative to the last one
    
    // on mouseup    
    target_wp.data("last_angle", s_rad);
    

    这是最终的working example。 (注意:我修复了鼠标处理程序的嵌套,因此每次单击后都不会再添加)

    $(function () {
        var dragging = false,
            target_wp,
            o_x, o_y, h_x, h_y, last_angle;
        $('.handle').mousedown(function (e) {
            h_x = e.pageX;
            h_y = e.pageY; // clicked point
            e.preventDefault();
            e.stopPropagation();
            dragging = true;
            target_wp = $(e.target).closest('.draggable_wp');
            if (!target_wp.data("origin")) target_wp.data("origin", {
                left: target_wp.offset().left,
                top: target_wp.offset().top
            });
            o_x = target_wp.data("origin").left;
            o_y = target_wp.data("origin").top; // origin point
            
            last_angle = target_wp.data("last_angle") || 0;
        })
    
        $(document).mousemove(function (e) {
            if (dragging) {
                var s_x = e.pageX,
                    s_y = e.pageY; // start rotate point
                if (s_x !== o_x && s_y !== o_y) { //start rotate
                    var s_rad = Math.atan2(s_y - o_y, s_x - o_x); // current to origin
                    s_rad -= Math.atan2(h_y - o_y, h_x - o_x); // handle to origin
                    s_rad += last_angle; // relative to the last one
                    var degree = (s_rad * (360 / (2 * Math.PI)));
                    target_wp.css('-moz-transform', 'rotate(' + degree + 'deg)');
                    target_wp.css('-moz-transform-origin', '50% 50%');
                    target_wp.css('-webkit-transform', 'rotate(' + degree + 'deg)');
                    target_wp.css('-webkit-transform-origin', '50% 50%');
                    target_wp.css('-o-transform', 'rotate(' + degree + 'deg)');
                    target_wp.css('-o-transform-origin', '50% 50%');
                    target_wp.css('-ms-transform', 'rotate(' + degree + 'deg)');
                    target_wp.css('-ms-transform-origin', '50% 50%');
                }
            }
        }) // end mousemove
        
        $(document).mouseup(function (e) {
            dragging = false
            var s_x = e.pageX,
                s_y = e.pageY;
            
            // Saves the last angle for future iterations
            var s_rad = Math.atan2(s_y - o_y, s_x - o_x); // current to origin
            s_rad -= Math.atan2(h_y - o_y, h_x - o_x); // handle to origin
            s_rad += last_angle;
            target_wp.data("last_angle", s_rad);
        })
    })
    .draggable_wp {
        position: absolute;
        left: 150px;
        top: 150px;
    }
    .el {
        width: 25px;
        height: 50px;
        background-color: yellow;
    }
    .handle {
        position: absolute;
        left:0;
        top:-75;
        width: 25px;
        height: 25px;
        background-color: blue;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <div class="draggable_wp">
        <div class="el"></div>
        <div class="handle"></div>
    </div>

答案 1 :(得分:0)

他们在变换属性中使用矩阵函数。您可以通过旋转矩阵muliplay您的矩阵(元素坐标)来旋转元素。

transform:  matrix(a, c, b, d, tx, ty)

此处有更多信息和示例:The CSS3 matrix() Transform for the Mathematically Challenged