旋转元素到点击位置

Posted

技术标签:

【中文标题】旋转元素到点击位置【英文标题】:Rotate element to click position 【发布时间】:2015-03-12 02:13:41 【问题描述】:

我有一个带有圆圈的项目,当单击该圆圈时,它会旋转到预定义的位置。它几乎就在那里,但最后一个要求是它总是顺时针旋转到标记。我似乎无法弄清楚如何获得正确的值,因此当我设置 css transform:rotate(Xdeg) 时,它总是顺时针方向。将角度保持在 0 到 360 度之间也将是另一个优点,但不是必需的。

见这个小提琴,下面还有 javascript Rotation

$(function () 
$('body').on('click', '#graph1', function (e) 

    console.log('********************');
    //get mouse position relative to div and center of div for polar origin
    var pos = getMousePosAndCenter(e, 'graph1');

    //get the current degrees of rotation from the css
    var currentRotationDegrees = getCs-s-rotation('#graph1');
    console.log('CSS Rotation Value: ' + currentRotationDegrees);

    //current rotation in radians
    var currentRotationRadians = radians(currentRotationDegrees);

    //radians where clicked
    var clickRadiansFromZero = Math.atan2(pos.y - pos.originY, pos.x - pos.originX);

    //degrees the click is offset from 0 origin
    var offsetDegrees = degrees(clickRadiansFromZero);

    //how many degrees to rotate in css to put the mouse click at 0
    var degreesToZero;
    if (offsetDegrees >= 0)
        degreesToZero = currentRotationDegrees - Math.abs(offsetDegrees);
    else
        degreesToZero = currentRotationDegrees + Math.abs(offsetDegrees);

    console.log("Degrees to Zero: " + degreesToZero);

    //distance in pixels from origin
    var distance = calculateDistance(pos.originX, pos.originY, pos.x, pos.y);

    console.log("Distance From Origin(px): " + distance);

    $('#graph1').css('transform','rotate(' + degreesToZero + 'deg)')
);

);

function getMousePosAndCenter(e, id) 
    var rect = document.getElementById(id).getBoundingClientRect();
    return 
        x: (((e.clientX - rect.left) / rect.width) * rect.width) + 0.5 << 0,
        y: (((e.clientY - rect.top) / rect.height) * rect.height) + 0.5 << 0,
        originY: (rect.height / 2),
        originX: (rect.width / 2)
    ;


function radians(degrees) 
    return degrees * Math.PI / 180;
;

function degrees(radians) 
    return radians * 180 / Math.PI;
;

function calculateDistance(originX, originY, mouseX, mouseY) 
    return Math.floor(Math.sqrt(Math.pow(mouseX - originX, 2) + Math.pow(mouseY - originY, 2)));


function getCs-s-rotation(id) 
    var matrix = $(id).css('transform');
    var values = matrix.split('(')[1],
    values = values.split(')')[0],
    values = values.split(',');

    var a = values[0];
    var b = values[1];
    var c = values[2];
    var d = values[3];

    var cssRotation = degrees(Math.atan2(b, a));
    return cssRotation;

【问题讨论】:

为我的答案添加了一个小提琴,它为您提供了 CSS 的流畅帧率。 【参考方案1】:

跳出框框思考: 我们可以CSS3 rotate 一个带有transform 的元素,即:720° ... 它会 顺时针 转 2 圈。 (好吧,在我们的 UI 中,它最多只能转 359 圈,但让我们按照数学计算) 如果我们将其设置为 810°...这只是意味着 它将顺时针移动 90°

所以我们需要做的就是总是增加一个度数变量到疯狂!

嘿!如果在某个时候您想跟踪当前的标准化 0-360 度...您可以随时检索该值 ourCurrentInsanelyHighDegree % 360 = UIdegrees

Here's a jsBin demo

这就是你需要的所有 JS。

