Featured image of post 第三章 移动Web开发基础(下)

第三章 移动Web开发基础(下)

HTML5 常用 API

检测网络连接

在 HTML5 出现之前,可以通过 window.navigator.onLine 来检查用户当前的网络状态,它会返回一个布尔值,false 表示没有连接网络,true 表示已连接网络。需要注意的是,这种方式在不同浏览器中会存在差异。

为了更好地实现网络连接的检测,HTML5 提供了 onlineoffline 两个事件,它们监听的都是 window 对象。其中,online在用户网络连接时调用,offline在用户网络断开时调用。

1
window.addEventListener

全屏操作

HTMIL5 提供了 requestFullscreen() 方法,允许用户自定义网页上任一元素的全屏显示,并提供了 exitFullscreen() 方法关闭全屏显示。需要注意的是,这两个方法存在兼容性问题,不同浏览器需要添加不同的私有前缀。

浏览器 前缀 方法
Chrome(WebKit 内核) webkit webkitRequestFullScreen() 或 webkitCancelFullScreen()
火狐(Gecko 内核) moz mozRequestFullScreen() 或 mozCancelFullScreen()
Opera(Presto 内核) o oRequestFullScreen() 或 oCancelFullScreen()
IE(Trident 内核) ms msRequestFullscreen() 或 msExitFullscreen()
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div>
        <img src="/MyPra/img/icon.jpg" alt="">
        <br>
        <button id="full">全屏显示</button>
        <button id="cancelFull">取消全屏</button>
        <button id="isFull">判断当前是否全屏</button>
    </div>

    <script>
        const div = document.querySelector('div');
        // document.querySelector('#full') 返回表示 <div id="full"></div> 的DOM元素
        document.querySelector('#full').onclick = function () {
            if (div.requestFullscreen) {
                div.requestFullscreen();
            } else if (div.webkitRequestFullscreen) {
                div.webkitRequestFullScreen();              // webkit
            } else if (div.mozRequestFullScreen) {
                div.mozRequestFullScreen();                 // moz
            } else if (div.msRequestFullscreen) {
                div.msRequestFullscreen();                  // ms
            } else if (div.oRequestFullScreen) {
                div.oRequestFullScreen();                   // o
            } else {
                alert('浏览器不支持全屏');
            }
        };

        document.querySelector('#cancelFull').onclick = function () {
            if (document.exitFullscreen) {
                document.exitFullscreen();
            } else if (document.webkitCancelFullscreen) {
                document.webkitCancelFullScreen();          // webkit
            } else if (document.mozCancelFullScreen) {
                document.mozCancelFullScreen();             // moz
            } else if (document.msExitFullscreen) {
                document.msExitFullscreen();                // ms
            } else if (document.oCancelFullScreen) {
                document.oCancelFullScreen();               // o
            } else {
                alert('浏览器不支持');
            }
        };

        document.querySelector('#isFull').onclick = function () {
            alert(document.webkitIsFullScreen);
        }    
    </script>
</body>

</html>

文件读取

如果想要把图片的缩略图显示到页面中,这就需要用到 HTML5 给我们提供的文件读取接口来实现。该接口通过 FileReader 对象来读取本地存储的文件,然后使用 File 对象来指定读取的文件或数据。

File 对象可以是来自用户在一个元素上(如 <input>)选择文件后返回的 FileList 对象,也可以是自由拖放操作生成的 DataTransfer 对象。dataTransfer 对象只能访问文件的一些基本的信息。

由于 Web 环境的特殊性,为了考虑文件安全问题,浏览器不允许 JavaSctipt 直接访问文件系统,使用 <input> 表单元素的文件域 <input type="file"> 来实现文件的上传。

input 元素还有一个 multiple 属性(HTML 5 新增),可以实现一次上传多个文件。在用户选择文件以后,可以得到一个 FileList 对象,它代表所选的文件列表。

地理定位

拖曳

拖曳操作需要借助鼠标来实现,如文件或图片的移动操作等。在开发中,经常使用原生的 JavaScript 来实现拖曳效果,实现起来比较复杂。因此,HTML5 提供了更好用的接口或者事件,在很大程度上降低了页面中拖曳交互的实现难度。

在 HTML5 中,任何元素都能够实现拖曳操作,可以通过为元素添加属性 draggable = “true” 来实现。需要注意的是,图片和链接默认是可以拖曳的,它们不用添加 draggable 属性。一个完整的拖曳效果是由拖曳(Drag)和释放(Drop)组成的。在拖曳操作中, 被拖动的元素称作源对象 ,是指页面中设置了draggable = “true” 属性的元素; 源对象进入的元素称作目标元素 ,目标元素可以是页面中的任一元素。

