Javascript学习笔记21 HTML5 API (requestAnimationFrame FileReader WebWoker)

requestAnimationFrame()

为解决setInterval()setTimeout()执行动画事件不精确的问题,HTML5 创造了该方法来告诉浏览器您希望执行动画操作并请求浏览器在下一次重绘之前调用指定的函数来更新动画。回调的次数通常是每秒60次,当运行在后台标签页或者隐藏的<iframe> 里时,requestAnimationFrame() 会暂停调用以提升性能和电池寿命。

window.requestAnimationFrame(callbackFunction);
  • 该方法接受一个回调函数,用于在下次重新绘制动画时调用。这个回调函数只有传参,DOMHighResTimeStamp,指示当前被 requestAnimationFrame() 排序的回调函数被触发的时间,单位为毫秒。若想要在下次重绘时产生另一个动画画面,您的回调例程必须调用requestAnimationFrame()
  • 返回一个请求ID,可以传给window.cancelAnimationFrame() 取消回调函数

示例

var start = null;
var element = document.getElementById('SomeElementYouWantToAnimate');
element.style.position = 'absolute';

function step(timestamp) {
  if (!start) start = timestamp;
  var progress = timestamp - start;
  element.style.left = Math.min(progress / 10, 200) + 'px';
  if (progress < 2000) {
    window.requestAnimationFrame(step);
  }
}

window.requestAnimationFrame(step);

Page Visbility API

使开发人员知道页面是否对用户可见。如果页面最小化了或者被隐藏在了其他标签页后面,那么可以使某些功能(例如轮播图)暂停下来

属性

  • document.hidden: 隐藏时返回true,否则返回false
  • document.visibilityState:展示文档可先性的字符串。可能的值为visible(页面内容至少部分可见),hidden(不可见),prerender(正在渲染,用户不可见),unloaded(页面正在被卸载)

事件
visibilityChange事件:当文档从可见变为不可见或从不可见变为可见时触发

//startSimulation 和 pauseSimulation 在其他地方定义
function handleVisibilityChange() {
  if (document.hidden) {
    pauseSimulation();
  } else  {
    startSimulation();
  }
}

document.addEventListener("visibilitychange", handleVisibilityChange, false);

Geolocation API

地理位置 API 允许用户向 Web 应用程序提供他们的位置。出于隐私考虑,报告地理位置前会先请求用户许可。地理位置 API 通过 navigator.geolocation 提供。

检测浏览器是否支持该API

if ("geolocation" in navigator) {
  /* 地理位置服务可用 */
} else {
  /* 地理位置服务不可用 */
}

获取当前定位

您可以调用 getCurrentPosition() 方法获取用户当前定位位置。该方法接受3个参数:成功回调函数,可选的失败回调函数和可选的选项对象。

navigator.geolocation.getCurrentPosition(function(position) {
  do_something(position.coords.latitude, position.coords.longitude);
});
  • 成功回调函数会接受到一个Position对象参数,Position.coors.latitudePosition.coors.longitude属性保存着以十进制度数表示的纬度和经度坐标
  • 失败回调函数会接受到一个对象,其包含两个属性messagecode,分别为出错的信息和错误的类型
  • 第三个参数选项对象用于设置一些定位参数enableHighAccuracy是一个布尔值,表示是否使用精确定位,除非确实需要,都应该设置为false。timeout表示等待位置信息的最长时间,单位为毫秒,maximumAge为表示上一次取得坐标信息的有效时间,单位为毫秒,如果时间已超过有效时间,则重新获取坐标,否则使用上一次取得的坐标。
navigator.geolocation.getCurrentPosition(function(position) {
    do_something(position.coords.latitude, position.coords.longitude);
},function(error){
    console.log(error.message);
},{
    enableHighAccuracy:true,
    timeout:5000,
    maximumAge:25000
});

跟踪用户位置

通过 watchPosition() 方法实现该功能。它与 getCurrentPosition() 接受相同的参数,但回调函数会被调用多次。错误回调函数与 getCurrentPosition() 中一样是可选的,也会被多次调用。实际上其与定时调用getgetCurrentPosition()的效果相同

var watchID = navigator.geolocation.watchPosition(function(position) {
    do_something(position.coords.latitude, position.coords.longitude);
});
  • watchPosition() 方法会返回一个 ID,唯一地标记该位置监视器。您可以将这个 ID 传给 clearWatch() 方法来停止监视用户位置
