• 27 Click And Drag 中文指南
    • 挑战任务
    • 实现效果
    • 编程思路
    • 过程指南
    • 延伸思考

    27 Click And Drag 中文指南

    本篇作者:©大史快跑Dashrun——Chinasoft Frontend Developer

    简介:JavaScript30 是 Wes Bos 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 27 篇。完整指南在 GitHub,喜欢请 Star 哦♪(^∇^*)

    创建时间:2017-10-24
    最后更新:2017-10-229

    挑战任务

    初始文档index-start.html中提供了一组条幅,本次的编程任务需要实现的效果是当鼠标拖动画面移动时,条幅同步向水平方向移动。

    实现效果

    结果展示

    编程思路

    在最外层的items元素上监听鼠标的按下,移动,弹起事件并编写相应的回调函数即可,在对应的回调函数中获取到鼠标横向滑动的距离,将该距离值翻倍后赋值予条幅的scrollLeft属性可调整元素在水平方向上滚动的位置。

    style.css中已为条幅编写好active类,当鼠标移动时只需要将此类添加给对应的类即可看到很棒的CSS特效。

    过程指南

    1.在条幅容器上监听鼠标按下事件

    1. const slider = document.querySelector(".items");
    2. let isMouseDown = false;//记录鼠标是否按下
    3. let startX;//按下时位置的x坐标
    4. let scrollLeft;//记录视口相对于items最左侧已经滚过的距离
    5. slider.addEventListener('mousedown',(e) =>{
    6. isMouseDown = true;
    7. slider.classList.add('active');
    8. startX = e.pageX - slider.offsetLeft;//记录鼠标按下时的相对位置
    9. scrollLeft = slider.scrollLeft;
    10. });

    2.在条幅容器上监听鼠标弹起事件

    1. slider.addEventListener('mouseup',(e) =>{
    2. isMouseDown = false;
    3. slider.classList.remove('active');
    4. });

    3.在条幅容器上监听鼠标移动事件

    1. slider.addEventListener('mousemove',(e) =>{
    2. if (!isMouseDown) {
    3. return;
    4. }//若鼠标未按下,则不进行操作
    5. e.preventDefault();
    6. const x = e.pageX - slider.offsetLeft;
    7. const walk = (x - startX) * 3; //将鼠标移动距离放大后作为条幅的移动距离
    8. slider.scrollLeft = scrollLeft - walk;
    9. });

    延伸思考

    本例中的js部分并不复杂,令人感兴趣的是style.css样式部分使用了较多CSS3高级用法,使得元素在滚动过程中呈现出透视效果,笔者在此对CSS的实现方法作以简单说明,感兴趣的小伙伴可以自行查找资料深入学习。
    除去颜色部分,active类中的动态效果其实只用到了3行代码:

    1. /*透视距离,即视点位于垂直距离屏幕的距离,数值越大,离的越远,变形效果看起来越微小*/
    2. .items{perspective: 500px;}
    3. /*所有奇数序号的子元素沿X轴放大,并绕Y轴旋转(相当于人绕柱子转)*/
    4. .item:nth-child(even) { transform: scaleX(1.31) rotateY(40deg); }
    5. /*所有奇数序号的子元素沿X轴放大,并绕Y轴逆向旋转(相当于人绕柱子反转一定角度)*/
    6. .item:nth-child(odd) { transform: scaleX(1.31) rotateY(-40deg); }