JS-WebAPIs-PC端特效练习(拖拽/缓动动画/轮播图/返回顶部)

PC端网页特效练习题

重点

1.重点: 拖拽原理

2.重点: 缓动动画

// 匀速动画 就是 盒子是当前的位置 + 固定的值 10
// 缓动动画就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)

注意: 多个目标之间缓速移动实现时候注意取整

从小数值移动到大数值, 每次移动的步长都向上取整, 否则最后会有一个小于10的差距;

比如0到10: style.left=0+10/10=1; 1+9/10=1.9; 1.9+8.1/10=2.71 … 始终无法精确到10

步长向上取整后: style.left=0+10/10=1; 1+|9/10|=2; 2+|8/10|=3; …可以精确到10

从大数值移动到小数值, 此时步长为负数, 步长向下取整!

一个封装好的animate.js就做好了:

function animate(obj, target, callback) {
    
    
    // console.log(callback);  callback = function() {}  调用的时候 callback()

    // 先清除以前的定时器,只保留当前的一个定时器执行
    //否则随着点击次数增加, 盒子移速会递增
    clearInterval(obj.timer);
    obj.timer = setInterval(function() {
    
    
        // 步长值写到定时器的里面
        // 把步长值改为整数 不要出现小数的问题; 比如8.1取成9, 否则盒子会停在差几像素位置
        // var step = Math.ceil((target - obj.offsetLeft) / 10);
        var step = (target - obj.offsetLeft) / 10;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        if (obj.offsetLeft == target) {
    
    
            // 停止动画 本质是停止定时器
            clearInterval(obj.timer);
            // 回调函数写到定时器结束里面
            if (callback) {
    
    
                // 调用函数
                callback();
            }
        }
        // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
        obj.style.left = obj.offsetLeft + step + 'px';

    }, 15);
}    

一, offset系列属性练习

1. 拖拽弹出框(模态框)

要求:

1.点击按钮弹出模态框, 并且显示灰色半透明遮挡层—display:block;

2.点击关闭, 关闭模态框, 并且同时关闭灰色遮挡层—display:none;

3.鼠标放到模态框最上一行(title是事件源)可以按住拖动—

4.鼠标松开停止拖动, 模态框停在原地—mouseup

第三步实现要点:mousedown,mousemove;获取鼠标在图形内相对位置, 鼠标绝对位置-相对位置=盒子左侧距页面距离

按住移动过程中, 按下鼠标一瞬间开始, 鼠标在盒子内的相对位置是不变的, 获取这个相对位置.

随后, 鼠标移动, 此时鼠标在页面内的位置改变, 要按照: 改变鼠标位置-获取盒子offsetLeft-赋新值给left和top

            // 4. 开始拖拽
            // (1) 当我们鼠标按下, 就获得鼠标在盒子内的坐标
        title.addEventListener('mousedown', function(e) {
    
    
            var x = e.pageX - login.offsetLeft;
            var y = e.pageY - login.offsetTop;
            // (2) 鼠标移动的时候,把鼠标在页面中的坐标,减去 鼠标在盒子内的坐标就是模态框的left和top值
            document.addEventListener('mousemove', move)
			//方便移除, 把函数拿出来取名
            function move(e) {
    
    
                login.style.left = e.pageX - x + 'px';
                login.style.top = e.pageY - y + 'px';
            }
            // (3) 鼠标弹起,就让鼠标移动事件移除
            document.addEventListener('mouseup', function() {
    
    
                document.removeEventListener('mousemove', move);	//移除须有函数名
            })
        })

3. 商品放大镜

二, scroll属性练习

1. 淘宝固定右侧侧边栏

a. 开始滚动时, 侧边栏随着用户一起滚动;—scroll事件的事件源是document

b. 当侧边栏滚动到最上方, 变为固定定位, 页面滚动而侧边栏不动;—并非scroll属性

c. 并且侧边栏中出现’前往顶部’选项;

注意区分window.pageYOffset和element.scrollTop

页面被卷去的头部: 通过window.pageYOffset获得, 被卷左侧通过window.pageXOffset;

元素被卷头部则通过element.scrollTop获得;

//还有注意O大写,我写成小写浪费好多时间改bug,难受

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        * {
     
     
            margin: 10 auto;
            padding: 0;
        }
        
        .page {
     
     
            float: left;
            width: 100%;
            height: 7500px;
            background-color: pink;
        }
        
        button {
     
     
            position: fixed;
            display: block;
            width: 100px;
            height: 100px;
            margin: 370px 680px;
            background: red;
        }
    </style>
</head>

<body>

    <div class="page">123
    </div>
    <button></button>


    <script>
        var button = document.querySelector('button');
        button.onclick = function() {
     
     
            windowScrollToTarget(0);
        };
        // 动画函数

        function windowScrollToTarget(target, callback) {
     
     
            var timer = setInterval(function() {
     
     
                var step = (target - window.pageYOffset) / 10;
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
                if (window.pageYOffset == target) {
     
     
                    clearInterval(timer);
                    callback && callback();
                }
                var targetPositionY = window.pageYOffset + step;
                window.scroll(0, targetPositionY);
            }, 15);
        }
    </script>
</body>

</html>

三, 动画

1. 飘动的盒子们

// 匀速动画 就是 盒子是当前的位置 + 固定的值 10
// 缓动动画就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        div {
     
     
            position: absolute;
            left: 0;
            width: 100px;
            height: 100px;
            background-color: pink;
        }
        
        span {
     
     
            position: absolute;
            left: 0;
            top: 200px;
            display: block;
            width: 150px;
            height: 150px;
            background-color: purple;
        }
    </style>
</head>

<body>
    <button class="btn500">点击夏雨荷到500</button>
    <button class="btn800">点击夏雨荷到800</button>
    <span>夏雨荷</span>
    <script>
        // 缓动动画函数封装obj目标对象 target 目标位置
        // 思路:
        // 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。
        // 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
        // 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
        function animate(obj, target, callback) {
     
     
            // console.log(callback);  callback = function() {}  调用的时候 callback()

            // 先清除以前的定时器,只保留当前的一个定时器执行
            //否则随着点击次数增加, 盒子移速会递增
            clearInterval(obj.timer);
            obj.timer = setInterval(function() {
     
     
                // 步长值写到定时器的里面
                // 把我们步长值改为整数 不要出现小数的问题
                // var step = Math.ceil((target - obj.offsetLeft) / 10);
                var step = (target - obj.offsetLeft) / 10;
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
                if (obj.offsetLeft == target) {
     
     
                    // 停止动画 本质是停止定时器
                    clearInterval(obj.timer);
                    // 回调函数写到定时器结束里面
                    if (callback) {
     
     
                        // 调用函数
                        callback();
                    }
                }
                // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
                obj.style.left = obj.offsetLeft + step + 'px';

            }, 15);
        }
        var span = document.querySelector('span');
        var btn500 = document.querySelector('.btn500');
        var btn800 = document.querySelector('.btn800');

        btn500.addEventListener('click', function() {
     
     
            // 调用函数
            animate(span, 500);
        })
        btn800.addEventListener('click', function() {
     
     
                // 调用函数
                animate(span, 800, function() {
     
     
                    // alert('你好吗');
                    span.style.backgroundColor = 'red';
                });
            })
            // 匀速动画 就是 盒子是当前的位置 +  固定的值 10 
            // 缓动动画就是  盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
    </script>
</body>

</html>

2. 轮播图

参见淘宝网的core-slide制作

把上个案例的animate函数封装, 方便随时调用

Guess you like

Origin blog.csdn.net/Fky_mie/article/details/115253203