JavaScript进阶第五天(PC网页特效+动画)

01、PC网页特效导读

02、offsetLeft和offsetTop获取元素偏移

eg:

    <script>
        // offset 系列
        var father = document.querySelector('.father');
        var son = document.querySelector('.son');
        // 1.可以得到元素的偏移 位置 返回的不带单位的数值  
        console.log(father.offsetTop);
        console.log(father.offsetLeft);
        // 它以带有定位的父亲为准  如果么有父亲或者父亲没有定位 则以 body 为准
        console.log(son.offsetLeft);
        var w = document.querySelector('.w');
        // 2.可以得到元素的大小 宽度和高度 是包含padding + border + width 
        console.log(w.offsetWidth);
        console.log(w.offsetHeight);
        // 3. 返回带有定位的父亲 否则返回的是body
        console.log(son.offsetParent); // 返回带有定位的父亲 否则返回的是body
        console.log(son.parentNode); // 返回父亲 是最近一级的父亲 亲爸爸 不管父亲有没有定位
    </script>

在这里插入图片描述

03、offsetWidth和offsetHeight获取元素大小、offsetParent返回父亲

见上

04、offset和style的区别

在这里插入图片描述

05、案例:获取鼠标在盒子里面的坐标

在这里插入图片描述
在这里插入图片描述
// 我们在盒子内点击, 想要得到鼠标距离盒子左右的距离。
// 首先得到鼠标在页面中的坐标( e.pageX, e.pageY)
// 其次得到盒子在页面中的距离(box.offsetLeft, box.offsetTop)
// 用鼠标距离页面的坐标减去盒子在页面中的距离, 得到 鼠标在盒子内的坐标

<body>
    <div class="box"></div>
    <script>
        var box = document.querySelector('.box');
        box.addEventListener('mousemove', function(e) {
            var x = e.pageX - this.offsetLeft;
            var y = e.pageY - this.offsetTop;
            this.innerHTML = 'x坐标是' + x + ' y坐标是' + y;
        })
    </script>
</body>

06-08、拖动模态框

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

html:

    <div class="login-header"><a id="link" href="javascript:;">点击,弹出登录框</a></div>
    <div id="login" class="login">
        <div id="title" class="login-title">登录会员
            <span><a id="closeBtn" href="javascript:void(0);" class="close-login">关闭</a></span>
        </div>
        <div class="login-input-content">
            <div class="login-input">
                <label>用户名:</label>
                <input type="text" placeholder="请输入用户名" name="info[username]" id="username" class="list-input">
            </div>
            <div class="login-input">
                <label>登录密码:</label>
                <input type="password" placeholder="请输入登录密码" name="info[password]" id="password" class="list-input">
            </div>
        </div>
        <div id="loginBtn" class="login-button"><a href="javascript:void(0);" id="login-button-submit">登录会员</a></div>
    </div>
    <!-- 遮盖层 -->
    <div id="bg" class="login-bg"></div>

js:

    <script>
        // 1. 获取元素
        var login = document.querySelector('.login');
        var mask = document.querySelector('.login-bg');
        var link = document.querySelector('#link');
        var closeBtn = document.querySelector('#closeBtn');
        var title = document.querySelector('#title');
        // 2. 点击弹出层这个链接 link  让mask 和login 显示出来
        link.addEventListener('click', function () {
            mask.style.display = 'block';
            login.style.display = 'block';
        })
        // 3. 点击 closeBtn 就隐藏 mask 和 login 
        closeBtn.addEventListener('click', function () {
            mask.style.display = 'none';
            login.style.display = 'none';
        })
        // 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) //这里使用函数名称的原因在于:之后需要用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);
            })
        })
    </script>

09-13、仿京东的放大镜效果

在这里插入图片描述

1、制作放大镜的框框mask

                <div class="preview_img">
                    <img src="upload/s3.png" alt="">
                    <div class="mask"></div>
                    <div class="big">
                        <img src="upload/big.jpg" alt="" class="bigImg">
                    </div>
                </div>

2、设置样式:

.mask {
    display: none;
    position: absolute;
    top: 0;
    left: 0;
    width: 300px;
    height: 300px;
    background: #FEDE4F;
    /* 半透明效果 */
    opacity: .5;
    border: 1px solid #ccc;
    /* 鼠标经过后,鼠标样式改为十字 */
    cursor: move;
}