navigator.geolocation.clearWatch(watchID);

File API

HTML5在DOM中为文件输入元素添加了一个files集合,在通过文件输入字段选择了一或多个文件时,files集合中将包含一组File对象,每个File对象对应着一个文件。每个File对象都有下列只读属性

  • name:本地文件系统中的文件名
  • size:文件的字节大小
  • type:字符串,文件的MIME类型
  • lastModifiedDate:字符串,文件上一次被修改的时间(只有Chrome实现了该属性)
var filesList = document.getElementById("files-list");
filesList.addEventListener("change",function(event){
    var files = event.files,   //获取files集合
        i = 0,
        len = files.length;
    while(i < len){
        console.log(files[i].name + ',' + files[i].type + ',' +files[i].size);
        i++;
    }
},false);

FileReader类型

FileReader类型实现的是一种异步文件读取机制。可以将FileReader想象成XMLHttpRequest,区别只是它读取的是文件系统,而不是远程服务器。更多信息及使用例子见 https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader
https://blog.csdn.net/zjw_python/article/details/78993654

其提供如下几个方法:

  • readAsText(file,encoding):以纯文本形式读取文件,将读取到的文本保存在result属性中,第二个用于指定编码类型,可选
  • readAsDataURL(file):读取文件并将文件以数据URL的形式保存在result属性中
  • readAsBinaryString(file):读取文件并将一个字符串保存在result属性中,字符串中每个字符表示一字节
  • readAsArrayBuffer(file):读取文件并将一个包含文件内容的ArrayBuffer保存在result属性中

提供了几个事件,最有用的包括

  • process:读取过程中不断触发,event对象具有lengthComputable,loaded和total属性,可用于显示读取文件进度
  • error:读取发生错误时触发,错误信息保存在FileReader对象的error属性中,error属性是一个对象,其具有code属性,1表示未找到文件,2表示安全性错误,3表示读取中断,4表示文件不可读,5表示编码错误
  • load:文件读取完毕则触发,发生错误则不触发
  • loadend:读取完毕或读取发生错误中断,就会触发

读取部分文件内容可以使用slice()方法(旧版本浏览器,可能会有不同的前缀,例如mozSlice()),该方法接受两个参数:起始字节的索引及要读取的字节数,返回一个Blob实例。Blob是File类型的父类型,可以对它进行读取

var files = event.files,
    reader = new FileReader(),
    blob = files[0].slice(0,32); //返回包含文件32b内容的blob实例

if (blob){
    reader.readAsText(blob);   //读取文件32b的内容
}

对象URL

对象URL也被称为blob URL,指的是引用保存在File或Blob中数据的URL。

要创建对象URL,可以使用window.URL.createObjectURL()方法,并传入File或Blob对象,返回值是一个URL字符串,指向内存的地址。

var files = event.files,
    reader = new FileReader(),
    url = window.URL.createObjectURL(files[0]); //返回URL

if (url){
    myDiv = doucment.getElementById("mydiv");
    myDiv.innerHTML = "<img src=\"" + url + "\">";  //显示图片
}

如果不需要相应的数据,可以将对象URL传给window.URL.revokeObjectURL()释放内存

window.URL.revokeObjectURL(url);

读取拖放的文件

除了图片和链接,从桌面把文件拖放到浏览器中也会触发drop事件。可以在event.dataTransfer.files中读取到被放置的文件,此时其是一个File对象。可以显示基本的文件信息,还能结合XMLHttpRequest实现拖放文件上传

var files = event.dataTransferfiles,   //获取files集合
    i = 0,
    len = files.length;

while(i < len){
    console.log(files[i].name + ',' + files[i].type + ',' +files[i].size);
    i++;
}

使用XHR上传文件

通过File API能够访问到文件内容 ,利用XHR就可以直接把文件上传到服务器。除了将文件内容放在send()方法中,利用POST请求上传文件外,还可以使用FormData类型,传入File对象,再上传

FormData类型介绍:https://blog.csdn.net/zjw_python/article/details/79985706

...
data = new FormData();
files = event.dataTransfer.files;  //获取drop事件中的文件

while (i < files.length){
    data.append("file"+i,files[i]);
}

xhr = new XMLHttpRequest();
xhr.open("post","load.php",true);
xhr.send(data);

