第一章 移动互联网的浪潮之巅
HTML是用来承载信息的载体,那么HTML5是用来承载更多更强大信息的载体。
Web标准的精髓不仅仅在于内容结构、表现和行为的分离,更在于提供结构化互联网信息的工具。
Web标准就是降低开发复杂度,简化代码的规范。
Web语义化指让机器理解内容。
爬虫程序是一种自动访问互联网页面并收集信息以供人们检索的程序。
HTML5有八个类别:
图像和特效
SVG、Canvas、WebGL
通信
Web Socket、Server-Sent Events
设备访问
Orientation API、Geolocation API
多媒体
Video、Audio
离线存储
HTML5 App Cache、Local Storage、Indexed DB、File API
性能和集成
Web Worker
语义网
语义化标签 header、footer等
呈现
CSS3
第二章 HTML5基础
2.1 HTML的核心要素:标签
2.2 HTML的语义来源:元素名称、元素属性
2.3 HTML5的元素和属性:
2.3.1 全局属性
常用属性:id、class、style、lang、translate、dir、title、accesskey、tabindex
contenteditable、contextmenu、draggable、dropzone、hidden、spellcheck、data-*
事件处理属性(默认前面加on):
Window事件:
load、unload
afterprint、beforeprint、beforeunload、error、haschange、message、offline、online、page hide、pageshow、pop state、redo、resize、storage、undo
Form事件:
blur、change、focus、reset、select、submit
contextmenu、formchange、forminput、input、invalid
Keyboard事件:
keydown、keypress、keyup
Mouse事件:
click、dbclick、drop、mousedown、mousemove、mouseup、mouseover、mousemouseout
drag、dragstart、dragenter、dragend、dragover、dragleave、mousewheel、scroll
Media事件:
abort、waiting
canplay、canplaythrough、durationchange、emptied、ended、error、loadeddata、loadedmetadata、loadstart、pause、play、playing、progress、ratechange、readystatechange、seeked、seeking、stalled、suspend、timeupdate、volumchange
2.3.2 HTML5与它的全局变量
1)contentEditable属性:元素内容是否可编辑
2)contextmenu属性:设置右键菜单属性
3)draggable属性:元素是否可拖动
dropzone属性:元素是否可放置拖拽的元素
4)hidden属性:设置元素不再与页面相关
5)spellcheck属性:是否对元素进行拼写和语法检查
6)data-*属性:自定义属性来存储数据
2.3.3 元素分类与内容模型(Content Model)
HTMLL元素所能表达的内容的描述及与这些元素如何互相作用的描述叫内容模型。
简单说就是不能按照之前用CSS的样式来把HTML元素划分成块级元素、内联元素,而是按照内容模型来划分。
内容模式大致分成七类:
- Metadata
- Flow
- Sectioning
- Heading
- Phrasing
- Embedded
- Interactive
HTML中的每个元素都可以是上面分类的零个或多个。
1)元数据式内容(Metadata content)
指head元素之间的元素,如:base、command、link、meta、noscript、script、style、title
2)流式内容(Flow content)
指文档大部分元素,如:div、p
3)章节式内容(Sectioning Content)
指用于定义标题与页脚范围之间的元素,如:article、aside、nav、section
4)标题式内容(Heading Content)
指定义标题的元素,如:h1~h6,hgroup
5)段落式内容(Phrasing Content)
指段落内的元素,如:a、span、abbr
6)嵌入式内容(Embedded Content)
指当前文档引用到其他资源的元素,如:audio、canvas、embed、iframe、img、object、svg、video
7)交互式内容(Interactive Content)
指与用户发生交互的元素,如:form、input
2.3.4 文档元数据
1)title:文档的标题或名称,标签之间是纯文本
2)base:文档的基地址及链接打开方式
3)link:引用文档其他资源
4)meta:提供页面元信息
2.3.5 区块内容
该类标签如下:
- body
- article
- section
- nav
- aside
- h1~h2、hgroup
- header、footer
- address
1)article:用来定义内容可单独发布或重用的文档、页面、应用等。如:一篇帖子、文章、评论甚至一个页面交互组件
2)section:用来定义需要出现在文档的提纲中的章节或区块。如:一篇文章的章节
3)nav:用来定义导航区块。如:导航栏
4)aside:用来定义当前已有内容的相关内容。如:一篇文章的相关背景、广告、引述、评论等
5)h1~h6:用来定义区块的标题,h1级别最高
hgroup:用来定义多个级别的标题,如:标题和副标题
6)header:用来定义头部的内容,footer:用来定义底部的内容。如:目录标题、搜索框、logo、友情链接等
与前面的article、section、nav、aside相比,header和footer不具备产生大纲视图的特性。
7)address:用来定义它最近的父级article或body元素里内容相关的联系信息。
2.3.6 分组内容
p:段落
hr:水平线
pre:已排版的内容
blockquote:引用来自其他来源的内容
ol:有序列表
ul:无序列表
li:列表项
dl:定义列表
dt:定义的项目
dd:定义的描述
div: 块级元素
figure:定义插图注解、图表、照片、代码列表等
figcaption:figure元素的标题
2.3.7 文本内容
a:超链接
em:强调
strong:内容重要性
small:旁注,如免责声明、使用条款、版权信息等
s:有误文本,如商品标价
cite:作品标题的引用,如书影音画等
q:短引用,如某人的一句话
dfn:定义的实例,通常用来定义术语
abbr:缩写词,可以配合dfn定义术语
code:计算机代码
var:定义变量
samp:计算机程序的输出
kbd:用户输入(按键),如:Enter
sub:下标文本
sup:上标文本
i:斜体
b:粗体
u:下划线
bdo:定义文本显示的方向
span:无语义
br:换行
wbr:规定在文本中的何处适合添加换行符
data:为元素赋予机器可读的数据
time:data标签的时间格式版本
mark:标记或高亮文本
ruby,rt,rp:注音标示
bdi:定义文本的文本方向,如:双向文本排版
2.3.8 修改记录
ins,del:表示文档的增删改记录。
2.3.9 嵌入内容
1)img:图片
2)iframe:窗体
3)embed:Flash插件、视频
4)object:视频
5)vidoe:视频、audio:音频
6)canvas:游戏、3D/2D效果
7)mathml:数学公式
8)svg:渲染
2.3.10 表格数据
table:表格
caption:表格标题
colgroup:对表格中的列进行组合
col:表示列
tbody:一段表格主体
thead:表格表头
tfoot:表格的页脚
tr:表格中的行
td:表格中的单元格
th:表格表头中的单元格
2.3.11 HTML5表单
HTML5给表单input输入框提供了很多类型及更丰富的属性。
input的type值可以为:email、tel、url、serach、color、number、range、date等。
required属性:该字段必须要填写才能提交
autocomplete属性:填写该文本时会出现记录以前填写时的内容
placeholder属性:文本框提示
pattern属性:该文本输入的内容需要通过该正则验证后才能提交
min属性:最小值 type值为number时
max属性:最大值 type值为number时
step属性:调整数字的步长 type值为number时
list属性:配合datalist元素,可实现自动提示功能
autofocus属性:自动聚焦到搜索框内
后头直接省略,理由:浏览器对HTML5表单的兼容性还有很长一段路要走。
第三章 初探CSS3
3.2.1 特殊性
比如多个CSS样式操作同一个元素的背景色,其最终样式取决于特殊性的加权结果。组合特殊性值越大,该样式对元素起作用。基本规则如下:
- 1.内联样式,及使用style属性的 +1
- 2.使用元素或伪元素选择器(:before) +1
- 3.使用类或伪类选择器(:hover) +1
- 4.使用ID选择器 +1
3.6.1 透视 perspective
/* 透视深度*/
-webkit-perspective: 250px;
/* preseve-3d指定元素的子元素在3d空间内定位 /
-webkit-transform-style: preserve-3d;
/ 指定用户从哪个方向看过来的 */
-webkit-perspective-origin: -100% -50%;
3.7响应式设计基础
响应式设计可以理解成”PC端和移动端共享一套代码”,其主要包含的内容有:
- 使用流式布局或栅格布局以适应不同屏幕。
- 使用CSS3媒体查询技术对不同尺寸的屏幕进行样式微调。
- 使用流式图片
基本概念:
CSS像素与设备像素
设备像素(device pixel):屏幕上最小的发色单元。
CSS像素(CSS pixel):定义的样式尺寸大小。
PPI与设备像素比
PPI:设备像素密度。
设备像素比(devicePixelRatio):设备上物理像素和设备独立像素的比例。
设备像素比可用来判断设备是否是retina设备。
视口(viewport)
视口:表示浏览器窗口的可视区域。
移动设备浏览器定义了两个视口:
- 布局视口:默认是980px,决定桌面版网站的CSS
- 可见视口:决定移动版网站的CSS
meta的name属性为viewport时,content属性值可以为:
- width:布局视口宽度
- height:布局视口高度
- initial-scale:初始缩放比例(0~10.0)
- minimum-scale:最小缩放比例
- maximum-scale:最大缩放比例
- user-scalable:用户是否可缩放,默认yes
语法:
@media :<sMedia> { sRules }
取值:
<sMedia>:指定设备名称。
{sRules}:样式表定义。
media_query: [only | not]? [ and <expression> ]*
expression: ( <media_feature> [: <value>]? )
media_type: all | aural | braille | handheld | print | projection | screen | tty | tv | embossed
media_feature(”min-“或”max-“): width | height | device-width | device-height | color | color-index | resolution | orientation | scan | grid | device-aspect-ratio | monochrome
在JavaScript中,可使用matchMedia()检查媒体查询是否成功,即看其matches属性是true还是false。
3.7.3 响应式栅格系统
HTML代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| <div class="container"> <div class="row"> <div class="header">header</div> </div> <div class="row"> <div class="col1"> nav</div> <div class="col2"> main </div> <div class="col1"> aside </div> </div> <div class="row"> <div class="footer">footer</div> </div> </div>
|
CSS代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| .row { width: 960px; } .row:after { clear: left; content: ''; display: table; } [class^="col"] { float: left; } .col1 { width: 25%; } .col2 { width: 50%; } .col3 { width: 75%; }
@media (min-width: 1200px) { .row { width: 1170px; } }
@media (min-width: 768px) and (max-width: 979px) { .row { width: 724px; } }
@media (max-width: 767px) { .row { width: 100%; } }
@media (max-width: 480px) { }
|
3.7.4 移动优先理念
对于一个新产品,先设计移动版,然后才是桌面版。
这样的好处是:
- 产品功能会更简洁
- 移动设备可以用的功能电脑上同样可以用
- 能写出性能更好的程序
- 可加新功能,因为加功能比删功能更容易
3.7.5 另一种思路:后端模块输出的优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| <head> <link rel="stylesheet" href="common.css"> <% if (!is_mobile()) {%> <link rel="stylesheet" href="desktop.css"> <% } else { %> <link rel="stylesheet" href="mobile.css"> <% } %> <script> function is_mobile(){ var ua=navigator.userAgent.toLowerCase(); if (/iphone|ipad|ipod/.test(ua)){ reutrn true; }else if(/android/.test(ua)){ return true; }else{ retur false; } } </script> </head> <body> <div class="header"></div> <div class="main"> <div class="main-content"></div> <% if (!is_mobile()) {%> <div class="side"></div> <% } %> </div> <div class="footer"></div> </body>
|
3.7.6 其他细节
触摸和非触摸
1
| document.documentElement.className+=('ontouchstart' in window) ? 'touch' : 'no-touch'
|
1 2 3 4
| html .no-touch .item:hover{ cursor:pointer; background-color:#ff9; }
|
retina屏幕的图片使用
1 2 3 4 5 6 7 8
| .icon{ background-image:url(icon.png); } @media all and (max-width:320px) and (-webkit-min-device-pixel-ratio:2){ .icon{ background-size:50% 50%; } }
|
第四章 从网页到应用
4.2 本地存储升级
4.2.1 cookie
cookie是如何存储的?
用户浏览器第一次向服务器发生请求时,服务器会返回set-Cookie:xxx,浏览器会记下xxx,当浏览器再次请求服务器时会带上Cookie:xxx。
简单说,cookie会随着HTTP请求发送到服务器端。
cookie是如何设置的?
1
| document.cookie="name=value"
|
cookie的大小和数量限制?
IE6及以下 每个域最多20个
IE7及以上 每个域最多50个
Firefox 每个域最多50个
Google、Safari 没明确限制,但是cookie超过了HTTP头部大小的限制时,服务器将无法处理
cookie的大小限制在4096B
cookie不适合在本地存储数据,本地存储大量数据请使用Web Storage。
4.2.2 web storage
web storage不会随着HTTP请求发送到服务器端,使用它不会影响网站的性能。
浏览器不允许开发者实例化Storage对象,已经有两个实例化好的对象,分别是localStorage和sessionStorage。
localStorage会持久化数据,当关闭浏览器再打开网站,依然可以访问这个域的数据,而使用sessionStorage不能。
web storage使用:
1 2 3 4 5 6 7 8 9 10 11 12
| localStorage['ww']=JSON.stringify({name:"ww",age:22}); localStorage.setItem('zl',JSON.stringify({name:'zl',age:22}));
localStorage.length; localStorage.key('0'); JSON.parse(localStorage['ww']); JSON.parse(localStorage.getItem('zl'));
delete localStorage['ww']; localStorage.removeItem('zl'); localStorage.clear();
|
4.3离线应用
4.3.1 缓存和应用缓存
应用缓存就是将服务器的资源文件缓存至本地,有以下三大优点:
- 加速应用启动速度
- 离线访问页面
- 节省服务器资源,减少请求
4.3.2 应用缓存的基本用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| <script> function getAppCacheStatus() { var appCache = window.applicationCache; switch (appCache.status) { case appCache.UNCACHED: return 'UNCACHED'; break; case appCache.IDLE: return 'IDLE'; break; case appCache.CHECKING: return 'CHECKING'; break; case appCache.DOWNLOADING: return 'DOWNLOADING'; break; case appCache.UPDATEREADY: return 'UPDATEREADY'; break; case appCache.OBSOLETE: return 'OBSOLETE'; break; default: return 'UKNOWN CACHE STATUS'; break; }; } </script>
<script>
window.addEventListener('load', function(e) {
window.applicationCache.addEventListener('updateready', function(e) { if (getAppCacheStatus() === 'UPDATEREADY') { window.applicationCache.swapCache(); if (confirm('本程序有更新,是否刷新?')) { window.location.reload(); } } else { } }, false); }, false); </script>
<script> function handleCacheEvent(e) { }
function handleCacheError(e) { alert('Error: Cache failed to update!'); };
appCache.addEventListener('cached', handleCacheEvent, false);
appCache.addEventListener('checking', handleCacheEvent, false);
appCache.addEventListener('downloading', handleCacheEvent, false);
appCache.addEventListener('error', handleCacheError, false);
appCache.addEventListener('noupdate', handleCacheEvent, false);
appCache.addEventListener('obsolete', handleCacheEvent, false);
appCache.addEventListener('progress', handleCacheEvent, false);
appCache.addEventListener('updateready', handleCacheEvent, false); </script>
|
第五章 指尖下的浏览器
touch事件:
- touchstart:开始触摸时
- touchmove:触摸移动时
- touchend :触摸结束时
触摸事件对象e包含的属性有:
- touches:所有屏幕上所有手指动作的列表,是一个TouchList类型的对象,对象里有多个Touch对象
- targetTouches:当前DOM元素上所有手指动作列表
- changedTouches:当前改变的手指动作列表
每一根手指都会产生一个Touch对象,Touch对象包含的属性有:
identifier:一个数字,标识唯一
target:动作目标的DOM元素
clientX、clientY:触摸点相对于浏览器视口的位置
pageX、pageY:触摸点相对于页面的位置
screenX、screenY:触摸点相对于屏幕的位置
第六章 地理定位
百度地图我的位置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> <style type="text/css"> body, html,#allmap {width: 280px;height: 200px;overflow: hidden;margin:0;font-family:"微软雅黑";} </style> <script src="http://cdn.bootcss.com/jquery/2.1.4/jquery.js"></script> <title>添加动画标注点</title> </head> <body> <div id="allmap"></div> </body> </html> <script type="text/javascript"> window.onload=function() { var script = document.createElement("script"); script.type = "text/javascript"; script.src = "http://api.map.baidu.com/api?v=2.0&ak=X5w1ZLsQvWwxRwNv5nonp4MX&callback=init"; document.body.appendChild(script); } function init() { var map = new BMap.Map("allmap"); var point = new BMap.Point(104.083963,30.623718); map.centerAndZoom(point,18); var marker = new BMap.Marker(point); map.addOverlay(marker); map.addEventListener("tilesloaded",function(){ setTimeout(function(){ $(".BMap_cpyCtrl").remove(); },500); }); } </script>
|
第七章 Web Worker
Web Worker技术是为了解决JavaScript因运行在浏览器单线程环境里,无法创建线程问题。
使用Web Worker:
1
| var myWorker=new Worker("xxx.js");
|
在xxx.js里可以做一些耗时操作,通过messaage事件和postMessage方法进行通信。
xxxx.js里
1 2 3 4 5
| var num=0; for(var i=0;i<100;i++){ num+=i; } postMessage(num);
|
调用:
1 2 3 4
| var myWorker=new Worker("xxx.js"); myWorker.addEventListener('message',function(e){ console.log(e.data); },false);
|
Worker技术虽然给客户端进行大量提供了便利,但对于移动设备而言,过分依赖Worker并不是一个好主意。
第八章 通信基础
XRH2:XML HttpRequest Level2,提供一种利用JavaScript与服务器端通信的方式。
Ajax基本步骤:
1 2 3 4 5 6 7 8 9 10 11 12
| var xhr=new XmlHttpRequest(); xhr.open('GET','/img.jpg',true); xhr.responseType='blob'; xhr.onload = function(e) { if (this.status == 200) { var url=window.URL.createObjectURL(this.response); var img=new Image(); img.src=url; document.body.appendChild(img) } }; xhr.send();
|
第九章 实时Web技术
使用Socket.IO实现在线实时聊天室
index.html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <link href='style.css' rel='stylesheet'/> </head> <body> <h1>Socket.IO Chat Demo</h1> <div class="wrap" class="chatroom"> <div class="nickname"> <form class="set-nickname"> <label for="nick">输入昵称后进入聊天室</label> <input class="nick" name="nick" type="text" placeholder="昵称" /> <button type="submit">进入</button> <p class="nickname-err">该昵称已经有人使用</p> </form> </div> <div class="messages"> <div class="nicknames"> <span>当前在线: </span> </div> <div class="lines"></div> </div> <form class="send-message"> <span class="to"> 发送给<b>所有人</b>:</span> <input class="message" type="text"/ placeholder="在这里输入消息发送" /> <button>发送</button> </form> </div> <script src='http://code.jquery.com/jquery-latest.min.js'></script> <script src='socket-io.js'></script> <script src='index.js'></script> </body> </html>
|
style.css:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
| body { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; background: #eee; }
h1 { text-align: center; font-size: 40px; color: rgba(0, 0, 0, .8); text-shadow: 0 1px 1px #fff; }
.wrap { max-width: 900px; position: relative; margin: auto; border: 1px solid #ddd; border-radius: 10px; background: #f3f3f3; box-shadow: 0 0 25px rgba(0, 0, 0, .07), inset 0 1px 11px rgb(255, 255, 255); }
input[type="text"] { border: 1px solid #ccc; padding: 12px; width: 250px; font-size: 14px; color: #777; border-radius: 5px; box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2); margin-bottom: 10px; } input[type="text"]:focus { border-color: #999; outline: 0; } button { margin: 0; display: inline-block; text-decoration: none; background: #00b5d6; border: 1px solid #00a5c3; border-radius: 7px; color: #fff; box-shadow: inset 0 1px 1px rgba(255, 255, 255, .6), inset 0 0 10px #008da7; font: 600 1.3em/1.7em "helvetica neue", helvetica, arial, sans-serif; text-align: center; text-shadow: 0 1px 1px #006679; cursor: pointer; } button:hover, button:active, button:focus { background: #009cb8; box-shadow: inset 0 1px 1px rgba(255, 255, 255, .7), inset 0 0 10px #007287; }
.nickname { text-align: center; font: 15px; color: rgba(0, 0, 0, .5); display: block; }
label { display: block; margin: 20px 0; font-size: 18px; }
.nickname .nickname-err { color: #8b0000; font-size: 12px; visibility: hidden; } .nickname { } .messages { border-radius: 10px; overflow: hidden; display: none; } .send-message { display: none; }
.messages em { text-shadow: 0 1px 0 #fff; color: #999; } .messages p { margin: 0; color: rgba(0, 0, 0, .5); font: 13px Helvetica, Arial; padding: 5px 10px; } .messages p b { display: inline-block; padding-right: 10px; color: rgba(0, 0, 0, .8); } .messages p:nth-child(even) { background: #fafafa; } .messages .nicknames { padding: 10px; font-size: 13px; } .messages .nicknames span { color: #000; font-weight: bold; } .messages .nicknames b { display: inline-block; color: #fff; background: #4FA72C; padding: 3px 6px; margin-right: 5px; border-radius: 5px; text-shadow: 0 1px 0 rgba(0, 0, 0, .2); cursor: pointer; } .messages .lines { height: 250px; border-top: 1px solid #ddd; background: #fff; overflow: auto; overflow-x: hidden; overflow-y: auto; } .send-message { padding: 10px; position: relative; } .send-message input:focus { outline: 0; }
.send-message button { width: 110px; }
@media (min-width: 960px) { .nicknames { float: right; width: 160px; } .nicknames b, .nicknames span { display: block !important; margin-bottom: 4px; text-align: center; } }
@media (max-width: 959px) { h1 { font-size: 30px; } }
@media (max-width: 320px) { .to { display: none; } .send-message button { width: auto; } .message { width: 190px !important; } h1 { font-size: 20px; } }
|
重点及核心代码
前端代码:
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| $(function() { var $chatroom = $('.chat'), $lines = $('.lines'), $nickname = $('.nickname'), $setNickname = $('.set-nickname'), $nicknames = $('.nicknames'), $messages = $('.messages'), $message = $('.message'), $nick = $('.nick'), $sendMessage = $('.send-message'), $to = $('.to'), $nicknameErr = $('.nickname-err'), toUser = null, myself = null var socket = io.connect() socket.on('announcement', function(msg) { $lines.append($('<p>').append($('<em>').text(msg))) }) socket.on('nicknames', function(nicknames) { $nicknames.empty().append($('<span>当前在线: </span>')) $.each(nicknames, function (key, val) { $nicknames.append($('<b>').text(val)) }) }) function message(from, msg, opt_to) { var label if (opt_to) { label = $('<b>').text(from + '对' + opt_to + '说:') } else { label = $('<b>').text(from + ':') } $lines.append($('<p>').append(label, msg)) } socket.on('user:pub', message) socket.on('user.private', message) socket.on('reconnect', function() { $lines.remove() message('<i>系统消息</i>', '重连了!') }) socket.on('reconnecting', function() { message('<i>系统消息</i>', '尝试重连中…') }) socket.on('error', function(e) { message('<i>系统消息</i>', e ? e : '未知错误!') }) function clear() { $message.val('').focus() } $setNickname.submit(function(e) { socket.emit('nickname', $nick.val(), function(set) { if (!set) { clear() myself = $nick.val() $nickname.hide() $messages.show() $sendMessage.show() return } $nicknameErr.css('visibility', 'visible') }) return false }) $sendMessage.submit(function() { if (toUser) { message('我对' + toUser + '说', $message.val()) socket.emit('user:private', $message.val(), toUser) } else { message('我', $message.val()) socket.emit('user:pub', $message.val()) } clear() $lines.scrollTop(10000000) return false }) $nicknames.on('click', 'b', function (e) { toUser = $(e.target).text() if (toUser === myself) { $to.find('b').text('所有人') toUser = null return } $to.find('b').text(toUser) }) })
|
后端js代码:
server.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| var http = require('http') var fs = require('fs')
var connect = require('connect') var app = connect.createServer( connect.static(__dirname) ).listen(8080) var sio = require('socket.io') var io = sio.listen(app), nicknames = {}, onlines = {} io.sockets.on('connection', function(socket) { socket.on('user:pub', function(msg) { socket.broadcast.emit('user:pub', socket.nickname, msg) }) socket.on('user:private', function (msg, to) { if(onlines[to]) { onlines[to].emit('user.private', socket.nickname, msg, to) } }) socket.on('nickname', function(nick, fn) { if (nicknames[nick]) { fn(true) } else { fn(false) nicknames[nick] = socket.nickname = nick onlines[nick] = socket socket.broadcast.emit('announcement', nick + ' 已连接') io.sockets.emit('nicknames', nicknames) } }) socket.on('disconnect', function() { if (!socket.nickname) { return } delete nicknames[socket.nickname]; delete onlines[socket.nickname] socket.broadcast.emit('announcement', socket.nickname + ' 断开连接了') socket.broadcast.emit('nicknames', nicknames) }) })
|
第十章 感官世界
感知方向和动作:
deviceorientation事件:在设备有明显的方向变化时触发
alpha:右手坐标系y变的夹角度数
beta:右手坐标系x变的夹角度数
gamma:右手坐标系z变的夹角度数
orientationchange事件:检测设备横竖屏幕
devicemotion事件:在设备进行自由落体时触发,很少用
compassneedscalibration事件:在需要校准设备时触发,很少用
随着手机的旋转、倾斜,浏览器里面的图片也跟着旋转、倾斜:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <style> div { -webkit-perspective: 250px; } </style> <div style="text-align:center;padding-top:50px;"> <img src="../iphone.png" id="iphone" alt="" width="200"> </div>
<script> var iphone = document.getElementById('iphone') window.addEventListener('deviceorientation', function(e) { iphone.style.webkitTransform = "rotate(" + e.gamma + "deg) rotate3d(1,0,0, " + (e.beta * -1) + "deg)" }, true) </script>
|
判断是横屏还是竖屏:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <script> window.addEventListener('orientationchange', function() { var displayStr = "Orientation : " switch (window.orientation) { case 0: displayStr += "Portrait" break case -90: displayStr += "Landscape (right, screen turned clockwise)" break case 90: displayStr += "Landscape (left, screen turned counterclockwise)" break case 180: displayStr += "Portrait (upside-down portrait)" break } console.log(displayStr) }, false) </script>
|
音视频捕获:
1
| navigator.getUserMedia(type,successCallback,errorCallback)
|
获取媒体流实现截屏:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <video></video> <img> <canvas></canvas> <script> var video = document.querySelector('video') var canvas = document.querySelector('canvas') var ctx = canvas.getContext('2d') var localMediaStream = null function snapshot() { if (localMediaStream) { ctx.drawImage(video, 0, 0) document.querySelector('img').src = canvas.toDataURL('image/webp') } }
video.addEventListener('click', snapshot, false) navigator.webkitGetUserMedia({video:true,audio:true}, function(stream) { video.src = window.URL.createObjectURL(stream) localMediaStream = stream },function(){}) </script>
|
第十一章 history与导航
使用history.js实现页面无刷新更改URL的需求:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <script src="plugins/native.history.js"></script> <script> (function(window,undefined){ // History对象是history.js提供的唯一对象,它拥有和window.history 几乎一样的API History.Adapter.bind(window,'statechange',function(){ var state = History.getState() console.log(state) }) History.pushState({state:1}, 'title 1', '?state=1') // log: {state:1}, 'title 1', '?state=1' History.pushState({state:2}, 'title 2', '?state=2') // log: {state:2}, 'title 2', '?state=2' History.replaceState({state:3}, 'title 3', '?state=3') // log: {state:3}, 'title 3', '?state=3' History.pushState(null, null, '?state=4') // log: {}, '', '?state=4' History.back() // log: {state:3}, 'title 3', '?state=3' History.back() // log: {state:1}, 'title 1', '?state=1' History.back() // log: {}, 'Home Page', '?' History.go(2) // log: {state:3}, 'title 3', '?state=3' })(window) </script>
|
到目前为止,关于HTML5相关的基础已经介绍的差不多了,对自己而言,那些东西可能只是基础中的基础,了解下原理和语法就行了。
HTML5现在感觉还在处于发展期,很多规范和接口还没有完全统一,真正想在HTML5有所作为,肯定离不开框架的使用,而且如果你只想用HTML5一手遮天的做项目那是绝对不可能的,根据需求而定是很重要的选择哦。