真正考前端的题应该是这样的:
----
使用JavaScript实现一个固定元素的拖拽效果,要求函数符合以下签名:
```javascript
/**
* @
param {HTMLElement} element 需要提供拖拽功能的元素
*/
function draggable(element) {
}
```
`element`符合以下前提:
- 在`<body>`元素之下,且不在其它元素内(作为`<body>`的直接子元素)
- 含有未知的子元素或内容,但大小不超过可视范围
在执行该方法后,`element`将具备以下功能:
- 按下鼠标后可开始拖动,放开鼠标时拖动结束
- 可以在当前浏览器可视区域区域内任意拖动
- 在拖动过程中,原元素`element`保持位置不变,使用一个透明度为0.4、视觉效果与`element`一致的元素跟随鼠标
- 拖动完毕后,原元素移至最终放开鼠标的位置,移动过程无需动画
### 知识点
1. 基本DOM操作
2. HTML drag & drop
3. CSS属性性能
4. 用户体验优化
### 关键细节
- 使用`cloneNode`并设置样式(添加特殊`class`更好)实现跟随鼠标的元素
- 如果使用HTML drag & drop实现,需要使用`e.transfer.setDragImage`实现跟随鼠标的元素
- 不使用HTML drag & drop时,使用`translate-3d`性能优于`translate`,`translate`优于`left / top`
- 原始位置的计算需要使用`getBoundingClientRect`、`scrollTop`、`scrollLeft`等属性
- 如果使用`translate`同步位置的话,要考虑原始已有`translate`的影响
- 对于跟随鼠标的元素,需要主动设置`position: absolute`
- `mousemove`和`mouseup`需要绑定在`documentElement`上
- 需要在`mousedown`时计算位置,`mousemove`时计算偏移量才可实现准确跟随,不能仅计算`mousemove`时的鼠标位置
- 出于用户体验考虑,可在移动若干像素(或鼠标按下若干毫秒)后才开始拖拽效果
- 拖拽结束后`element`移动位置为跟随鼠标的元素的位置,而非鼠标本身的位置