3、再准备一个放大效果的盒子big

                <div class="preview_img">
                    <img src="upload/s3.png" alt="">
                    <div class="mask"></div>
                    <div class="big">
                        <img src="upload/big.jpg" alt="" class="bigImg">
                    </div>
                </div>

4、大盒子样式

.big {
    display: none;
    /* 子绝父相 */
    position: absolute;
    left: 410px;
    top: 0;
    width: 500px;
    height: 500px;
    background-color: pink;
    /* 设在最外层 */
    z-index: 999;
    border: 1px solid #ccc;
    /* 多余的隐藏起来 */
    overflow: hidden;
}

.big img {
    /* 子绝父相 */
    position: absolute;
    top: 0;
    left: 0;
}

5、js分析:
①html中引入js文件:

    <!-- 引入我们的js 文件 -->
    <script src="js/detail.js"></script>

②给所有的js设置load:先加载,然后js

window.addEventListener('load', function()

③获取元素:

    var preview_img = document.querySelector('.preview_img');
    var mask = document.querySelector('.mask');
    var big = document.querySelector('.big');

④当我们鼠标经过 preview_img 就显示和隐藏 mask 遮挡层 和 big 大盒子

    preview_img.addEventListener('mouseover', function() {
        mask.style.display = 'block';
        big.style.display = 'block';
    })
    preview_img.addEventListener('mouseout', function() {
            mask.style.display = 'none';
            big.style.display = 'none';
        })

⑤鼠标移动的时候伴随放大镜的移动:
1)获取鼠标距离盒子的位置(用e.page和offset做)
2)获取放大镜距离盒子的位置(用1)中的结果减去放大镜的边框即可)
3)考虑放大镜位置的特殊情况(坐标超出边框时按照在边框上处理)
4)更新放大镜的位置(用放大镜的.style.leftright做)

        // 2. 鼠标移动的时候,让黄色的盒子跟着鼠标来走
    preview_img.addEventListener('mousemove', function(e) {
        // (1). 先计算出鼠标在盒子内的坐标
        var x = e.pageX - this.offsetLeft;
        var y = e.pageY - this.offsetTop;
        // console.log(x, y);
        // (2) 减去盒子高度 300的一半 是 150 就是我们mask 的最终 left 和top值了
        // (3) 我们mask 移动的距离
        var maskX = x - mask.offsetWidth / 2;
        var maskY = y - mask.offsetHeight / 2;
        // (4) 如果x 坐标小于了0 就让他停在0 的位置
        // 遮挡层的最大移动距离
        var maskMax = preview_img.offsetWidth - mask.offsetWidth;
        if (maskX <= 0) {
            maskX = 0;
        } else if (maskX >= maskMax) {
            maskX = maskMax;
        }
        if (maskY <= 0) {
            maskY = 0;
        } else if (maskY >= maskMax) {
            maskY = maskMax;
        }
        mask.style.left = maskX + 'px';
        mask.style.top = maskY + 'px';

⑥放大图片跟随的移动效果
1)由等比例移动的关系:
在这里插入图片描述
则:
大图片的移动距离 = 遮挡层移动距离 * 大图片最大移动距离 / 遮挡层的最大移动距离
2)由公式计算
遮挡层移动距离 = maskX/Y
大图片最大移动距离 = 图片的最大宽度-盒子的最大宽度 = bigIMg.offsetWidth - big.offsetWidth
遮挡层的最大移动距离 = maskMax
3)大图的移动方向和放大镜的移动方向相反:

        bigIMg.style.left = -bigX + 'px';
        bigIMg.style.top = -bigY + 'px';

代码:

        // 3. 大图片的移动距离 = 遮挡层移动距离 * 大图片最大移动距离 / 遮挡层的最大移动距离
        // 大图
        var bigIMg = document.querySelector('.bigImg');
        // 大图片最大移动距离
        var bigMax = bigIMg.offsetWidth - big.offsetWidth;
        // 大图片的移动距离 X Y
        var bigX = maskX * bigMax / maskMax;
        var bigY = maskY * bigMax / maskMax;
        bigIMg.style.left = -bigX + 'px';
        bigIMg.style.top = -bigY + 'px';

14、client系列

在这里插入图片描述
client 宽度 和我们offsetWidth 最大的区别就是 不包含边框border,但是都包含padding
其他基本都一样

15、立即执行函数

在这里插入图片描述
立即执行函数: 不需要调用,立马能够自己执行的函数
立即执行函数最大的作用就是 独立创建了一个作用域, 里面所有的变量都是局部变量 不会有命名冲突的情况

