Loading...
墨滴

恶名扬

2022/01/07  阅读:23  主题:极简黑

「学习笔记」WebAPI_3

元素偏移量 offset 系列

offset 概述

offset 翻译过来就是偏移量, 我们使用 offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等。

  1. 获得元素距离带有定位父元素的位置

  2. 获得元素自身的大小(宽度高度)

  3. 注意:返回的数值都不带单位

offset 与 style 区别

offset

  • offset 可以得到任意样式表中的样式值

  • offset 系列获得的数值是没有单位的

  • offsetWidth 包含padding+border+width

  • offsetWidth 等属性是只读属性,只能获取不能赋值

  • 所以,我们想要获取元素大小位置,用offset更合适

style

  • style 只能得到行内样式表中的样式值

  • style.width 获得的是带有单位的字符串

  • style.width 获得不包含padding和border 的值

  • style.width 是可读写属性,可以获取也可以赋值

  • 所以,我们想要给元素更改值,则需要用style改变

因为平时我们都是给元素注册触摸事件,所以重点记住 targetTocuhes

案例:获取鼠标在盒子内的坐标

  1. 我们在盒子内点击,想要得到鼠标距离盒子左右的距离。
  2. 首先得到鼠标在页面中的坐标(e.pageX, e.pageY)
  3. 其次得到盒子在页面中的距离 ( box.offsetLeft, box.offsetTop)
  4. 用鼠标距离页面的坐标减去盒子在页面中的距离,得到 鼠标在盒子内的坐标
  5. 如果想要移动一下鼠标,就要获取最新的坐标,使用鼠标移动
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;
})

案例:模态框拖拽

弹出框,我们也称为模态框。

​ 1.点击弹出层,会弹出模态框, 并且显示灰色半透明的遮挡层。

​ 2.点击关闭按钮,可以关闭模态框,并且同时关闭灰色半透明遮挡层。

​ 3.鼠标放到模态框最上面一行,可以按住鼠标拖拽模态框在页面中移动。

​ 4.鼠标松开,可以停止拖动模态框移动

案例分析:

  1. 点击弹出层, 模态框和遮挡层就会显示出来 display:block;
  2. 点击关闭按钮,模态框和遮挡层就会隐藏起来 display:none;
  3. 在页面中拖拽的原理:鼠标按下并且移动, 之后松开鼠标
  4. 触发事件是鼠标按下mousedown,鼠标移动mousemove 鼠标松开 mouseup
  5. 拖拽过程:  鼠标移动过程中,获得最新的值赋值给模态框的left和top值,这样模态框可以跟着鼠标走了
  6. 鼠标按下触发的事件源是最上面一行,就是  id 为 title
  7. 鼠标的坐标减去 鼠标在盒子内的坐标, 才是模态框真正的位置。
  8. 鼠标按下,我们要得到鼠标在盒子的坐标。
  9. 鼠标移动,就让模态框的坐标  设置为  :鼠标坐标 减去盒子坐标即可,注意移动事件写到按下事件里面。
  10. 鼠标松开,就停止拖拽,就是可以让鼠标移动事件解除
 // 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)

            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);
            })
        })

案例:仿京东放大镜

  1. 整个案例可以分为三个功能模块
  2. 鼠标经过小图片盒子, 黄色的遮挡层 和 大图片盒子显示,离开隐藏2个盒子功能
  3. 黄色的遮挡层跟随鼠标功能。
  4. 移动黄色遮挡层,大图片跟随移动功能。

案例分析:

  1. 黄色的遮挡层跟随鼠标功能。
  2. 把鼠标坐标给遮挡层不合适。因为遮挡层坐标以父盒子为准。
  3. 首先是获得鼠标在盒子的坐标。
  4. 之后把数值给遮挡层做为left 和top值。
  5. 此时用到鼠标移动事件,但是还是在小图片盒子内移动。
  6. 发现,遮挡层位置不对,需要再减去盒子自身高度和宽度的一半。
  7. 遮挡层不能超出小图片盒子范围。
  8. 如果小于零,就把坐标设置为0
  9. 如果大于遮挡层最大的移动距离,就把坐标设置为最大的移动距离
  10. 遮挡层的最大移动距离:小图片盒子宽度 减去 遮挡层盒子宽度
