• WEB前端第六十五课——H5新特性:Worker线程、Files、FileReader、getUserMedia


    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>
    
  • 相关阅读:
    数据结构和算法(Golang实现)(9)基础知识-算法复杂度及渐进符号
    基于深度学习方法的dota2游戏数据分析与胜率预测(python3.6+keras框架实现)
    基于CBOW网络手动实现面向中文语料的word2vec
    《Machine Learning Yearing》读书笔记
    使用神经网络预测航班起飞准点率
    使用LSTM-RNN建立股票预测模型
    基于selenium+phantomJS的动态网站全站爬取
    TensorFlow保存、加载模型参数 | 原理描述及踩坑经验总结
    学习笔记--python中使用多进程、多线程加速文本预处理
    通过外汇对冲手段稳定获利的可行性验证
  • 原文地址:https://www.cnblogs.com/husa/p/14451820.html
Copyright © 2020-2023  润新知