根据触摸事件旋转元素

Posted

技术标签:

【中文标题】根据触摸事件旋转元素【英文标题】:Rotate element based on touch event 【发布时间】:2012-12-01 14:04:35 【问题描述】:

我正在寻找一些指导和/或示例来创建一种触摸对象并旋转它的方法。假设我们有一个圆圈的图像,我希望能够触摸一个点,围绕该圆圈拖动并在我的手指移动时操纵它旋转。

我找到了很多关于旋转的教程:

http://www.williammalone.com/briefs/how-to-rotate-html5-canvas-around-center/ http://www.switchonthecode.com/tutorials/html-5-canvas-tutorial-rotation

我只需要将触摸部分合并。

以前有人做过,或者可以解释一下吗?

【问题讨论】:

【参考方案1】:

您可以简单地将触摸的旋转映射到元素的transform: rotate(Ndeg) CSS。

并非所有支持触摸的浏览器都在event 对象上提供rotate 属性,因此您可以通过数学计算得出值。

document
.getElementById("some-element")
.addEventListener("touchmove", function(event) 
    var rotation = event.rotation;

    // This isn't a fun browser!
    if ( ! rotation) 
         rotation = Math.arctan2(event.touches[0].pageY - event.touches[1].pageY,
               event.touches[0].pageX - event.touches[1].pageX) * 180 / Math.PI;
    

    // Take into account vendor prefixes, which I haven't done.
    this.style.transform = "rotate(" + rotation + "deg)":
);

如果您希望用户能够多次旋转它,您还需要存储之前的旋转值并根据它调整这个值。 :)

【讨论】:

我在触摸事件中找不到任何旋转属性。如何访问它?【参考方案2】:

鼠标/触摸拖动时旋转元素

这是一个关于如何拖动-旋转元素的完整示例:

存储起始角度,即坐标处的相对角度减去当前角度。按鼠标移动 XY 坐标角度的差值(增量)旋转从中心减去起始角度。

const rotate = (EL) => 
  
  let ang = 0; // All angles are expressed in radians
  let angStart = 0;
  let isStart = false;

  const angXY = (ev) => 
    const bcr = EL.getBoundingClientRect();
    const radius = bcr.width / 2;
    const  clientX, clientY  = ev.touches ? ev.touches[0] : ev;
    const y = clientY - bcr.top - radius;  // y from center
    const x = clientX - bcr.left - radius; // x from center
    return Math.atan2(y, x);
  ;

  const mousedown = (ev) => 
    isStart = true;
    angStart = angXY(ev) - ang;
  ;

  const mousemove = (ev) => 
    if (!isStart) return;
    ev.preventDefault();
    ang = angXY(ev) - angStart;
    EL.style.transform = `rotateZ($angrad)`;
  ;

  const mouseup = () => 
    isStart = false; 
  ;

  EL.addEventListener("mousedown", mousedown);
  document.addEventListener("mousemove", mousemove);
  document.addEventListener("mouseup", mouseup);
;

document.querySelectorAll(".rotate").forEach(rotate);
.rotate 
  border-radius: 50%;
  width: 180px;
  cursor: ns-resize;
<img class="rotate" src="https://www.gravatar.com/avatar/1771ce957b38fbb7f9bb01f58b89fd3f?s=328&d=identicon&r=PG" >
<img class="rotate" src="https://i.stack.imgur.com/qCWYU.jpg?s=328&g=1" >

【讨论】:

【参考方案3】:

您需要考虑在您的canvas 上实现MouseDownMouseUpMouseMove 事件侦听器,因为与触摸屏的“触摸”交互只不过是一种花哨的鼠标移动。

MouseDownMouseUp 可用于查找用户是否在canvas 上拖动。 MouseMove 是您需要放置旋转处理逻辑的位置。剩下的就是实现了:

/* Borrowed from http://www.marceloduende.com/blog/?p=25 */ function addCrossBrowseEventListener(myElement, myEvent, myFunction) if(myElement.addEventListener) myElement.addEventListener(myEvent, myFunction, false); return true; else myElement.attachEvent('on'+myEvent, myFunction); return true;

myElement 是画布的 DOM 元素,myEvent 是要为其添加侦听器的事件的名称,myFunction 是负责处理事件逻辑的函数的名称。

或者,您可以使用 jQuery 来完成大部分工作,因为它有许多更简洁的事件处理方法。

【讨论】:

谢谢贾斯汀——一切都说得通,不幸的是我没有足够的经验来独自完成这一切。你知道我可以逆向工程的任何例子吗?谢谢 我不确定 OP 是否需要移动事件,他们说的是“触摸”而不是“点击”,所以我倾向于认为这是针对触摸屏设备上的某些东西。在这种情况下,事件将是“touchstart”和“touchmove”

以上是关于根据触摸事件旋转元素的主要内容,如果未能解决你的问题,请参考以下文章

如何避免 Touches 取消事件?

(转)使用OpenGL显示图像响应触摸事件

触摸事件

js移动端触摸事件

学习记录 -- 移动端的触摸事件

触摸事件中touchstartouchmovetouchendtouchcancel事件应用方法及实例