⤴Top⤴

Touch & Drag 事件

博客分类: 前端

Touch & Drag 事件

Touch & Drag 事件

Touch 事件

TouchEvent 是一类描述手指在触摸平面(如触摸屏、触摸板等)的状态变化的事件。TouchList 对象代表多个触点的一个列表。每个 Touch 对象代表一个触点,每个触点都由其位置、大小、形状、压力大小和目标 element 描述。

触摸事件类型

主要有以下几种:

document.addEventListener('touchstart', touchEvent ,false);

TouchList

每个触摸事件被触发后,会生成一个 event 对象,event 对象里额外包括以下三个触摸列表:

Touch

这些列表里的每次触摸由 Touch 对象组成,Touch 对象里包含着触摸信息,主要属性如下:

{
  screenX: 511,
  screenY: 400, // 触点相对于屏幕左边沿的Y坐标
  clientX: 244.37899780273438,
  clientY: 189.3820037841797, // 相对于可视区域
  pageX: 244.37,
  pageY: 189.37, // 相对于 HTML 文档顶部,当页面有滚动的时候与 clientX=Y 不等
  force: 1, // 压力大小,是从0.0(没有压力)到1.0(最大压力)的浮点数
  identifier: 1036403715, // 一次触摸动作的唯一标识符
  radiusX: 37.565673828125,  // 能够包围用户和触摸平面的接触面的最小椭圆的水平轴(X轴)半径
  radiusY: 37.565673828125,
  rotationAngle: 0, // 它是这样一个角度值:由 radiusX 和 radiusY 描述的正方向的椭圆,需要通过顺时针旋转这个角度值,才能最精确地覆盖住用户和触摸平面的接触面
  target: {}  // 此次触摸事件的目标 element
}

查看以下 JSFiddle 示例:

Touch 案例

做一个移动端触摸点,仅限于屏幕窗口内移动,也可响应点击事件:

var doc = document;
var screenW = doc.body.clientWidth || screen.width;
var screenH = doc.body.clientHeight || screen.height;
var width = 48;
var isMoved = false;
var backToTop = doc.querySelector('.back-to-top');

backToTop.addEventListener('touchstart', touchstart, false);
backToTop.addEventListener('touchmove', touchmove, false);
backToTop.addEventListener('touchend', touchend, false);

function touchstart(ev) {
  isMoved = false;
}

function touchmove(ev) {
  isMoved = true;

  var event = getEvent(ev);
  var coordinateX = event.changedTouches[0].clientX;
  var coordinateY = event.changedTouches[0].clientY;
  var left = parseFloat(coordinateX) - 20;
  var top = parseFloat(coordinateY) - 20;

  left = left <= 1.45 ? 1.45 : (left >= screenW - width ? screenW - width : left);
  top = top <= 1 ? 1 : (top >= screenH - width ? screenH - width : top);

  backToTop.style.left = left + 'px';
  backToTop.style.top = top + 'px';
  console.log('left: %f, top: %f', left, top);
}

function touchend(ev) {
  !isMoved && alert('click');
}

function getEvent(ev) {
  return ev ? ev : window.event;
}

Drag 事件

DragEvent 鼠标进行拖拽(drag)和释放(drop),一定要设置可拖拽目标,即设置属性 draggable="true"

拖拽事件类型

DataTransfer

拖拽事件周期中会初始化一个 DataTransfer 对象,用于保存拖拽数据和交互信息:

draggableElement.addEventListener('dragstart', function (event) {
  event.dataTransfer.setData('text', 'Hello World');
}, false);

draggableElement.ondragstart = function(event) {
  event.dataTransfer.setData('text', 'Hello World');
}

Drag 案例

做一个 web 端触摸点,仅限于屏幕窗口内移动:

var doc = document;
var screenW = doc.body.clientWidth || screen.width;
var screenH = doc.body.clientHeight || screen.height;
var width = 48;
var offsetX = 0;
var offsetY = 0;
var backToTop = doc.querySelector('.back-to-top');

backToTop.addEventListener('dragstart', ondragstart, false);
backToTop.addEventListener('drag', ondrag, false);
backToTop.addEventListener('dragend', ondragend, false);

function ondragstart(ev) {
  var event = getEvent(ev);
  offsetX = event.offsetX;
  offsetY = event.offsetY;
}

function ondrag(ev) {
  var event = getEvent(ev);
  var coordinateX = event.clientX;
  var coordinateY = event.clientY;
  if (coordinateX === 0 && coordinateY === 0) {
    return; // 不处理拖动最后一刻X和Y都为0的情形
  }
  coordinateX -= offsetX;
  coordinateY -= offsetY;

  coordinateX = coordinateX <= 0 ? 0 : (coordinateX >= screenW - width ? screenW - width : coordinateX);
  coordinateY = coordinateY <= 0 ? 0 : (coordinateY >= screenH - width ? screenH - width : coordinateY);

  backToTop.style.left = coordinateX + 'px';
  backToTop.style.top = coordinateY + 'px';
  console.log('left: %f, top: %f', coordinateX, coordinateY);
}

function ondragend(ev) {
  console.log('drag end');
}

做一个垃圾回收示例 JSFiddle:

拖拽图片预览 JSFiddle:

事件对象的位置

event-clientX.png

参考链接

  1. MDN - TouchEvent
  2. 移动端 Touch 事件介绍 By kujian
  3. js 中的 touch 事件及 gesture(手势)事件详解 — 第13.4.9节 By flyingpig2016
  4. 原生拖拽,拖放事件(drag and drop) By qiu_deqing
  5. HTML5 – 拖拽 API(含超经典例子) By 冯小东
  6. 一张图轻松搞懂 javascript event 对象的 clientX、offsetX、screenX、pageX 区别 By ruoyiqing