JS原生系列-DOM篇(延伸)

关于DOM,这就是最后一部分了,这部分都是后台或者最新的dom api,学的时候需要多的记忆一次,有印象有保障!

-.ajax的介绍:ajax输出json格式文件 jsonp的介绍 xhr2的介绍

     http://www.w3school.com.cn/ajax/ajax_xmlhttprequest_create.asp 

-.cookie的介绍:设置cookie和删除cookie

-.html5 存储的介绍:web客户端存储(localStorage sessionsStorage) 缓存( cache manifest 文件)

-.html5中新元素如canvas,video、audio的api简单介绍

     http://www.w3school.com.cn/tags/html_ref_audio_video_dom.asp

     http://www.w3school.com.cn/tags/html_ref_canvas.asp 

-.html设备支持的接口介绍:webaudio 

-.其他dom接口相关介绍:

 

一、ajax的解读

XMLHttpRequest 是 AJAX 的基础。

所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject)。
XMLHttpRequest 用于在后台与服务器交换数据。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

 

人家写的定义,我们只要知道ajax是通过

XMLHttpRequest  对象为依据,并且在ie6不兼容就好了

1. 创建ajax对象

variable=new XMLHttpRequest();                                        标准浏览器

variable=new ActiveXObject("Microsoft.XMLHTTP");           ie6,哪里还能找到ie5?

咱们已经学过能力监测,做个检测就好了,最后的时候

var xmlhttp;
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }

我们发现这次的能力检测与以前的有点区别,以前通过if,里面的一句都是 ele.xxx,这此换成了window,因为这个对象实在window对象下的,dom也是window下的,window对象是全局对象,我们所有的东西都是直接或者间接的属于他下面的内容

这段检测的原理就是:

判断window下面有没有XMLHttpRequest,,有的话执行下面的新建,没有,就执行else的,通过ActiveXObject新建

我们到这一步,已经创建好了一个ajax的对象!

2.发送ajax请求:

xmlhttp.open("GET","test1.txt",true);
xmlhttp.send();

open(method,url,async)方法,定义请求,类型(get、post),url(地址),同步还是异步(async=true/false)

send(string)方法,发送请求 有string,必须post请求

3.应答处理

onreadystatechange    ajax的准备状态事件,只要xhr的准备状态属性变化,就会自动触发事件

readyState                   请求状态属性,

存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。

  • 0: 请求未初始化

  • 1: 服务器连接已建立

  • 2: 请求已接收

  • 3: 请求处理中

  • 4: 请求已完成,且响应已就绪

status                           状态属性

200: "OK"

404: 未找到页面

当 readyState 等于 4 且状态为 200 时,表示响应已就绪:(jsax请求完成,有页面)

xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
    }
  }

xmlhttp.responseText 代表请求到的数据

4.返回数据的处理

responseText       获得字符串形式的响应数据。

responseXML        获得 XML 形式的响应数据 

第一个返回的是字符串,第二个是xml,我们会发现,我们一般返回的是json格式文件啊,其实json格式是把返回的字符串进行了封装

原生返回的格式是:

text (responseText属性)

xml (responseXML属性)

自定义返回新格式

json(来自text的处理)

 eval("var objResults =" + xmlhttp.responseText);              
 var displaytext = "";  
 for (var i=0; i < objResults.Results.computer.length; i++) 
 {  
       displaytext += objResults.Results.computer[i].Manufacturer +  "<br>";  
 }   
 我们被封装返回的test1.txt文件如下:

{"Results": {  
    "total_computers": "2",  
    "computer": [  
      {  
        "Manufacturer":"Dell",  
        "Model":"Latitude",  
        "Price":"1650"  
      },  
      {  
        "Manufacturer":"Dell",  
        "Model":"Inspiron",  
        "Price":"1850"  
      }  
          ]  
        }  
}

                    

下面我们做一个整个流程的案例!

整体页面如下:

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>m</title>
<link rel="stylesheet" href="css/main.css" />
</head>
<body>
 <h3>下面是test1.txt文件内容</h3>
 <div id="jsonshow"></div>
    <span id="send" style="display:inline-block; background:#9C0;">快点,点我</span>
</body>
<script type="text/javascript">
    //声明对象实例  
    var xmlhttp = false;  
    //产生一个XMLHttpRequest对象实例  
    getHTTPRequestObject();       
    function getHTTPRequestObject()  
    {  
        try  
        {  
            xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");  
        }  
        catch(e)  
        {  
            try  
            {  
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");  
            }  
            catch(E)  
            {  
                xmlhttp = false;  
            }  
        }  
        if(!xmlhttp && typeof XMLHttpRequest!= 'undefined')  
        {  
            xmlhttp = new XMLHttpRequest();  
        }  
    };  
    //回调处理  
    function callback()  
    {  
            if(xmlhttp.readyState == 4)   
            {  
                if(xmlhttp.status == 200)  
                {   
                  // 转换Json数据为javascript对象  
                  var text= xmlhttp.responseText; 
      var json=eval(text);
                  var jsonshow = document.getElementById("jsonshow");//寻找显示容器
      jsonshow.innerHTML = json[0].Name;//引用解析好了的数据   
                }   
            }  
    };  
    //触发事件  
    function btnClick()  
    {  
        // 本地测试
        xmlhttp.open("GET", "ceshi.txt", true);  
        xmlhttp.onreadystatechange = callback;  
        xmlhttp.send(null);  
    };  
 
 var send = document.getElementById("send");//发送请求
 send.onclick=function(){
  btnClick();
 }; 
</script>
</html>

ajax请求的ceshi.txt内容如下

 [
{
"Name" : "Alfreds Futterkiste",
"City" : "Berlin",
"Country" : "Germany"
},
{
"Name" : "Berglunds snabbk?p",
"City" : "Lule?",
"Country" : "Sweden"
},
{
"Name" : "Centro comercial Moctezuma",
"City" : "México D.F.",
"Country" : "Mexico"
},
{
"Name" : "Ernst Handel",
"City" : "Graz",
"Country" : "Austria"
},
{
"Name" : "FISSA Fabrica Inter. Salchichas S.A.",
"City" : "Madrid",
"Country" : "Spain"
},
{
"Name" : "Galería del gastrónomo",
"City" : "Barcelona",
"Country" : "Spain"
},
{
"Name" : "Island Trading",
"City" : "Cowes",
"Country" : "UK"
},
{
"Name" : "K?niglich Essen",
"City" : "Brandenburg",
"Country" : "Germany"
},
{
"Name" : "Laughing Bacchus Wine Cellars",
"City" : "Vancouver",
"Country" : "Canada"
},
{
"Name" : "Magazzini Alimentari Riuniti",
"City" : "Bergamo",
"Country" : "Italy"
},
{
"Name" : "North/South",
"City" : "London",
"Country" : "UK"
},
{
"Name" : "Paris spécialités",
"City" : "Paris",
"Country" : "France"
},
{
"Name" : "Rattlesnake Canyon Grocery",
"City" : "Albuquerque",
"Country" : "USA"
},
{
"Name" : "Simons bistro",
"City" : "K?benhavn",
"Country" : "Denmark"
},
{
"Name" : "The Big Cheese",
"City" : "Portland",
"Country" : "USA"
},
{
"Name" : "Vaffeljernet",
"City" : "?rhus",
"Country" : "Denmark"
},
{
"Name" : "Wolski Zajazd",
"City" : "Warszawa",
"Country" : "Poland"
}
]

html文件和txt要放在同一级目录下,ajax的大致流程

1.创建ajax对象

2.定义请求

3.判断是否成功,成功的返回值用eval()处理成js可用,做具体处理

4.发送ajax

