1.Web Worker线程
JavaScript语言是单线程模型,通过Web Worker为JS创造多线程环境;
由主线程创建Worker线程,将一些任务分配给Worker运行,两者异步执行;
Worker完成计算任务后,再将结果返回给主线程。
优点:可以分担计算密集型或高延迟的任务,确保主线程运行会更加流畅;
缺点:Worker一旦创建成功,为随时响应主线程通信,如不主动关闭结束,
会一直运行,造成资源耗费。
代码示例:
<script> // 调用Worker()构造函数,创建worker线程。 // 由于Worker不能读取本地文件,因此其参数只能是脚本地址。 var myWorker=new Worker('myWorker.js'); //主线程创建监听事件,接收子线程返回的信息。 myWorker.onmessage=function (event) { console.log(event); //子线程返回的信息为对象,其中,通过data属性可以回去返回数据。 console.log('Receive msg:'+event.data); if(event.data>18){ //主线程中使用“terminate()”方法结束Worker子线程 myWorker.terminate(); } clearTimer(); } function clearTimer() { //向子线程后台发送消息,使用”postMessage()“方法,该方法在主线程和子线程通用。 myWorker.postMessage('Stop'); } console.log('Hello world.'); //先于Worker线程执行。 </script>
// 创建Worker脚本任务 var n=0; self.postMessage(n); var timer=setInterval(function () { n+=3; //返回数据结果 postMessage(n); },1000); //添加消息事件监听,使用“addEventListener”或“onmessage()”两种方式都可以。 self.addEventListener('message',function (e) { if (e.data=='Stop'&&n>15){ clearInterval(timer); postMessage('The Worker stopped!') //返回消息给主线程。 //子线程中使用“close()”方法关闭Worker线程。 self.close(); } },false);
2.文件操作
文件上传标签:<input type='file'/>
⑴ files集合
H5中所有“file”类型的元素都具有files属性,files为包含一组file对象的集合。
每个file对象都具有上传文件的所有信息,包括:name、size、type、lastModifiedDate等。
通过侦听“change”事件并读取Files集合,可以获得每个文件对象的属性信息。
代码示例:
<body> <input type="file" id="upLoadFile" multiple/> <div id="fileInfo"></div> <script> var file=document.querySelector('#upLoadFile'); var fileInfo=document.querySelector('#fileInfo'); file.onchange=function () { console.log(this.files); //结果为对象类型数据,文件列表。 var fileInfoArr=[]; for (var i=0;i<this.files.length;i++){ var fileData=file.files[i]; var j=i+1; var fileInfoTemp='<br>第'+j+'个文件<br/>'+'名称:'+fileData.name+'<br/>类型:'+fileData.type+ // 计算文件大小时,可利用“Math.round()”方法进行四舍五入。 '<br>大小:'+Math.round((fileData.size/1024/1024)*100)/100+'M<br>修改时间:'+ fileData.lastModifiedDate.toGMTString()+'<br/>'; //可利用“toGMTString”或“toUTCString”方法转换时间格式。 fileInfoArr.push(fileInfoTemp); } console.log(fileInfoArr); fileInfo.innerHTML=fileInfoArr.join(''); //将数组转换为字符串,并进行赋值。 console.log(fileInfo.innerHTML); } </script> </body>
⑵ FileReader构造函数,
File API提供了FileReader接口用于读取文件数据。
① FileReader属性:
error,读取文件时发生的错误,
错误码code:1-未找到文件、2-安全性错误、3-读取中断、4-不可读取、5-编码错误
readyState,FileReader对象的当前状态,状态常量包括三个:
常量名 值 描述
EMPTY 0 还没有加载任何数据
LOADING 1 数据正在加载中
DONE 2 已完成全部读取任务
result,表示读取到的文件内容,该属性只有在读取操作完成后才有效,
读取数据的格式取决于读取操作使用的哪种方法。
② FileReader接口有4个操作方法(前两个为核心方法):
readAsText(file或Blob,encoding),以纯文本形式读取File或Blob对象的内容,
第二个参数(可选)用于指定编码类型,默认为“UTF-8”;
readAsDataURL(file或Blob),将文件读取为DataURL格式(Base64编码);
readAsBinaryBuffer(file或Blob),将文件读取为二进制编码形式;(已废弃)
abort(),终止该读取操作。
上述3中读取文件的方法,读取结果都保存在“result”属性中!!
③ FileReader相关事件:
onabort,读取操作终止时调用;
onloadstart,读取操作开始时调用;
onerror,读取发生错误时调用;
onload,读取操作成功完成时调用;
onloadend,读取操作完成时调用,不论操作发生错误、中断还是成功。
onprogress,读取过程中周期性调用。
一般情况下,读取文件时,首先触发onloadstart事件,此时readyState状态值为1,result为空。
读取文件过程中,约每隔50ms触发一次onprogress事件,通过事件对象可以获取文件进度信息,
lengthComputable(是否未完成/有可计算长度)、loaded(已加载)、total(进度总长度)。
读取文件成功完成时,触发load事件,此时readyState状态值为2,result为文件内容。
如果读取文件过程中发生了错误,则触发error事件,而不会触发load事件。
代码示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>FileReader</title> </head> <body> <input type="file" id="upLoadFile" multiple/> <div id="filePreview"></div> <script> var file=document.querySelector('#upLoadFile'); var filePreview=document.querySelector('#filePreview'); /* //判断浏览器是否支持FileReader接口 if (typeof FileReader=='undefined'){ filePreview.innerHTML ='浏览器不支持FileReader接口!'; // 将文件选择控件失效。 file.setAttribute('disabled','disabled'); }else { filePreview .innerHTML ='<p>图片预览区域</p>'; } //创建FileReader函数——readAsDataURL()方法 function readURL(){ // 先判断选择的file对象是否为图片 var uploadFile=document.getElementById('upLoadFile').files[0]; //使用RegExp正则表达式判断文件类型是否为图片。 if (!/image/w+/.test(uploadFile.type)){ alert ('请选择图片文件!'); return false; } //创建FileReader对象实例。 var reader=new FileReader(); reader.readAsDataURL(uploadFile); //通过“readAsDataURL”方法读取图片文件url地址 reader.onload=function () { //将读取到的图片地址拼接到显示容器,展示图片。 filePreview.innerHTML = '<img src="'+this.result+'"/>'; } }*/ //创建FileReader函数——readAsText()方法 function readText(){ var uploadFile=document.getElementById('upLoadFile').files[0]; if (uploadFile){ //创建FileReader对象实例。 var reader=new FileReader(); //通过“readAsText”方法读取文件内容,注意编码格式参数! reader.readAsText(uploadFile,'GB2312'); reader.onload=function () { //将读取到到内容显示。 filePreview.innerHTML = this.result; } } } file.onchange=function () { readText(); //调用FileReader函数 console.log(this.files); //结果为对象类型数据,文件列表。 } </script> </body> </html>
3.getUserMedia
getUserMedia()方法是H5提供的用于访问用户设备媒体(视频、音频、位置等)的API接口,
在新版Web标准中,getUserMedia()方法是window.navigator.mediaDevices下的一个方法。
语法:navigator.mediaDevices.getUserMedia(constraints);
说明:
⑴ navigator是window的一个只读属性,该对象包含了访问者浏览器的相关信息;
navigator对象属性:
appCodeName,浏览器的代码名
appName,浏览器的名称
appVersion,浏览器的平台和版本信息
cookieEnabled,浏览器中是否启用 cookie 的布尔值
platform,运行浏览器的操作系统平台
userAgent,浏览器代理信息,由客户机发送服务器的user-agent头部的值
⑵ mediaDevices是Navigator的一个只读属性,返回一个MediaDevices对象,
该对象可提供对相机、麦克风、屏幕共享等媒体设备的连接访问,
并且该对象是一个单例对象,通常只需直接调用改对象的成员。
⑶ getUserMedia()方法提示用户给予使用一个视频或音频输入设备的许可,
该方法接受三个参数,语法:
navigator.mediaDevices.getUserMedia(constraints,onSuccess,onError);
① constraints,多媒体类型设置
该参数是一个对象,用于设置多媒体类型,即获取哪些设备;
语法:{
video:true/false, //video参数还可以直接设置分辨率
audio:true/false
}; //两个参数中至少有一个类型被启用!
video参数值为分辨率时,语法:
video:{ 1280,height:960},
设置video分辨率时,除了“width和height”,还可以使用关键字“min,max,ideal”;
如果是移动设备时,video参数还可以强制使用前置或后置摄像头,语法:
video:{facingMode:'user'}, //强制使用前置摄像头
video:{facingMode:{exact:environment}}, //强制使用后置摄像头
② promise说明
getUserMedia()方法是一个异步执行的方法,所以不会立即返回最终的值,
而是返回一个“Promise”对象,Promise对象代表了异步操作的最终完成或者失败,
当发生情况之一时,该对象绑定的相应回调函数就会被调用,返回结果也是Promise。
通常使用Promise对象的“then() 和 catch()”方法链式排列相关处理程序。
语法示例:
var promise = navigator.mediaDevices.getUserMedia(constraints);
promise.then(function onSuccess(mediaStream){...})
.catch(function onError(errorObj){...});
或者简写为:
navigator.mediaDevices.getUserMedia(constraints).then(onSuccess,onError);
说明:
then()的参数可选,catch(errorCallback) 是 then(null,successCallback)的缩略形式;
catch()之后可以继续接then(),进行其他链式操作。
③ successCallback,成功回调函数
获取多媒体设备成功时调用该回调函数。Success回调函数的参数是一个数据流对象,
数据流对象mediaStream的两个内置方法“getAudioTracks() 和getVideoTracks()”,
分别返回一个数组,数组成员是数据流包含的音轨audio和视轨video对象。
语法示例:
function onSuccess(mediaStream) {
var video = document.getElementById("video");
video.src = window.URL.createObjectURL(mediaStream);
}
说明:
成功(resolve)Promise对象的回调函数会带一个“MediaStream”对象作为其参数;
URL.createObjectURL()方法可以将媒体流转换为一个二进制对象的URL(Blob URL),
该URL可以作为 video元素 src 的属性值。
④ errorCallback,失败回调函数
获取多媒体设备失败时调用该回调函数。Error回调函数接受一个error对象作为参数,
Error对象有三个属性值,
PERMISSION_DENIED:用户拒绝提供信息。
NOT_SUPPORTED_ERROR:浏览器不支持硬件设备。
MANDATORY_UNSATISFIED_ERROR:未发现指定的硬件设备。
语法示例:
function onError(error) {
console.log("错误名称: "+ error.name+"<br/>错误信息:"+error.message);
}
⑷ 视频拍照
获取视频后通过 Canvas API提供的 “ctx.drawImage(video,0,0)”方法实现拍照功能,该方法
可以将视频的一帧转换为canvas元素,进行截图拍照。
语法示例:
var ctx=canvas.getContext('2d'); //创建2d画笔
ctx.drawImage(video,0,0); //在画布上绘制图像
⑸ 视频、截图示例代码:
<body> <video src="" width="360" height="300" id="videoCase"></video> <input type="button" value="开始视频" onclick="startVideo()"/> <canvas width="360" height="300" id="canvas"></canvas> <button id="btn" onclick="takePhoto()">拍照</button> <script> function startVideo() { // 获取视频区域元素 var video=document.getElementById('videoCase'); // 设置媒体设备启动类型 var constraints={ video:{360,height:300}, //启动摄像头,参数可以直接写“true” audio:true //启动麦克风 } // 使用”getUserMedia()“方法启动媒体设备,设备启动类型”constraints“作为参数, // 该方法的返回值为"Promise"对象,Promise对象返回成功后,它的回调函数会带一个“MediaStream”作为参数, // then()方式是Promise的一个“异步执行”方法,then()前面所有方法执行完成后再执行其内部的程序,避免数据获取失败或缺失! var promise=navigator.mediaDevices.getUserMedia(constraints); promise.then(function onSuccess (MediaStream) { console.log(MediaStream); //返回值:MediaStream {id: "5eDj...jdna", active: true, onaddtrack: null, onremovetrack: null, onactive: null, …} console.log(typeof MediaStream); //返回值:object video.srcObject=MediaStream; console.log(video); //返回值:<video src="<unknown>" width="360" height="300" id="videoCase"></video> console.log(typeof video); //返回值:object video.play(); //或video.autoplay=true; }).catch(function errorCallback(error) { console.log(error.name+':'+error.message); //返回值:NotAllowedError:Permission denied console.log(error); //返回值:DOMException: Permission denied console.log(typeof error); //返回值:object }) } function takePhoto() { var video=document.getElementById('videoCase'); var canvas=document.getElementById('canvas'); var paintBrush=canvas.getContext('2d'); paintBrush.drawImage(video,0,0,360,300); } </script> </body>