如何使对象随拖动旋转,如何获取围绕原点的旋转点使用sin或cos? [英] How to make object rotate with drag, how to get a rotate point around the origin use sin or cos?

查看:160
本文介绍了如何使对象随拖动旋转,如何获取围绕原点的旋转点使用sin或cos?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在搜索很久,但找不到更好的方法来解决我的问题,

让div可拖动,旋转和调整每个句柄像这样2示例 1 2 ,现在可以拖动,但旋转..

I've been searching long time, but can't find a better way solve my problem,
make div draggable, rotate and resize by each handle like these 2 example 1 2,, now it can be draggable, but rotate..

关于 Prasanth KC Chango Yi Jiang ..的答案,这些代码可能不正确,

1。它应该有一个围绕原点的旋转点。

2.需要考虑半径。


但是我不知道如何使用sin或cos在这里旋转考虑半径?

任何建议将不胜感激。
http://jsfiddle.net/tBgLh/8/

Regarding Prasanth K C, Chango, Yi Jiang ..'s answer, these code maybe not correct,
1. it should have a rotate point around the origin.
2. need to consider radius.

But I don't know how to use sin or cos here to make rotate consider radius?
Any suggestion will be be appreciated. 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>


推荐答案

您的方法有两个问题:


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

  1. The origin shouldn't be where the user clicked (that is the handle), but a fixed point in your 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

也会使用点击的点, (更多):

You will use the clicked point also, but for something else (more later):

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



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

Finally, the origin should be fixed (i.e. should not change between rotations). One way of doing so is preserving it as a data attribute (there are other options though):

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 ,如果存在 - 它应该确保鼠标尽可能接近手柄。这是一个实验性功能,因此实际响应可能会有所不同。 P.S。我不确定将它设置为 50%50%是一个好主意,因为转换本身可能会改变元素的宽度和高度,顶部和左侧。

Update: One good candidate for the origin is the CSS property transform-origin, if present - it should ensure that the mouse follow the handle as closely as possible. This is an experimental feature, however, so the actual resulsts may vary. P.S. I'm not sure setting it to 50% 50% is a good idea, since the transformation itself may vary the element's width and height, top and left.

要找到角度,您不应该仅在鼠标点上调用 atan2 ,因为它将只计算角度在该点和页面的左上角之间。您希望该点与原点之间的角度:

To find the angle, you should not call atan2 on the mouse point only, since it will only calculate the angle between that point and the top left corner of the page. You want the angle between that point and the origin:

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

这会带给你一半,但它仍然会表现奇怪(它将围绕元素原点旋转,但不按照你所期望的句柄)。要跟随手柄,您应该调整相对于点击点的角度 - 这将作为旋转量的基础:

That'll lead you halfway, but it will still behave oddly (it will rotate around the element origin, but not following the handle as you expect). To make it follow the handle, you should adjust the angle in relation to the clicked point - which will serve as a base for the amount to rotate:

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

之后你得到旋转工作(至少为一个用户迭代)。

After that you get the rotation working (for one user iteration at least).

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

You'll notice the handle does not follow the mouse precisely, and the reason is the choice of the origin point - defaulting to the element's top/left corner. Adjust it to somewhere inside the element (maybe using a data- attribute) and it should work as expected.

但是,如果用户多次与手柄交互,只需设置旋转角度就够了,您必须更新,无论在上次迭代过程中如何。因此,我添加了一个 last_angle var,将在第一次点击时设置,然后在拖动期间添加到最终角度:

However, if the user interacts with the handle multiple times, it's not enough to just set the rotation angle, you must update whatever it was during the last iteration. So I'm adding a last_angle var that will be set on the first click and then added to the final angle during drag:

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

这是最后的工作示例。 (注意:我修复了鼠标处理程序的嵌套,因此每次点击后不会再添加)

Here's the final working example. (Note: I fixed the nesting of your mouse handlers, so they don't get added again after each click)

$(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>

这篇关于如何使对象随拖动旋转,如何获取围绕原点的旋转点使用sin或cos?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