DOM&BOM基础第6篇

作者: 硅谷干货 | 来源:发表于2021-12-22 10:13 被阅读0次

    前言

    DOM&BOM基础是很重要前端知识,在这里我准备了所有相关知识的概念描述以及示例Demo,连载7篇,和大家一起温故而知新,覆盖每一个知识点,相信在以后的开发和面试中你总会用到它。

    自定义 animate.js 动画函数

    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();
                // }
                callback && callback();
            }
            // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
            obj.style.left = obj.offsetLeft + step + 'px';
    
        }, 15);
    }
    

    自定义 flexible.js 函数

    (function flexible(window, document) {
        var docEl = document.documentElement
        var dpr = window.devicePixelRatio || 1
    
        // adjust body font size
        function setBodyFontSize() {
            if (document.body) {
                document.body.style.fontSize = (12 * dpr) + 'px'
            } else {
                document.addEventListener('DOMContentLoaded', setBodyFontSize)
            }
        }
        setBodyFontSize();
    
        // set 1rem = viewWidth / 10
        function setRemUnit() {
            var rem = docEl.clientWidth / 10
            docEl.style.fontSize = rem + 'px'
        }
    
        setRemUnit()
    
        // reset rem unit on page resize
        window.addEventListener('resize', setRemUnit)
        window.addEventListener('pageshow', function(e) {
            if (e.persisted) {
                setRemUnit()
            }
        })
    
        // detect 0.5px supports
        if (dpr >= 2) {
            var fakeBody = document.createElement('body')
            var testElement = document.createElement('div')
            testElement.style.border = '.5px solid transparent'
            fakeBody.appendChild(testElement)
            docEl.appendChild(fakeBody)
            if (testElement.offsetHeight === 1) {
                docEl.classList.add('hairlines')
            }
            docEl.removeChild(fakeBody)
        }
    }(window, document))
    

    动画原理

    <head>
        <style>
            div {
                position: absolute;
                left: 0;
                width: 100px;
                height: 100px;
                background-color: pink;
            }
        </style>
    </head>
    
    <body>
        <div></div>
        <script>
            // 动画原理
            // 1. 获得盒子当前位置  
            // 2. 让盒子在当前位置加上1个移动距离
            // 3. 利用定时器不断重复这个操作
            // 4. 加一个结束定时器的条件
            // 5. 注意此元素需要添加定位, 才能使用element.style.left
            var div = document.querySelector('div');
            var timer = setInterval(function() {
                if (div.offsetLeft >= 400) {
                    // 停止动画 本质是停止定时器
                    clearInterval(timer);
                }
                div.style.left = div.offsetLeft + 1 + 'px';
            }, 30);
        </script>
    </body>
    
    </html>
    

    简单动画函数封装

    <head>
        <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>
        <div></div>
        <span>夏雨荷</span>
        <script>
            // 简单动画函数封装obj目标对象 target 目标位置
            function animate(obj, target) {
                var timer = setInterval(function() {
                    if (obj.offsetLeft >= target) {
                        // 停止动画 本质是停止定时器
                        clearInterval(timer);
                    }
                    obj.style.left = obj.offsetLeft + 1 + 'px';
    
                }, 30);
            }
    
            var div = document.querySelector('div');
            var span = document.querySelector('span');
            // 调用函数
            animate(div, 300);
            animate(span, 200);
        </script>
    </body>
    
    </html>
    

    给不同对象添加不同定时器

    <head>
        <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>点击夏雨荷才走</button>
        <div></div>
        <span>夏雨荷</span>
        <script>
            // var obj = {};
            // obj.name = 'andy';
            // 简单动画函数封装obj目标对象 target 目标位置
            // 给不同的元素指定了不同的定时器
            function animate(obj, target) {
                // 当我们不断的点击按钮,这个元素的速度会越来越快,因为开启了太多的定时器
                // 解决方案就是 让我们元素只有一个定时器执行
                // 先清除以前的定时器,只保留当前的一个定时器执行
                clearInterval(obj.timer);
                obj.timer = setInterval(function() {
                    if (obj.offsetLeft >= target) {
                        // 停止动画 本质是停止定时器
                        clearInterval(obj.timer);
                    }
                    obj.style.left = obj.offsetLeft + 1 + 'px';
    
                }, 30);
            }
    
            var div = document.querySelector('div');
            var span = document.querySelector('span');
            var btn = document.querySelector('button');
            // 调用函数
            animate(div, 300);
            btn.addEventListener('click', function() {
                animate(span, 200);
            })
        </script>
    </body>
    
    </html>
    

    缓动动画原理

    <html lang="en">
    
    <head>
        <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>点击夏雨荷才走</button>
        <span>夏雨荷</span>
        <script>
            // 缓动动画函数封装obj目标对象 target 目标位置
            // 思路:
            // 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。
            // 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
            // 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
            function animate(obj, target) {
                // 先清除以前的定时器,只保留当前的一个定时器执行
                clearInterval(obj.timer);
                obj.timer = setInterval(function() {
                    // 步长值写到定时器的里面
                    var step = (target - obj.offsetLeft) / 10;
                    if (obj.offsetLeft == target) {
                        // 停止动画 本质是停止定时器
                        clearInterval(obj.timer);
                    }
                    // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
                    obj.style.left = obj.offsetLeft + step + 'px';
    
                }, 15);
            }
            var span = document.querySelector('span');
            var btn = document.querySelector('button');
    
            btn.addEventListener('click', function() {
                    // 调用函数
                    animate(span, 500);
                })
                // 匀速动画 就是 盒子是当前的位置 +  固定的值 10 
                // 缓动动画就是  盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
        </script>
    </body>
    
    </html>
    

    缓动动画多个目标值之间移动

    <body>
        <button class="btn500">点击夏雨荷到500</button>
        <button class="btn800">点击夏雨荷到800</button>
        <span>夏雨荷</span>
        <script>
            // 缓动动画函数封装obj目标对象 target 目标位置
            // 思路:
            // 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。
            // 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
            // 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
            function animate(obj, target) {
                // 先清除以前的定时器,只保留当前的一个定时器执行
                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);
                    }
                    // 把每次加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);
                })
                // 匀速动画 就是 盒子是当前的位置 +  固定的值 10 
                // 缓动动画就是  盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
        </script>
    </body>
    

    缓动动画添加回调函数

    <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>
    

    引用animate动画函数

    <head>
        <style>
            .sliderbar {
                position: fixed;
                right: 0;
                bottom: 100px;
                width: 40px;
                height: 40px;
                text-align: center;
                line-height: 40px;
                cursor: pointer;
                color: #fff;
            }
            
            .con {
                position: absolute;
                left: 0;
                top: 0;
                width: 200px;
                height: 40px;
                background-color: purple;
                z-index: -1;
            }
        </style>
        <script src="animate.js"></script>
    </head>
    
    <body>
        <div class="sliderbar">
            <span>←</span>
            <div class="con">问题反馈</div>
        </div>
    
        <script>
            // 1. 获取元素
            var sliderbar = document.querySelector('.sliderbar');
            var con = document.querySelector('.con');
            // 当我们鼠标经过 sliderbar 就会让 con这个盒子滑动到左侧
            // 当我们鼠标离开 sliderbar 就会让 con这个盒子滑动到右侧
            sliderbar.addEventListener('mouseenter', function() {
                // animate(obj, target, callback);
                animate(con, -160, function() {
                    // 当我们动画执行完毕,就把 ← 改为 →
                    sliderbar.children[0].innerHTML = '→';
                });
    
            })
            sliderbar.addEventListener('mouseleave', function() {
                // animate(obj, target, callback);
                animate(con, 0, function() {
                    sliderbar.children[0].innerHTML = '←';
                });
    
            })
        </script>
    </body>
    
    </html>
    

    仿淘宝返回顶部

    <head>
        <style>
            .slider-bar {
                position: absolute;
                left: 50%;
                top: 300px;
                margin-left: 600px;
                width: 45px;
                height: 130px;
                background-color: pink;
            }
            
            .w {
                width: 1200px;
                margin: 10px auto;
            }
            
            .header {
                height: 150px;
                background-color: purple;
            }
            
            .banner {
                height: 250px;
                background-color: skyblue;
            }
            
            .main {
                height: 1000px;
                background-color: yellowgreen;
            }
            
            span {
                display: none;
                position: absolute;
                bottom: 0;
            }
        </style>
    </head>
    
    <body>
        <div class="slider-bar">
            <span class="goBack">返回顶部</span>
        </div>
        <div class="header w">头部区域</div>
        <div class="banner w">banner区域</div>
        <div class="main w">主体部分</div>
        <script>
            //1. 获取元素
            var sliderbar = document.querySelector('.slider-bar');
            var banner = document.querySelector('.banner');
            // banner.offestTop 就是被卷去头部的大小 一定要写到滚动的外面
            var bannerTop = banner.offsetTop
                // 当我们侧边栏固定定位之后应该变化的数值
            var sliderbarTop = sliderbar.offsetTop - bannerTop;
            // 获取main 主体元素
            var main = document.querySelector('.main');
            var goBack = document.querySelector('.goBack');
            var mainTop = main.offsetTop;
            // 2. 页面滚动事件 scroll
            document.addEventListener('scroll', function() {
                    // console.log(11);
                    // window.pageYOffset 页面被卷去的头部
                    // console.log(window.pageYOffset);
                    // 3 .当我们页面被卷去的头部大于等于了 172 此时 侧边栏就要改为固定定位
                    if (window.pageYOffset >= bannerTop) {
                        sliderbar.style.position = 'fixed';
                        sliderbar.style.top = sliderbarTop + 'px';
                    } else {
                        sliderbar.style.position = 'absolute';
                        sliderbar.style.top = '300px';
                    }
                    // 4. 当我们页面滚动到main盒子,就显示 goback模块
                    if (window.pageYOffset >= mainTop) {
                        goBack.style.display = 'block';
                    } else {
                        goBack.style.display = 'none';
                    }
    
                })
                // 3. 当我们点击了返回顶部模块,就让窗口滚动的页面的最上方
            goBack.addEventListener('click', function() {
                // 里面的x和y 不跟单位的 直接写数字即可
                // window.scroll(0, 0);
                // 因为是窗口滚动 所以对象是window
                animate(window, 0);
            });
            // 动画函数
            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 - window.pageYOffset) / 10;
                    step = step > 0 ? Math.ceil(step) : Math.floor(step);
                    if (window.pageYOffset == target) {
                        // 停止动画 本质是停止定时器
                        clearInterval(obj.timer);
                        // 回调函数写到定时器结束里面
                        // if (callback) {
                        //     // 调用函数
                        //     callback();
                        // }
                        callback && callback();
                    }
                    // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
                    // obj.style.left = window.pageYOffset + step + 'px';
                    window.scroll(0, window.pageYOffset + step);
                }, 15);
            }
        </script>
    </body>
    
    </html>
    

    touch触摸事件

    <body>
        <div></div>
        <script>
            // 1. 获取元素
            // 2. 手指触摸DOM元素事件
            var div = document.querySelector('div');
            div.addEventListener('touchstart', function() {
                console.log('我摸了你');
    
            });
            // 3. 手指在DOM元素身上移动事件
            div.addEventListener('touchmove', function() {
                console.log('我继续摸');
    
            });
            // 4. 手指离开DOM元素事件
            div.addEventListener('touchend', function() {
                console.log('轻轻的我走了');
    
            });
        </script>
    </body>
    

    触摸事件对象touchEvent

    <body>
        <div></div>
        <script>
            // 触摸事件对象
            // 1. 获取元素
            // 2. 手指触摸DOM元素事件
            var div = document.querySelector('div');
            div.addEventListener('touchstart', function(e) {
                // console.log(e);
                // touches 正在触摸屏幕的所有手指的列表 
                // targetTouches 正在触摸当前DOM元素的手指列表
                // 如果侦听的是一个DOM元素,他们两个是一样的
                // changedTouches 手指状态发生了改变的列表 从无到有 或者 从有到无
                // 因为我们一般都是触摸元素 所以最经常使用的是 targetTouches
                console.log(e.targetTouches[0]);
                // targetTouches[0] 就可以得到正在触摸dom元素的第一个手指的相关信息比如 手指的坐标等等
    
    
            });
            // 3. 手指在DOM元素身上移动事件
            div.addEventListener('touchmove', function() {
    
    
            });
            // 4. 手指离开DOM元素事件
            div.addEventListener('touchend', function(e) {
                // console.log(e);
                // 当我们手指离开屏幕的时候,就没有了 touches 和 targetTouches 列表
                // 但是会有 changedTouches
    
    
            });
        </script>
    </body>
    

    移动端拖动元素

    <head>
        <style>
            div {
                position: absolute;
                left: 0;
                width: 100px;
                height: 100px;
                background-color: pink;
            }
        </style>
    </head>
    
    <body>
        <div></div>
        <script>
            // (1) 触摸元素 touchstart:  获取手指初始坐标,同时获得盒子原来的位置
            // (2) 移动手指 touchmove:  计算手指的滑动距离,并且移动盒子
            // (3) 离开手指 touchend:
            var div = document.querySelector('div');
            var startX = 0; //获取手指初始坐标
            var startY = 0;
            var x = 0; //获得盒子原来的位置
            var y = 0;
            div.addEventListener('touchstart', function(e) {
                //  获取手指初始坐标
                startX = e.targetTouches[0].pageX;
                startY = e.targetTouches[0].pageY;
                x = this.offsetLeft;
                y = this.offsetTop;
            });
    
            div.addEventListener('touchmove', function(e) {
                //  计算手指的移动距离: 手指移动之后的坐标减去手指初始的坐标
                var moveX = e.targetTouches[0].pageX - startX;
                var moveY = e.targetTouches[0].pageY - startY;
                // 移动我们的盒子 盒子原来的位置 + 手指移动的距离
                this.style.left = x + moveX + 'px';
                this.style.top = y + moveY + 'px';
                e.preventDefault(); // 阻止屏幕滚动的默认行为
            });
        </script>
    </body>
    
    </html>
    

    上一篇:DOM&BOM基础第5篇 - 简书 (jianshu.com)
    下一篇:DOM&BOM基础第7篇 - 简书 (jianshu.com)

    点赞加关注,永远不迷路

    相关文章

      网友评论

        本文标题:DOM&BOM基础第6篇

        本文链接:https://www.haomeiwen.com/subject/fohqqrtx.html