事件 事件描述
ondragstart 当拖曳开始时触发
ondrag 作用于整个拖曳过程(鼠标可能移动或不移动)
ondragend 当拖曳结束时触发
ondragenter 当源对象进入目标元素时触发
ondragover 当源对象悬停在目标元素上方时触发
ondragleave 当源对象离开目标元素时触发
ondrop 当源对象在目标元素上方释放鼠标时触发

需要注意的是,只有当源对象上的 鼠标点 进入目标元素时,才会触发 ondragenter 事件。默认情况下,浏览器会默认阻止 ondrop 事件,如果想要触发该事件,则需要在 ondragover 事件中使用 “return false;"(或者 e.preventDefault())来阻止其默认行为。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            border: 2px solid black;
            width: 285px;
            height: 500px;
            float: left;
            margin: 10px;
            text-align: center;
        }
    </style>
</head>

<body>
    <div id="d0">
        <h3>课程列表</h3>
        <p id="p1" draggable="true">数据结构(周一9-10节)</p>
        <p id="p2" draggable="true">数据结构(周二9-10节)</p>
        <p id="p3" draggable="true">移动技术应用开发(周三1-4节)</p>
        <p id="p4" draggable="true">移动技术应用开发(周四1-4节)</p>
        <p id="p5" draggable="true">移动技术应用开发(周五1-4节)</p>
        <p id="p6" draggable="true">前端技术应用(周五5-8节)</p>
    </div>
    <div id="d1">
        <h3>周一课程</h3>
    </div>
    <div id="d2">
        <h3>周二课程</h3>
    </div>
    <div id="d3">
        <h3>周三课程</h3>
    </div>
    <div id="d4">
        <h3>周四课程</h3>
    </div>
    <div id="d5">
        <h3>周五课程</h3>
    </div>

    <script>
        document.ondragstart = function (e) {
            console.log('源对象开始被拖动' + ',目标id为:' + e.target.id);
            e.dataTransfer.setData('text', e.target.id);
        };
        document.ondrag = function (e) {
            console.log('源对象拖动中');
        }; 
        document.ondragend = function (e) {
            console.log('源对象结束拖动');
        };
        document.ondragenter = function (e) {
            console.log('源对象进入目标对象');
            console.log(e.target)
        };
        document.ondragover = function (e) {
            console.log('源对象悬停');
            return false;
        };
        document.ondragleave = function (e) {
            console.log('源对象离开目标对象');
        };
        document.ondrop = function (e) {
            console.log('源对象在目标对象上释放');
            let	id = e.dataTransfer.getData('text');
            e.target.appendChild(document.getElementById(id));
        };
    </script>
</body>

</html>

Web 存储

Web Storage

随着互联网的快速发展,基于网页的应用越来越普遍,同时也变得越来越复杂。为了满足各种各样的需求,会经常在本地设备上存储大量的数据。

例如,记录历史活动信息。传统的方式是使用 document.cookie 来进行存储,但是由于其存储空间有限(大约4KB),并且需要复杂的操作来解析,给开发者带来了诸多不便。为此,HTMIL5 规范提出了网络存储相关的解决方案,即 Web Storage (Web存储)和本地数据库 Web SQL Database。

Web Storage API 中包含 window. sessionStoragewindow.localStorage 两个关键的对象。前者用于区域存储,后者用于本地存储。Web Storage 具有以下特点:

  • 容量较大,sessionStorage 大约为 5MB,localStorage 大约为 20MB。
  • 在移动平台上具有良好的兼容性,能够减少网络流量的使用。
  • 可以临时存储数据,在用户浏览页面期间使用,关闭窗口就可以丢弃。
  • 从本地读取数据比从服务器获取数据要快很多,能快速显示数据,且网页通过本地缓存可以立即显示。
方法/属性 描述
key(n) 该方法用于返回存储对象中第 n 个 key 的名称
setItem(key,value) 该方法接收一个键名和值作为参数,将会把键值对存储起来,如果键名存在,则更新其对应的值
getItem(key) 该方法接收一个键名作为参数,返回键名对应的值
removeltem(key) 该方法删除键名为 key 的存储内容
clear() 该方法清空所有存储内容
length 该属性返回 Storage 存储对象中包含的 item 的数量