5.触发条件,何时触发上面的ajax

延伸介绍:

XMLHttpRequest升级到2.0,我们上面都是1.0
DOMString、Document、FormData、Blob、File、ArrayBuffer这些大致类型

DOMString就是String        responseText属性得到

Document                        responseXML属性得到

 XMLHttpRequest.responseType()   方法,可是进行类型设置

FormData表单序列换类型

Blob 二进制大对象类型

File 从属于Blob

ArrayBuffer 二进制数组缓冲区类型,从属于Blob,该缓冲区用于存储各种类型化数组的数据

加入我们得到了ArrayBuffer类型数据,我们是无法直接操作的,我们需要通过类型数组新建转化

// 创建一个8字节的ArrayBuffer 
var b = new ArrayBuffer(8);  
// 创建一个指向b的视图v1,采用Int32类型,开始于默认的字节索引0,直到缓冲区的末尾 
var v1 = new Int32Array(b);  
// 创建一个指向b的视图v2,采用Uint8类型,开始于字节索引2,直到缓冲区的末尾 
var v2 = new Uint8Array(b, 2);  
// 创建一个指向b的视图v3,采用Int16类型,开始于字节索引2,长度为2 
var v3 = new Int16Array(b, 2, 2); 

把二进制数据转为其他类型数据,存放在数组中!

 

、dom的本地存储实现

 cookie大家肯定不会陌生,他是用来存放客户的信息,并且存放在客户本地!

cookie是浏览器提供的一种机制,它将document 对象的cookie属性提供给JavaScript。可以由JavaScript对其进行控制,而并不是JavaScript本身的性质。cookie是存于用户硬盘的一个文件,这个文件通常对应于一个域名,当浏览器再次访问这个域名时,便使这个cookie可用。因此,cookie可以跨越一个域名下的多个网页,但不能跨越多个域名使用。

cookie机制将信息存储于用户硬盘,因此可以作为全局变量,这是它最大的一个优点。它可以用于以下几种场合。

(1)保存用户登录状态。例如将用户id存储于一个cookie内,这样当用户下次访问该页面时就不需要重新登录了,现在很多论坛和社区都提供这样的功能。 cookie还可以设置过期时间,当超过时间期限后,cookie就会自动消失。因此,系统往往可以提示用户保持登录状态的时间:常见选项有一个月、三个 月、一年等。

(2)跟踪用户行为。例如一个天气预报网站,能够根据用户选择的地区显示当地的天气情况。如果每次都需要选择所在地是烦琐的,当利用了 cookie后就会显得很人性化了,系统能够记住上一次访问的地区,当下次再打开该页面时,它就会自动显示上次用户所在地区的天气情况。因为一切都是在后 台完成,所以这样的页面就像为某个用户所定制的一样,使用起来非常方便。

(3)定制页面。如果网站提供了换肤或更换布局的功能,那么可以使用cookie来记录用户的选项,例如:背景色、分辨率等。当用户下次访问时,仍然可以保存上一次访问的界面风格。

(4)创建购物车。正如在前面的例子中使用cookie来记录用户需要购买的商品一样,在结账的时候可以统一提交。例如淘宝网就使用cookie记录了用户曾经浏览过的商品,方便随时进行比较。

当然,上述应用仅仅是cookie能完成的部分应用,还有更多的功能需要全局变量。cookie的缺点主要集中于安全性和隐私保护。主要包括以下几种:

(1)cookie可能被禁用。当用户非常注重个人隐私保护时,他很可能禁用浏览器的cookie功能;
(2)cookie是与浏览器相关的。这意味着即使访问的是同一个页面,不同浏览器之间所保存的cookie也是不能互相访问的;
(3)cookie可能被删除。因为每个cookie都是硬盘上的一个文件,因此很有可能被用户删除;
(4)cookie安全性不够高。所有的cookie都是以纯文本的形式记录于文件中,因此如果要保存用户名密码等信息时,最好事先经过加密处理。

 设置cookie

document.cookie="userId=828";
如果要一次存储多个名/值对,可以使用分号加空格(; )隔开,例如:

document.cookie="userId=828; userName=hulk"; 

escape()函数进行编码,它能将一些特殊符号使用十六进制表示,例如空格将会编码为“20%”,从而可以存储于cookie值中,而且使用此 种方案还可以避免中文乱码的出现

document.cookie="str="+escape("I love ajax");

当使用escape()编码后,在取出值以后需要使用unescape()进行解码才能得到原来的

document.cookie="userId=828";
document.cookie="userName=hulk";

会创建2个cookie,不会把上一个删除

获取cookie

cookie的值可以由document.cookie直接获得:

我们测试一次设置和获取

代码:

    document.cookie="userId=828"; 
 document.cookie="userName=hulk"; 
 var strCookie=document.cookie; 
 alert(strCookie);

 我们输出了一段字符串,里面有我们设置的内容;

我们下载要获取当中的userId,这个cookie存在那一堆字符串中,我们相当于要做一个截取操作

相关知识:

字符串对象有一个分割方法

strobj.split("arg")    方法,把字符串按照arg进行分割,并且返回成一个数组

我们运行下面代码:

    var strobj="123;456;789;000";
 alert(strobj.length)//分割前,字符串长度
 var sp=strobj.split(";") 
 alert(sp.length)//分割后,数组长度
 alert(sp[1]);

 第一次输出了字符串长度,第二次,我们按照 ; 分割分成4份,长度为4,第三次输出第2项,完全正确

我们把cookie进行按照 ; 的分割,得到转化的数组后,我们要找到userId对应的数值;加入分割后处在一个项,我们得到的

sp[0]=="userId=828";

我们其实要获取的是828,怎么再次获取呢?我们在执行一次split(),这次按照 = 分割,获取第二项就是我们要的数值了;

我们按着目的去处理,做出如下代码:

    document.cookie="userId=828"; 
 document.cookie="userName=hulk"; 
 var strCookie=document.cookie; 
 var cookied=strCookie.split(";");
 var val="userId";
 for(var i=0;i<cookied.length;i++){
  var dd=cookied[i].split("=");
  if(dd[0]==val){
   alert(dd[1])
  }
 };

完美828的输出,我们可以进行方法的封装,用于指定cookie某个值的获取

这些不过是内存的而操作,并没有真的存放在客户,我们需要设置周期 expiress

cookie终止日期设置

document.cookie="userId=828; expiress=GMT_String";
其中GMT_String是以GMT格式表示的时间字符串,这条语句就是将userId这个cookie设置为GMT_String表示的过期时间,超过这个时间,cookie将消失,不可访问。例如:如果要将cookie设置为10天后过期,可以这样实现:

var date=new Date(); 
 var expiresDays=10; 
 //将date设置为10天以后的时间 
 date.setTime(date.getTime()+expiresDays*24*3600*1000); 
 //将userId和userName两个cookie设置为10天后过期 
 document.cookie="userId=828; userName=hulk; expires="+date.toGMTString();

相关知识:

通过new Date() 可以新建一个时间对象,默认参数就是当前时间,假如今天是2015.8.10,那么新建的date就是代表这个时间,

调用getTime() 获取的是距离1970.1.1的毫秒数,1秒是1000毫秒,那么这里获取的就是2015.8.10距离1970.1.1的毫秒数

我们10天过期,算出10天的毫秒数,1天=24小时,1小时60分,1分60秒,1秒1000毫秒,

date的setTime()与get相反,传入的是毫秒数,返回的是一个时间转化,这里date对象就由8.10变成了8.20,

cookie的周期可读日期必须是gmt格式,我们调用date的gmt转化方法toGMTString()就完成了操作;周期的设置就是对cookie的