写法:
1.(function() {})();

eg:

        (function(a, b) {
            console.log(a + b);
            var num = 10;
        })(1, 2); // 第二个小括号可以看做是调用函数
  1. (function(){}());
    eg:
        (function sum(a, b) {
            console.log(a + b);
            var num = 10; // 局部变量
        }(2, 3));

16、淘宝flexibleJS源码分析之核心原理

(function flexible(window, document) {
    // 获取的html 的根元素
    var docEl = document.documentElement
    // dpr 物理像素比
    var dpr = window.devicePixelRatio || 1

    // adjust body font size  设置我们body 的字体大小
    function setBodyFontSize() {
        // 如果页面中有body 这个元素 就设置body的字体大小
        if (document.body) {
            document.body.style.fontSize = (12 * dpr) + 'px'
        } else {
            // 如果页面中没有body 这个元素,则等着 我们页面主要的DOM元素加载完毕再去设置body
            // 的字体大小
            document.addEventListener('DOMContentLoaded', setBodyFontSize)
        }
    }
    setBodyFontSize();

    // set 1rem = viewWidth / 10    设置我们html 元素的文字大小
    function setRemUnit() {
        var rem = docEl.clientWidth / 10
        docEl.style.fontSize = rem + 'px'
    }

    setRemUnit()

    // reset rem unit on page resize  当我们页面尺寸大小发生变化的时候,要重新设置下rem 的大小
    window.addEventListener('resize', setRemUnit) // resize指当浏览器页面大小发生了变化时
    // pageshow 是我们重新加载页面触发的事件,比load更加灵敏,它会在火狐的后退操作后也发生重新加载
    window.addEventListener('pageshow', function (e) {
        // e.persisted 返回的是true 就是说如果这个页面是从缓存取过来的页面,也需要从新计算一下rem 的大小
        if (e.persisted) {
            setRemUnit()
        }
    })

    // detect 0.5px supports  有些移动端的浏览器不支持0.5像素的写法
    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))

17、元素滚动scroll系列

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
eg:每滚动一次就记录一下scrollTop的值

        div.addEventListener('scroll', function() {
            console.log(div.scrollTop);
        })

18、仿淘宝固定侧边栏

需要实现的功能:
在这里插入图片描述
html:

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

css略
JS:
首先侧边栏的位置是固定的absolute
当滚动到banner的部分时,更改为fixed
当滚动到main的部分时,出现返回顶部的锚点

①获取元素

        var sliderbar = document.querySelector('.slider-bar');
        var banner = document.querySelector('.banner');
        var main = document.querySelector('.main');
        var goBack = document.querySelector('.goBack');
        var mainTop = main.offsetTop;

②记录banner和main和侧边栏sliderbar的盒子上面被减去的头部:

var bannerTop = banner.offsetTop;
var mainTop = main.offsetTop;
// 当我们侧边栏固定定位之后应该变化的数值
var sliderbarTop = sliderbar.offsetTop - bannerTop;

③制作页面滚动事件

        document.addEventListener('scroll', function () {
            // 3 .当我们页面被卷去的头部大于等于了 172(到达了banner处) 此时 侧边栏就要改为固定定位
            if (window.pageYOffset >= bannerTop) {
                sliderbar.style.position = 'fixed';
                sliderbar.style.top = sliderbarTop + 'px'; // 固定的位置要处于172处而不是CSS中定义的页面中央,让动画更丝滑
            } 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';
            }
        })

21、三大系列总结

在这里插入图片描述
在这里插入图片描述

22、mouseentermouseover的区别

在这里插入图片描述

23、动画原理

在这里插入图片描述
获取用offset,赋值用style

        var div = document.querySelector('div');
        var timer = setInterval(function() {
            if (div.offsetLeft >= 400) {
                // 停止动画 本质是停止定时器
                clearInterval(timer);
            }
            div.style.left = div.offsetLeft + 1 + 'px';
        }, 30);

24、简单动画函数封装

因为动画需要用到style中的left,而这个属性只有定位才有,所以必须给元素加定位!!!

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

25、动画函数-给不同元素记录不同定时器

对象.属性的方法取代var声明变量,从而做到元素都有自己的定时器,比如:div.timer()/p.timer()/btn.timer()

    <script>
        // 给不同的元素指定了不同的定时器
        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>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值