window.addEventListener('load'function({
    var preview_img = document.querySelector('.preview_img');
    var mask = document.querySelector('.mask');
    var big = document.querySelector('.big');
    // 1. 当我们鼠标经过 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';
        })
        // 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';
        // 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';

    })

})

元素可视区 client 系列

client概述

client 翻译过来就是客户端,我们使用 client 系列的相关属性来获取元素可视区的相关信息。通过 client 系列的相关属性可以动态的得到该元素的边框大小、元素大小等。

淘宝 flexible.js 源码分析

立即执行函数 (function(){})()  或者 (function(){}())

主要作用: 创建一个独立的作用域。 避免了命名冲突问题

下面三种情况都会刷新页面都会触发 load 事件。

1.a标签的超链接

2.F5或者刷新按钮(强制刷新)

3.前进后退按钮

但是 火狐中,有个特点,有个“往返缓存”,这个缓存中不仅保存着页面数据,还保存了DOM和JavaScript的状态;实际上是将整个页面都保存在了内存里。

所以此时后退按钮不能刷新页面。

此时可以使用 pageshow事件来触发。,这个事件在页面显示时触发,无论页面是否来自缓存。在重新加载页面中,pageshow会在load事件触发后触发;根据事件对象中的persisted来判断是否是缓存中的页面触发的pageshow事件

注意这个事件给window添加。

元素滚动 scroll 系列

scroll 概述

scroll 翻译过来就是滚动的,我们使用 scroll 系列的相关属性可以动态的得到该元素的大小、滚动距离等。

页面被卷去的头部

如果浏览器的高(或宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发 onscroll事件。

案例:仿淘宝固定右侧侧边栏

  1. 原先侧边栏是绝对定位
  2. 当页面滚动到一定位置,侧边栏改为固定定位
  3. 页面继续滚动,会让 返回顶部显示出来

案例分析:

  1. 需要用到页面滚动事件 scroll  因为是页面滚动,所以事件源是document
  2. 滚动到某个位置,就是判断页面被卷去的上部值。
  3. 页面被卷去的头部:可以通过window.pageYOffset 获得  如果是被卷去的左侧window.pageXOffset
  4. 注意,元素被卷去的头部是element.scrollTop  , 如果是页面被卷去的头部 则是 window.pageYOffset
  5. 其实这个值 可以通过盒子的 offsetTop可以得到,如果大于等于这个值,就可以让盒子固定定位了
  //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';
            }

        })

页面被卷去的头部兼容性解决方案

需要注意的是,页面被卷去的头部,有兼容性问题,因此被卷去的头部通常有如下几种写法:

  1. 声明了 DTD,使用 document.documentElement.scrollTop
  2. 未声明 DTD,使用  document.body.scrollTop
  3. 新方法 window.pageYOffset和 window.pageXOffset,IE9 开始支持
function getScroll({
    return {
      leftwindow.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft||0,
      topwindow.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
    };
 } 
使用的时候  getScroll().left

三大系列总结

他们主要用法:

1.offset系列 经常用于获得元素位置    offsetLeft  offsetTop

2.client经常用于获取元素大小  clientWidth clientHeight

3.scroll 经常用于获取滚动距离 scrollTop  scrollLeft

4.注意页面滚动的距离通过 window.pageXOffset  获得

mouseenter 和mouseover的区别

  • 当鼠标移动到元素上时就会触发mouseenter 事件
  • 类似 mouseover,它们两者之间的差别是
  • mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发。mouseenter  只会经过自身盒子触发
  • 之所以这样,就是因为mouseenter不会冒泡
  • 跟mouseenter搭配鼠标离开 mouseleave  同样不会冒泡

动画函数封装

动画实现原理

核心原理:通过定时器 setInterval() 不断移动盒子位置。

实现步骤:

  1. 获得盒子当前位置
  2. 让盒子在当前位置加上1个移动距离
  3. 利用定时器不断重复这个操作
  4. 加一个结束定时器的条件
  5. 注意此元素需要添加定位,才能使用element.style.left

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

如果多个元素都使用这个动画函数,每次都要var 声明定时器。我们可以给不同的元素使用不同的定时器(自己专门用自己的定时器)。

核心原理:利用 JS 是一门动态语言,可以很方便的给当前对象添加属性。

 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);
        }

