本期介紹一個前端拖拽插件interact.js,JavaScript拖放、調整大小和多點觸控手勢,適用於瀏覽器(以及IE9+).
interact.js採用了一種與大多數拖放庫略有不同的方法。為了儘可能多地提供控制,它嘗試提供一個簡單、靈活的API,該API為您提供移動元素所需的所有拖拽api
安裝
npm install interactjs
CDN直接引入
<script src='interact.min.js'></script>
使用教程
拖拽
拖拽是interactive .js提供的最簡單的動作。要使元素可拖放,請創建一個與您想要的目標可交互的元素,然後使用您需要的選項調用拖放方法。
<div class="draggable"> Draggable Element </div>
const position = { x: 0, y: 0 }
interact('.draggable').draggable({
listeners: {
start (event) {
console.log(event.type, event.target)
},
move (event) {
position.x += event.dx
position.y += event.dy
event.target.style.transform =
`translate(${position.x}px, ${position.y}px)`
},
}
})
dragmove還有dragEnter和dragLeave 兩個事件
調整大小
Resize事件有rect和deltaRect屬性。rect在每個resizemove事件上更新,deltaRect中的值反映了更改。在resizestart中,rect將與interactable返回的rect相同。getrect (element)和deltaRect將具有全零屬性。
interact('.resizable')
.resizable({
edges: { top: true, left: true, bottom: true, right: true },
listeners: {
move: function (event) {
let { x, y } = event.target.dataset
x = (parseFloat(x) || 0) + event.deltaRect.left
y = (parseFloat(y) || 0) + event.deltaRect.top
Object.assign(event.target.style, {
width: `${event.rect.width}px`,
height: `${event.rect.height}px`,
transform: `translate(${x}px, ${y}px)`
})
Object.assign(event.target.dataset, { x, y })
}
}
})
拖動和放置
dropzone定義了可拖放目標的元素,以及哪些元素可以被接受。和拖放事件一樣,拖放事件不會修改DOM來重新創建父元素。如果需要,您必須在自己的事件監聽器中這樣做。
Dropzone Events
interact(dropTarget)
.dropzone({
ondrop: function (event) {
alert(event.relatedTarget.id
+ ' was dropped into '
+ event.target.id)
}
})
.on('dropactivate', function (event) {
event.target.classList.add('drop-activated')
})
accept
dropzone接受選項是一個CSS選擇器或元素,它必須匹配被拖動的元素,以便觸發拖放事件。
interact('.dropzone').dropzone({
accept: '.drag0, .drag1',
});
checker
checker選項是一個函數,你可以設置它來另外檢查一個拖動的元素是否可以拖放到dropzone中。
interact(target).dropzone({
checker: function (
dragEvent, // related dragmove or dragend
event, // Touch, Pointer or Mouse Event
dropped, // bool default checker result
dropzone, // dropzone Interactable
dropzoneElement, // dropzone element
draggable, // draggable Interactable
draggableElement // draggable element
) {
// only allow drops into empty dropzone elements
return dropped && !dropElement.hasChildNodes();
}
});
多點觸摸旋轉(僅觸摸屏)
當兩個手指移動時,手勢事件被觸發。在手勢事件中,頁面和客户端座標是觸摸座標的平均值,速度是根據這些平均值計算的。
var angle = 0
interact('#rotate-area').gesturable({
listeners: {
move (event) {
var arrow = document.getElementById('arrow')
angle += event.da
arrow.style.webkitTransform =
arrow.style.transform =
'rotate(' + angle + 'deg)'
document.getElementById('angle-info').textContent =
angle.toFixed(2) + '\u00b0'
}
}
})
記住使用CSS touch-action: none來防止當用户用觸摸指針拖動時瀏覽器進行平移,user-select: none來禁用文本選擇。
雙指放大(僅觸摸屏)
和旋轉方法一樣
var angleScale = {
angle: 0,
scale: 1
}
var gestureArea = document.getElementById('gesture-area')
var scaleElement = document.getElementById('scale-element')
var resetTimeout
interact(gestureArea)
.gesturable({
listeners: {
start (event) {
angleScale.angle -= event.angle
clearTimeout(resetTimeout)
scaleElement.classList.remove('reset')
},
move (event) {
// document.body.appendChild(new Text(event.scale))
var currentAngle = event.angle + angleScale.angle
var currentScale = event.scale * angleScale.scale
scaleElement.style.webkitTransform =
scaleElement.style.transform =
'rotate(' + currentAngle + 'deg)' + 'scale(' + currentScale + ')'
// uses the dragMoveListener from the draggable demo above
dragMoveListener(event)
},
end (event) {
angleScale.angle = angleScale.angle + event.angle
angleScale.scale = angleScale.scale * event.scale
resetTimeout = setTimeout(reset, 1000)
scaleElement.classList.add('reset')
}
}
})
.draggable({
listeners: { move: dragMoveListener }
})
function reset () {
scaleElement.style.webkitTransform =
scaleElement.style.transform =
'scale(1)'
angleScale.angle = 0
angleScale.scale = 1
}
Tap, doubletap and hold
手指事件: 單擊 雙擊 長按
interact('.tap-target')
.on('tap', function (event) {
event.currentTarget.classList.toggle('switch-bg')
event.preventDefault()
})
.on('doubletap', function (event) {
event.currentTarget.classList.toggle('large')
event.currentTarget.classList.remove('rotate')
event.preventDefault()
})
.on('hold', function (event) {
event.currentTarget.classList.toggle('rotate')
event.currentTarget.classList.remove('large')
})