expires 设置。

cookie的删除

为了删除一个cookie,可以将其过期时间设定为一个过去的时间,例如:

var date=new Date(); 
 var expiresDays=10; 
 date.setTime(date.getTime-1000); 
 //将userId和userName两个cookie设置为10天前 
 document.cookie="userId=828; userName=hulk; expires="+date.toGMTString();

设置cookie的使用路径

document.cookie="userId=320; path=/";              表示整个网站页面都可以用

document.cookie="userId=320; path=/show";      表示网站show目录下的可用

 

总结:

我们学cookie用到了

strobj.split()  字符串分割为数组

new Date()   新建日期对象,默认当前时间做参数

dateobj.getTime()   获取日期对象距离1970年的毫秒数,

dateobj.setTime()   把日期对象转化为指定毫秒数距离1970年的时间

dateobj.toGMTString()  日期对象转化为gmt格式的字符串形式,用于cookie可读

既然字符串可以分割为数组,同时数组也可以拼接为字符串,做相反操作

arrayobj.join("arg");  指定用什么拼接

代码如下:

var arr=[123,456,789];
var stra=arr.join("-");
alert(stra)

把数组通过 - 拼接为一个字符串

我们发现数组真的非常重要,前面对找到的node我们也是存入数组,

--数组处理

我们已经用过对数组的处理方法:

arrayobj.push()        数组插入内容,尾部插入

arrayobj.lenght        数组长度

arrayobj.join()          数组拼接为字符串

既然数组有尾部插入,那么就会有尾部删除,会有头部插入,和头部删除

同样还会有中间部分删除,

我们也会用到整个数组一部分,就会有获取子数组处理

数组是一个集合,自然可以排序处理

同样也要可以反过来

我们想到要有的,去一个个列出来,加以演示:

arrayobj.pop()      删除数组最后一项,出栈

 var arrayobj=[1111111,222222222,33333333,4444444];
 arrayobj.pop()
 alert(arrayobj)

arrayobj.shift()    删除数组第一项,返回新数组

 var arrayobj=[1111111,222222222,33333333,4444444];
 arrayobj.shift()
 alert(arrayobj)

arrayobj.unshift("arg")     数组头部插入内容

 var arrayobj=[1111111,222222222,33333333,4444444];
 arrayobj.unshift("0000")
 alert(arrayobj)

arrayobj.splice(start,len)         删除数组,删除起始索引和删除长度

var arrayobj=[1111111,222222222,33333333,4444444];
 arrayobj.splice(2,1)
 alert(arrayobj)

 arrayobj.slice(start,end)     获取子数组,指定获取的起始位置,和结束位置,结束不写,直接获取到数组尾部

 var arrayobj=[1111111,222222222,33333333,4444444];
 var newarr=arrayobj.slice(2)
 alert(newarr)

arrayobj.reverse()   数组反转

var arrayobj=[1111111,222222222,33333333,4444444];
 arrayobj.reverse()
 alert(arrayobj)

 arrayobj.concat()    数组拼接 

var arrayobj=[1111111,222222222,33333333,4444444];
 var add1=[999,8888];
 var he=arrayobj.concat(add1);
 alert(he)

arrayobj.sort() 数组排序

var arrayobj=[1,23,111,333];
 arrayobj.sort();
 alert(arrayobj)

我们发现输出的有问题,这些数字不是按照从小到大的排列

原来:元素将按照 ASCII 字符顺序进行升序排列。所有出现的就是1,111,23,333,我们如何实现出现想要结果1,23,111,333

var arrayobj=[1,23,111,333];
 arrayobj.sort(function(a,b) { return a - b } );
 alert(arrayobj)

我们要想正确排序,必须使用一个排序函数,1.必须是函数2.会返回a和b两个参数3.返回值a-b>0, 在b后面,<0,在b前面

--字符串处理

通过上面的调用和演示,对数组的操作就差不多了

通过字符串的spilt和数组和join可以实现两种类型的转化

我们看看字符串可以进行那些处理操作:

strobj.charAt()    获取指定索引字符(char)

var strobj="abcedfg";
 var str=strobj.charAt(2);
 alert(str)

strobj.charCodeAt() 获取指定索引字符编码,

var strobj="abcedfg";
 var str=strobj.charCodeAt(2);
 alert(str)

strobj.indexOf()  返回指定字符或子字符串在字符串的第一次出现位置,没有返回-1

var strobj="abcedfg";
 var str=strobj.indexOf("ce");
 alert(str)

strobj.lastIndexOf() 返回指定字符或子字符串在字符串中最后出现位置,没有返回-1

var strobj="abcedfgce";
 var str=strobj.lastIndexOf("ce");
 alert(str)

strobj.substr() 返回字字符串,指定起始位置,长度不写,获取到结尾

var strobj="abcedfgce";
 var str=strobj.substr(4);
 alert(str)

strobj.substring() 返回字字符串,指定起始位置和结束位置,不可省略

var strobj="abcedfgce";
 var str=strobj.substring(2,3);
 alert(str)

strobj.slice() 返回字字符串,指定起始位置和结束位置,可省略,获取到尾部

var strobj="abcedfgce";
 var str=strobj.slice(2);
 alert(str)

strobj.replace()  第一个参数为被替换者,第二个为替换后新对象

 var strobj="abcedfgce";
var str=strobj.replace("a","1");
alert(str)

 strobj.search() 查找,返回第一次出现的额位置,没有返回-1

var strobj="abcedfgce";
 var str=strobj.search("b");
 alert(str)

 strobj.match()  查找匹配返回到的内容,没有返回null

var strobj="abcedfgce";
var str=strobj.match("ce");
alert(str)

 我们学完了字符串和数组的处理方式,我们做一些综合处理的实例:

1.数组中,一个字符串在其中的位置

 var dd="123";
 var arr=[456,897,685,745,215,123,569,7894];
 for(var i=0;i<arr.length;i++){
  if(arr[i]==dd){alert(i)}
 };

 2.我们获取数组最小值在数组中的位置

 var arr=[456,897,685,745,215,123,569,7894];
 var newarr=[];
 for(var i=0;i<arr.length;i++){  
  newarr.push(arr[i]);
 }; 
 arr.sort(function(a,b){return a-b});
 for(var i=0;i<arr.length;i++){  
  if(newarr[i]==arr[0]){alert(i)}
 };

3.字符串去掉重复内容

var str="1111,22222,33333,56874,98525,256,111,222,111";
 var arr=str.split(",");
 arr.sort();
 var newarr=[];
 for(var i=0;i<arr.length;i++){  
  if(arr[i]==arr[i+1]){
   continue;
  }else{
   newarr.push(arr[i]);
  }
 }; 
 alert(newarr)

 continue 方法,跳过当前处理,继续执行下面的操作,主要用于数组循环的判断操作

 break   方法,终止程序,不在执行

--时间处理

今天是8/10,以今日为例

new Date();         新建时间对象,里面涵盖了所有当前时间的信息,默认传出时间,当前

date.getDate()     返回年月日的日,是10

date.getTime();    返回距离1970.1.1的毫秒数,8/10距离那天的时间

date.setTime(t+5*24*60*60*1000);    通过毫秒,设置时间对象为具体时间,加了5天,所以date.getTime(); 为15

date.toGMTString()   返回一个日期,该日期用格林威治标准时间 (GMT) 表示并已被转换为字符串

我们做一个例子:

假如一个活动是三天后过期,那么,我们就是计算出当前时间与3天后时间的毫秒差值,在转为分钟,去倒计时!

js代码:

var date=new Date(); 
 var t=date.getTime(); 
 date.setTime(t+3*24*60*60*1000) 
 var d=date.getTime();
 var m=(d-t)/(1000*60*60);
 alert("还有"+m+"小时过期")

 

