这次的功能主要是做画面的一个点击拖曳,当点击后往左拖曳画面会往右跑,反之。
主要之架构。
<div class="items"> <!-- 放一个a来做测试,当我们拖曳时,放开不想触发a --> <a href="http://www.google.com/" class="item item1" >01 </a> <div class="item item2">02</div> <div class="item item3">03</div> <div class="item item4">04</div> <div class="item item5">05</div> <div class="item item6">06</div> <div class="item item7">07</div> <div class="item item8">08</div> <div class="item item9">09</div> <div class="item item10">10</div> <div class="item item11">11</div> <div class="item item12">12</div> <div class="item item13">13</div> <div class="item item14">14</div> <div class="item item15">15</div> <div class="item item16">16</div> <div class="item item17">17</div> <div class="item item18">18</div> <div class="item item19">19</div> <div class="item item20">20</div> <div class="item item21">21</div> <div class="item item22">22</div> <div class="item item23">23</div> <div class="item item24">24</div> <div class="item item25">25</div> </div>
先理解拖曳的观念
1.开始 => mousedown
开始
2.ing => mousemove
正在拖(mousedown依然没放开)
3.结束 => mouseup
(放开)、mouseleave(离开拖曳元素之範围)
获取元素目标并增听所需之事件。
const list = document.querySelector('.items'); // 判断在a上的鼠标是否有拖曳 let moved = false; list.addEventListener('mousedown', startDragHandler); // 手机事件改用 touchstart list.addEventListener('mousemove', DragingHandler); // 手机事件改用 touchmove list.addEventListener('mouseup', stopDragHandler); // 手机事件改用 touchend list.addEventListener('mouseleave', stopDragHandler); 对所有a都绑定点击事件。 document.querySelectorAll('.items a').forEach(dom => { dom.addEventListener('click', function (e) { // 假如动了就防止触发预设功能 if (moved) { e.preventDefault(); } }) })
设置拖曳的起始点,并在mousedown事件函数处理,当按下去,会触发样式active来反馈说已经按下鼠标,而由于我们的目标会一直切换
,故无法使用offsetX,改用pageX
,当点下去时,就获取起始点。
// 起始点 let startX = 0; // 开始拖曳 const startDragHandler = function (e) { list.classList.add('active'); // 在拖曳时,发现e.target会一直切换 // 原本想使用offsetX(从该元素开始计算)来计算距离,但由于我们元素内的目标有好几个,item1,item2... // 改使用pageX(从全页面)开始计算距离 // <div class="item item2">02</div> , 0 , 13 console.log(e.target, e.offsetX, e.pageX); // 获取起始点 startX = e.pageX; 没移动故false moved = false; }
拖曳中(需按下鼠标后),拖曳会有很多东西(如连结、文字、图片),都会被触发在移动上
,所以要做preventDefault但当拖曳时,原本a的click就会被触发,所以要额外去preventDefault a标籤
。
先判断是否有active样式,以判断是否按下鼠标,并开始拖曳,获取拖曳的距离(拖曳后位置-当前起始点),并且在算完距离后,要改变起始点,并且在最后要将画面呈现拖曳效果,也就是使用scrollLeft滚动离左边的距离,但由于移动方向跟拖曳方向是反的,故用减法
。
const DragingHandler = function (e) { e.preventDefault(); // 移动为true moved = true; // 先判断是否mousedown if (list.classList.contains('active')) { // 移动的距离(当前鼠标位置-前起始点) let move = e.pageX - startX; // 每次拖曳改变起始点 startX = e.pageX; // 元素移动 list.scrollLeft -= move; // list.scrollLeft -= move * 5; // 如想拖曳速度增加可乘以倍数 } }
最后,结束拖曳。
// 结束拖曳 const stopDragHandler = function (e) { list.classList.remove('active'); }