动画函数封装

缓动效果原理

缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来

思路:

  1. 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。
  2. 核心算法: (目标值 - 现在的位置)   /  10    做为每次移动的距离步长
  3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
  4. 注意步长值需要取整

动画函数多个目标值之间移动

可以让动画函数从 800 移动到 500。

当我们点击按钮时候,判断步长是正值还是负值

​ 1.如果是正值,则步长往大了取整

​ 2.如果是负值,则步长 向小了取整

动函数添加回调函数

回调函数原理:函数可以作为一个参数。将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数,这个过程就叫做回调。

回调函数写的位置:定时器结束的位置。

动画完整版代码:

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);
}

常见网页特效案例

案例:网页轮播图

轮播图也称为焦点图,是网页中比较常见的网页特效。

功能需求:

​ 1.鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮。

​ 2.点击右侧按钮一次,图片往左播放一张,以此类推,左侧按钮同理。

​ 3.图片播放的同时,下面小圆圈模块跟随一起变化。

​ 4.点击小圆圈,可以播放相应图片。

​ 5.鼠标不经过轮播图,轮播图也会自动播放图片。

​ 6.鼠标经过,轮播图模块, 自动播放停止。

window.addEventListener('load'function() {
    // 1. 获取元素
    var arrow_l = document.querySelector('.arrow-l');
    var arrow_r = document.querySelector('.arrow-r');
    var focus = document.querySelector('.focus');
    var focusWidth = focus.offsetWidth;
    // 2. 鼠标经过focus 就显示隐藏左右按钮
    focus.addEventListener('mouseenter'function() {
        arrow_l.style.display = 'block';
        arrow_r.style.display = 'block';
        clearInterval(timer);
        timer = null; // 清除定时器变量
    });
    focus.addEventListener('mouseleave'function() {
        arrow_l.style.display = 'none';
        arrow_r.style.display = 'none';
        timer = setInterval(function() {
            //手动调用点击事件
            arrow_r.click();
        }, 2000);
    });
    // 3. 动态生成小圆圈  有几张图片,我就生成几个小圆圈
    var ul = focus.querySelector('ul');
    var ol = focus.querySelector('.circle');
    // console.log(ul.children.length);
    for (var i = 0; i < ul.children.length; i++) {
        // 创建一个小li 
        var li = document.createElement('li');
        // 记录当前小圆圈的索引号 通过自定义属性来做 
        li.setAttribute('index', i);
        // 把小li插入到ol 里面
        ol.appendChild(li);
        // 4. 小圆圈的排他思想 我们可以直接在生成小圆圈的同时直接绑定点击事件
        li.addEventListener('click'function() {
            // 干掉所有人 把所有的小li 清除 current 类名
            for (var i = 0; i < ol.children.length; i++) {
                ol.children[i].className = '';
            }
            // 留下我自己  当前的小li 设置current 类名
            this.className = 'current';
            // 5. 点击小圆圈,移动图片 当然移动的是 ul 
            // ul 的移动距离 小圆圈的索引号 乘以 图片的宽度 注意是负值
            // 当我们点击了某个小li 就拿到当前小li 的索引号
            var index = this.getAttribute('index');
            // 当我们点击了某个小li 就要把这个li 的索引号给 num  
            num = index;
            // 当我们点击了某个小li 就要把这个li 的索引号给 circle  
            circle = index;
            // num = circle = index;
            console.log(focusWidth);
            console.log(index);

            animate(ul, -index * focusWidth);
        })
    }
    // 把ol里面的第一个小li设置类名为 current
    ol.children[0].className = 'current';
    // 6. 克隆第一张图片(li)放到ul 最后面
    var first = ul.children[0].cloneNode(true);
    ul.appendChild(first);
    // 7. 点击右侧按钮, 图片滚动一张
    var num = 0;
    // circle 控制小圆圈的播放
    var circle = 0;
    // flag 节流阀
    var flag = true;
    arrow_r.addEventListener('click'function() {
        if (flag) {
            flag = false; // 关闭节流阀
            // 如果走到了最后复制的一张图片,此时 我们的ul 要快速复原 left 改为 0
            if (num == ul.children.length - 1) {
                ul.style.left = 0;
                num = 0;
            }
            num++;
            animate(ul, -num * focusWidth, function() {
                flag = true; // 打开节流阀
            });
            // 8. 点击右侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放
            circle++;
            // 如果circle == 4 说明走到最后我们克隆的这张图片了 我们就复原
            if (circle == ol.children.length) {
                circle = 0;
            }
            // 调用函数
            circleChange();
        }
    });

    // 9. 左侧按钮做法
    arrow_l.addEventListener('click'function() {
        if (flag) {
            flag = false;
            if (num == 0) {
                num = ul.children.length - 1;
                ul.style.left = -num * focusWidth + 'px';

            }
            num--;
            animate(ul, -num * focusWidth, function() {
                flag = true;
            });
            // 点击左侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放
            circle--;
            // 如果circle < 0  说明第一张图片,则小圆圈要改为第4个小圆圈(3)
            // if (circle < 0) {
            //     circle = ol.children.length - 1;
            // }
            circle = circle < 0 ? ol.children.length - 1 : circle;
            // 调用函数
            circleChange();
        }
    });

    function circleChange() {
        // 先清除其余小圆圈的current类名
        for (var i = 0; i < ol.children.length; i++) {
            ol.children[i].className = '';
        }
        // 留下当前的小圆圈的current类名
        ol.children[circle].className = 'current';
    }
    // 10. 自动播放轮播图
    var timer = setInterval(function() {
        //手动调用点击事件
        arrow_r.click();
    }, 2000);

})