、dom的存储实现(html5)

cookie是比较早的实现,但是他的存储空间较小,

我们的html5开始支持 localStoragesessionStorage,html5主要做的就是能力监测:

localStorage         

sessionStorage  

首先自然是检测浏览器是否支持本地存储。在HTML5中,本地存储是一个window的属性,包括localStoragesessionStorage,从名字应该可以很清楚的辨认二者的区别,前者是一直存在本地的,后者只是伴随着session,窗口一旦关闭就没了。二者用法完全相同,这里以localStorage为例。

cookie是document的属性,这写是window的属性,docuemnt也是window的属性

能力监测代码:

if(window.localStorage){
  alert('支持localStorage');
 }else{
  alert('不支持localStorage');
 }

 他的操作与cookie一样,

localStorage.a = 3;//设置a为"3"
 localStorage["a"] = "sfsf";//设置a为"sfsf",覆盖上面的值
 localStorage.setItem("b","isaac");//设置b为"isaac"
 var a1 = localStorage["a"];//获取a的值
 var a2 = localStorage.a;//获取a的值
 var b = localStorage.getItem("b");//获取b的值
 localStorage.removeItem("c");//清除c的值
 alert(a1);
 alert(a2);
 alert(b);

我们发现除了和cookie的设置一样外,提供了getItem()和setItem()

清除方法removeItem()。如果希望一次性清除所有的键值对,可以使用clear()

毕竟html5,所有什么都写好了,我们操作比较省事

html5离线机制(cache manifest)

看到 cache 这个词。它是一种缓存的机制。它可以通过一个 .manifest 文件来配置需要缓存的或者一定要保持联网缓存的文件

我们在html可以指定缓存文件,添加manifest属性

<html manifest="path/to/NAME.manifest">

 

、dom之html5-audio/video

关于audio和video的属性、事件。方法有这些

属性 描述
audioTracks 返回可用的音轨列表(MultipleTrackList对象)
autoplay 媒体加载后自动播放
buffered 返回缓冲部件的时间范围(TimeRanges对象)
controller 返回当前的媒体控制器(MediaController对象)
controls 显示播控控件
crossOrigin CORS设置
currentSrc 返回当前媒体的URL
currentTime 当前播放的时间,单位秒
defaultMuted 缺省是否静音
defaultPlaybackRate 播控的缺省倍速
duration 返回媒体的播放总时长,单位秒
ended 返回当前播放是否结束标志
error 返回当前播放的错误状态
initialTime 返回初始播放的位置
loop 是否循环播放
mediaGroup 当前音视频所属媒体组 (用来链接多个音视频标签)
muted 是否静音
networkState 返回当前网络状态
paused 是否暂停
playbackRate 播放的倍速
played 当前播放部件已经播放的时间范围(TimeRanges对象)
preload 页面加载时是否同时加载音视频
readyState 返回当前的准备状态
seekable 返回当前可跳转部件的时间范围(TimeRanges对象)
seeking 返回用户是否做了跳转操作
src 当前音视频源的URL
startOffsetTime 返回当前的时间偏移(Date对象)
textTracks 返回可用的文本轨迹(TextTrackList对象)
videoTracks 返回可用的视频轨迹(VideoTrackList对象)
volume 音量值
事件 描述
abort 当音视频加载被异常终止时产生该事件
canplay 当浏览器可以开始播放该音视频时产生该事件
canplaythrough 当浏览器可以开始播放该音视频到结束而无需因缓冲而停止时产生该事件
durationchange 当媒体的总时长改变时产生该事件
emptied 当前播放列表为空时产生该事件
ended 当前播放列表结束时产生该事件
error 当加载媒体发生错误时产生该事件
loadeddata 当加载媒体数据时产生该事件
loadedmetadata 当收到总时长,分辨率和字轨等metadata时产生该事件
loadstart 当开始查找媒体数据时产生该事件
pause 当媒体暂停时产生该事件
play 当媒体播放时产生该事件

playing 当媒体从因缓冲而引起的暂停和停止恢复到播放时产生该事件
progress 当获取到媒体数据时产生该事件
ratechange 当播放倍数改变时产生该事件
seeked 当用户完成跳转时产生该事件
seeking 当用户正执行跳转时操作的时候产生该事件
stalled 当试图获取媒体数据,但数据还不可用时产生该事件
suspend 当获取不到数据时产生该事件
timeupdate 当前播放位置发生改变时产生该事件
volumechange 当前音量发生改变时产生该事件
waiting 当视频因缓冲下一帧而停止时产生该事件

 

我们大家简单理一下思路,然后就粘贴出示例代码

1.我们首先还有一个视频路径,对src属性进行赋值

2.我们要获取总时长,就是duration属性,但是必须等待视频加载完,通过loadedmetadata载入完成事件进行总时长获取

3.我们要进行播放暂停,就是调用play和pause方法

4.控制音量大小就是对volume属性设置

5.静音对muted属性设置

6.进度条处理,我们可以获取当前播放到时间currenttime用它除以总时长duration就是进度

7.播放进度拖拽就是改变currenttime的属性,位置

8.进度条自动变化,调用timeupdate事件,时间变化事件及视频播放中出现,

整体的代码,这里需要jq库,请加载到本地,需要一个本地.mp4文件