function getCs-s-rotation( $el ) 
  var matrix = $el.css('transform'),
      v = matrix.split('(')[1].split(')')[0].split(','),
      rds = Math.atan2(v[1], v[0]);
  return rds*180/Math.PI <<0; // Degrees


var $EL = $("#graph1"),
  w = $EL.width(),
  r = w/2,                             // Radius
  x = parseInt($EL.css("left"), 10),
  y = parseInt($EL.css("top"),  10),
  d = getCs-s-rotation( $EL );           // Initial degree (ONLY ONCE!)

$EL.on("click", function(e)
  var mx = e.clientX-x-r,              // Click coord X
      my = e.clientY-y-r,              // Click coord Y
      rds = Math.atan2(-my, -mx),      // Radians
      md = (rds*180/Math.PI<<0) + 180; // Mouse Degrees
  d += (360-md);                       // always increment to insanity!!
  $(this).css(transform:"rotate("+ d +"deg)");
);
#graph1 
    position:absolute;
    top:10px;    left:30px;
    width:200px; height:200px;
    background:url(//placehold.it/200x200&text=IMAGE);
    transition:transform 2s ease;
    transform:rotate(30deg);
    transform-origin:50% 50%;
    border-radius:50%;

#marker 
    position: absolute;
    top:110px;
    left:230px;
    border-top:1px solid black;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="graph1"></div>
<div id="marker">Wherever you click, it rotates to here</div>

【讨论】:

【参考方案2】:

更新: 认为这很容易做到,我发现它比我想象的要难一些。 jQuery.animate 的另一个答案有效,但 animate 没有 css 动画所具有的流畅帧速率(它在 GPU 上运行)。

这是一个带有 CSS 解决方案的修改过的小提琴:http://jsfiddle.net/2g17cjuL/2/

将角度保持在 0 到 360 度之间也会是一个加分项

你不能继续前进(即旋转正数)并保持旋转正数,但是,在我的小提琴offsetDegrees(额外旋转的度数)中,或者totalDegrees除以 360 的其余部分应该给你你需要在其他地方使用的东西。

【讨论】:

【参考方案3】:

要求:它总是顺时针旋转。

有一件事:如果您使用 CSS 过渡,它会为您计算最短路径。您想要更多地控制旋转方向,所以我在您的 CSS 中注释掉了 transition:transform 1s ease;,因为我们将手动控制它。

JAVASCRIPT

我借用了this JQuery function 并对其进行了修改,以便我们可以为它提供一个起始角度和结束角度,它会为我们制作#graph1 的动画。 (阅读链接以更改持续时间、缓动和使用 complete 回调)

$.fn.animateRotate = function(angle, start, duration, easing, complete) 
  var args = $.speed(duration, easing, complete);
  var step = args.step;
  return this.each(function(i, e) 
    args.complete = $.proxy(args.complete, e);
    args.step = function(now) 
      $.style(e, 'transform', 'rotate(' + now + 'deg)');
      if (step) return step.apply(e, arguments);
    ;

    $(deg: start).animate(deg: angle, args);
  );
;

我还修改了您的 JQuery,使其不会逆时针旋转:当 currentRotationDegrees 大于 degreesToZero 时,它将减去 360,然后使用这个新值作为 `animateRotate() 的起始位置.

if(currentRotationDegrees > degreesToZero)
    currentRotationDegrees -= 360;


$('#graph1').animateRotate(degreesToZero, currentRotationDegrees);

它正在行动。

http://jsfiddle.net/q4nad31t/1/

【讨论】:

以上是关于旋转元素到点击位置的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript基础 事件

Raphael.js 获取旋转后集合中单个元素的位置

AFrame:重新设置元素保持其世界位置,旋转

已解决appium开始点击元素到点击完成花费了十几秒,可能会更长时间

已解决appium开始点击元素到点击完成花费了十几秒,可能会更长时间

已解决appium开始点击元素到点击完成花费了十几秒,可能会更长时间