Web计时

Web Timing API用于度量页面加载过程中各个阶段的时间值,从而全面了解页面在被加载过程中都经历了哪些阶段,而哪些阶段可能是影响性能的瓶颈。更多内容见:https://www.w3.org/TR/navigation-timing/

window.performance对象是WEB计时的核心,其具有两个属性navigationtiming,这两者都是对象。前者包含着与页面导航有关的属性(例如页面是第一次加载的,还是重载的,还是前进后退按钮打开的)。而后者则具有很多表示页面加载各个过程时间戳的属性。
这里写图片描述

可以通过这些时间戳的计算,来显示某个阶段的所用时间值,例如计算页面加载完成所需要的总时间

var perfData = window.performance.timing; 
var pageLoadTime = perfData.loadEventEnd - perfData.navigationStart;

Web Worker

Web Worker使Javascript在后台运行,解决了长时间运行Javascript进程导致浏览器冻结用户界面的问题。 Web worker中它所执行的 js 代码完全在另一个作用域中,其不能访问页面的DOM,也不能使用window对象的默认方法和属性,但是某些功能,例如XMLHttpRequest仍然可以使用,具有有哪些功能支持,见:https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Functions_and_classes_available_to_workers

首先创建一个worker对象,并传入要执行的Javascript文件名

//页面
var worker = new Workder("example.js");

接着,使用postMessage()方法将要处理的数据发送给worker,内容可以是任何能够被序列化的值,因此包括任意对象数据

//页面
worker.postMessage({name1:"value1",name2:"value2"});

最后,指定message事件用于接受worker处理完成后的数据

//页面
worker.onmessage = function(event){
    var data = event.data;
    // 继续操作处理后的数据
};

worker.onerror = function(event){  //处理worker执行中出现的错误
    console.log(event.filename + evnet.lineno + event.message);
};

传入的example.js文件

//example.js
self .onmessage = function(evnet){  //此处的self对象引用的是worker执行环境中的worker对象
                                     //并不是window对象,也不是页面中创建的worker对象
    var data = event.data   //接受页面传来的数据
    //处理数据
    self.postMessage(data);  //将处理过后的数据传回页面
}

停止worker工作,有两种方法,worker停止后,后续所有过程都不会再发生

//页面中停止worker
worker.terminate();
//Worker环境中停止worker
self.close();

可以使用importScripts()在web worker中添加其他脚本

//web worker中
importScripts("file1.js","files2.js");

Share worker

上述介绍的web worker是专有的,一个专用worker仅仅能被生成它的脚本所使用。而Share worker可以被多个脚本使用——即使这些脚本正在被不同的window、iframe或者worker访问。如果共享worker被多个浏览上下文调用,所有这些浏览上下文必须属于同源(相同的协议,主机和端口号)。 SharedWorker 提供了能力能够让不同标签中页面共享的同一个 Worker 脚本线程

创建Share worker对象

//页面
var myWorker = new SharedWorker('worker.js');

一个非常大的区别在于,与一个共享worker通信必须通过端口对象——一个确切的打开的端口供脚本与worker通信,打开端口有两种方法:使用onmessage事件处理函数或者start()方法start()方法的调用只在一种情况下需要,那就是消息事件被addEventListener()方法使用。

在使用start()方法打开端口连接时,如果父级线程和worker线程需要双向通信,那么它们都需要调用start()方法

//页面
myWorker.port.start();  // 父级线程中的调用
//web worker中
port.start(); // worker线程中的调用, 假设port变量代表一个端口

发送数据

myWorker.port.postMessage(data);

接收处理后的数据

//页面
myWorker.port.onmessage = function(event) {
    data = event.data
    console.log('Message received from worker');
};

worker.js中处理数据,首先,当一个端口连接被创建时(例如:在父级线程中,设置onmessage事件处理函数,或者显式调用start()方法时),使用onconnect事件处理函数来执行代码。使用事件的ports属性来获取端口并存储在变量中。

//web worker中
onconnect = function(e) {
  var port = e.ports[0];  //获取指定端口

  port.onmessage = function(e) {  //对指定端口发送处理后的数据
      var workerResult = 'Result: ' + (e.data[0] * e.data[1]);
      port.postMessage(workerResult);
  };
};

猜你喜欢

转载自blog.csdn.net/zjw_python/article/details/80277375