CSS3 的 3D 变换
transform 属性
attr | des | css level |
---|---|---|
transform | 向元素应用 2D 或 3D 转换。 | 3 |
transform-origin | 允许你改变被转换元素的位置。 | 3 |
transform-style | 规定被嵌套元素如何在 3D 空间中显示。 | 3 |
perspective | 规定 3D 元素的透视效果。 | 3 |
perspective-origin | 规定 3D 元素的底部位置。 | 3 |
backface-visibility | 定义元素在不面对屏幕时是否可见。 | 3 |
@transfrom 兼容性
IE10,firefox 以及 Opera 支持 @keyframe,而 chrome 和 safari 需要加浅醉-webkit-,IE9 及早期 IE 版本是不支持的,所以这些功能一般是在移动端使用.
一个 demo
这个 div 会沿着 Y 轴旋转 130deg
1 2 3 4 5 |
div { transform: rotateY(130deg); } |
一个 H5 上的应用场景
实现一个旋转木马的效果,这里列出核心代码,完整的后续放在 github 上
核心是 css 代码
一个 div 作为舞台的
1 2 3 4 5 6 |
<div <span class="keyword">class</span>=<span class="string">"container"</span>> </div> .container { perspective: <span class="number">800</span>px; <span class="comment">//这里是一个视角的位置,</span> } |
perspective 800px 是一个视角的位置,表示屏幕距离 3d 变化中心点的位置,一般是这个经验值,可以设置大一点,这样你看到的动画什么的就会离你很远。。。。
一个容器
1 2 3 4 5 6 7 8 |
<div <span class="keyword">class</span>=<span class="string">"container"</span>> <ul id=<span class="string">"js-course-list-3"</span> <span class="keyword">class</span>=<span class="string">"m-courseList"</span>></ul> </div> .m-courseList { transform-style: preserve-<span class="number">3</span>d; } |
preserve-3d 是透视属性,有了这个用户看到的效果才有空间感,没有的话看到的效果就和 2d 没区别了。
所有卡片给到一个旋转的角度
用模板实现是很方便的一件事情
1 2 |
style="transform: rotateY(<%=opt.deg%>deg) translateZ(<%=opt.tz%>px);-webkit-transform: rotateY(<%=opt.deg%>deg) translateZ(<%=opt.tz%>px)" |
默认情况下上面所有的卡片效果看起来是旋转了,但是都挤到一起去了,上面的 translateZ 是让每个卡片向它们的正前方平移一个具体的,这样看来才会形成一个类似立体圆柱的效果,也就是旋转木马的效果了
要让它动起来,js 也少不了,在每次滑动结束后触发每个卡片的旋转
1 2 3 4 5 6 7 |
$.map(M.lis, <span class="keyword">function</span>(item, i) { <span class="keyword">var</span> deg = Math.floor(<span class="number">360</span>/M.max); $(item).css({ transform: <span class="string">'rotateY('</span>+ (index+i) * deg+<span class="string">'deg) translateZ('</span> + <span class="number">130</span> / Math.tan(deg /<span class="number">360</span> * Math.PI) +<span class="string">'px)'</span> }) }); |
CSS3 @keyframe 规则
属性
attr | des | css level |
---|---|---|
@keyframes | 规定动画。 | 3 |
animation | 所有动画属性的简写属性,除了 animation-play-state 属性。 | 3 |
animation-name | 规定 @keyframes 动画的名称。 | 3 |
animation-duration | 规定动画完成一个周期所花费的秒或毫秒。默认是 0。 | 3 |
animation-timing-function | 规定动画的速度曲线。默认是 "ease"。 | 3 |
animation-delay | 规定动画何时开始。默认是 0。 | 3 |
animation-iteration-count | 规定动画被播放的次数。默认是 1。 | 3 |
animation-direction | 规定动画是否在下一周期逆向地播放。默认是 "normal"。 | 3 |
animation-play-state | 规定动画是否正在运行或暂停。默认是 "running"。 | 3 |
animation-fill-mode | 规定对象动画时间之外的状态。 | 3 |
@keyframe 兼容性
IE10,firefox 以及 Opera 支持 @keyframe,而 chrome 和 safari 需要加浅醉-webkit-,IE9 及早期 IE 版本是不支持的,所以这些功能一般是在移动端使用
一个 demo
该 demo 的作用是使 div 的背景从红色变成绿色,整个动画时间是 5s
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@keyframes myfirst { from {background: red;} to {background: yellow;} } div { animation: myfirst <span class="number">5</span>s; -moz-animation: myfirst <span class="number">5</span>s; <span class="comment">/* Firefox */</span> -webkit-animation: myfirst <span class="number">5</span>s; <span class="comment">/* Safari 和 Chrome */</span> -o-animation: myfirst <span class="number">5</span>s; <span class="comment">/* Opera */</span> } |
一个 H5 上的应用场景
H5 页面分屏的时候,底部一般会有一个小三角上下移动,表示还有一页内容的。
代码如下:
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 |
.item-1::after { position: absolute; left: 50%; margin-left: -11px; bottom: 1%; content: ''; background: url(../img/arrow.png) no-repeat center top; height: 22px; width: 20px; -webkit-animation: hover1 1s ease-in-out infinite alternate; animation: hover1 1s ease-in-out infinite alternate; -webkit-background-size: contain; background-size: contain; } @-webkit-keyframes hover1{ 0% { -webkit-transform: translateY(-10px); transform: translateY(-10px); } 100% { -webkit-transform: translateY(0); transform: translateY(0px); } } @keyframes hover1{ 0% { -webkit-transform: translateY(-10px); transform: translateY(-10px); } 100% { -webkit-transform: translateY(0); transform: translateY(0); } } |
可直接套用运行
最后的最后
在经历上面一番折腾之后,其实最终实现了的是另一种效果,感兴趣的同学可以用手机访问这里,看看第二页的效果。动画没什么特别,主要是变来变去的过程中用到了一些新的东西。
概念
域名系统(英文:Domain Name System,缩写:DNS)是因特网的一项服务。它作为将域名和 IP 地址相互映射的一个分布式数据库,能够使人更方便的访问互联网。DNS 使用 TCP 和 UDP 端口 53。当前,对于每一级域名长度的限制是 63 个字符,域名总长度则不能超过 253 个字符。
正向解析:从域名到 ip 的转换
反向解析:从 ip 到域名的转换
- 根域
就是一个".", 就是我们的网址,比如 www.example.com,实际是"www.example.com.", 最后是有一个点的。当然一般是被我们忽略了的。
全球共有 504 个根域服务器,分为 13 组。 - 域的划分
一种是按性质划分,如 org.,edu. 等,另一中是按国家划分, 如 cn.,jp. 等
每个域都有自己的域名服务器,也叫做权威服务器。
如 example.com 就是顶级域名,而 www.example.com 就表示 example.com 域下面的一个 www 主机。当然也有网站直接将顶级域名映射到 www 这个主机上的,这样就可以直接通过顶级域名来访问主机。
解析步骤
1、在浏览器中输入 www.example.com 域名,操作系统会先检查自己本地的 hosts 文件是否有这个网址映射关系,如果有,就先调用这个 IP 地址映射,完成域名解析。
2、如果 hosts 里没有这个域名的映射,则查找本地 DNS 解析器缓存,是否有这个网址映射关系,如果有,直接返回,完成域名解析。
3、如果 hosts 与本地 DNS 解析器缓存都没有相应的网址映射关系,首先会找 TCP/ip 参数中设置的首选 DNS 服务器,在此我们叫它本地 DNS 服务器,此服务器收到查询时,如果要查询的域名,包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析,此解析具有权威性。
4、如果要查询的域名,不由本地 DNS 服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个 IP 地址映射,完成域名解析,此解析不具有权威性。
5、如果本地 DNS 服务器本地区域文件与缓存解析都失效,则根据本地 DNS 服务器的设置(是否设置转发器)进行查询,如果未用转发模式,本地 DNS 就把请求发至 13 组根 DNS,根 DNS 服务器收到请求后会判断这个域名 (.com) 是谁来授权管理,并会返回一个负责该顶级域名服务器的一个 IP。本地 DNS 服务器收到 IP 信息后,将会联系负责.com 域的这台服务器。这台负责.com 域的服务器收到请求后,如果自己无法解析,它就会找一个管理.com 域的下一级 DNS 服务器地址 (example.com) 给本地 DNS 服务器。当本地 DNS 服务器收到这个地址后,就会找 example.com 域服务器,重复上面的动作,进行查询,直至找到 www.example.com 主机。
6、如果用的是转发模式,此 DNS 服务器就会把请求转发至上一级 DNS 服务器,由上一级服务器进行解析,上一级服务器如果不能解析,或找根 DNS 或把转请求转至上上级,以此循环。不管是本地 DNS 服务器用是是转发,还是根提示,最后都是把结果返回给本地 DNS 服务器,由此 DNS 服务器再返回给客户机。
node 框架
npm 上有一个 dns 的框架,可以做域名解析
- 安装
1 2 |
npm install -g dns |
- 正向解析
1 2 3 4 5 |
<span class="keyword">var</span> dns = <span class="keyword">require</span>(<span class="string">'dns'</span>); dns.lookup(<span class="string">'www.google.com'</span>, <span class="keyword">function</span> onLookup(err, addresses, family) { console.log(<span class="string">'addresses:'</span>, addresses); }); |
- 反向解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span class="keyword">var</span> dns = <span class="keyword">require</span>(<span class="string">'dns'</span>); dns.resolve4(<span class="string">'www.google.com'</span>, <span class="keyword">function</span> (err, addresses) { <span class="keyword">if</span> (err) <span class="keyword">throw</span> err; console.log(<span class="string">'addresses: '</span> + JSON.stringify(addresses)); addresses.<span class="keyword">forEach</span>(<span class="keyword">function</span> (a) { dns.reverse(a, <span class="keyword">function</span> (err, hostnames) { <span class="keyword">if</span> (err) { <span class="keyword">throw</span> err; } console.log(<span class="string">'reverse for '</span> + a + <span class="string">': '</span> + JSON.stringify(hostnames)); }); }); }); |
更多 API,这里
实战
一个反向代理的小实践
实现一个本地的服务,对于普通文件则直接取本地文件,对于请求则转发到服务器上,可配置希望转发的具体 ip。
代码会上传到 github 上。
背景
当前网速越来越快,但是随着网页内容越来越丰富,其实我们打开网页的速度并未得到什么提升,相反,过多的内容会导致网页打开速度变慢。于是,出现了一些性能优化的方法。
1. 合并文件,如 css,js 等
2. 将 js 文件放在文档的底部
3. 将服务器部署到离用户近的地方,如 cdn 技术
4. 缓存技术
5. 负载均衡
6. 文档直出
等等
有这么多通用的方式能够适用于我们的产品中,每一种实现的技术难度不大,当我们都应用了这些技术,发现网站性能依然不那么乐观的时候,会考虑到一些非常规、适用于某些特定场景的优化技术
另一种思路
Facebook 的研究科学家 changhao jiang 提出了一个优化方案,名字叫做 bigpipe,应用了此项技术的 facebook 首页,访问速度提升一倍。它极大的提升了 fackebook 的性能。它是怎么做到的。
传统的一个打开页面的步骤
- 浏览器发送 HTTP 请求
- 服务器接收到 HTTP 请求,解析请求,从存储层拉取数据,拼接 HTML,发回一个 HTTP 响应
- 这个请求通过网络传输到浏览器
- 浏览器解析接收到的数据,构造 DOM 树,下载 CSS 和 JavaScript
- 浏览器下载了 CSS 之后,开始解析 CSS,渲染页面
- 下载 JavaScript 之后,开始解析 JavaScript,执行 JavaScript
Bigpipe 的思路
- Request parsing:服务器解析和检查 http request
- Datafetching:服务器从存储层获取数据
- Markup generation:服务器生成 html 标记
- Network transport : 网络传输 response
- CSS downloading:浏览器下载 CSS
- DOM tree construction and CSS styling: 浏览器生成 DOM 树,并且使用 CSS
- JavaScript downloading: 浏览器下载页面引用的 JS 文件
- JavaScript execution: 浏览器执行页面 JS 代码
看着 bigpipe 的步骤和普通的方式没什么区别,其实,它只是其中一个模块(pagelet)的流程而已。而一个页面是可以分解成 N 个模块,多个模块以流水线式的方式运行
demo
一个 node 实现的 demo,实现基本的分块的思想
模拟服务器部分
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 |
http.createServer(<span class="keyword">function</span>(request, response) { <span class="comment">// Write the document</span> response.writeHead(<span class="number">200</span>, {<span class="string">"Content-Type"</span> : <span class="string">"text/html"</span>}); response.write(<span class="string">'<!DOCTYPE html>'</span>); response.write(<span class="string">'<head><script type="text/javascript">function arrived(id,text) { var b=document.getElementById(id); b.innerHTML = text; }</script>'</span>); response.write(<span class="string">"</head><body><div>Progressive Loading"</span>); <span class="keyword">for</span>(<span class="keyword">var</span> i = <span class="number">0</span>; i < <span class="number">6</span>; i++) { response.write(<span class="string">"<div id='"</span> + i + <span class="string">"'>"</span> + i + <span class="string">"</div>"</span>); } response.write(<span class="string">"</div>"</span>); <span class="keyword">var</span> down = <span class="number">6</span>; <span class="keyword">for</span> (i = <span class="number">0</span>; i < <span class="number">6</span>; i++) { http.get(<span class="string">"http://localhost:2000/?id="</span> + i, <span class="keyword">function</span>(res) { res.on(<span class="string">'data'</span>, <span class="keyword">function</span>(chunk) { response.write(chunk, <span class="string">'binary'</span>); }); res.on(<span class="string">'end'</span>, <span class="keyword">function</span>() { console.log(<span class="string">"down"</span>+down) <span class="keyword">if</span>((--down )== <span class="number">0</span>) { response.end(); } }) }); } response.write(<span class="string">"</body></html>"</span>); }).listen(<span class="number">8080</span>); |
模拟请求的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
http.createServer(<span class="keyword">function</span>(request, response) { <span class="comment">// Some delay upto upto 2 seconds</span> <span class="keyword">var</span> delay = Math.round(Math.random() * <span class="number">2000</span>); setTimeout(<span class="keyword">function</span>() { <span class="keyword">var</span> params = url.parse(request.url, <span class="keyword">true</span>); <span class="keyword">var</span> id = params.query.id; response.writeHead(<span class="number">200</span>, {<span class="string">"Content-Type"</span> : <span class="string">"text/html"</span>}); <span class="keyword">var</span> content = <span class="string">"<span>Content of Module "</span> + id + <span class="string">"</span>"</span>; response.write(<span class="string">"<script>"</span> + <span class="string">"arrived('"</span> + id + <span class="string">"', '"</span> + content + <span class="string">"');"</span> + <span class="string">"</script>"</span>); response.end(); }, delay); }).listen(<span class="number">2000</span>); |
一个框架
https://github.com/bigpipe/bigpipe
BigPipe is a radical new web framework for Node.JS. The general idea is to decompose web pages into small re-usable chunks of functionality called Pagelets and pipeline them through several execution stages inside web servers and browsers. This allows progressive rendering at the front-end and results in exceptional front-end performance.
框架会有些重,小型开发场景下可以考虑自己实现
存在的问题
1.seo
设置 useagent,爬虫来的时候给完整页面(有淘宝同学说这里存在 seo 问题,是否有 seo 问题还待确认,因为本身页面是在一个请求内完成)