这是以前作HTML 5的学习笔记,以后还会分享出一些其余的笔记。都是一些早期无知少年笔记,喜欢就看吧。不喜欢,扔了!!javascript
能够将内容复制粘贴本身看,或者直接另存成HTML文件也能够。笔记是经过evernote编写的,本人能够直接导出成HTML文档等。须要的能够留Email,我能够发文件。
php
这个文档只适合看看了解一下HTML 5,里面也有demo。或者复习一下,真正深刻学习的话,仍是买点书。研究一下协议~~
html
一、主体结构元素
<article>
<header>
<h1>苹果</h1>
<p>发表日期:<time pubdate="pubdate">2010/10/09</time></p>
</header>
<p><b>苹果</b>, 植物类水果,屡次花果.....("苹果"文章正文)</p>
<footer>
<p><small>著做版权###公司全部。</small></p>
</footer>
</article>
article元素是能够嵌套使用的,内层的内容再原则上须要与外层的内容相关联。例如,一篇博文,针对该文章的评论就可使用嵌套article。(pubdate表明发布时间)
....
<p><b>苹果</b>, 植物类水果,屡次花果.....("苹果"文章正文)</p>
<section>
<h2>评论</h2>
<article>
<header>
<h3>发表者:lucy</h3>
<p>
<time pubdate datetime="2010-10-10T19:00-08:00">
1小时前
</time>
</p>
<header>
</article>
<article>...</article>
</section>
</article>
article元素也能够用来表示插件,它的做用是使插件看起来好像内嵌在页面中。
<article>
<h1>My Fruit Spinner</h1>
<object>
<param name="allowFullScreen" value="true">
<embed src="#" width="600" height="395"></embeb>
</object>
</article>
section元素用于对网站或应用程序中页面上的内容进行分块。section元素由内容和标题组成。但section元素是一个特殊的容器元素,当一个容器须要被直接定义样式或经过脚本定义行为时,推荐使用div而非section元素。一般不推荐位那些没有标题的内容使用section元素。
<body>
<h1>技术资料</h1>
<nav>
<ul>
<li><a href="/">主页</a></li>
<li><a herf="/events">开发文档</a></li>
</ul>
</nav>
<article>
<header>
<h1> HTML 5 与 CSS 3的历史</h1>
<nav>
<ul>
<li><a href="#HTML 5">HTML 5的历史</a></li>
<li><a href="#CSS 3">CSS 3的历史</a></li>
</ul>
</nav>
</header>
<section id="HTML 5">
<h1>HTML 5的历史</h1>
<p>讲述HTML 5的历史的正文</p>
</section>
<section id="CSS 3">
<h1>CSS 3的历史</h1>
<p>讲述CSS 3的历史的正文</p>
</section>
..。
<footer>
<p>
<a href="?edit">编辑</a> |
<a href="?delete">删除</a> |
<a href="?rename">重命名</a>
</p>
</footer>
</article>
<footer>
<p><small>版权全部...</small></p>
</footer>
</body>
nav元素能够用于如下这些场合
传统导航条
侧边栏导航
页内导航
翻页操做
aside元素用来表示当前页面或文章的附属信息部分,它能够包含与当前页面或主要内容相关的引用、侧边栏、广告、导航条
有些机器编码过程会对时间产生歧义,HTML 5增长了一个新的元素来无歧义地、明确地对机器的日期和时间进行编码,而且以让人易读的方式来展现它
<time datetime="2010-11-13">2010年11月13日</time>
<time datetime="2010-11-13T20:00">我生日的晚上8点</time>
编码时机器读到的部分在datetime属性里,而元素的开始标记和结束标记中间的部分显示在网页上。
<header>
<hgroup>
<h1>IT 新技术</h1>
<a href="http://blog.sina.com.cn/itnewtech">
http://blog.sina.com.cn/itnewtech
</a>
<a href="#">[订阅]</a>
<a href="#">[手机订阅]</a>
</hgroup>
<nav>
<ul>
<li>首页</li>
<li><a href="#">博文目录</a></li>
<li><a href="#">图片</a></li>
<li><a href="#">关于我</a></li>
</ul>
</nav>
</header>
hgroup元素
hgroup元素是将标题及其子标题进行分组的元素。hgroup元素一般会将h1~h6元素进行分组,譬如一个内容区块的标及其子标题算一组。
<header>
<hgroup>
<h1>主标题</h1>
<h2>子标题</h2>
</hgroup>
</header>
footer元素能够做为其上层父级内容区块或者根区块的脚注。footer一般包括其相关区块的脚注信息,如做者、相关阅读连接及版权信息等。
address元素
address元素用来在文档呈现联系信息,包括文档做者或文档维护者的名字、他们的网站连接、电子邮箱、真实地址、电话号码等。
<address>
<a href="#">lucy</a>
<a href="#">lily</a>
<a href="#">cecil</a>
</address>
结构元素大致用div也能够实现,只是若是使用结构元素的话,那么网页代码的可读性则会大大增强。纯HTML 5结构的网页实例:
2、表单和文件
一、新增元素和属性
在HTML4中,表单内的从属元素必须书写在表单内部,可是在HTML5中,能够把它们书写在页面上任何地方,而后给该元素指定一个form属性,属性值为该表单的id,这样就能够声明该元素从属于指定表单了。
<form id="testform">
<input type="text">
</form>
<textarea form="testform"></textarea>
在HTML4中,一个表单内的全部元素都只能经过表单的action属性统一提交到另外一个页面,而在HTML5中能够给全部的提交按钮,诸如<input type="submit">、
<input type="image">、<button type="submit">都增长不一样的formaction属性
<form id="testform" action="serve.jsp">
<input type="submit" name="s1" value="v1" formation="s1.jsp">提交到S1
<input type="submit" name="s2" value="v2" formation="s2.jsp">提交到S2
<input type="submit" name="s3" value="v3" formation="s3.jsp">提交到S3
<input type="submit">
</form>
PS: 目前尚没有浏览器支持这一属性
placeholder是指当文本框(input、textarea)处于未输入状态时文本框中显示的输入提示。
<input type="text" placeholder="input me"/>
给文本框、选择框或按钮控件加上该属性,当画面打开时,该控件自动得到光标焦点
<input type="text" autofocus/>
在HTML5中,为单行文本框(<input type="text">) 增长了一个list属性,该属性的值为某个datalist元素的id。datalist元素也是HTML5新增的元素,改元素相似于选择框,可是当用户想要设定的值不在选择列表以内时,容许其自行输入。该元素自己并不显示,而是当文本框得到焦点时以提示输入的方式显示。为了不在没有支持该元素的浏览器显示,能够用CSS将其隐藏。
<input type="text" name="greeting" list="greetings"/>
<!--使用style="display:none;" 将datalist元素设定为不显示-->
<datalist id="greetings" style="display:none;">
<option value="Good Morning">Good Morning</option>
<option value="Hello">Hello</option>
<option value="Good Afternoon">Good Afternoon</option>
</datalist>
辅助输入所用的自动完成
<input type="text" name="greeting" list="greetings" autocomplete="on"/>
PS: chrome20不支持
search、tel、url、email等,可参照:
output元素
output元素必须从属于某个表单,也就是说,必须将它书写在表单内部,或者对它添加form属性
<form id="testform">
请选择一个值
<input name="range1" type=range min=0 max=100 step=5/>
<output onforminput="value=range1.value">50</output>
</form>
PS: 目前只有Opera支持得比较好
二、表单验证
2.一、自动验证
<form method="post">
<input name="text" type="text" required pattern="^\w.*$"/>
<input type="submit"/>
</form>
min与max这两个属性是数值类型或日期类型的input元素的专用属性
step属性控制input元素中的值增长或减小时的步幅
2.二、显示验证
form元素与input元素(包括select元素与textarea元素)都具备一个checkValidity方法。调用该方法,能够显示地对表单内全部元素内容或单个元素内容进行有效性验证。checkValidity方法以boolean的形式返回验证结果。
<script language="javascript">
function check(){
var email = document.getElementById("email");
if(email.value==""){
alert("请输入Email地址");
return false;
}...
}
</script>
<form id="testform" onsubmit="return check();">
Email:
<input name="email" type="email" id="email"/><br/>
<input type="submit"/>
</form>
三、加强的页面元素
figure元素用来表示网页上一块独立的内容,能够是图片、统计图或代码示例,甚至是音频插件、视频插件等。figcaption元素表示figure元素的标题,从属figure元素,必须写在figure元素内部。
<figure>
<img src="lufu.jpg" alt="lufu"/>
<img src="lufu2.jpg" alt="lufu"/>
<figcaption>路飞</figcaption>
</figure>
提供了一种替代JavaScript的、将画面上局部区域进行展开或收缩的方法。summary元素从属于details元素,用鼠标点击summary元素中的内容文字时,detail元素中的其余从属元素将会展开或收缩。若是没有summary元素,浏览器也会提供默认的样式。details元素还提供了“open”属性, 使用<details open>,则默认页面加载时就打开details里面的内容。
<details>
<summary>HTML 5</summary>
This document teaches you everything you have to learn about HTML5
</details>
mark元素表示页面中须要突出显示或高亮显示的,通常能够用于显示关键字高亮,或者是与用户相关须要提醒用户的时候使用。
<h1>搜索"<mark>HTML 5</mark>", 找到相关网页约10,200,000篇,用时0.041秒</h1>
<section id="search-results">
<article>
<h2>
<a href="#">专题:<mark>HTML 5 </mark> 下一代web开发标准</a>
</h2>
<p><mark>HTML 5</mark>近十年XXXXXXXXX</p>
</article>
<article>
<h2>
<a href="#">专题:<mark>HTML 5 </mark> 下一代web开发标准</a>
</h2>
<p><mark>HTML 5</mark>近十年XXXXXXXXX</p>
</article>
</section>
PS:mark元素的做用与em元素、strong元素是有区别的,mark元素的标示目的与原文做者无关,而是在后来引用时添加上去的,目的是为了吸引当前用户或者给用户作参考。而em、strong是原文做者用来强调一段文字的重要性添加的。
progress元素表明一个任务的完成进度
meter元素表示规定范围内的数量值
四、文件API
在HTML5中,经过添加multiple属性,file控件内容许一次放置多个文件。控件内的每个用户选择的文件都是一个file对象,而FileList对象则为这些file对象的列表,表明用户选择的全部文件。
<script language=javascript>
function showFileName(){
var file;
for(var i=0; i < document.getElementById("file").files.length; i++){
file = document.getElementById("file").files[i];
alert(file.name + ": 最后一次修改时间" + file.lastModifiedDate);
}
}
</script>
选择文件:
<input type="file" id="file" multiple size="80"/><br/>
<input type="button" onclick="showFileName();" value="show File Name"/>
表示二进制原始数据,它提供了一个slice方法,能够经过该方法访问到字节内部的原始数据块。file对象继承了Blog对象。Blob对象有两个属性,size属性表示一个Blob对象的字节长度,type属性表示Blob的MIME类型,若是未知类型,返回空字符。
HTML5 对file控件添加了accept属性,但目前仅支持图像,其余的设置无效
<input type="file" id="file" multiple size="80" accept="image/*"/>
FileReader接口拥有4个方法,3个用于读取文件(readAsBinaryString、readAsText、readAsDataURL【主要是图片和html文件】),另外一个用来将读取过程当中断(abort)。另外,FileReader接口还提供了一套完整的事件模型。(onabort、onerror、onloadstart、onprogerss、onload、onloadend)
PS: 须要在服务器上运行才有效
<script language=javascript>
var result = document.getElementById("result");
var file = document.getElementById("file");
if(typeof FileReader == 'undefined'){
result.innerHTML = "<p>抱歉,你的浏览器不支持 FileReader</p>";
file.setAttribute('disabled', 'disabled');
}
//将文件以Data URL形式读入页面
function readAsDataURL(){
var file = document.getElementById("file").files[0];
if(file == null){
alert("请选择文件!!");
return false;
}
if(!/image\/\w+/.test(file.type)){
alert("请确保文件为图像类型");
return false;
}
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(e){
var result = document.getElementById("result");
result.innerHTML = '<img src="' + this.result + '" alt=""/>';
}
}
//将文件以二进制形式读入页面
function readAsBinaryString(){
var file = document.getElementById("file").files[0];
if(file == null){
alert("请选择文件!!");
return false;
}
var reader = new FileReader();
reader.readAsBinaryString(file);
reader.onload = function(f){
var result = document.getElementById("result");
result.innerHTML = this.result;
}
}
//将文件以文本形式读入页面
function readAsText(){
var file = document.getElementById("file").files[0];
if(file == null){
alert("请选择文件!!");
return false;
}
var reader = new FileReader();
reader.readAsText(file);
reader.onload = function(f){
var result = document.getElementById("result");
result.innerHTML = this.result;
}
}
</script>
<p>
<label>请选择一个文件: </label>
<input type="file" id="file"/><br/>
<input type="button" value="读取图像" onclick="readAsDataURL();"/>
<input type="button" value="读取二进制数据" onclick="readAsBinaryString();"/>
<input type="button" value="读取文本文件" onclick="readAsText();"/>
</p>
<div name="result" id="result">
</div>
五、拖放API
5.1 操做:
- 将想要拖放的对象元素的draggable属性设为true(draggable="true"),另外,img元素与a元素(必须指定href)默认容许拖放
- 编写与拖放相关的事件处理代码(dragstart、drag、dragenter、dragover、dragleave、drop、dragend)
<script language=javascript>
function init(){
var source = document.getElementById("dragme");
var dest = document.getElementById("text");
//drag start
source.addEventListener("dragstart", function(ev){
var dt = ev.dataTransfer;
//DataTransfer专门用来存放拖放时要携带的数据
dt.effectAllowed = "all";
dt.setData("text/plain", "hello");
}, false);
//drag end
dest.addEventListener("dragend", function(ev){
ev.preventDefault();
}, false);
//drop
dest.addEventListener("drop", function(ev){
var dt = ev.dataTransfer;
var text = dt.getData("text/plain");
dest.textContent += text;
ev.preventDefault();
ev.stopPropagation();
},false);
}
document.ondragover = function(e){e.preventDefault();};
document.ondrop = function(e){e.preventDefault();};
</script>
<body onload="init()">
<h1>simple drag demo</h1>
<div id="dragme" draggable="true" style="width: 200px; border: 1px solid gray;">
please drag
</div>
<div id="text" style="width: 200px; height: 200px; border: 1px solid gray;"></div>
</body>
5.2 DataTransfer对象的属性与方法
如今支持拖动处理的MIME的类型为text/plain、text/html、text/xml、text/uri-list。
若是DataTransfer对象的属性和方法使用得好,能够实现定制拖放图标,让它只支持特定拖放(譬如拷贝/移动)等。
3、绘制图形
一、canvas绘制
首先,要指定ID、width、height三个属性。canvas在页面放置的时候跟其余元素没有太大区别。
<canvas id="canvas" width="400" height="300"/>
绘制步骤:
- 取得canvas元素
- 取得上下文,须要使用canvas对象的getContext方法来得到图形上下文。
- 填充与绘制边框
- 设定绘制样式
- 指定线宽lineWidth
- 指定颜色值
- 绘制矩形
canvas元素绘制图形,通常有两种方式——填充(fill) 与绘制边框 (stroke), 经过filleStyle指定填充样式,strokeStyle指定图形边框样式。fillRect方法和storkeRect方法来填充矩形和绘制矩形边框。
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<title> first canvas demo ### </title>
<script type="text/javascript" src="firstCanvas.js"></script>
</head>
<body onload="draw('canvas')">
<h1>canvas元素实例</h1>
<canvas id="canvas" width="400" height="300"/>
</body>
#########firstCanvas.js######
function draw(id){
var canvas = document.getElementById(id);
if(canvas == null)
return false;
//
if(!!!canvas.getContext){
alert("抱歉,你的浏览器不支持canvas!!");
return false;
}
var context = canvas.getContext('2d');
context.fillStyle="#EEEEFF";
context.fillRect(0, 0, 400, 300);
context.fillStyle = "red";
context.strokeStyle = "blue";
context.lineWidth = 1;
context.fillRect(50, 50, 100, 100);
context.strokeRect(50, 50, 100, 100);
}
另外,还有一个context.clearRect(x, y, width, height)方法, 该方法将擦除指定的矩形区域中的图形,使得矩形区域中的颜色所有变为透明。
二、使用路径
除了长方形或正方形,要画其余的图形,须要使用路径,依然是最开始取得上下文,以后步骤:
- 开始建立路径 context.beginPath()
- 建立图形的路径 context.arc(x, y, radius, startAngle, endAngle, anticlockwise)
- 路径建立完成后,关闭路径 context.closePath()
- 设定绘制样式,调用绘制方法,绘制路径 contex.fillStyle="rgba(255, 0, 0, 0.25)" ;context.fill();
function draw(id){
var canvas = document.getElementById(id);
if(canvas == null)
return false;
//
if(!!!canvas.getContext){
alert("抱歉,你的浏览器不支持canvas!!");
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = '#EEEEFF';
context.fillRect(0, 0, 400, 300);
var n = 0;
for(var i=0; i < 10; i++){
context.beginPath();
context.arc(i*25, i*25, i*10, 0, Math.PI*2, true);
context.closePath();
context.fillStyle = 'rgba(255, 0, 0, 0.25)';
context.fill();
}
}
绘制直线时,通常会用到moveTo与lineTo。moveTo(x, y)方法是将光标移动到指定坐标点,lineTo(x, y)方法在moveTo方法中指定的直线起点与参数中指定的直线终点之间绘制一条线。
function draw(id){
var canvas = document.getElementById(id);
if(canvas == null)
return false;
//
if(!!!canvas.getContext){
alert("抱歉,你的浏览器不支持canvas!!");
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = '#EEEEFF';
context.fillRect(0, 0, 400, 300);
var n = 0;
var dx = 150;
var dy = 150;
var s = 100;
context.beginPath();
context.fillStyle = 'rgb(100, 255, 100)';
context.strokeStyle = 'rgb(0, 0, 100)';
var x = Math.sin(0);
var y = Math.cos(0);
var dig = Math.PI / 15 * 11;
for(var i=0; i < 30; i++){
var x = Math.sin(i * dig);
var y = Math.cos(i * dig);
context.lineTo(dx + x * s, dy + y * s);
}
context.closePath();
context.fill();
context.stroke();
}
三、绘制渐变图形
3.1 线性渐变
绘制线性渐变时,须要用到LinearGradient对象。使用图形上下文对象的createLinearGradient方法建立该对象:
context.createLinearGradient(xStart, yStart, xEnd, yEnd),xStart为渐变起始地点的横坐标,yStart为渐变起始地点的纵坐标,xEnd为渐变结束点的横坐标,yEnd为渐变结束点的纵坐标。
在LinearGradient对象后,使用addColorStop方法进行渐变的颜色设定:
context.addColorStop(offset, color), offset为所设定的颜色离开渐变起始点的偏移量。该参数的值是一个范围在0到1之间的浮点值。由于是渐变,须要至少使用两次addColorStop方法以追加两个颜色(开始颜色与结束颜色),能够追加多个颜色。例如“从蓝色渐变到白色,而后渐变到绿色”。
以后把fillStyle设定为LinearGradient对象,而后执行填充的方法,就能够绘制出渐变图形。
function draw(id){
var canvas = document.getElementById(id);
if(canvas == null)
return false;
//
if(!!!canvas.getContext){
alert("抱歉,你的浏览器不支持canvas!!");
return false;
}
var context = canvas.getContext('2d');
var g1 = context.createLinearGradient(0, 0, 0, 300);
g1.addColorStop(0, 'rgb(255, 255, 0)');
g1.addColorStop(1, 'rgb(0, 255, 255)');
context.fillStyle = g1;
context.fillRect(0, 0, 400, 300);
var n = 0;
var g2 = context.createLinearGradient(0, 0, 300, 0);
g2.addColorStop(0, 'rgba(0, 0, 255, 0.5)');
g2.addColorStop(1, 'rgba(255, 0, 0, 0.5)');
for(var i=0; i < 10; i++){
context.beginPath();
context.fillStyle = g2;
context.arc(i * 25, i * 25, i * 10, 0, Math.PI * 2, true);
context.closePath();
context.fill();
}
}
3.2 径向渐变
径向渐变指沿着圆形的半径方向向外进行扩散的渐变方式,方法定义以下:
context.createRadialGradient(xStart, yStart, radiusStart, xEnd, yEnd, radiusEnd),xStart为渐变开始圆的圆心横坐标,yStart为渐变开始圆的圆心纵坐标,radiusStart为开始圆的半径,xEnd为渐变结束圆的圆心横坐标,yEnd为渐变结束圆的圆心纵坐标,radiusEnd为结束圆的半径。分别指定了两个圆的大小与位置,从第一个圆的圆心处向外进行扩散渐变,一直扩散到第二圆的外轮廓处。
function draw(id){
var canvas = document.getElementById(id);
if(canvas == null)
return false;
//
if(!!!canvas.getContext){
alert("抱歉,你的浏览器不支持canvas!!");
return false;
}
var context = canvas.getContext('2d');
var g1 = context.createRadialGradient(400, 0, 0, 400, 0, 400);
g1.addColorStop(0.1, 'rgb(255, 255, 0)');
g1.addColorStop(0.3, 'rgb(255, 0, 255)');
g1.addColorStop(1, 'rgb(0, 255, 255)');
context.fillStyle = g1;
context.fillRect(0, 0, 400, 300);
var n = 0;
var g2 = context.createLinearGradient(250, 250, 0, 250, 250, 300);
g2.addColorStop(0.1, 'rgba(255, 0, 0, 0.5)');
g2.addColorStop(0.7, 'rgba(255, 255, 0, 0.5)');
g2.addColorStop(1, 'rgba(0, 0, 255, 0.5)');
for(var i=0; i < 10; i++){
context.beginPath();
context.fillStyle = g2;
context.arc(i * 25, i * 25, i * 10, 0, Math.PI * 2, true);
context.closePath();
context.fill();
}
}
四、绘制变形图形
4.1 坐标变换
context.translate(x, y); x表示将坐标轴原点向左移动多少个单位,默认状况下为像素;y表示将坐标轴原点向下移动多少个单位。
context.scale(x, y); x是水平方向的放大倍数,y是垂直方向的放大倍数,若是是缩写,能够填入0到1之间的小数。
context.rotate(angle); angle指旋转的角度,旋转的中心点是坐标轴的原点,旋转是以顺时针进行的,要想逆时针旋转,则把angle设为负数
function draw(id){
var canvas = document.getElementById(id);
if(canvas == null)
return false;
//
if(!!!canvas.getContext){
alert("抱歉,你的浏览器不支持canvas!!");
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = '#EEEEFF';
context.fillRect(0, 0, 400, 300);
//绘制图形
context.translate(200, 50);
context.fillStyle = 'rgba(255, 0, 0, 0.25)';
for(var i=0; i < 50; i++){
context.translate(25, 25);
context.scale(0.95, 0.95);
context.rotate(Math.PI/10);
//画矩形
context.fillRect(0, 0, 100, 50);
}
}
4.2 坐标变换与路径的结合使用
function draw(id){
var canvas = document.getElementById(id);
if(canvas == null)
return false;
//
if(!!!canvas.getContext){
alert("抱歉,你的浏览器不支持canvas!!");
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = '#EEEEFF';
context.fillRect(0, 0, 400, 300);
//绘制图形
context.translate(200, 50);
context.fillStyle = 'rgba(255, 0, 0, 0.25)';
for(var i=0; i < 50; i++){
context.translate(25, 25);
context.scale(0.95, 0.95);
context.rotate(Math.PI/10);
//画复杂图形
create5Star(context);
context.fill();
}
}
function create5Star(context){
var n = 0;
var dx = 100;
var dy = 0;
var s = 50;
//建立路径
context.beginPath();
context.fillStyle = 'rgba(255, 0 ,0 , 0.5)';
var x = Math.sin(0);
var y = Math.cos(0);
var dig = Math.PI/5 * 4;
for(var i=0; i < 5; i++){
var x = Math.sin(i * dig);
var y = Math.cos(i * dig);
context.lineTo(dx + x * s, dy + y * s);
}
}
4.3 矩阵变换
变换矩阵是专门用来实现图形变形的,它与坐标一块儿配合使用,以达到变形的目的。当图形上下文被建立完毕时,事实上也建立了一个默认的变换矩阵,若是不对这个变换矩阵进行修改,那么接下来绘制的图形将以画布的最左上角为坐标原点绘制图形,绘制出来的图形也不通过缩放、变形的处理,但若是对这个变换矩阵进行修改,那么状况就彻底不同了。
context.transform(m11, m12, m21, m22, dx, dy);
PS: transform须要必定的矩阵知识,比较难理解。
function draw(id){
var canvas = document.getElementById(id);
if(canvas == null)
return false;
//
if(!!!canvas.getContext){
alert("抱歉,你的浏览器不支持canvas!!");
return false;
}
var context = canvas.getContext('2d');
var colors = ['red', 'orange', 'yellow', 'green', 'blue', 'navy', 'purple'];
context.lineWidth = 10;
context.transform(1, 0 , 0 , 1, 100, 0);
for(var i=0; i < colors.length; i++){
context.transform(1, 0, 0, 1, 0, 10);
context.strokeStyle = colors[i];
context.beginPath();
context.arc(50, 100, 100, 0, Math.PI, true);
context.stroke();
}
}
4.4 图形组合
使用上下文对象的globalCompositeOperation属性能决定图形的组合方式,使用方法以下:
context.globalCompositeOperation=type
type的值必须是下面几种字符串之一:
- source-over(默认) 新建立的图形覆盖到原有图形之上
- destination-over 表示原有图形之下绘制新图形
- source-in 新图形与原有图形作in运算,只显示重叠部分,新旧图形其余部分变成透明
- destination-in 原有图形与新图形作in运算,只显示原有图形中与新图形重叠部分,其余部分透明
- source-out 新图形与原有图形作out运算,只显示新图形中与原有图形不重叠部分,其余部分透明
- destination-out 原有图形和新图形作out运算,只显示原有图形中与新图形不重叠的部分,其余部分透明
- source-atop 只绘制新图形中与原有图形重叠的部分与未被重叠覆盖的原有图形,新图形的其余部分透明
- destination-atop 只绘制原有图形中被新图形重叠的部分与新图形的其余部分,原有图形中的其余部门透明
- lighter 原有图形与新图形均绘制,重叠部分作加色处理
- xor 只绘制新图形中与原有图形不重叠的部分,重叠部分变成透明
- copy 只绘制新图形,原有图形中未与新图形重叠的部分变成透明
若是指定的type不在这几个字符串当中,则按默认方式组合图形。
function draw(id){
var canvas = document.getElementById(id);
if(canvas == null)
return false;
//
if(!!!canvas.getContext){
alert("抱歉,你的浏览器不支持canvas!!");
return false;
}
var context = canvas.getContext('2d');
var oprtns = new Array(
"source-atop",
"source-in",
"source-out",
"source-over",
"destination-atop",
"destination-in",
"destination-out",
"destination-over",
"lighter",
"copy",
"xor"
);
i=8;
context.fillStyle = "blue";
context.fillRect(10, 10, 60, 60);
context.globalCompositeOperation = oprtns[i];
context.beginPath();
context.fillStyle = "red";
context.arc(60, 60, 30, 0, Math.PI*2, false);
context.fill();
}
4.5 给图形绘制阴影
使用Canvas元素给添加阴影效果时,只需利用图形上下文对象的几个关于阴影绘制的属性就能够了,以下:
shadowOffsetX —— 阴影的横向位移量
shadowOffsetY —— 阴影的纵向位移量
shadowColor —— 阴影的颜色
shadowBlur —— 阴影的模糊范围
function draw(id){
var canvas = document.getElementById(id);
if(canvas == null)
return false;
//
if(!!!canvas.getContext){
alert("抱歉,你的浏览器不支持canvas!!");
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = '#EEEEFF';
context.fillRect(0, 0, 400, 300);
//阴影参数
context.shadowOffsetX = 10;
context.shadowOffsetY = 10;
context.shadowColor = 'rgba(100, 100, 100, 0.5)';
context.shadowBlur = 7.5;
//绘制图形
context.translate(0, 50);
for(var i=0; i < 3; i++){
context.translate(50, 50);
if(i == 2){
context.shadowColor = 'rgba(0, 0, 0, 0)';
}
create5Star(context);
context.fill();
}
}
shadowBlur属性可选,它表示图形阴影边缘的模糊范围。若是不但愿阴影的边缘太清晰,能够设定该属性值。可是必须大于0,不然会被忽略。通常设定在0至10之间。
若是不想每一个图形具备阴影效果,能够在绘制绘制的时候,设置shadowColor为rgba(0, 0, 0, 0)。
4.6 使用图像
4.6.1 绘制图像
CanvasAPI不只能够绘制图形,还能够读取磁盘或网络中的图像文件,而后使用CanvasAPI将该图像绘制在画布中。
绘制图像时,须要使用drawImage方法,定义以下:
- context.drawImage(image, x, y);
- context.drawImage(image, x, y, w, h);
- context.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);
第一个方法:image能够是img元素、video元素或者JS中的Image对象,xy为绘制该图像在画布中的起始坐标
第二个方法: 前三个参数与上面的一致,w、h是指绘制图像的宽度与高度
第三个方法: image和第一个方法同样,sx、sy、sw、sh表示复制图像的起点宽高,dx、dy、dw、dh表示复制到画布的起点宽高,该方法能够用于剪切图像,或者缩放图像。
由于设定好Image对象的src属性后,不必定就马上显示图像,因此建议:
image.onload = function(){绘制图像函数}
在Image对象的onload事件中同步执行绘制图像的函数,就能够一边装载一边绘制
function draw(id){
var canvas = document.getElementById(id);
if(canvas == null)
return false;
//
if(!!!canvas.getContext){
alert("抱歉,你的浏览器不支持canvas!!");
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = '#EEEEFF';
context.fillRect(0, 0, 400, 300);
image = new Image();
image.src = 'lufu.jpg';
image.onload = function(){
drawImg(context, image);
}
}
function drawImg(context, image){
for(var i=0; i < 7; i++){
context.drawImage(image, 0 + i * 50, 0 + i * 25, 100, 100);
}
}
//######## 局部方法Demo
function drawImg(context, image){
var i = 0;
context.drawImage(image, 0, 0, 100, 100);
context.drawImage(image, 23, 5, 57, 80, 110, 0, 100, 100);
}
4.6.2 图像平铺
图像平铺有两种方法,一种就是上面的drawImage:
function drawImg(canvas, context, image){
//平铺比例
var scale = 2;
//缩小后图像宽度
var n1 = image.width/scale;
var n2 = image.height/scale;
//平铺横向个数
var n3 = canvas.width/n1;
var n4 = canvas.width/n2;
for(var i=0; i < n3; i++)
for(var j=0; j < n4; j++)
context.drawImage(image, i*n1, j*n2, n1, n2);
}
可是该方法比较复杂,HTML 5提供了一个更简便的方法,利用上下文对象的createPattern,以下:
context.createPattern(iamge, type);
image为平铺的图像,type参数的值必须为下面的字符串之一:
- no-repeat: 不平铺
- repeat-x: 横向平铺
- repeat-y: 纵向平铺
- repeat: 全方向平铺
建立image对象并制定图像文件以后,使用createPattern方法建立填充样式,而后将该样式制定给图形上下文对象的fillStyle属性。
var context = canvas.getContext('2d');
image = new Image();
image.src = 'pig.gif';
image.onload = function(){
var ptrn = context.createPattern(image, 'repeat');
//填充样式
context.fillStyle = ptrn;
context.fillRect(0, 0, 400, 300);
}
4.6.2 图像裁剪
Canvas API的图像裁剪功能是指,在画布内使用路径,只绘制该路径所包括区域内的图像,不绘制路径外部的图像。首先建立好路径,以后调用上下文的clip方法设置裁剪区域。
function draw(id){
var canvas = document.getElementById(id);
if(canvas == null)
return false;
//
if(!!!canvas.getContext){
alert("抱歉,你的浏览器不支持canvas!!");
return false;
}
var context = canvas.getContext('2d');
var gr = context.createLinearGradient(0, 400, 300, 0);
gr.addColorStop(0, 'rgb(255, 255, 0)');
gr.addColorStop(1, 'rgb(0, 255, 255)');
context.fillStyle = gr;
context.fillRect(0, 0, 400, 300);
iamge = new Image();
image.onload = function(){
drawImg(context, image);
}
image.src = 'lufu.jpg';
function drawImg(context, image){
create5StarClip(context);
context.drawImage(image, -50, -150, 300, 300);
}
function create5StarClip(context){
var n = 0;
var dx = 100;
var dy = 0;
var s = 150;
//建立路径
context.beginPath();
context.translate(100, 150);
var x = Math.sin(0);
var y = Math.cos(0);
var dig = Math.PI/5 * 4;
for(var i=0; i < 5; i++){
var x = Math.sin(i * dig);
var y = Math.cos(i * dig);
context.lineTo(dx + x * s, dy + y * s);
}
context.clip();
}
裁剪区域一旦设置好以后,后面绘制的全部图片就均可以使用这个裁剪区域,若是须要取消裁剪区域,那就须要使用绘制状态的保存与恢复功能。这两个功能保存与恢复图形上下文的临时状态。在设置图像裁剪区域时,首先调用save方法保存图像上下文的当前状态,在绘制完通过裁剪的图像后,在调用restore恢复以前保存的图形上下文的状态。
4.6.3 像素处理(chrome不支持,opera和FF支持)
使用Canvas API 可以获取图像中的每个像素,而后获得该像素颜色的rgb值或rgba值。使用上下文的getImageData方法来获取图像中的像素,定义以下:
var imagedata = context.getImageData(sx, sy, sw, sh);
sx、sy、sw、sh分别指起点和宽高,imagedata变量是一个CanvasPixelArray对象,具备height,width,data等属性。data属性是一个保存像素数据的数组,内容相似“[r1,g1,b1,a1,r2,g2,b2,a2,r3,g3,b3,a3,....]”。
context.putImageData(imagedata, dx, dy[,dirtyX,dirtyY,dirtyWidth,dirtyHeight ]);
putImageData 能够传入3个或者7个参数,dx, dy 表示重绘图像的起点横坐标,起点纵坐标,dirtyX、Y.... 则为起点的坐标和宽高
function draw(id){
var canvas=document.getElementById(id);
if(canvas==null){
return false;
}
var context=canvas.getContext('2d');
image=new Image();
image.src="lufu.jpg";
image.onload=function(){
context.drawImage(image,0,0);
var imagedata=context.getImageData(0,0,image.width,image.height);
for(var i=0,n=imagedata.data.length;i<n;i+=4){
imagedata.data[i+0]=255-imagedata.data[i+0];
imagedata.data[i+1]=255-imagedata.data[i+2];
imagedata.data[i+2]=255-imagedata.data[i+1];
}
context.putImageData(imagedata, 0, 0);
//context.putImageData(imagedata,30,30,10, 10, 50, 50);
};
}
4.7 绘制文字
在HTML 5中,Canvas也能够绘制文字,使用fillText方法或strokeText方法。fillText方法用填充方式绘制字符串,filleText(text, x, y, [maxWidth]);,第四个是可选参数,表示显示文字是的最大宽度,防止文字溢出。
strokeText(text, x, y, [maxWidth]);用轮廓的方式绘制字符串。
在绘制以前,要对一些属性进行设置:
- font属性:设置文字字体
- textAlign属性: 设置文字水平对齐方式,属性值能够为start、end、left、right、center。默认值为start
- textBaseline属性:设置文字垂直对齐方式,属性值能够为top、hanging、middle、alphabetic、ideographic、bottom。默认值为alphabetic
meatureText方法能够获得文字的宽度, metrics = context.meatrueText(text)
function draw(id){
var canvas = document.getElementById(id);
if(canvas == null)
return false;
//
if(!!!canvas.getContext){
alert("抱歉,你的浏览器不支持canvas!!");
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = '#00f';
context.font = 'italic 20px sans-serif';
var txt = '字符串的宽度为';
var tm1 = context.measureText(txt);
context.fillText (txt, 10, 30);
context.fillText(tm1.width, tm1.width + 10, 30);
context.font = 'bold 30px sans-serif';
var tm2 = context.measureText(txt);
context.fillText (txt, 10, 30);
context.fillText(tm2.width, tm2.width + 10, 30);
}
4.8 绘制文字
4.8.1 save和restore
以前提过若是裁剪样式定了以后,以后都会居于裁剪样式进行绘图,可是以后可能不要,那么能够采用save当前在状态,而后绘制了裁剪图片以后,能够restore回来。
var x, y;
for(var j=1; j < 50; j++){
ctx.save();
ctx.fillStyle = '#fff';
x = 75 - Math.floor(Math.random() * 150);
y = 75 - Math.floor(Math.random() * 150);
ctx.translate(x, y);
drawStar(ctx, Math.floor(Math.random() * 4) + 2);
ctx.restore();
}
4.8.2 保存文件
Canvas API也提供了保存文件的功能,Canvas API保存文件的原理其实是把当前的绘画状态输出到一个data URL地址所指向的数据中的过程,所谓data URL,是指目前大多数浏览器可以识别的一种base64位编码的URL,主要用于小型的、能够在网页中直接嵌入,而不须要从外部文件嵌入的数据,譬如img元素中的图像文件等。
Canvas API 使用toDataURL方法把绘画状态输出到一个data URL中,而后从新装载,客户可直接把装载后的文件进行保存。
canvas.toDataURL(type); 该方法使用一个参数type,表示要输出数据的MIME类型。
function draw(id){
var canvas = document.getElementById(id);
if(canvas == null)
return false;
//
if(!!!canvas.getContext){
alert("抱歉,你的浏览器不支持canvas!!");
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = 'rgb(0, 0, 255)';
context.fillRect(0, 0, 400, 300);
context.fillStyle = 'rgb(255, 255, 0)';
context.fillRect(10, 20, 50, 50);
window.location = canvas.toDataURL('image/jpeg');
}
4.8.2 简单动画制做
实际上就是不断擦除、重绘、擦除、重绘的过程,具体步骤以下:
预先编写好用来绘图的函数,在该函数中先用clearRect方法将画布总体或局部擦除。
使用setInterval方法设置动画的间隔时间
var context;
var width, height;
var i;
function draw(id){
var canvas = document.getElementById(id);
if(canvas == null)
return false;
//
if(!!!canvas.getContext){
alert("抱歉,你的浏览器不支持canvas!!");
return false;
}
context = canvas.getContext('2d');
width = canvas.width;
height = canvas.height;
i=0;
setInterval(rorate, 100);
}
function rorate(){
context.clearRect(0, 0, width, height);
context.fillStyle = 'red';
context.fillRect(i, 0, 20, 20);
i = i + 20;
if(i == 400){
i = 0;
}
}
4、多媒体播放
HTML 5提供了两个新元素 —— video元素与audio元素,其中video元素专门用来播放网络上的视频或电影,而audio元素专门用来播放网络上的音频数据。
PS: 记得加controls="controls",否则不显示播放控件,默认不会自动播放歌曲
另外,能够经过source元素来为同一个媒体数据指定多个播放格式与编码格式,以确保浏览器能够从中选择一种本身支持的播放格式进行播放,浏览器的选择顺序为代码中的书写顺序,它会从上往下判断本身对该播放格式是否支持。
<video controls="controls">
<source src="sample.ogv" type="video/ogg; codecs='theora, vorbis'">
<source src="sample.mov" type="video/quicktime">
</video>
type表示媒体类型,其属性值为播放文件的MIME类型,该属性中的codecs参数表示所使用的媒体的编码格式。
一、属性
- src 指定媒体数据的URL地址
- autoplay 指定媒体是否在页面加载后自动播放(IOS不支持),<video src="ddd.mov" autoplay></video>
- preload 指定视频或音频数据是否预加载。该属性有三个可选择的值,none、metadata与auto,默认值为auto
-
- none表示不行预加载
- metadata表示只预加载媒体的元数据(媒体字节数,第一帧,播放列表、持续时间等)。
- auto表示预加载所有视频或音频
- poster(video独有) 当视频不可用时,可使用该元素向用户展现一幅替代图片,<video src="ddd.mov" poster="cannotuse.jpg"></video>
- loop 指定是否循环播放
- controls 指定是否为视频或音频添加浏览器自带的播放用的控制条 <video src="sample.mov" controls></video>,固然也能够自定义
- width与height(video独有)
- error属性 若是在媒体播放出问题时,error属性将返回一个MediaError对象,该对象的code返回对应的错误状态,错误状态共有4个值:
-
- MEDIA_ERR_ABORTED(数字值为1): 下载过程因为用户的操做缘由而被终止
- MEDIA_ERR_NETWORK(数字值2):确认资源可用,可是在下载时出现网络错误,下载过程被终止
- MEDIA_ERR_DECODE(数字值3):确认资源可用,解码时发生错误
- MEDIA_ERR_SRC_NOT_SUPPORTED(数字值4):媒体资源不可用媒体格式不被支持
error属性为只读属性
var video = document.getElementById("videoElement");
video.addEventListener("error", function(){
var error = video.error;
...
}
- networkState属性 在媒体数据加载过程当中可使用video元素或audio元素的networkState属性读取当前网络状态,共有4个值:
-
- NETWORK_EMPTY(数字值为0):元素处于初始状态
- NETWORK_IDLE(数字值1):浏览器已选择好用什么编码格式来播放媒体,但还没有创建网络链接
- NETWORK_LOADING(数字值2):媒体加载中
- NETWORK_NO_SOURCE(数字值为3):没有支持的编码格式
var video = document.getElementById("videoElement");
video.addEventListener("progress", function(e){
var networkStateDisplay = document.getElementById("networkState");
if(video.networkState == 2){
//
}
.....
}
- currentSrc属性 读取URL地址: video/audio.currentSrc
- buffered属性 可使用video元素或audio元素的buffered属性来返回一个对象,该对象实现TimeRanges接口,以确认浏览器是否已缓存媒体数据。
- readyState属性 返回媒体当前播放位置的就绪状态,共5个值:
-
- HAVE_NOTHING(数字值为0):没有获取到媒体的任何信息,当前播放位置没有可播放数据
- HAVE_METADATA(数字值为1):获取到的媒体数据无效,不能播放
- HAVE_CURRENT_DATA(数字值为2):当前媒体位置已经有数据能够播放,但没有获取到可让播放器前进的数据。
- HAVE_FUTURE_DATA(数字值为3):当前媒体位置已经有数据能够播放,获取到可让播放器前进的数据。
- HAVE_ENOUGH_DATA(数字值为4):当前媒体位置已经有数据能够播放,获取到可让播放器前进的数据,并且加载速度能够确保媒体顺利播放
- seeking属性与seekable属性 seeking属性能够返回一个布尔值,表示浏览器是否正在请求某一个特定播放位置的数据,seekable属性返回一个TimeRanges对象,
- currentTime属性、startTime属性与duration属性 currentTime当前播放位置,能够经过修改currentTime属性来修改当前播放位置。startTime开始时间,一般为0。duration总的播放时间
- played属性、paused属性、ended属性
- defaultPlaybackRate属性与playbackRate属性 播放速率
- volume属性与muted属性 播放音量,0到1,1为最大,muted表示静音状态,布尔值。
二、方法
- play方法 将元素的paused属性的值变为false
- pause方法 使用pause方法来暂停播放,自动将元素的paused属性的值变为true
- load方法 使用load方法来从新载入媒体进行播放
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>video first Demo #######</title>
<script>
var video;
function init(){
video = document.getElementById("video1");
video.addEventListener("ended", function(){
alert("播放结束");
}, true);
video.addEventListener("error", function(){
switch(video.error.code){
case MediaError.MEDIA_ERROR_ABORTED:
alert("视频的下载过程被停止");
break;
case MediaError.MEDIA_ERROR_NETWORK:
alert("网络发生故障,视频的下载过程被停止");
break;
case MediaError.MEDIA_ERROR_DECODE:
alert("解码失败");
break;
case MediaError.MEDIA_ERROR_SRC_NOT_SUPPORTED:
alert("不支持的视频播放格式");
break;
default:
alert("未知错误");
}
}, false);
}
function play(){
video.play();
}
function pause(){
video.pause();
}
function next(){
if(video.src.indexOf("ren") > 0){
video.src = "KW7142.mp4";
}else{
video.src = "chonglangnanren.mp4";
}
}
</script>
</head>
<body onload="init()">
<video src="chonglangnanren.mp4" width="320" height="240" id="video1">
Your browser does not support the vedio element.
</video><br/>
<button onclick="play();">播放</button>
<button onclick="pause();">暂停</button>
<button onclick="next();">下一首</button>
</body>
</html>
- canPlayType 测试浏览器是否支持指定的媒体类型
var support = videoElement.canPlayType(type);
type值是MIME类型,与source元素的type参数同样,该方法返回3个可能值:空字符,表示浏览器不支持;maybe,表示浏览器可能支持;probably,表示浏览器肯定该类型。
PS:addEventListener,若是capture,两个嵌套元素同一个事件发生从外元素开始触发,若是bubbing,则内元素开始触发
三、事件
3.1 事件介绍
- loadstart 浏览器开始在网上寻找媒体数据
- progress 浏览器正在获取媒体数据
- suspend 浏览器暂停获取媒体数据,可是下载过程并无结束
- abort 浏览器在下载彻底部媒体数据以前停止获取媒体数据,可是并非有错误引发
- error 获取媒体数据过程当中出错
- emptied video元素或audio元素所在网络忽然变为未初始化状态,可能的缘由有两个:
-
- 载入媒体过程当中忽然发生一个致命错误
- 在浏览器正在选择支持的播放格式时,又调用了load方法从新载入媒体
- stalled 浏览器尝试获取媒体数据失败
- play 即将开始播放,当执行了play方法时触发,或数据下载后元素被设为autoplay属性
- pause 播放暂停,当执行了pause方法时触发
loadedmetadata 浏览器获取完毕媒体的时间长和字节数
loadeddata 浏览器加载完毕当前播放位置的媒体数据,准备播放
waiting 播放过程犹豫的得不到下一帧而暂停播放,但很快就可以获得下一帧
playing 正在播放
canplay 浏览器可以播放媒体,但估计以当前播放速率不能直接将媒体播放完毕
canplaythrough 浏览器可以播放媒体,当前播放速率能直接将媒体播放完毕
seeking seeking属性变为true,浏览器正在请求数据
seeked seeking属性变为false,浏览器中止请求数据
timeupdate 当前播放位置被改变,多是播放过程当中的天然改变,也多是被认为地改变,或因为播放不能连续而发生的跳变
ended 播放结束后中止播放
ratechange defaultplaybackRate属性或playbackRate属性被改变
durationchange 播放时长被改变
volumechange volume属性被改变或muted属性被改变
5、本地存储
一、WebStorage
webstorage 分sessionStorage和localstorage,sessionStorage是临时保存,localStorage是永久保存。sessionStorage若是浏览器关闭了,数据就没有了,而localStorage则不会。基本使用方法:
sessionStorage:
保存数据 sessionStorage.setItem(key, value);
读取数据 sessionStorage.getItem(key);
localStorage:
保存数据 localStorage.setItem(key, value);
读取数据 localStorage.getItem(key);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Web Storage示例</title>
<script type="text/javascript" src="webStorage.js"></script>
</head>
<body>
<h1>Web Storage 示例</h1>
<p id="msg"></p>
<input type="text" id="input">
<button onclick="saveStorage('input');">保存数据</button>
<button onclick="loadStorage('msg');">读取数据</button>
</body>
</html>
function saveStorage(id){
var target = document.getElementById(id);
var str = target.value;
sessionStorage.setItem("message", str);
}
function loadStorage(id){
var target = document.getElementById(id);
var msg = sessionStorage.getItem("message");
target.innerHTML = msg;
}
若是使用得好,也可将webStorage做为一个简易的数据库,键的值采用JSON字符串就能够。固然这只是能够实现,运用的时候,webStorage的空间仍是很珍贵的,通常大多数浏览器都只提供5M左右的空间。
2、本地数据库
HTML 5的本地数据库就是“SQLLite”文件型的SQL数据库,首先使用openDatabase方法来建立一个访问数据库的对象。该方法的使用以下:
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);
第一个参数是数据库名称,第二个参数为版本号,第三个参数为数据库的描述,第四个参数为数据库的大小。该方法返回建立后的数据库访问对象,若是该数据库不存在,则建立该数据库。实际访问数据库的时候,还须要调用transaction方法,用来执行事务处理,防止在对数据库操做的时候受外界打扰,组织别的用户操做数据库。
db.transaction(function (tx){
tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS(id unique, Log)');
});
transaction使用一个回调函数为参数,这个函数中,执行访问数据库的语句。函数里面tx其实就是SQLTransaction(事务),这个事务只有一个
executeSql方法。
executeSql(sqlQuery, [], dataHandler, errorHandler);
第一个参数是执行的语句,第二个是执行语句里面的参数,dataHandler成功执行返回处理,包含两个参数tx,rs(结果集),errorHandler也包含两个参数tx,error(错误信息)。
<!DOCTYPE HTML>
<HTML>
<HEAD>
<TITLE> HTML 5 SQLLite </TITLE>
<META charset="utf-8">
<SCRIPT type="text/javascript" src="webDB.js"></SCRIPT>
</HEAD>
<BODY onload="init();">
<h1>使用数据库实现web留言板</h1>
<table>
<tr><td>姓名:</td><td><input type="text" id="name"/></td></tr>
<tr><td>留言:</td><td><input type="text" id="memo"/></td></tr>
<tr><td colspan="2"><button onclick="saveData();">保存</button></td></tr>
</table>
<!--建立一条水平线。 水平分隔线-->
<hr/>
<table id="datatable" border="1"></table>
<p id="msg"></p>
<button onclick="deleteAllData();">删除全部数据</button>
</BODY>
</HTML>
JS:
var datatable = null;
var db = openDatabase("MyData", "", "My Database", 1024 * 1024);
function init(){
datatable = document.getElementById("datatable");
showAllData();
}
function removeAllData(){
for(var i=datatable.childNodes.length - 1; i>=0; i--){
datatable.removeChild(datatable.childNodes[i]);
}
var tr = document.createElement('tr');
var th1 = document.createElement('th');
var th2 = document.createElement('th');
var th3 = document.createElement('th');
th1.innerHTML = '姓名';
th2.innerHTML = '留言';
th3.innerHTML = '时间';
tr.appendChild(th1);
tr.appendChild(th2);
tr.appendChild(th3);
datatable.appendChild(tr);
}
function showData(row){
var tr = document.createElement('tr');
var td1 = document.createElement('td');
td1.innerHTML = row.name;
var td2 = document.createElement('td');
td2.innerHTML = row.message;
var td3 = document.createElement('td');
var t = new Date();
td3.innerHTML = t.toLocaleDateString() + " " + t.toLocaleTimeString();
tr.appendChild(td1);
tr.appendChild(td2);
tr.appendChild(td3);
datatable.appendChild(tr);
}
function showAllData(){
db.transaction(function(tx){
tx.executeSql("CREATE TABLE IF NOT EXISTS MsgData(name TEXT, message TEXT, time INTEGER)", []);
tx.executeSql("SELECT * FROM MsgData", [], function(tx, rs){
removeAllData();
for(var i=0; i < rs.rows.length; i++){
showData(rs.rows.item(i));
}
});
});
}
function addData(name, message, time){
db.transaction(function(tx){
tx.executeSql('INSERT INTO MsgData VALUES(?, ?, ?)'
, [name, message, time], function(tx, rs){
alert("保存数据成功!!");
}, function(tx, error){
alert(error.source + "::" + error.message);
}
);
});
}
function saveData(){
var name = document.getElementById("name").value;
var memo = document.getElementById("memo").value;
var time = new Date().getTime();
addData(name, memo, time);
showAllData();
}
function deleteAllData(){
db.transaction(function(tx){
tx.executeSql('DELETE FROM MsgData'
, [], function(tx, rs){
alert("删除数据成功!!");
}, function(tx, error){
alert(error.source + "::" + error.message);
}
);
});
showAllData();
}
另外,在chrome里面Web Storage能够经过清理缓存什么的清除,可是SQLLite不能够,也不可使用“drop database dbName”语句清除数据库,由于SQLLite归根结底只是一个嵌入的数据库,是一个文件,要到Chrome/User Data里面去删除文件。
6、离线Web应用
HTML 5提供了本地缓存,能够Web应用离线的状况下依然可使用。
Web应用程序的本地缓存是经过每一个页面的manifest文件来管理的。manifest文件是一个简单文本文件,在该文件以清单的形式列举须要缓存和不须要缓存的资源文件的名字,以及这些资源文件的访问路径。能够为每一个页面指定一个manifest文件,也能够为整个应用指定一个manifest文件。
CACHE MANIFEST
#文件的开头必需要书写CACHE MANIFEST
#这个manifest文件的版本号
#version 7
CACHE:
other.html
hello.js
images/myphoto.jpg
NETWORK:
http://localhost/NotOffline
NotOffline.php
*
FALLBACK:
online.js locale.js
CACHE:
newhello.html
newhello.js
在manifest文件中,第一行必须是“CACHE MANIFEST”文字,以把本文件的做用告知给浏览器。同时,真正运行或测试离线Web应用程序的时候,
须要对服务器进行配置,让服务器支持text/cache-manifest这个MIME类型(text/cache-manifest)。例如Apache服务器进行配置的时候,须要找到{apache_home}/conf/mine.types这个文件,并在文件最后添加一行代码:
text/cache-manifest manifest
而在tomcat里面的配置则以下:
在 tomcat根目录 -> conf -> web.xml 中的<web-app>内添加html5
<
extension
>manifest</
extension
>
<
mime-type
>text/cache-manifest</
mime-type
>
</
mime-mapping
>
在指定资源文件的时候,能够把资源文件分为三类:分别是CACHE、NETWORK、FALLBACK。在CHACHE类别中指定须要被缓存在本地的资源文件。NETWORK类别为显示指定不进行本地缓存的资源文件。“*”为通配符,表示没有在本manifest文件中指定的资源文件都不进行本地缓存。FALLBACK类别中的每行中指定两个资源文件,第一个资源文件为可以在线访问时使用的文件,第二个为为不能联网时使用的资源文件。
容许在同一个manifest文件中重复书写同一个类别。
为了让浏览器可以正常阅读该文本文件,须要在Web应用程序页面上的html标签的manifest属性由指定manifest文件的URL地址。指定方法以下:
<html manifest="hello.manifest">
...
</html>
浏览器在与服务器交互时,会检查manifest文件是否更改,若是更改,则会根据manifest的要求把资源文件缓存。缓存以后,会触发applicationCache
对象的updateready事件:
applicationCache.addEventListener( "updateready",function(){
alert("本地缓存已经更新,请刷新页面查看最新应用!");
});
PS:
资源文件修改了,若是manifest文件没有修改,缓存页面是不会更新的,也就是用户不会看到最新的应用,若是你对缓存的要求没有修改,那么能够经过
修改manifest文件的version版本号来提示浏览器更新缓存
另外能够经过applicationCache对象的swapCache手工执行本地缓存的更新,它只能在applicationCache对象的updateReady事件被触发时调用。
updateReady就是服务器manifest有更新,而且已经把缓存的文件都已经下载到本地了。以后就能够执行swapCache更新。这样就能够控制页面是否当即更新缓存,由于可能用户正在作一些重要的操做,不想当即更新缓存。可使用confirm方法让用户选择更新的时机。
applicationCache.addEventListener(
"updateready",function(){
alert("正在更新本地缓存,请稍等....");
applicationCache.swapCache();
alert("本地缓存已被更新,您能够刷新页面来获得本程序的最新版本");
});
applicationCache对象的另外一个方法applicationCache.update,该方法的做用是检查服务器上的manifest文件是否有更新。
applicationCache除了一些方法以外固然也有一些事件监听,
详细。
7、通讯API
一、跨文档消息传输
HTML 5提供了网页文档之间互相接受和发送消息的功能。接受消息的网页须要作监听:
window.addEventListener("message", function{...}, false);
发送消息的页面传输消息的方法:
window.postMessage(message, targetOrigin);
targetOrigin为接受消息的网页URL地址
早期作过的一个
Demo,如文所述,IE8的监听不是message,而是onmessage。
二、Web Sockets
Web Sockets是HTML 5提供的Web应用中客户端和服务器端
非HTTP 的通讯机制。能够实现HTTP不易实现的功能,好比消息推送。这个连接是双向的,实时且永久的,除非显示关闭。
var websocket = new WebSockets("ws://localhost:8080/socket");
将URL字符串做为参数传入,经过调用WebSockets对象的构造器实现与服务器端创建通讯。 URL字符串必须以“ws”或“wss”(加密通讯时)文字做为开头。
websocket.send(data);
经过send方法发送信息
websocket.onmessage = function(event){
var data = event.data;
...
}
经过onmessage属性接收服务器传来的信息
websocket.onopen = function(event){
//开统统信时处理
}
监听socket打开事件
websocket.onclose = function(event){
//开统统信时处理
}
监听socket关闭事件
websocket.close();
切断通讯
另外能够经过readyState的属性值来获取WebSocket对象的状态:
CONNECTING(数值为0):表示正在链接
OPEN(数字值为1):表示已创建链接
CLOSING(数字值为2):表示正在关闭
CLOSED(数字值为3):表示已经关闭
<!DOCTYPE HTML>
<html>
<head>
<title>Web Socket Demo -- EchoClient</title>
<meta charset="utf-8">
</head>
<script type="text/javascript">
var websocket = null;
function connect(){
var msg = document.getElementById("msg");
try{
var readyState = new Array("正在链接", "已创建链接", "正在关闭链接"
, "已关闭链接");
var host = "ws://localhost:8000";
websocket = new WebSocket(host);
websocket.onopen = function(){
msg.innerHTML += "<p>Socket状态: " + readyState[websocket.readyState] + "</p>";
}
websocket.onmessage = function(event){
msg.innerHTML += "<p>接收信息: " + event.data + "</p>";
}
websocket.onclose = function(){
msg.innerHTML += "<p>Socket状态: " + readyState[websocket.readyState] + "</p>";
}
msg = document.getElementById("msg");
msg.innerHTML += "<p>Socket状态: " + readyState[websocket.readyState] + "</p>";
}catch(exception){
msg.innerHTML += "<p>有错误发生</p>";
}
}
function send(){
var msg = document.getElementById("msg");
var text = document.getElementById("text").value;
if(text == ""){
msg.innerHTML += "<p>请输入一些文字</p>";
return;
}
try{
websocket.send(text);
msg.innerHTML += "<p>发送数据: " + text + "</p>";
}catch(exception){
msg.innerHTML += "<p>发送数据出错</p>";
}
document.getElementById("text").value = "";
}
function disconnect(){
websocket.close();
}
</script>
<body>
<h1>WebSocket客户端实例</h1>
<div id="msg" style="height: 300px;"></div>
<p>请输入一些文字</p>
<input type="text" id="text"/>
<button id="connect" onclick="connect();">创建链接</button>
<button id="send" onclick="send();">发送数据</button>
<button id="disconnect" onclick="disconnect();">断开链接</button>
</body>
</html>
服务端:
package socket;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.security.MessageDigest;
public class EchoServer {
private int port = 8000;
private ServerSocket serverSocket;
public EchoServer() throws IOException {
serverSocket = new ServerSocket(port);
System.out.println("服务器启动");
}
private void service() {
Socket socket = null;
while (true) {
try {
socket = serverSocket.accept();
Thread workThread = new Thread(new Handler(socket));
workThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Handler implements Runnable {
private Socket socket;
private boolean hasHandshake = false;
Charset charset = Charset.forName("UTF-8");
public Handler(Socket socket) {
this.socket = socket;
}
private PrintWriter getWriter(Socket socket) throws IOException {
OutputStream socketOut = socket.getOutputStream();
return new PrintWriter(socketOut, true);
}
public String echo(String msg) {
return "echo:" + msg;
}
public void run() {
try {
System.out.println("New connection accepted"
+ socket.getInetAddress() + ":" + socket.getPort());
InputStream in = socket.getInputStream();
PrintWriter pw = getWriter(socket);
//读入缓存
byte[] buf = new byte[1024];
//读到字节
int len = in.read(buf, 0, 1024);
//读到字节数组
byte[] res = new byte[len];
System.arraycopy(buf, 0, res, 0, len);
String key = new String(res);
if(!hasHandshake && key.indexOf("Key") > 0){
key = key.substring(0, key.indexOf("==") + 2);
key = key.substring(key.indexOf("Key") + 4, key.length()).trim();
key+= "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(key.getBytes("utf-8"), 0, key.length());
byte[] sha1Hash = md.digest();
sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
key = encoder.encode(sha1Hash);
pw.println("HTTP/1.1 101 Switching Protocols");
pw.println("Upgrade: websocket");
pw.println("Connection: Upgrade");
pw.println("Sec-WebSocket-Accept: " + key);
pw.println();
pw.flush();
hasHandshake = true;
//接收数据
byte[] first = new byte[1];
int read = in.read(first, 0, 1);
while(read > 0){
int b = first[0] & 0xFF;
//boolean fin = (b & 0x80) > 0;
// int rsv = (b & 0x70) >>> 4;
byte opCode = (byte) (b & 0x0F);
if(opCode == 8){
socket.getOutputStream().close();
break;
}
b = in.read();
// Client data must be masked
if ((b & 0x80) == 0) {
//NO-DO
}
int payloadLength = b & 0x7F;
if (payloadLength == 126) {
byte[] extended = new byte[2];
in.read(extended, 0, 2);
int shift = 0;
payloadLength = 0;
for (int i = extended.length - 1; i >= 0; i--) {
payloadLength = payloadLength + ((extended[i] & 0xFF) << shift);
shift += 8;
}
} else if (payloadLength == 127) {
byte[] extended = new byte[8];
in.read(extended, 0, 8);
int shift = 0;
payloadLength = 0;
for (int i = extended.length - 1; i >= 0; i--) {
payloadLength = payloadLength + ((extended[i] & 0xFF) << shift);
shift += 8;
}
}
//掩码
byte[] mask = new byte[4];
in.read(mask, 0, 4);
int readThisFragment = 1;
ByteBuffer byteBuf = ByteBuffer.allocate(payloadLength + 10);
byteBuf.put("echo: ".getBytes("UTF-8"));
while(payloadLength > 0){
int masked = in.read();
masked = masked ^ (mask[(int) ((readThisFragment - 1) % 4)] & 0xFF);
byteBuf.put((byte) masked);
payloadLength--;
readThisFragment++;
}
byteBuf.flip();
responseClient(byteBuf, true);
printRes(byteBuf.array());
in.read(first, 0, 1);
}
}
in.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (socket != null)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 方法说明:
* @开发:linrb
* @建立时间:2012-8-14
* @param byteBuf
* @throws IOException
*/
private void responseClient(ByteBuffer byteBuf, boolean finalFragment) throws IOException {
OutputStream out = socket.getOutputStream();
int first = 0x00;
//是不是输出最后的WebSocket响应片断,默认
if (finalFragment) {
first = first + 0x80;
first = first + 0x1;
}
out.write(first);
if (byteBuf.limit() < 126) {
out.write(byteBuf.limit());
} else if (byteBuf.limit() < 65536) {
out.write(126);
out.write(byteBuf.limit() >>> 8);
out.write(byteBuf.limit() & 0xFF);
} else {
// Will never be more than 2^31-1
out.write(127);
out.write(0);
out.write(0);
out.write(0);
out.write(0);
out.write(byteBuf.limit() >>> 24);
out.write(byteBuf.limit() >>> 16);
out.write(byteBuf.limit() >>> 8);
out.write(byteBuf.limit() & 0xFF);
}
// Write the content
out.write(byteBuf.array(), 0, byteBuf.limit());
out.flush();
}
/**
* 方法说明:
* @开发:linrb
* @建立时间:2012-8-14
* @param array
*/
private void printRes(byte[] array) {
ByteArrayInputStream byteIn = new ByteArrayInputStream(array);
InputStreamReader reader = new InputStreamReader(byteIn, charset.newDecoder());
int b = 0;
String res = "";
try {
while((b = reader.read()) > 0){
res += (char)b;
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(res);
}
}
public static void main(String[] args) throws IOException {
new EchoServer().service();
}
}
8、Web Workers
Web Worker是HTML 5提供的一种后台线程,线程下面能够有子线程。可是线程不能调用document和页面的元素。可是,页面交互其实可让前台处理。而且先后能够进行数据交互。这样能够避免,犹豫前台JS处理时间过长致使页面奔溃。
一、数据交互
建立对象:
var worker = new Worker("脚本路径");
能够在前台里面持有worker对象,而后经过:
worker.onmessage = function(event){
//处理后台线程传过来的数据
}
worker.postMessage(message);
进行数据交互,固然若是要传对象的话,把对象经过JSON对象的stringify方法转成文本传入就行。后台的js脚本里面也经过调用onmessage 和 postMessage与前台交互。
<!DOCTYPE HTML>
<html>
<head>
<title>Worker Demo 1 ###1</title>
<meta charset="utf-8">
</head>
<script type="text/javascript">
var worker = new Worker("js/SumCalculate.js");
worker.onmessage = function(event){
alert("结果为:" + event.data);
}
function calculate(){
var val = document.getElementById("inputVal").value;
if(val != null && !isNaN(val) && parseInt(val) > 1){
worker.postMessage(parseInt(val));
}else{
alert("请输入大于1的整数!!");
}
}
</script>
<body>
<hgroup>
<h1>Worker Demo 1</h1>
<h2>运算1到输入指定数字递增数列的值</h2>
</hgroup>
<section>
<input type="text" id="inputVal" placeholder="请输入大于1的整数"/>
<button onclick="calculate();">提交</button>
</section>
</body>
</html>
JS:
onmessage = function(event){
var data = event.data;
var result = 0;
for(var i=0; i <= data; i++){
result += i;
}
postMessage(result);
}
PS: Chrome须要服务器才能运行,Opera和FF则不用
固然也可使用线程嵌套,主线程下面建立子线程。只是
Chrome,WebKit内核的目前不支持,线程下面建立子线程。
二、线程可用变量、函数与类
2.1 self
self关键词用来表示本线程范围内的做用域
2.2 postMessage(message)
向线程的源窗口发送消息
2.3 onmessage
获取接受消息的事件句柄
2.4 importScripts(url)
导入其余JavaScript脚本文件,需保证同域同端口。
2.5 navigator对象
与window.navigator对象相似,具备appName、platform、userAgent、appVersion这些属性。
2.6 sessionStorage/localStorage
能够在线程中使用Web Storage
2.7 XMLHttpRequest
能够在线程中处理Ajax请求
2.8 setTimeout()/setInterval()
能够在线程中实现定时处理
2.9 close
能够结束本线程
2.10 eval()、isNaN()、escape()等
可使用全部JS核心函数
2.11 object
能够建立和使用本地对象
2.12 WebSocket
可使用WebSocket API来想服务器发送和接受信息
9、Geolocation API
PS: 这章不怎么详记,限制比较多,使用起来诸多问题
在HTML 5中,提供了Geolocation API,不过经过《HTML 5 揭秘》这本书了解到。获取地理位置,PC主要是经过你使用的运营商分给的IP地址,手机是经过信号基站和GPS,另外
PC获取地址仍是得须要用户受权。HHTML 5 中,为window.navigator对象新增了一个geolocation属性,可使用Geolocation API来对该属性进行访问。
一、取得当前位置
navigator.geolocation.getCurrentPosition(onSuccess, onError, options);
第一个参数为获取当前位置信息成功时所执行的回调函数,第二个是失败的回调函数,第三个是可选属性的列表,第2、三个参数是可选的。可选属性有(列举部分):
- enableHighAccuracy: 是否要求高级毒的地理位置(不少设备没有)
- timeout: 获取地址超时限制
- maximumage: 获取地理信息进行缓存下来的有效时间
二、持续监视
navigator.geolocation.watchCurrentPosition(onSuccess, onError, options);
该方法有点相似JS的setInterval方法,能够经过clearWatch方法中止当前位置监视。
demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>HTML5 Geolocation</title>
<style>
body {background-color:#fff;}
</style>
</head>
<body>
<p id="geo_loc"><p>
<script>
function getElem(id) {
return typeof id === 'string' ? document.getElementById(id) : id;
}
function show_it(lat, lon) {
var str = '您当前的位置,纬度:' + lat + ',经度:' + lon;
getElem('geo_loc').innerHTML = str;
}
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
show_it(position.coords.latitude, position.coords.longitude);
}, function(err) {
getElem('geo_loc').innerHTML = err.code + "\n" + err.message;
});
} else {
getElem('geo_loc').innerHTML = "您当前使用的浏览器不支持Geolocation服务";
}
</script>
</body>
</html>
google Map:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>HTML5 Geolocation</title> <style> body {background-color:#fff;} </style> </head> <body> <p id="map_canvas"><p> <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> <script> function getElem(id) { return typeof id === 'string' ? document.getElementById(id) : id; } function success(position) { var mapcanvas = document.createElement('div'); mapcanvas.id = 'mapcanvas'; mapcanvas.style.height = '400px'; mapcanvas.style.width = '560px'; getElem("map_canvas").appendChild(mapcanvas); var latlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude); var myOptions = { zoom: 15, center: latlng, mapTypeControl: false, navigationControlOptions: {style: google.maps.NavigationControlStyle.SMALL}, mapTypeId: google.maps.MapTypeId.ROADMAP }; var map = new google.maps.Map(document.getElementById("mapcanvas"), myOptions); var marker = new google.maps.Marker({ position: latlng, map: map, title:"你在这里!" }); } if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(success); } else { alert("您当前使用的浏览器不支持geolocation服务"); } </script> </body> </html>