由于 sessionStorage 对象和 localStorage 对象都是 Storage 的实例,所以都可以使用 Storage 接口提供的方法和属性。

sessionStorage 对象

sessionStorage 是 HTML5 新增的一个 会话存储 对象,用于 临时 保存同一窗口(或标签页)的数据,在关闭窗口或标签页之后将会删除这些数据。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <input type="text" id="username">
    <button id="setData">设置数据</button>
    <button id="getData">获取数据</button>
    <button id="delData">删除数据</button>

    <script>
        const username = document.querySelector('#username');
        document.querySelector('#setData').onclick = function(){
            let data = username.value;
            window.sessionStorage.setItem('username', data);
        };
        document.querySelector('#getData').onclick = function(){
            alert(window.sessionStorage.getItem('username'));
        };
        document.querySelector('#delData').onclick = function(){
            window.sessionStorage.removeItem('username');
        }   
    </script>
</body>
</html>

localStorage对象

localStorage 作为 HTML5 Web Storage 的 API 之一,主要作用是本地存储。localStorage可以将数据按照 键值对 的方式保存在客户端计算机中,直到用户或者脚本主动清除数据,否则该数据会一直存在。也就是说,使用了本地存储的数据将被持久化保存。

localStorage 与 sessionStorage 唯一的区别就是存储数据的 生命周期不同 。locaStorage 是永久性存储,而 sessionStorage 的生命周期与会话保持一致,会话结束时数据消失。

从硬件方面理解,localStorage 的数据是存储在硬盘中的,关闭浏览器时数据仍然在硬盘上,再次打开浏览器仍然可以获取。而sessionStorage 的数据保存在浏览器的内存中,当浏览器关闭后,内存将被自动清除。

播放视频和音频

<video> 标签用来定义视频播放器,它不仅是一个播放视频的标签,而且其控制栏还实现了包括播放、暂停、进度和音量控制、全屏等功能,更重要的是,用户可以自定义这些功能和控制栏的样式。video 标签基本语法如下:

1
<video src="视频文件路径" controls>你的浏览器不支持video标签</video>

视频格式 不支持 支持 支持 支持 不支
Ogg IE 9 Firefox 4.0 Opera 10.6 Chrome 6.0 Safari 3.0
MPEG4 支持 不支持 不支持 支持 支持
WebM 不支持 支持 支持 支持 不支持

可以看到,目前没有一种视频格式能让所有浏览器都支持。为此,HTMIL5中提供了 <source> 标签,用于指定多个备用的不同格式的文件路径,语法如下:

1
2
3
4
<video controls>
    <source src="视频文件地址">
    <source src="video/Pragmata_delay_ex.mp4">       
</video>

<audio> 标签用来定义 Web 上的声音文件或音频流,使用方法与 <video> 标签基本相同。

1
2
3
4
<audio src="audio/FinalFantasy_p4s.mp3" controls>你的浏览器不支持audio标签</audio>
<audio controls>
    <source srcset="">
</audio>

移动端常用事件

touch 事件

touch 事件即触屏操作事件,大部分主流浏览器支持 4 种最基本的 touch 事件。

事件 事件描述
touchstart 当手指触摸屏幕时触发
touchmove 当手指在屏幕上移动时触发
touchend 当手指离开屏幕时触发
touchcancel 当系统取消 Touch 事件的时候触发(如来电、弹出信息等)

在使用这些触摸事件时,需要通过 addEventListener() 方法向指定元素添加事件句柄,示例代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box {
            width: 500px;
            height: 500px;
            border: 2px solid black;
        }
    </style>
</head>

<body>
    <div class="box"></div>
    <script>
        window.onload = function () {
            const box = document.querySelector('.box');
            box.addEventListener('touchstart', function () {
                console.log('touchstart');
            });
            box.addEventListener('touchmove', function () {
                console.log('touchmove');
            });
            box.addEventListener('touchend', function () {
                console.log('touchend');
            });
        }
    </script>
</body>

</html>

在 PC 端中,当一个事件发生后,与事件相关的一系列信息数据的集合都会放到这个对象中,这个对象称为 event 事件对象。与 PC 端一样,移动端也有自己的事件对象,touch 触摸事件发生后也会产生 TouchEvent 对象,该对象包含了 3 个用于跟踪触摸的属性,用于返回不同的触摸点集合。

属性 属性描述
touches 表示当前屏幕上所有触摸点的列表
targetTouches 表示当前对象上所有触摸点的列表
changedTouches 返回在上一次触摸和此触摸之间状态发生变化的所有触摸对象的列表

