Rumah >hujung hadapan web >View.js >Amalan Vue: menggunakan arahan tersuai untuk mencapai kesan elemen seret tetikus
Artikel ini berkongsi pengalaman praktikal Vue, memperkenalkan penggunaan arahan tersuai Vue untuk mencapai kesan elemen seret tetikus dan menyelesaikan masalah penyesuaian terminal mudah alih.
Element.clientWidth
: Elemen boleh dilihat lebar. Element.clientHeight
: Ketinggian unsur yang boleh dilihat. MouseEvent.clientX
: Koordinat mendatar tetikus berbanding dengan bucu kiri atas penyemak imbas. MouseEvent.clientY
: Koordinat menegak tetikus berbanding dengan bucu kiri atas penyemak imbas. Touch.clientX
: Koordinat mendatar titik sentuh berbanding dengan bucu kiri atas penyemak imbas (harta mudah alih). Touch.clientY
: Koordinat menegak titik sentuh berbanding dengan bucu kiri atas penyemak imbas (harta mudah alih). HTMLElement.offsetLeft
: Jarak mengimbangi sudut kiri atas unsur semasa berbanding dengan sebelah kiri nod induk (HTMLElement.offsetParent
). Apabila elemen meninggalkan aliran dokumen (position: fixed
) ia diimbangi berbanding dengan asal (bucu kiri atas penyemak imbas). [Cadangan berkaitan: tutorial video vuejs]HTMLElement.offsetTop
: Jarak mengimbangi sudut kiri atas unsur semasa berbanding bahagian atas nod induk (HTMLElement.offsetParent
). Apabila elemen meninggalkan aliran dokumen (position: fixed
) ia diimbangi berbanding dengan asal (bucu kiri atas penyemak imbas). Element.style.top
: Boleh dibaca dan boleh ditulis, nilainya ialah offsetTop
. Element.style.left
: Boleh dibaca dan boleh ditulis, nilainya ialah offsetLeft
. Elemen yang hendak digelongsor mesti ditetapkan
position: fixed or absolute
Elemen gelongsor bergantung pada pergerakan tetikus Kedudukan bergerak tetikus menentukan kedudukan gelongsor elemen ditentukan dengan melaraskan koordinat bucu kiri atas, jadi kita perlu ketahui koordinat puncak kiri atas elemen selepas gelongsor, supaya elemen boleh dialihkan Bergerak ke lokasi yang ditentukan (tempat tetikus melayang).
Mula-mula, hitung kedudukan tetikus relatif kepada elemen sebelum menggerakkan elemen (x, y)
:
// 鼠标当前的位置减去元素当前的位置 (x, y) = (e.clientX - el.offsetLeft, e.clientY - el.offsetTop)
Kedudukan tetikus relatif kepada elemen merujuk kepada kedudukan relatif kepada puncak kiri atas unsur.
e
merujuk kepada acara tetikus dan el
merujuk kepada elemen gelongsor.
Sebaik sahaja anda mengetahui kedudukan relatif tetikus, dan pergerakan tetikus seterusnya, selagi anda mengetahui koordinat tetikus selepas pergerakan, anda boleh mengira dengan mudah koordinat bucu kiri atas unsur tersebut.
Kira koordinat bucu kiri atas unsur selepas pergerakan(x', y')
:
// 鼠标当前的位置减去滑动前的相对位置 (x‘, y’) = (e.clientX - x, e.clientY - y)
(x', y')
ialah koordinat akhir untuk dialihkan, dan kemudian laraskan kedudukan elemen
el.style.left = x' + 'px' el.style.top = y' + 'px'
<template> <div> <!-- 省略... --> </div> </template> <script> export default { data() { return { isDrag: false }, methods: { click() { if (this.isDrag) { return } // 省略... } }, directives: { drag(el, binding, vnode) { /** * 获取客户端可见内容的高度 * * @returns {number} */ const getClientHeight = () => { return window.innerHeight || Math.min(document.documentElement.clientHeight, document.body.clientHeight) } /** * 获取客户端可见内容的宽度 * * @returns {number} */ const getClientWidth = () => { return window.innerWidth || Math.min(document.documentElement.clientWidth, document.body.clientWidth) } /** * startX = null:获取鼠标相对于元素(左上顶点)的x轴坐标(移动前坐标) * startX != null:获取移动后的左上顶点x轴坐标 * * e.clientX:鼠标相对客户端(客户端左上顶点)的x轴坐标 * el.offsetLeft:元素顶点(左上顶点)相对客户端(客户端左上顶点)的x轴坐标(元素必须脱离文档流,position: fixed or absolute) * el.clientWidth:元素宽度 * * @param el * @param e * @param startX * @returns {number} */ const getX = (el, e, startX) => { if (startX === null) { // 返回鼠标相对于元素(左上顶点)的x轴坐标 return e.clientX - el.offsetLeft } // 客户端可视宽度 const clientWidth = getClientWidth() // 元素自身宽度 const elWidth = el.clientWidth // 移动到x轴位置 let x = e.clientX - startX // 水平方向边界处理 if (x <= 0) { // x轴最小为0 x = 0 } else if (x + elWidth > clientWidth) { // x是左上顶点的坐标,是否触碰到右边边界(超出可视宽度)要通过右顶点判断,所以需要加上元素自身宽度 x = clientWidth - elWidth } return x } /** * startY = null:获取鼠标相对于元素(左上顶点)的y轴坐标(移动前坐标) * startY != null:获取移动后的左上顶点y轴坐标 * * e.clientY:鼠标相对客户端(客户端左上顶点)的y轴坐标 * el.offsetTop:元素顶点(左上顶点)相对客户端(客户端左上顶点)的y轴坐标(元素必须脱离文档流,position: fixed or absolute) * el.clientHeight:元素高度 * * @param el * @param e * @param startY * @returns {number} */ const getY = (el, e, startY) => { if (startY === null) { // 返回鼠标相对于元素(左上顶点)的y轴坐标 return e.clientY - el.offsetTop } // 客户端可视高度 const clientHeight = getClientHeight() // 元素自身高度 const elHeight = el.clientHeight // 移动到y轴位置 let y = e.clientY - startY // 垂直方向边界处理 if (y <= 0) { // y轴最小为0 y = 0 } else if (y + elHeight > clientHeight) { // 同理,判断是否超出可视高度要加上自身高度 y = clientHeight - elHeight } return y } /** * 监听鼠标按下事件(PC端拖动) * * @param e */ el.onmousedown = (e) => { vnode.context.isDrag = false // 获取当前位置信息 (startX,startY) const startX = getX(el, e, null) const startY = getY(el, e, null) /** * 监听鼠标移动事件 * * @param e */ document.onmousemove = (e) => { // 标记正在移动,解决元素移动后点击事件被触发的问题 vnode.context.isDrag = true // 更新元素位置(移动元素) el.style.left = getX(el, e, startX) + 'px' el.style.top = getY(el, e, startY) + 'px' } /** * 监听鼠标松开事件 */ document.onmouseup = () => { // 移除鼠标相关事件,防止元素无法脱离鼠标 document.onmousemove = document.onmouseup = null } } /** * 监听手指按下事件(移动端拖动) * @param e */ el.ontouchstart = (e) => { // 获取被触摸的元素 const touch = e.targetTouches[0] // 获取当前位置信息 (startX,startY) const startX = getX(el, touch, null) const startY = getY(el, touch, null) /** * 监听手指移动事件 * @param e */ document.ontouchmove = (e) => { // 获取被触摸的元素 const touch = e.targetTouches[0] // 更新元素位置(移动元素) el.style.left = getX(el, touch, startX) + 'px' el.style.top = getY(el, touch, startY) + 'px' } /** * 监听手指移开事件 */ document.ontouchend = () => { // 移除touch相关事件,防止元素无法脱离手指 document.ontouchmove = document.ontouchend = null } } } } } </script> <style> .ball-wrap { position: fixed; } </style>
drag
ialah arahan tersuai kami, cuma ikat v-drag
pada elemen yang perlu digelongsorkan.
Tidak boleh diakses dalam arahan tersuai directives
this
, jika anda perlu mengubah suai nilai dalam data
, anda perlu mengubah suainya melalui vnode.context.字段名 = 值
.
Jujukan pencetus acara tetikus:
mouseover - mousedown - mouseup - click - mouseout
Premis gelongsor ialah bahawa tetikus mesti Tekan dan kemudian gelongsor, jadi apabila kita melepaskan tetikus selepas gelongsor, acara click
akan dicetuskan.
Penyelesaian: Tentukan pembolehubah bendera untuk menunjukkan sama ada ia gelongsor Apabila acara klik dilaksanakan, pembolehubah ini digunakan sebagai prasyarat Jika ia gelongsor, ia tidak akan dilaksanakan .
// ... data() return { isDrag: false } } // ... el.onmousedown = (e) => { // ... vnode.context.isDrag = false document.onmousemove = (e) => { // 标记正在移动,解决元素移动后点击事件被触发的问题 vnode.context.isDrag = true // ... } } // ... methods: { click() { if (this.isDrag) { return } // ... } }
Acara lalai akan dicetuskan apabila menggelongsor pada bahagian mudah alih, menyebabkan gelongsor membeku.
Tambah @touchmove.prevent
pada elemen yang anda mahu cetuskan slaid untuk menghalang acara lalai daripada berlaku.
https://github.com/anlingyi/xeblog-vue/blob/master/src/components/xe-pokeball/index . vue
(Perkongsian video pembelajaran: pembangunan bahagian hadapan web, Video pengaturcaraan asas)
Atas ialah kandungan terperinci Amalan Vue: menggunakan arahan tersuai untuk mencapai kesan elemen seret tetikus. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!