节流阀

防止轮播图按钮连续点击造成播放过快。

节流阀目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发。

核心实现思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数。

开始设置一个变量var flag= true;

If(flag){flag = false; do something}       关闭水龙头

利用回调函数动画执行完毕, flag = true     打开水龙头

案例:返回顶部

  1. 带有动画的返回顶部
  2. 此时可以继续使用我们封装的动画函数
  3. 只需要把所有的left 相关的值改为 跟 页面垂直滚动距离相关就可以了
  4. 页面滚动了多少,可以通过 window.pageYOffset 得到
  5. 最后是页面滚动,使用 window.scroll(x,y)
  //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(window0);
        });

1.2.4. 案例:筋头云案例

  1. 利用动画函数做动画效果
  2. 原先筋斗云的起始位置是0
  3. 鼠标经过某个小li,把当前小li的offsetLeft 位置做为目标值即可
  4. 鼠标离开某个小li,就把目标值设为 0
  5. 如果点击了某个小li, 就把li当前的位置存储起来,做为筋斗云的起始位置
 window.addEventListener('load'function({
            // 1. 获取元素
            var cloud = document.querySelector('.cloud');
            var c_nav = document.querySelector('.c-nav');
            var lis = c_nav.querySelectorAll('li');
            // 2. 给所有的小li绑定事件 
            // 这个current 做为筋斗云的起始位置
            var current = 0;
            for (var i = 0; i < lis.length; i++) {
                // (1) 鼠标经过把当前小li 的位置做为目标值
                lis[i].addEventListener('mouseenter'function({
                    animate(cloud, this.offsetLeft);
                });
                // (2) 鼠标离开就回到起始的位置 
                lis[i].addEventListener('mouseleave'function({
                    animate(cloud, current);
                });
                // (3) 当我们鼠标点击,就把当前位置做为目标值
                lis[i].addEventListener('click'function({
                    current = this.offsetLeft;
                });
            }
        })

触屏事件

触屏事件概述

移动端浏览器兼容性较好,我们不需要考虑以前 JS 的兼容性问题,可以放心的使用原生 JS 书写效果,但是移动端也有自己独特的地方。比如触屏事件 touch(也称触摸事件),Android和 IOS 都有。

touch 对象代表一个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。触屏事件可响应用户手指(或触控笔)对屏幕或者触控板操作。

触摸事件对象(TouchEvent)

TouchEvent 是一类描述手指在触摸平面(触摸屏、触摸板等)的状态变化的事件。这类事件用于描述一个或多个触点,使开发者可以检测触点的移动,触点的增加和减少,等等

touchstart、touchmove、touchend 三个事件都会各自有事件对象。

案例:移动端拖动元素

  1. touchstart、touchmove、touchend可以实现拖动元素

  2. 但是拖动元素需要当前手指的坐标值 我们可以使用  targetTouches[0] 里面的pageX 和 pageY

  3. 移动端拖动的原理:    手指移动中,计算出手指移动的距离。然后用盒子原来的位置 + 手指移动的距离

  4. 手指移动的距离:  手指滑动中的位置 减去  手指刚开始触摸的位置

    拖动元素三步曲:

    (1) 触摸元素 touchstart: 获取手指初始坐标,同时获得盒子原来的位置

    (2) 移动手指 touchmove: 计算手指的滑动距离,并且移动盒子

    (3) 离开手指 touchend:

    注意: 手指移动也会触发滚动屏幕所以这里要阻止默认的屏幕滚动 e.preventDefault();

classList 属性

classList属性是HTML5新增的一个属性,返回元素的类名。但是ie10以上版本支持。

该属性用于在元素中添加,移除及切换 CSS 类。有以下方法

添加类:

element.classList.add(’类名’);

focus.classList.add('current');

移除类:

element.classList.remove(’类名’);

focus.classList.remove('current');

切换类:

element.classList.toggle(’类名’);

focus.classList.toggle('current');

注意:以上方法里面,所有类名都不带点

案例分析

  1. 小圆点跟随变化效果

  2. 把ol里面li带有current类名的选出来去掉类名 remove

  3. 让当前索引号的小li 加上 current   add

  4. 但是,是等着过渡结束之后变化,所以这个写到 transitionend 事件里面

    1551796072(1)
    1551796072(1)
  5. 手指滑动轮播图

  6. 本质就是ul跟随手指移动,简单说就是移动端拖动元素

  7. 触摸元素touchstart:  获取手指初始坐标

  8. 移动手指touchmove:  计算手指的滑动距离,并且移动盒子

  9. 离开手指touchend:   根据滑动的距离分不同的情况

  10. 如果移动距离小于某个像素  就回弹原来位置

  11. 如果移动距离大于某个像素就上一张下一张滑动。

  12. 滑动也分为左滑动和右滑动判断的标准是 移动距离正负 如果是负值就是左滑 反之右滑

  13. 如果是左滑就播放下一张 (index++)

  14. 如果是右滑就播放上一张  (index--)

案例:返回顶部

当页面滚动某个地方,就显示,否则隐藏

点击可以返回顶部

案例分析

  1. 滚动某个地方显示
  2. 事件:scroll页面滚动事件
  3. 如果被卷去的头部(window.pageYOffset )大于某个数值
  4. 点击,window.scroll(0,0) 返回顶部

click 延时解决方案

移动端 click 事件会有 300ms 的延时,原因是移动端屏幕双击会缩放(double tap to zoom) 页面。

解决方案:

​ 1. 禁用缩放。 浏览器禁用默认的双击缩放行为并且去掉300ms 的点击延迟。

  <meta name="viewport" content="user-scalable=no">

​ 2.利用touch事件自己封装这个事件解决300ms 延迟。

​ 原理就是:

  1. 当我们手指触摸屏幕,记录当前触摸时间
  2. 当我们手指离开屏幕, 用离开的时间减去触摸的时间
  3. 如果时间小于150ms,并且没有滑动过屏幕, 那么我们就定义为点击

代码如下:

//封装tap,解决click 300ms 延时
function tap (obj, callback{
        var isMove = false;
        var startTime = 0// 记录触摸时候的时间变量
        obj.addEventListener('touchstart'function (e{
            startTime = Date.now(); // 记录触摸时间
        });
        obj.addEventListener('touchmove'function (e{
            isMove = true;  // 看看是否有滑动,有滑动算拖拽,不算点击
        });
        obj.addEventListener('touchend'function (e{
            if (!isMove && (Date.now() - startTime) < 150) {  // 如果手指触摸和离开时间小于150ms 算点击
                callback && callback(); // 执行回调函数
            }
            isMove = false;  //  取反 重置
            startTime = 0;
        });
}
//调用  
  tap(div, function(){   // 执行代码  });

  1. 使用插件。fastclick 插件解决300ms 延迟。

移动端常用开发插件

什么是插件

移动端要求的是快速开发,所以我们经常会借助于一些插件来帮我完成操作,那么什么是插件呢?

JS 插件是 js 文件,它遵循一定规范编写,方便程序展示效果,拥有特定功能且方便调用。如轮播图和瀑布流插件。

特点:它一般是为了解决某个问题而专门存在,其功能单一,并且比较小。

我们以前写的animate.js 也算一个最简单的插件

fastclick 插件解决 300ms 延迟。 使用延时

GitHub官网地址: https://github.com/ftlabs/fastclick

插件的使用

  1. 引入 js 插件文件。

  2. 按照规定语法使用。

  3. fastclick 插件解决 300ms 延迟。 使用延时

  4. GitHub官网地址: https://github.com/ftlabs/fastclick

    if ('addEventListener' in document) {
                document.addEventListener('DOMContentLoaded'function({
                           FastClick.attach(document.body);
                }, false);
    }

Swiper 插件的使用

中文官网地址: https://www.swiper.com.cn/

  1. 引入插件相关文件。
  2. 按照规定语法使用

其他移动端常见插件

lsuperslide: http://www.superslide2.com/

l iscroll: https://github.com/cubiq/iscroll

插件的使用总结

1.确认插件实现的功能

2.去官网查看使用说明

3.下载插件

4.打开demo实例文件,查看需要引入的相关文件,并且引入

5.复制demo实例文件中的结构html,样式css以及js代码

移动端视频插件 zy.media.js

H5 给我们提供了 video 标签,但是浏览器的支持情况不同。

不同的视频格式文件,我们可以通过source解决。

但是外观样式,还有暂停,播放,全屏等功能我们只能自己写代码解决。

这个时候我们可以使用插件方式来制作。

我们可以通过 JS 修改元素的大小、颜色、位置等样式。

移动端常用开发框架

移动端视频插件 zy.media.js

框架,顾名思义就是一套架构,它会基于自身的特点向用户提供一套较为完整的解决方案。框架的控制权在框架本身,使用者要按照框架所规定的某种规范进行开发。

插件一般是为了解决某个问题而专门存在,其功能单一,并且比较小。

前端常用的框架有 Bootstrap、Vue、Angular、React 等。既能开发PC端,也能开发移动端

前端常用的移动端插件有 swiper、superslide、iscroll等。

框架: 大而全,一整套解决方案

插件: 小而专一,某个功能的解决方案

Bootstrap

Bootstrap 是一个简洁、直观、强悍的前端开发框架,它让 web 开发更迅速、简单。

它能开发PC端,也能开发移动端

Bootstrap JS插件使用步骤:

1.引入相关js 文件

2.复制HTML 结构

3.修改对应样式

4.修改相应JS 参数

本地存储

随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案。

本地存储特性

1、数据存储在用户浏览器中

2、设置、读取方便、甚至页面刷新不丢失数据

3、容量较大,sessionStorage约5M、localStorage约20M

4、只能存储字符串,可以将对象JSON.stringify() 编码后存储

window.sessionStorage

1、生命周期为关闭浏览器窗口

2、在同一个窗口(页面)下数据可以共享

3、以键值对的形式存储使用

存储数据:

sessionStorage.setItem(key, value)

获取数据:

sessionStorage.getItem(key)

删除数据:

sessionStorage.removeItem(key)

清空数据:(所有都清除掉)

sessionStorage.clear()

window.localStorage

1、声明周期永久生效,除非手动删除 否则关闭页面也会存在

2、可以多窗口(页面)共享(同一浏览器可以共享)

  1. 以键值对的形式存储使用

存储数据:

localStorage.setItem(key, value)

获取数据:

localStorage.getItem(key)

删除数据:

localStorage.removeItem(key)

清空数据:(所有都清除掉)

localStorage.clear()

案例:记住用户名

如果勾选记住用户名, 下次用户打开浏览器,就在文本框里面自动显示上次登录的用户名

案例分析

  1. 把数据存起来,用到本地存储

  2. 关闭页面,也可以显示用户名,所以用到localStorage

  3. 打开页面,先判断是否有这个用户名,如果有,就在表单里面显示用户名,并且勾选复选框

  4. 当复选框发生改变的时候change事件

  5. 如果勾选,就存储,否则就移除

- END -

恶名扬

2022/01/07  阅读:23  主题:极简黑

作者介绍

恶名扬