需要注意的是,touches 和 targetTouches 只存储接触屏幕的触点,如果想要获取触点最后离开的状态就要使用 changedTouches。另外,touches 和 targetTouches 在 Chrome 浏览器测试和真机测试中是没有区别的,推荐使用 targetTouches。

上述触摸点集合中每个 touch 对象代表一个触点,它包含一些用于获取触摸信息的常用属性,如位置、大小、形状、压力大小和目标 element 属性等。

属性 属性描述
clientX 触摸目标在视口中的 x 坐标
clientY 触摸目标在视口中的 y 坐标
identifier 标识触摸的唯一 ID
pageX 触摸目标在页面中的 x 坐标
pageY 触摸目标在页面中的 y 坐标
screenX 触摸目标在屏幕中的 x 坐标
screenY 触摸目标在屏幕中的 y 坐标
target 触摸的 DOM 节点目标

touch 事件实现轮播图效果

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .banner{
            width: 100%;
            overflow: hidden;
            position: relative;
        }
        .bannerImg{
            width: 100%;
            position: relative;
        }
        .bannerImg > li{
            width: 10%;
            float: left;
            list-style: none;
        }
        .bannerImg > li > img{
            display: block;
            width: 100%;
        }
    </style>
</head>
<body>
    <div class="banner">
        <ul class="bannerImg clearfix">
            <li>
                <a href="javascript:;">
                    <img src="/MyPra/img/bili/a1.avif" alt="">
                </a>
            </li>
            <li>
                <a href="javascript:;">
                    <img src="/MyPra/img/bili/a2.avif" alt="">
                </a>
            </li>
            <li>
                <a href="javascript:;">
                    <img src="/MyPra/img/bili/a3.avif" alt="">
                </a>
            </li>
            <li>
                <a href="javascript:;">
                    <img src="/MyPra/img/bili/a4.avif" alt="">
                </a>
            </li>
            <li>
                <a href="javascript:;">
                    <img src="/MyPra/img/bili/a5.avif" alt="">
                </a>
            </li>
            <li>
                <a href="javascript:;">
                    <img src="/MyPra/img/bili/a6.avif" alt="">
                </a>
            </li>
            <li>
                <a href="javascript:;">
                    <img src="/MyPra/img/bili/a7.avif" alt="">
                </a>
            </li>
        </ul>
    </div>
    <script>
        const banner = document.querySelector('.banner');
        const imgBox = document.querySelector('.bannerImg');
        const first = imgBox.querySelector('li:first-of-type');
        const last = imgBox.querySelector('li:last-of-type');
        imgBox.appendChild(first.cloneNode(true));
        imgBox.insertBefore(last.cloneNode(true), imgBox.firstChild);
        const lis = imgBox.querySelectorAll('li');
        const count = lis.length;
        const bannerWidth = banner.offsetWidth;
        imgBox.style.width = count * bannerWidth + 'px';
        for( let i = 0; i < lis.length; i++){
            lis[i].style.width = bannerWidth + 'px';
        };
        let index = 1;
        imgBox.style.left = -bannerWidth + 'px';
        let startX, moveX, distanceX;
        imgBox.addEventListener('touchstart', function(e){
            startX = e.targetTouches[0].clientX;
        });
        imgBox.addEventListener('touchmove', function(e){
            moveX = e.targetTouches[0].clientX;
            distanceX = moveX - startX;
            imgBox.style.transition = 'none';
            imgBox.style.left = (-index * bannerWidth + distanceX) + 'px';
        });
        imgBox.addEventListener('touchend', function(e){
            if(Math.abs(distanceX) > 80){
                if(distanceX > 0){
                    index --;
                }else{
                    index ++;
                }
                imgBox.style.transition = 'left 0.5s ease-in-out';
                imgBox.style.left = (-index * bannerWidth) + 'px';
            }else if(Math.abs(distanceX) > 0){
                imgBox.style.transition = 'left 0.5s ease-in-out';
                imgBox.style.left = -index * bannerWidth + 'px';
            }
        });
        imgBox.addEventListener('webkitTransitionEnd', function(){
            if(index == count - 1){
                index = 1;
            }else if( index == 0){
                index = count -2;
            }
            imgBox.style.transition = 'none';
            imgBox.style.left = - index * bannerWidth + 'px';
        })
    </script>
</body>
</html>
Blog for Sandy Memories