js代码 videoPlay("movie.mp4"); 调用

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width; initial-scale=1.0">
<title></title>
<style>
*{ margin:0; padding:0;}
body{ font-size:12px; font-family:"微软雅黑"}
.html5demo{ width:300px; height:212px; position:relative; background:#000; margin:200px;}
.videotoolsback{ position:absolute; bottom:0px; left:0px; height:30px;width:300px; background:url(default/controlBarBack.png) repeat-x left top; opacity:0.9; z-index:5px;}
.videotools{ position:absolute; bottom:0px; left:0px; height:30px;width:300px;z-index:999px;}
.play{ float:left; height:14px; width:14px; margin:8px 8px; background:url(default/play.png) no-repeat left center; cursor:pointer;}
span.pause{background:url(default/pause.png) no-repeat left center;}
.current{ float:left; margin:8px 0; height:14px; line-height:14px; width:50px; text-align:right; color:#fff; font-size:12px;}
.time-s{float:left; margin:5px 0; width:8px; height:20px; background:url(default/spliter.png) no-repeat center top;}
.duration{float:left; margin:8px 0; height:14px; line-height:14px; width:50px;color:#fff; font-size:12px;}
.progressBar{position: relative;width:30px;height: 6px;background: #6495ed; float:left; margin:12px 0; border-radius:3px;}
.timeBar{position: absolute;top: -5px;left:0;height:16px; width:16px; background:url(default/handle.png) no-repeat left top;margin-left:-8px; cursor:pointer;}
.protimeBar{position: absolute; background:#a2cd5a;border-radius:3px; width:0;height: 6px; left:0px; top:0px;}
.muted{ float:right; height:14px; width:19px; margin:8px 8px; background:url(default/volume.png) no-repeat left top; cursor:pointer;}
span.truemuted{ background:url(default/mute.png) no-repeat left top;}
.volumeBar{float:right; position: relative;width:50px;height:6px;background: #6495ed;  margin:12px 8px;border-radius:3px;}
.volume{ position: absolute;top: -5px;left: 50%;height:16px; width:16px; background:url(default/handle.png) no-repeat left top; margin-left:-8px;cursor:pointer;}
.fullscreen{ float:right; height:14px; width:14px; margin:8px 14px 8px 0px; background:url(default/full.png) no-repeat left top; cursor:pointer;}
span.unfullscreen{ background:url(default/unfull.png) no-repeat left top;}
div.full-html5demo{ margin:0; position:fixed; left:0; top:0; z-index:2;}
div.full-videotoolsw{ width:100%;}
.context-toggle{ position:absolute; top:100px; left:0px; width:100%; text-align:center; height:50px; line-height:50px; color:#FFF; display:none; z-index:9999; font-size:16px;}
</style>
</head>
<body>
   <div class="html5demo">
        <video class="video" width="300" height="212" id="video" preload>      
  </video>  
        <!--<audio class="video" width="300" height="212" id="video" preload>
        <source src="" ></source>  
        </audio>-->
        <div class="videotoolsback"></div>     
     <div class="videotools">
         <span class="play" del="1"></span>
            <span class="current"></span>
            <span class="time-s"></span>
            <span class="duration"></span>
            <div class="progressBar">
      <div class="protimeBar"></div>
               <div class="timeBar"></div>
            </div>
            <span class="fullscreen" del="1"></span>
            <div class="volumeBar">
              <div class="volume"></div>
            </div>
            <span class="muted" del="1"></span> 
            <!--<div class="control">
                <span class="ff">快进</span>
                <span class="rw">倒带</span>
                <span class="sl">快退</span>
            </div>--> 
     </div>
        <div class="context-toggle">按 ESC 退出全屏</div>
    </div> 
    
    <div style=" height:800px;"></div>                                  
</body>
<script src="jquery.js"></script>
<script>
$(function(){ 
 videoPlay("movie.mp4");
 
 function videoPlay(url){
  var video=document.getElementById("video");
  video.src=url;
  var paly=$(".play");
  //code
  //video.autoplay=true; 
  //播放暂停
  paly.click(function(){
   if(paly.attr("del")==1){
    video.play();
    paly.addClass("pause");
    paly.attr("del",0);
   }else{   
    video.pause();
    paly.removeClass("pause");
    paly.attr("del",1);  
   }
  });
  //载入后显示视频文件总时间
  video.onloadedmetadata=function(){
    var temp_sub=video.duration.toString().substring(0,parseInt(video.duration.toString().indexOf("."))+3).replace(".", ":");
   // alert(getCurrentTime(1000*video.duration));
    $('.duration').text(getCurrentTime(1000*video.duration));
  };
  //视频播放时,进度条显示
  $('.current').text(getCurrentTime(1000*video.currentTime));
  video.ontimeupdate=function(){
   var temp_sub=video.currentTime.toString().substring(0,parseInt(video.currentTime.toString().indexOf("."))+3).replace(".", ":");   
   $('.current').text(getCurrentTime(1000*video.currentTime));
   var currentPos = video.currentTime;     
      var maxduration = video.duration;     
      var percentage = 100 * currentPos / maxduration; 
      $(".timeBar").css('left',percentage+'%');
   $(".protimeBar").css('width',percentage+'%');
     
  };
  //进度条点击
  var timeDrag = false;  
  $('.progressBar').mousedown(function(e) {
     timeDrag = true;
     updatebar(e.pageX);
  });
  //页面抬起
  $(document).mouseup(function(e) {
     if(timeDrag) {
     timeDrag = false;
     updatebar(e.pageX);    
     };
     if(volumeDrag) {
     volumeDrag = false;
     updatevolume(e.pageX);    
     };
  });
  //页面移动
  $(document).mousemove(function(e) {
     if(timeDrag) {
     updatebar(e.pageX);    
     };
     if(volumeDrag) {
     updatevolume(e.pageX);    
     };
  });  
  //点击进度条跳转方法
  var updatebar = function(x) {
     var progress = $('.progressBar');
     var maxduration = video.duration;
     var position = x - progress.offset().left;
     var percentage = 100 * position / progress.width();  
     //点击超出判断
     if(percentage > 100) {
     percentage = 100;
     }
     if(percentage < 0) {
     percentage = 0;
     }
     //进度条跳转到点击位置
     $('.timeBar').css('left', percentage+'%'); 
           $(".protimeBar").css('width',percentage+'%');        
     video.currentTime = maxduration * percentage / 100;
  };
  
  //缓冲属性,缓存数据的最后一个值.
  var startBuffer = function() {
     var maxduration = video.duration;
     var currentBuffer = video.buffered.end(0);
     var percentage = 100 * currentBuffer / maxduration;
     $('.bufferBar').css('width', percentage+'%');
   
     if(currentBuffer < maxduration) {
     setTimeout(startBuffer, 500);
     }
  };
  setTimeout(startBuffer, 500);
  //是否静音
  $('.muted').click(function(){
   video.muted = !video.muted;
   if($(this).attr("del")==1){
      $(this).addClass("truemuted");
      $(this).attr("del",0);
   }else{
    $(this).removeClass("truemuted");
    $(this).attr("del",1);
   };
  });
  //声音控制
  video.volume=0.5;
  var volumeDrag = false;
  $(".volumeBar").mousedown(function(e){ 
     volumeDrag = true;
     updatevolume(e.pageX);
  });  
  //点击声音跳转方法
  var updatevolume = function(x) {
     var volumeBar= $('.volumeBar');
     var position = x - volumeBar.offset().left;
     var percentage = 100 * position / volumeBar.width();    
     //点击超出判断
     if(percentage > 100) {
     percentage = 100;
     }
     if(percentage < 0) {
     percentage = 0;
     }
     //进度条跳转到点击位置
     $('.volume').css('left', percentage+'%');
     video.volume = percentage / 100; 
  };   
  //快进/快退 倒带控制
  //$('.ff').on('click', function() {
 //    video.playbackrate = 3;
 // });
 //  
 // $('.rw').on('click', function() {
 //    video.playbackrate = -3;
 // });
 //  
 // $('.sl').on('click', function() {
 //    video.playbackrate = 0.5;
 // });
  //全屏播放
  var winWidth=$(window).width();
  var winHeight=$(window).height();
  var prossw=winWidth-300;
  var vidWidth=$(".html5demo").width();
  var vidHeight=$(".html5demo").height();
  var vidprossw=$(".progressBar").width();
  $(window).resize(function(){
   winWidth=$(window).width();
   winHeight=$(window).height();
   prossw=winWidth-300;
   if($('.fullscreen').attr("del")==0){   
    $(".html5demo,.video").width(winWidth);
    $(".html5demo,.video").height(winHeight);
    $(".progressBar").width(prossw);    
   }else{    
   };
  });
  $('.fullscreen').click(function(){   
   if($(this).attr("del")==1){
    $(".html5demo").addClass("full-html5demo");
    $(".videotoolsback,.videotools").addClass("full-videotoolsw");
    $(this).addClass("unfullscreen");    
    $(".html5demo,.video").width(winWidth);
    $(".html5demo,.video").height(winHeight);
    $(this).attr("del",0);
    $(".progressBar").width(prossw);
    $(".context-toggle").show();
    setTimeout(function(){$(".context-toggle").hide()},2000);
    
   }else{//unfull    
    $(".html5demo").removeClass("full-html5demo");
    $(".videotoolsback,.videotools").removeClass("full-videotoolsw");
    $(this).removeClass("unfullscreen");    
    $(".html5demo,.video").width(vidWidth);
    $(".html5demo,.video").height(vidHeight);
    $(this).attr("del",1);
    $(".progressBar").width(vidprossw);
    $(".context-toggle").hide();
   };
      
   //fullScreenCancel(video);
  });
  //keyunfull 
   /** Coding Here */
  $(window).keydown(function(e){
   if (e.which === 27) {     
    if($('.fullscreen').attr("del")==0){
    $(".html5demo").removeClass("full-html5demo");
    $(".videotoolsback,.videotools").removeClass("full-videotoolsw");
    $('.fullscreen').removeClass("unfullscreen");    
    $(".html5demo,.video").width(vidWidth);
    $(".html5demo,.video").height(vidHeight);
    $('.fullscreen').attr("del",1);
    $(".progressBar").width(vidprossw);
    }
    $(".context-toggle").hide();
   }
  });
  //全屏播放方法
  //function fullScreenCancel(video){  
//    if(video.requestFullScreen) {  
//   video.requestFullScreen();  
//    } else if(video .webkitRequestFullScreen ) {  
//   video.webkitRequestFullScreen();  
//    } else if(video .mozRequestFullScreen) {  
//   video.mozRequestFullScreen();  
//    }  
//  };  
 };
 
 //从毫秒数得到一个时间格式 
    function  getCurrentTime(ms) { 
  var  s = parseInt(ms / 1000); 
  var  m = parseInt(s / 60); 
  s -= m * 60; 
  var  h; 
  h = parseInt(m / 60); 
  m -= h * 60; 
  return  make2Str(m) + ":" + make2Str(s); 
 };
 //使数字时钟保持两位 
    function  make2Str(i) { 
  if (i < 10)  return  "0" + i; 
  else  return  "" + i; 
 }; 
});
</script>
</html>

 

、dom之html5-canvas

这些api都是dom提供好的,要想能用,就要去分析和尝试

下面是canvas的api

canvas.getContext('2d');

context.save();

context.restore();

context.translate(context.canvas.width/2, context.canvas.height/2);

context.beginPath();

context.lineWidth

context.moveTo(lastX,lastY);

context.lineTo(lastX,lastY);

context.strokeStyle = pencolor;

context.shadowColor = 'white'; //阴影

context.shadowBlur = 10;

context.stroke(); //绘制

context2.clearRect(0,0,canvas.width,canvas.height);

mycanvas.toDataURL("image/png");

context.clearRect(0,0,canvas.width,canvas.height);

context.fillStyle="#faa";

context.fillRect(0,0,200,80);

context.globalCompositeOperation="destination-out";

context.arc(movex,movey,penwidth,0,Math.PI*2,true);

context.closePath();

context.fill();

context.getImageData(0,0,200,80);/

imgData.data.length;

这些我就不做解释了,大家看我做的实例,或者w3c的介绍更好一些,实例链接

http://www.oschina.net/code/snippet_2352644_49974 

http://www.oschina.net/code/snippet_2352644_49815

 

、dom之html5-device(设备处理)

 

Html5 device api 新功能,新体验

一、音频处理 Web audio API
二、捕捉用户摄像头 - 媒体流 Media Capture
三、语音识别 Web Speech API
四、设备电量 Battery API
五、获取用户位置 - 地理位置 Geolocation API
六、环境光 Ambient Light API
七、陀螺仪 Deviceorientation
八、Websocket
九、NFC
十、震动 - Vibration API
十一、网络环境 Connection API
   

一、音频处理 Web audio API

Audio对象提供的只是音频文件的播放,而Web Audio则是给了开发者对音频数据进行分析、处理的能力,比如混音、过滤。

核心代码:

var context = new webkitAudioContext();
var source = context.createBufferSource();   // 创建一个声音源
source.buffer = buffer;   // 告诉该源播放何物
createBufferSourcesource.connect(context.destination);   // 将该源与硬件相连
source.start(0); //播放

技术分析:
当我们加载完音频数据后,我们将创建一个全局的AudioContext对象来对音频进行处理,AudioContext可以创建各种不同功能类型的音频节点AudioNode,比如

 

1、源节点(source node)
我们可以使用两种方式加载音频数据:
<1>、audio标签

var sound, audio = new Audio();
audio.addEventListener('canplay', function() {
 sound = context.createMediaElementSource(audio);
 sound.connect(context.destination);
});
audio.src = '/audio.mp3';

<2>、XMLHttpRequest

var sound, context = createAudioContext();
var audioURl = '/audio.mp3'; // 音频文件URL
var xhr = new XMLHttpRequest();
xhr.open('GET', audioURL, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function() {
 context.decodeAudioData(request.response, function (buffer) {
 source = context.createBufferSource();
 source.buffer = buffer;
 source.connect(context.destination);
 }
}
xhr.send();

2、分析节点(analyser node)
我们可以使用AnalyserNode来对音谱进行分析,例如:

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var analyser = audioCtx.createAnalyser();
analyser.fftSize = 2048;
var bufferLength = analyser.frequencyBinCount;
var dataArray = new Uint8Array(bufferLength);
analyser.getByteTimeDomainData(dataArray);

function draw() {
 drawVisual = requestAnimationFrame(draw);
 analyser.getByteTimeDomainData(dataArray);
 // 将dataArray数据以canvas方式渲染出来
};

draw();

3、处理节点(gain node、panner node、wave shaper node、delay node、convolver node等)
不同的处理节点有不同的作用,比如使用BiquadFilterNode调整音色(大量滤波器)、使用ChannelSplitterNode分割左右声道、使用GainNode调整增益值实现音乐淡入淡出等等。

二、捕捉用户摄像头 - 媒体流 Media Capture

通过getUserMedia捕捉用户摄像头获取视频流和通过麦克风获取用户声音。

核心代码:
1、摄像头捕捉

navigator.webkitGetUserMedia ({video: true}, function(stream) {
 video.src = window.URL.createObjectURL(stream);
 localMediaStream = stream;
}, function(e){

})

2、从视频流中拍照

btnCapture.addEventListener('touchend', function(){
 if (localMediaStream) {
  canvas.setAttribute('width', video.videoWidth);
  canvas.setAttribute('height', video.videoHeight);
  ctx.drawImage(video, 0, 0);
 }
}, false);

3、用户声音录制

navigator.getUserMedia({audio:true}, function(e) {
 context = new audioContext();
 audioInput = context.createMediaStreamSource(e); 
 volume = context.createGain();
 recorder = context.createScriptProcessor(2048, 2, 2);
 recorder.onaudioprocess = function(e){
  recordingLength += 2048;
  recorder.connect (context.destination);
 } 
}, function(error){});

4、保存用户录制的声音

var buffer = new ArrayBuffer(44 + interleaved.length * 2);
var view = new DataView(buffer);
fileReader.readAsDataURL(blob); // android chrome audio不支持blob
… audio.src = event.target.result;


三、语音识别 Web Speech API

1、将文本转换成语音;
2、将语音识别为文本。

核心代码:
1、文本转换成语音,使用SpeechSynthesisUtterance对象;

var msg = new SpeechSynthesisUtterance();
var voices = window.speechSynthesis.getVoices();
msg.volume = 1; // 0 to 1
msg.text = ‘识别的文本内容’;
msg.lang = 'en-US';
speechSynthesis.speak(msg);

2、语音转换为文本,使用SpeechRecognition对象。

var newRecognition = new webkitSpeechRecognition();
newRecognition.onresult = function(event){
 var interim_transcript = '';
 for (var i = event.resultIndex; i < event.results.length; ++i) {
  final_transcript += event.results[i][0].transcript;
 }
};


四、 设备电量 Battery API

查询用户设备电量及是否正在充电。

核心代码:

var battery = navigator.battery || navigator.webkitBattery || navigator.mozBattery || navigator.msBattery;
var str = '';
if (battery) {
 str += '

你的浏览器支持HTML5 Battery API
';
 if(battery.charging) {
 str += '

你的设备正在充电
';
} else {
 str += '

你的设备未处于充电状态
';
}
 str += '

你的设备剩余'+ parseInt(battery.level*100)+'%的电量
';
} else {
 str += '

你的浏览器不支持HTML5 Battery API
';
}


五、获取用户位置 - 地理位置 Geolocation

Geolocation API用于将用户当前地理位置信息共享给信任的站点,目前主流移动设备都能够支持。

核心代码:

var domInfo = $("#info");

// 获取位置坐标
if (navigator.geolocation) {
 navigator.geolocation.getCurrentPosition(showPosition,showError);
}
else{
 domInfo.innerHTML="抱歉,你的浏览器不支持地理定位!";
}

// 使用腾讯地图显示位置
function showPosition(position) {
 var lat=position.coords.latitude;
 var lon=position.coords.longitude;

 mapholder = $('#mapholder')
 mapholder.style.height='250px';
 mapholder.style.width = document.documentElement.clientWidth + 'px';

 var center = new soso.maps.LatLng(lat, lon);
 var map = new soso.maps.Map(mapholder,{
  center: center,
  zoomLevel: 13
 });

 var geolocation = new soso.maps.Geolocation();
 var marker = null;
 geolocation.position({}, function(results, status) {
  console.log(results);
  var city = $("#info");
  if (status == soso.maps.GeolocationStatus.OK) {
   map.setCenter(results.latLng);
   domInfo.innerHTML = '你当前所在城市: ' + results.name;
  if (marker != null) {
   marker.setMap(null);
  }
  // 设置标记
  marker = new soso.maps.Marker({
   map: map,
   position:results.latLng
  });
  } else {
   alert("检索没有结果,原因: " + status);
  }
 });
}

 

六、环境光 Ambient Light

Ambient Light API定义了一些事件,这些时间可以提供源于周围光亮程度的信息,这通常是由设备的光感应器来测量的。设备的光感应器会提取出辉度信息。

核心代码:
这段代码实现感应用前当前环境光强度,调整网页背景和文字颜色。


var domInfo = $('#info');
if (!('ondevicelight' in window)) {
 domInfo.innerHTML = '你的设备不支持环境光Ambient Light API';
} else {
 var lightValue = document.getElementById('dl-value');
 window.addEventListener('devicelight', function(event) {
  domInfo.innerHTML = '当前环境光线强度为:' + Math.round(event.value) + 'lux';
  var backgroundColor = 'rgba(0,0,0,'+(1-event.value/100) +')';
  document.body.style.backgroundColor = backgroundColor;
  if(event.value < 50) {
   document.body.style.color = '#fff'
  } else {
   document.body.style.color = '#000'
  }
 });
}

这些都是我在腾讯的一篇文章看到的,我们发现html5非常的强大,不过这里面很多都是没有实现的

下面我是对webaudio整理的实例,里面很多新的api,大家要去百度查看用法

谷歌下测试,测试时,上传一个.mp3文件

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>m</title>
<style>
#fileWrapper {transition: all 0.5s ease;}
#fileWrapper: hover {opacity: 1}
#visualizer_wrapper {text-align: center;}
#canvas{ background:#FF9;}
</style>
</head>
<body>
<div id="wrapper">
    <div id="fileWrapper" class="file_wrapper">
        <div id="info">
            请用谷歌浏览器好吗,浏览上传音频文件.mp3,已经在文件下有测试文件,也许请等候一会,黄色区域才会出现麦浪
        </div>
        <input type="file" id="uploadedFile"></input>
    </div>
    <div id="visualizer_wrapper">
        <canvas id='canvas' width="800" height="350"></canvas>
    </div>
</div>
</body>
<script>
window.onload = function() {
    new Visualizer().init();
};
//web audio class
var Visualizer = function() {
    this.file = null; //要处理的文件,后面会讲解如何获取文件
    this.fileName = null; //要处理的文件的名,文件名
    this.audioContext = null; //进行音频处理的上下文,稍后会进行初始化
    this.source = null; //保存音频
};
Visualizer.prototype = {
 init: function() {
        this._prepareAPI();
        this._addEventListner();
    },
    _prepareAPI: function() {
        //统一前缀,方便调用
        window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
        //这里顺便也将requestAnimationFrame也打个补丁,后面用来写动画要用
        window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame;
        //安全地实例化一个AudioContext并赋值到Visualizer的audioContext属性上,方便后面处理音频使用
        try {
            this.audioContext = new AudioContext();
        } catch (e) {
            console.log('!你的浏览器不支持AudioContext:(');
            console.log(e);
        }
    },
 _addEventListner: function() {
  var that = this,
   audioInput = document.getElementById('uploadedFile'),//长传按钮
   dropContainer = document.getElementById("canvas");//canvas
  //监听是否有文件被选中
  audioInput.onchange = function() {
   //这里判断一下文件长度可以确定用户是否真的选择了文件,如果点了取消则文件长度为0
   if (audioInput.files.length !== 0) {//上传表单的files属性
    that.file = audioInput.files[0]; //将文件赋值到Visualizer对象的属性上
    that.fileName = that.file.name;
    that._start(); //获取到文件后,开始程序,这个方法会在后面定义并实现
   };
  };
 },//文件转换为ArrayBuffer(二进制数组缓冲去类型)格式,才能够传递给AudioContext进行解码
 _start: function() {
  //read and decode the file into audio array buffer
  var that = this, //当前this指代Visualizer对象,赋值给that以以便在其他地方使用
   file = this.file, //从Visualizer对象上获取前面得到的文件
   fr = new FileReader(); //实例化一个FileReader用于读取文件
  //将上一步获取的文件传递给FileReader从而将其读取为ArrayBuffer格式,格式转化
  fr.readAsArrayBuffer(file);//读取file上传的文件,并且是ArrayBuffer类型
  fr.onload = function(e) { //文件读取成功,完后调用此函数
   var fileResult = fr.result; //这是读取成功得到的结果ArrayBuffer数据
   var audioContext = that.audioContext; //从Visualizer得到最开始实例化的AudioContext用来做解码ArrayBuffer
   audioContext.decodeAudioData(fileResult, function(buffer) { //解码成功则调用此函数,参数buffer为解码后得到的结果 解码必须为arraybuffer类型文件
    that._visualize(audioContext, buffer); //调用_visualize进行下一步处理,此方法在后面定义并实现
   }, function(e) { //这个是解码失败会调用的函数
    console.log("!文件解码失败:(");
   });
  };
  
 },
 _visualize: function(audioContext, buffer) {//得到了音频上下文对象,和解码可用音频数据
  var audioBufferSouceNode = audioContext.createBufferSource();//音频源对象,存放音频数据,核心对象(绑定硬件,绑定数据,播放等)
  var analyser = audioContext.createAnalyser();//创建音频分析对象  节点Analyser用于分析,可以通过这个节点取出声音的时域和频域信息
  //将source与分析器连接
  audioBufferSouceNode.connect(analyser);
  //将分析器与destination连接,这样才能形成到达扬声器的通路
  analyser.connect(audioContext.destination);
  audioBufferSouceNode.connect(audioContext.destination);//绑定音频硬件
  audioBufferSouceNode.buffer = buffer;//获取音频数据
  audioBufferSouceNode.start(0);//播放方法
  this._drawSpectrum(analyser);//可视化显示处理
 },
 _drawSpectrum: function(analyser) {
  var canvas = document.getElementById('canvas'),
   cwidth = canvas.width,
   cheight = canvas.height - 2,
   meterWidth = 10, //频谱条宽度
   gap = 2, //频谱条间距
   //频谱条数量  canvas总款除以单个柱形图宽度
   meterNum = 800 / (10 + 2), 
   YPositionArray = []; //将上一画面各个的位置保存到这个数组
  ctx = canvas.getContext('2d');
  var drawMeter = function() {
   //类型数组转换 得到的是处理后的int8位数组 二进制数组转化为10进制
   var array = new Uint8Array(analyser.frequencyBinCount);//获取0-255之间
   //获取数组
   analyser.getByteFrequencyData(array);
   //计算采样步长
   
   //数组/条数,可分解多个单元部分
   //1024*12/800=15
   var step = Math.round(array.length / meterNum); 
   //console.log(array.length);
   ctx.clearRect(0, 0, cwidth, cheight);//清空,实现动态显示
   for (var i = 0; i < meterNum; i++) {//循环 柱形条数次0-15
    //可认为1024里面值拿出15个存入YPositionArray
    var value = array[i * step]; //获取当前能量值 每step(15)个数量为一组 array中索引0 15 30 45 ....的数值
    if (YPositionArray.length < Math.round(meterNum)) {
     YPositionArray.push(value); //初始化保存帽头位置的数组,将第一个画面的数据压入其中
    };    
    //开始绘制频谱条
    ctx.fillStyle = "#ccc";
    ctx.fillRect(i * 12, cheight - value + 2, meterWidth, cheight);
   }
   requestAnimationFrame(drawMeter);//函数执行后再次动画调用当前函数,实现递归处理
  }
  requestAnimationFrame(drawMeter);//类似于setTimeout 间隔时间自动采用浏览器适配时间帧
 }
   
};
</script>
</html>


 、dom的其它api接口

 1.全屏的实现

我们浏览网页,在线播放器会有一个全屏按钮,现在html5页提供了这些接口,不过支持较差

html

<div id="quan" style="height:200px; width:200px; background:#9C3;">我要全屏</div>

js

function fullScreenCancel(ele){  
    if(ele.requestFullScreen) {  
   ele.requestFullScreen();  
    } else if(ele .webkitRequestFullScreen ) {  
   ele.webkitRequestFullScreen();  
    } else if(ele.mozRequestFullScreen) {  
   ele.mozRequestFullScreen();  
    }  
  }; 
  var quan=document.getElementById("quan");
        quan.onclick=function(){
    fullScreenCancel(this);
  }

点击它,我们就可以看到一个全屏的div了

ele.requestFullScreen();  给对象添加全屏效果

2.上传表单的处理 input type="file"

html

<input type="file" id="file" value="上传" />
    <input type="button" id="ce" value="ok" />

js

var file=document.getElementById("file");
 var ce=document.getElementById("ce");
 ce.onclick=function(){
  alert(file.files[0].size) 
 }

file.files[0]          获取上传文件的第一个

file.files[0].size    获取上传文件大小

file.files[0].type   获取上传文件类型

上传按钮具有files属性,可以获取所有上传文件

我们下载打算把上传的图片显示在img中,img的src属性要赋值为这个图片的地址

我们介绍一个新对象

new FileReader(file);   新建一个文件读取者对象,参数是一个文件,读取后存入对象

filereader.readAsDataURL() 读取转化方法,将文件转为url

filereader.onload    事件,载入完毕事件,表示其他操作都ok后执行

html:

<input type="file" id="file" value="上传" />
    <img src="" id="img" />

js:

 
 var file=document.getElementById("file");
 var img=document.getElementById("img");
 file.onchange=function(){
  if(!/image\/\w+/.test(file.files[0].type)){  
        alert("看清楚,这个需要图片!");  
        return false;  
  }  
  var reader = new FileReader();  
  //将文件以Data URL形式读入页面  
  reader.readAsDataURL(file.files[0]);  
  reader.onload=function(e){  
   //显示文件  
   img.src=this.result;
  } 
 }

我们的img就会显示我们上传的图片

3.load事件

load事件,是载入完成事件,在对象全部完成后触发

window.onload   避免html为载入完毕调用代码

img.onload         图片载入完调用,避免无图片处理

4.键盘事件

阻止f5刷新

  window.onkeydown=function(event){
   if(event.keyCode==116){return false;}
  };

返回false 阻止默认行为

5.双击可编辑的实现

html:

<div id="Td2" onDblClick="editCell(this)">双击编辑</div>

js:

function editCell(obj){
    if(obj.innerText==""){
      obj.innerHTML="<input value='' onblur='update(this.value)'>";               
//插入输入框,失去焦点时更新
    }else{
      obj.innerHTML="<input value="+obj.innerText+
" onblur='update(this.value)'>";//插入文本框,且指定内容
    }
}
function update(txt){
    document.getElementById("Td2").innerText=txt; 
 //文本框失去焦点时,需要更新表格的内容
}

 

、jsonp 跨域处理

 // 得到航班信息查询结果后的回调函数
    var flightHandler = function(data){
        alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
    };
    // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
    var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
    // 创建script标签,设置其属性
    var script = document.createElement('script');
    script.setAttribute('src', url);
    // 把script标签加入head,此时调用开始
    document.getElementsByTagName('head')[0].appendChild(script);

从代码可以看出,jsonp跨域用到的就是js可以跨域处理方式,加载其他地址的js文件,其他地址js文件会返回我要的数据,我在用本地js代码显示这个数据

我们很多时候利用百度的jq文件,不就是外部地址的js引用吗

 

、间隔处理函数(setInterval)和延伸

这个函数我们,我们在前面做漂浮广告就用过,并不陌生

setInterval(fun,time)               创建间隔动画,返回动画id
clearInterval(id)            清除动画,根据动画id

我们做一个简单的使用案例

html:

<div id="set1" >0</div>
    <input type="button" id="play" value="开始" />
    <input type="button" id="pause" value="暂停" />

js:

window.onload=function(){
 var set1=document.getElementById("set1");
 var play=document.getElementById("play");
 var pause=document.getElementById("pause");
 var se=setInterval(fun1,500);
 var i=0;  
 function fun1(){
  i=i+1;
  set1.innerHTML=i;
 };
 play.onclick=function(){
  se=setInterval(fun1,500);  
 };
 pause.onclick=function(){
  clearInterval(se);  
 };
};

通过开始和暂停,我们实现了数字的不断增加

setTimeout(fun,time) 创建间隔动画,返回动画id
clearTimeout(id) 清除动画,根据动画id

这个函数和inteval的区别就是执行次数,只会执行一次,我们叫他一次延时函数

看代码:

js:

window.onload=function(){
 var set1=document.getElementById("set1");
 var play=document.getElementById("play");
 var pause=document.getElementById("pause");
 var se=setTimeout(fun1,500);
 var i=0;  
 function fun1(){
  i=i+1;
  set1.innerHTML=i;
 };
 play.onclick=function(){
  se=setTimeout(fun1,500);  
 };
 pause.onclick=function(){
  clearTimeout(se);  
 };
};

修改后,看到区别就是每次只加一次

同样的,其实我们可以把这一次也封装成间隔函数,我们假设settime封装在一个函数里面,这个函数就是settimet调用的函数,看代码:

window.onload=function(){
 var set1=document.getElementById("set1");
 var play=document.getElementById("play");
 var pause=document.getElementById("pause");
 var i=0; 
 function wai(){
  i=i+1;
  set1.innerHTML=i;
  se=setTimeout(wai,500);
 };
 var se=setTimeout(wai,500);
  
};

调用本身,和间隔函数一样了,

在html5到来之际,在settimeout的基础上,又出现了更好的一次延时处理

requestAnimationFrame(fun)        据浏览器自己的频率进行执行函数

省去了自定义的延时时间,更具浏览器自动采用,使用方法用settimeout

结束了,DOM的介绍,我们从基础,到兼容,到高级处理,下一次就是BOM的学习了!

 

 

 

转载于:https://my.oschina.net/tbd/blog/490310

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值