看得出它的认可程度之高,让读者领悟它们之间

2019-10-06 作者:小鱼儿主页高手论坛   |   浏览(112)

理解SVG transform坐标变换

2015/10/11 · HTML5 · SVG

原文出处: 张鑫旭   

关于CSS Reset那些事(1):历史演变与Normalize.css

2015/08/01 · CSS · CSS Reset, Normalize.css

原文出处: Alsiso   

从输入 URL 到页面加载完成的过程中都发生了什么事情?

2015/10/03 · HTML5, JavaScript · 6 评论 · HTTP, 浏览器

原文出处: 百度FEX/吴多益(@吴多益)   

背景  本文来自于之前我发的一篇微博:

小鱼儿主页高手论坛 1

不过写这篇文章并不是为了帮大家准备面试,而是想借这道题来介绍计算机和互联网的基础知识,让读者了解它们之间是如何关联起来的。

为了便于理解,我将整个过程分为了六个问题来展开。

大型单页面应用的进阶挑战

2015/09/30 · HTML5, JavaScript · 单页应用

原文出处: 林子杰(@Zack__lin)   

阅读须知:这里的大型单页面应用(SPA Web App)是指页面和功能组件在一个某个量级以上,举个栗子,比如 30 个页面100 个组件,同时伴随着大量的数据交互操作和多个页面的数据同步操作。并且这里提到的页面,均属于 hash 页面,而多页面概念的页面,是一个独立的 html 文档。基于这个前提,我们再来讨论,否则我怕我们 Get 不到同一个 G 点上去。

一、HTML transform和SVG transform

SVG中自带transform属性,没错,是属性,例如:

小鱼儿主页高手论坛,JavaScript

<svg width="200" height="150"> <rect x="30" y="30" width="120" height="90" transform="rotate(45)"></rect> </svg>

1
2
3
<svg width="200" height="150">
    <rect x="30" y="30" width="120" height="90" transform="rotate(45)"></rect>
</svg>

普通的HTML元素没有transform属性,但是支持CSS3的transform, 好奇的小伙伴可能会疑问了,CSS3中的transform变换,跟SVG中的transform是什么关系呢?

恩,有点类似于谢霆锋和陈冠希之间的关系,有些小复杂。

小鱼儿主页高手论坛 2

OK, 先说说相似之处吧。
一些基本的变换类型是一样的,包括:位移translate, 旋转rotate, 缩放scale, 斜切skew以及直接矩阵matrix. 但只局限于2D层面的变换。SVG似乎只支持二维变换(若有不对,欢迎指正),且类似translateXrotateX也都是不支持的。

下面就是不一样的地方了:
1. CSS3 transform一般用在普通元素上,虽然也可以应用在SVG元素上,但是IE浏览器(IE edge未测试)却不支持SVG元素;

JavaScript

rect { /* IE说:你这是弄啥来? */ transform:rotate(45deg); }

1
2
3
4
rect {
    /* IE说:你这是弄啥来? */
    transform:rotate(45deg);
}

2. HTML元素的CSS3 transform和SVG的transform坐标系统大相径庭;

平常我们使用transform其坐标是相对于当前元素而言的,默认是元素的中心点变换,我们可以通过transform-origin属性改变变换的中心点。而SVG中的transform的坐标变换的是相对于画布的左上角计算的,跟HTML的transform差别较大,理解上也更加麻烦。而本文就是彻底理清SVG中的transform到底是怎么工作的。

3. 具体的语法细节有差异。SVG transform属性语法有些自带偏移。而CSS transform则更加纯粹些。

//zxx: 据说CSS的transform和SVG的transform属性即将合并。

前言

近期在翻阅陈旧的历史资料,整理之前饱受争议的CSS Reset问题,不过好像十多年过去,现在大家统一了口径,纷纷推荐使用Normalize.css,包括Bootstrap都进行了内置使用,可见它的认可程度之高。

由于文章涉及内容较多,会分为系列文章

第一章
整理CSS Reset历史的演变痕迹,从第一份CSS Reset的诞生,到提出No CSS Reset的思想,再到国产CSS Reset 1.0骄傲的诞生;最终时过境迁,CSS Reset被Normalize.css所替代;
随后开始认识Normalize.css,了解它都做了那些事情,诉说与CSS Reset的区别,突出优势,告诉你为什么要使用它。

第二章
由于Normalize.css只提供了英文文档,没有提供对应的中文版本,所以从这章开始对其源码进行翻译整理与解读,本章包含 html与body,HTML5元素,链接,语义化文本标签,内嵌元素,群组元素等内容解读。

第三章,
继续来介绍源码中的表单和表格部分,并且整理一份normalize-zh.css中文注释的版本上传至Github,供大家参考使用,敬请期待

第一个问题:从输入 URL 到浏览器接收的过程中发生了什么事情?

挑战一:前端组件化

基于我们所说的前提,第一个面对的挑战是组件化。这里还是要强调的是组件化根本目的不是为了复用,很多人根本没想明白这点,总是觉得造的轮子别的业务可以用,说不定以后也可以用。

其实前端发展迭代这么快,交互变化也快,各种适配更新层出不穷。今天造的轮子,过阵子别人造了个高级轮子,大家都会选更高档的轮子,所以现在前端界有一个现象就是为了让别人用自己的轮子,自己使劲不停地造。

在前端工业化生产趋势下,如果要提高生产效率,就必须让组件规范化标准化,达到怎样的程度呢?一辆车除了底盘和车身框架需要自己设计打造之外,其他标准化零件都可以采购组装(专业学得差,有啥谬误请指正)。也就是说,除了 UI 和前端架构需要自己解决之外,其他的组件都是可以奉行拿来主义的,如果打算让车子跑得更稳更安全,可以对组件进行打磨优化完善。

说了这么说,倒不如看看徐飞的文章《2015前端组件化框架之路》 里面写的内容都是经过一定实践得出的想法,所以大部分内容我是赞成而且深有体会的。

二、SVG transform translate位移

我们先来看下最简单最基本的translate位移变换,例如,我们偏移(295,115)大小的位置,HTML元素的偏移(下图左)和SVG元素的偏移(下图右)就会不一样。一个是相对自己的中心点(下图左),一个是SVG的左上角(下图右)。

小鱼儿主页高手论坛 3

虽然两者的相对位置不一样,但是,对于单纯地位移来讲,无论你相对于那个点位置,实际偏移的位置都是一样的,因此,从表现上讲,两者最终的位置看上去还是一样的。

您可以狠狠地点击这里:HTML translate和SVG translate比对demo

小鱼儿主页高手论坛 4

前面我们提到过,SVG元素也能使用CSS3的transform进行变换(非IE浏览器),但是只能支持2D层面的几个属性,例如translateX(tx),translateY(ty)以及translate(tx[, ty])translateZ(tz)则并不支持。

如果我们使用SVG元素自带的transform属性进行变换,则仅支持translate(tx[ ty])这种用法(缺省使用0代替),当多个参数值的时候,可以使用逗号,或者直接空格分隔,但是不能包含单位,例如下面这种写法直接翘辫子:

CSS

transform="translate(30px 12px)"

1
transform="translate(30px 12px)"

下面这种无单位写法才可以:

CSS

transform="translate(30 12)" transform="translate(30, 12)"

1
2
transform="translate(30 12)"        
transform="translate(30, 12)"

另外,和CSS3的transform一样,SVG中的translate位移也是支持多声明累加的。例如:

CSS

transform="translate(30 12) translate(30 12)"

1
transform="translate(30 12) translate(30 12)"

等同于:

CSS

transform="translate(60 24)"

1
transform="translate(60 24)"

需要注意的是,俩个translate中间不要混有其他的transform变换。否则,最终的位移就不是简单的相加了。

CSS Reset 历史回顾

从触屏到 CPU

首先是「输入 URL」,大部分人的第一反应会是键盘,不过为了与时俱进,这里将介绍触摸屏设备的交互。

触摸屏一种传感器,目前大多是基于电容(Capacitive)来实现的,以前都是直接覆盖在显示屏上的,不过最近出现了 3 种嵌入到显示屏中的技术,第一种是 iPhone 5 的 In-cell,它能减小了 0.5 毫米的厚度,第二种是三星使用的 On-cell 技术,第三种是国内厂商喜欢用的 OGS 全贴合技术,具体细节可以阅读这篇文章。

当手指在这个传感器上触摸时,有些电子会传递到手上,从而导致该区域的电压变化,触摸屏控制器芯片根据这个变化就能计算出所触摸的位置,然后通过总线接口将信号传到 CPU 的引脚上。

以 Nexus 5 为例,它所使用的触屏控制器是 Synaptics S3350B,总线接口为 I²C,以下是 Synaptics 触摸屏和处理器连接的示例:小鱼儿主页高手论坛 5

左边是处理器,右边是触摸屏控制器,中间的 SDA 和 SCL 连线就是 I²C 总线接口。

挑战二:路由去中心化

基于我们所说的前提,中心化的路由维护起来很坑爹(如果做一两个页面 DEMO 的就没必要出来现眼了)。MV* 架构就是存在这么个坑爹的问题,需要声明中心化 route(angular 和 react 等都需要先声明页面路由结构),针对不同的路由加载哪些组件模块。一旦页面多起来,甚至假如有人偷懒直接在某个路由写了一些业务耦合的逻辑,这个 route 的可维护性就变得有些糟糕了。而且用户访问的第一个页面,都需要加载 route,即使其他路由的代码跟当前页面无关。

我们再回过头来思考静态页面简单的加载方式。我们只要把 nginx 搭起来,把 html 页面放在对应的静态资源目录下,启动 nginx 服务后,在浏览器地址栏输入 127.0.0.1:8888/index.html 就可以访问到这个页面。再复杂一点,我们把目录整成下面的形式:

/post/201509151800.html /post/201509151905.html /post/201509152001.html /category/js_base_knowledge.html /category/css_junior_use.html /category/life_is_beautiful.html

1
2
3
4
5
6
/post/201509151800.html
/post/201509151905.html
/post/201509152001.html
/category/js_base_knowledge.html
/category/css_junior_use.html
/category/life_is_beautiful.html

这种目录结构很熟吧,对 SEO 很友好吧,当然这是后话了,跟我们今天说的不是一回事。这种目录结果,不用我们去给 Web Server 定义一堆路由规则,页面存在即返回,否则返回 404,完全不需要多余的声明逻辑。

基于这种目录结构,我们可以抽象成这样子:

/{page_type}/{page_name}.html

1
/{page_type}/{page_name}.html

其实还可以更简单:

/p/{name}.html

1
/p/{name}.html

从组件化的角度出发,还可以这样子:

/p/{name}/name.js /p/{name}/name.tpl /p/{name}/name.css

1
2
3
/p/{name}/name.js
/p/{name}/name.tpl
/p/{name}/name.css

所以,按照我们简化后的逻辑,我们只需要一个 page.js 这样一个路由加载器,按照我们约定的资源目录结构去加载相应的页面,我们就不需要去干声明路由并且中心化路由这种蠢事了。具体来看代码。咱也懒得去解析了,里面有注释。

三、SVG transform rotate旋转

上面的位移变换,我们似乎没看到明显的不一样。但是,从这里的旋转变换开始,就可以看出明显的差异了。

下面图示的是基本的45度旋转(来自css-tricks)(左HTML元素,右SVG元素):

小鱼儿主页高手论坛 6

由于SVG元素的默认是SVG左上角为中心变换的,因此,矩形旋转的幅度就有了过山车的感觉。

您可以狠狠地点击这里:HTML rotate和SVG rotate比对demo

小鱼儿主页高手论坛 7

结果会发现,两者位置大相径庭了:

CSS transform中的rotate语法比较直白:rotate(angle),就一个angle参数,表示角度大小,不过必须要有单位,比如deg(度), turn(圈), grad(百分度 – 一种角的测量单位,定义为一个圆周角的1/400。常用于建筑或土木工程的角度测量),甚至可以使用calc()计算,例如:calc(.25turn - 30deg).

但是,SVG中的属性transform旋转就没有这么多花头,单位?哦,别逗了,毛线都没有,直接光秃秃的数值,表示角度deg,例如:

CSS

transform="rotate(45)"

1
transform="rotate(45)"

具体语法为:rotate(angle[ x y]). 大家注意到没有,这里有个[ x y][]表示这个可选参数。也就是说,SVG中的rotate旋转比CSS的rotate多了一个可选参数,那这个可选参数[ x y]表示什么意思呢?

告诉你,是非常有用的东西。用来偏移transform变换中心点的。

为什么说非常有用呢?SVG元素默认是基于左上角的,但是我们的旋转元素往往都在SVG的中间区域,此时旋转跨度太大,智商余额不足的我们就脑补不过来,此时难免希望可以像CSS的transform变换一样,围绕元素的中心点变换。怎么办?

我们可以借助CSS3 transform-origin修改SVG元素默认的变换中心点,然后配合CSS变换。但是,我们前面多次提到,IE浏览器的SVG元素不识别CSS中的transform. 所以,从兼容性上讲,CSS策略是不可行的。难道就没有其他办法了,有,就是这里的可选参数[ x y],通过对变换中心点的偏移修正,我们也能让SVG元素围绕自身的中心点旋转了。

所以,上面的demo,我们稍微修改下,就能让矩形围绕自己旋转了,见下:

JavaScript

<rect x="30" y="30" width="120" height="90" rx="10" ry="10" fill="#a0b3d6" transform="rotate(45, 90 75)"></rect> <!-- 90 = 30 120/2 --> <!-- 75 = 30 90/2 -->

1
2
3
<rect x="30" y="30" width="120" height="90" rx="10" ry="10" fill="#a0b3d6" transform="rotate(45, 90 75)"></rect>
<!-- 90 = 30 120/2 -->
<!-- 75 = 30   90/2 -->

您可以狠狠地点击这里:SVG元素也围绕自身中心点旋转demo

小鱼儿主页高手论坛 8

使用原理图表示就是下面这样(左HTML旋转,右SVG元素偏移旋转):

小鱼儿主页高手论坛 9

同样的,rotate旋转可以多个值并存,例如下面的CSS和attribute用法:

CSS

transform: rotate(45deg) rotate(-45deg); transform="rotate(45) rotate(-45)

1
2
transform: rotate(45deg) rotate(-45deg);
transform="rotate(45) rotate(-45)

然而,需要注意的是,SVG属性的transform声明的中心变换坐标是不能共享的。

因此,虽然transform="rotate(45, 90 75)"是中心点旋转,但是,后面再添加其他东西,例如:rotate(-45)则偏移值忽略,终中心点还是SVG的左上角(0,0)位置,好惨!

例如原来的45度旋转,再加个-45度反向旋转:

XHTML

<rect x="30" y="30" width="120" height="90" rx="10" ry="10" fill="#a0b3d6" transform="rotate(45, 90 75) rotate(-45)"></rect>

1
<rect x="30" y="30" width="120" height="90" rx="10" ry="10" fill="#a0b3d6" transform="rotate(45, 90 75) rotate(-45)"></rect>

结果位置回去了?才怪呢!小鱼儿主页高手论坛 10

CSS的是又回去了,但是SVG的确是挂在月球上了。究其原因是rotate(-45)又是相对SVG左上角变换的啦!

小鱼儿主页高手论坛 11

您可以狠狠地点击这里:SVG连续旋转demo

虽然乍看上去,好像SVG的坐标系统有些怪怪的,但是,实际上,在有些需求场景下,SVG这种看似独立的偏移系统更容易实现一些功能。

比方说,我们希望某个SVG元素先以右下角为中心旋转90度,然后再以右上角为中心旋转90度,该怎么处理?

对于SVG transform,我们直接面向需求写数值就可以了。假设我们的SVG元素的高宽是120*90, 左上角坐标是(30,30), 则,显然,右下角坐标是(150,120), 右上角坐标是(150,30),于是,我们的transform值就很简单:

XHTML

transform="rotate(90, 150 120) rotate(90 150 30)"

1
transform="rotate(90, 150 120) rotate(90 150 30)"

参见下面的示意图(示意图的坐标与上面略有出入,但不影响原理示意):小鱼儿主页高手论坛 12

但是,如果我们使用之前容易理解的CSS3来实现,反而就复杂了,因为CSS3中的transform的变换点只能一次性指定,如果要实现不同变换点的旋转效果,只能通过translate再次偏移,例如,实现上面的右下角再右上角90度旋转,则要这样:

CSS

transform-origin: right bottom; /* 或者 100% 100% */ transform: rotate(90deg) translate(0, -100%) /* 从右下到右上 */ rotate(90deg) translate(0, 100%);

1
2
3
4
5
6
transform-origin: right bottom; /* 或者 100% 100% */
transform:
  rotate(90deg)
  translate(0, -100%) /* 从右下到右上 */
  rotate(90deg)
  translate(0, 100%);

Gif示意下就是:小鱼儿主页高手论坛 13

显然要麻烦很多。可见,两种坐标系统没有绝对的优劣。

您可以狠狠地点击这里:右下再右上旋转90度demo

小鱼儿主页高手论坛 14

上图为两种变换的最终效果,虽然最终的效果是一样的,但是,从理解上而言,这回,是SVG的transform反而更容易理解。还是那句话,辩证看问题,凡事无绝对。

第一份 CSS Reset

为什么会有CSS Reset的存在呢?那是因为早期的浏览器支持和理解的CSS规范不同,导致浏览器在渲染页面时效果不一致,出现很多兼容性问题。 关于 浏览器的默认样式 请点击查阅!

根据玉伯的文章中透漏,最早的一份CSS Reset来自Tantek 的undohtml.css,从URL中的日期可以看出时间是2004年,Tantek根据自身需要对于一些标签进行了简单的重置,源码如下:

CSS

/* undohtml.css */ /* (CC) 2004 Tantek Celik. Some Rights Reserved. */ :link,:visited { text-decoration:none } ul,ol { list-style:none } h1,h2,h3,h4,h5,h6,pre,code { font-size:1em; } ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,body,html,p,blockquote, fieldset,input{ margin:0; padding:0 } a img,:link img,:visited img { border:none } address { font-style:normal }

1
2
3
4
5
6
7
8
9
/* undohtml.css */
/* (CC) 2004 Tantek Celik. Some Rights Reserved.             */
:link,:visited { text-decoration:none }
ul,ol { list-style:none }
h1,h2,h3,h4,h5,h6,pre,code { font-size:1em; }
ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,body,html,p,blockquote,
fieldset,input{ margin:0; padding:0 }
a img,:link img,:visited img { border:none }
address { font-style:normal }

CPU 内部的处理

移动设备中的 CPU 并不是一个单独的芯片,而是和 GPU 等芯片集成在一起,被称为 SoC(片上系统)。

前面提到了触屏和 CPU 的连接,这个连接和大部分计算机内部的连接一样,都是通过电气信号来进行通信的,也就是电压高低的变化,如下面的时序图:小鱼儿主页高手论坛 15

在时钟的控制下,这些电流会经过 MOSFET 晶体管,晶体管中包含 N 型半导体和 P 型半导体,通过电压就能控制线路开闭,然后这些 MOSFET 构成了 CMOS,接着再由 CMOS 实现「与」「或」「非」等逻辑电路门,最后由逻辑电路门上就能实现加法、位移等计算,整体如下图所示(来自《计算机体系结构》):小鱼儿主页高手论坛 16

除了计算,在 CPU 中还需要存储单元来加载和存储数据,这个存储单元一般通过触发器(Flip-flop)来实现,称为寄存器。

以上这些概念都比较抽象,推荐阅读「How to Build an 8-Bit Computer」这篇文章,作者基于晶体管、二极管、电容等原件制作了一个 8 位的计算机,支持简单汇编指令和结果输出,虽然现代 CPU 的实现要比这个复杂得多,但基本原理还是一样的。

另外其实我也是刚开始学习 CPU 芯片的实现,所以就不在这误人子弟了,感兴趣的读者请阅读本节后面推荐的书籍。

挑战三:领域数据中心化

对于单向数据流循环和数据双向绑定谁优谁劣是永远也讨论没结果的问题,要看是什么业务场景什么业务逻辑,如果这个前提没统一好说啥都是白搭。当然,这个挑战的前提是非后台的单页面应用,后台的前端根本就不需要考虑前端内存缓存数据的处理,直接跟接口数据库交互就行了。明确了这个前提,我们接着讨论什么叫领域数据中心化。

前面讨论到两种数据绑定的方式,但是如果频繁跟接口交互:

  • 内存数据销毁了,重新请求数据耗时浪费流量
  • 如果两个接口字段部分不一样但是使用场景一样
  • 多个页面直接有部分的数据相同,但是先来后到导致某些计数字段不一致
  • 多个页面的数据相同,其中某些数据发生用户操作行为导致数据发生变动

因此,我们需要在业务视图逻辑层和数据接口层中间增加一个 store(领域模型),而这个 store 需要有一个统一的 内存缓存 cache,这个 cache 就是中心化的数据缓存。那这个 store 究竟是用来弄啥勒?

小鱼儿主页高手论坛 17

Store 具有多形态,每个 store 好比某一类物品的仓储(领域,换个词容易理解),如蔬果店 fruit-store, 服装店 clothes-store,蔬果店可以放苹果香蕉黑木耳,服装店可以放背心底裤人字拖。如果品种过于繁多,我们可以把蔬果店精细化运营变成香蕉专卖店,苹果专卖店(!== appstore),甚至是黑木耳专卖店…( _ _)ノ|,蔬果种类不一样,但是也都是称重按斤卖嘛。

var bannerStore = new fruitStore();

var appleStore = new fruitStore();

有了这些仓储之后,我们可以放心的把数据丢给视图逻辑层大胆去用。想修改数据?直接让 store 去改就行了,其他页面的 DOM 文本内容也得修改吧?那是其他页面的业务逻辑做的事,我们把事件抛出去就好了,他们处不处理那是他们的事,咱别瞎操心(业务隔离)。

那么 store 具体弄啥勒?

小鱼儿主页高手论坛 18

  • 32 个赞位置可点赞或者取消,三个页面的赞数需要同步,按钮点赞与取消的状态也要同步。
  • 条目是否已收藏,取消收藏后 Page B 需要删除数据,Page A C 需要同步状态,如果在 Page C 又有收藏操作,Page B 需要相应增减数据,Page A 状态需要同步。
  • 发评论,Page C 需要更新评论列表和评论数,Page A B 需要更新评论数。如果 Page B 没有被加载过,这时候 Page B 拿到的数据应该是最新的,需要同步给 A C 页面对应的数据进行更新。

所以,store 干的活就是数据状态读写和同步,如果把数据状态的操作放到各个页面自己去处理,页面一旦多了或者复杂起来,就会产生各个页面数据和状态可能不一致,页面之前双向引用(业务耦合严重)。store 还有另一个作用就是数据的输入输出格式化,简单举个栗子:小鱼儿主页高手论坛 19

  • 任何接口 API 返回的数据,都需要经过 input format 进行统一格式化,然后再写入 cache,因为读取的数据已按照我们约定的规范进行的处理,所以我们使用的时候也不需要理会接口是返回怎样的数据类型。
  • 某些组件需要的数据字段格式可能不同,如果把数据处理放在模板进行处理,会导致模板无法更加简洁通用(业务耦合),所以需要 output format 进行处理。

所以,store 就是扮演着这样的角色——是数据状态读写和同步,以及数据输入输出的格式化处理。

四、SVG transform scale缩放

SVG中的缩放的语法就比较单纯了,就scale(sx[, sy])sx表示横坐标缩放比例,sy表示纵坐标缩放比例。其中sy是可缺省的,如果缺失,表示使用和sx一样的值,也就是等比例缩放。其中,sxsy两个参数可以逗号分隔,也可以使用空格分隔。这和CSS3中的使用有所不同,两外,SVG transform属性值缩放是不支持scaleXscaleY这些鬼的。

同样的,CSS控制的transform和SVG元素属性控制的transform的坐标系统是不一样的。一个默认元素中心(下图左),一个是SVG画布左上角(下图右),于是(from css-tricks):小鱼儿主页高手论坛 20

因此,当我们对SVG元素scale缩放时候,发现位置也有出乎我们意料,就应该知道是怎么回事了。

rotate旋转虽然也是迥异坐标,但是其参数自带偏移参数,我们我们移个花接个木,还是可以得到我们想要的结果。但是,scale缩放这里,就要悲惨很多了,没有自带偏移参数,于是,当我们要实现SVG元素居中缩放的效果,还需要使用translate手动偏移。

怎么个手动偏移法呢?即使先translate其中心点位置到元素的中心坐标位置,然后缩放,然后坐标再反方向还原回去。例如,某元素中心点坐标是(95, 75), 垂直缩放1.5倍的效果则是:

CSS

transform="translate(95 75) scale(1, 1.5) translate(-95 -75)"

1
transform="translate(95 75) scale(1, 1.5) translate(-95 -75)"

您可以狠狠地点击这里:CSS transform和SVG transform scale缩放demo

对应的CSS代码就简单多了,直接:

CSS

.scale { transform: scale(1, 1.5); }

1
2
3
.scale {
    transform: scale(1, 1.5);
}

然后最终效果都是一样的:小鱼儿主页高手论坛 21

使用Gif原理示意如下:

小鱼儿主页高手论坛 22

CSS Reset 核心代码与作用

随后加入到CSS RESET的行列的大牛越来越多,比如业界领袖 YUI团队 以及Eric Meyer把这份CSS Reset变的更加充实,但是大家不难发现代码的核心部分还是重置,从此可以结论出早期的CSS Reset的作用就是清除所有浏览器默认样式,让它一切归零!

CSS

* { margin:0; padding:0 }

1
* { margin:0; padding:0 }

不过在此之后一段时间,有人开始批判这种暴力清零的CSS Reset方式,随后部分前端开发者们也传来一些争议声音,比如:

  1. *{ margin:0; padding:0; }会带来性能问题
  2. 使用通配符存在隐性问题
  3. 过渡的标签重置等于画蛇添足
  4. 过渡的标签重置导致语言元素失效

注:由于都是一些陈旧的老问题,就不提供出处了,再此不过多讨论,感兴趣Google~

从 CPU 到操作系统内核

前面说到触屏控制器将电气信号发送到 CPU 对应的引脚上,接着就会触发 CPU 的中断机制,以 Linux 为例,每个外部设备都有一标识符,称为中断请求(IRQ)号,可以通过 /proc/interrupts 文件来查看系统中所有设备的中断请求号,以下是 Nexus 7 (2013) 的部分结果:

shell@flo:/ $ cat /proc/interrupts CPU0 17: 0 GIC dg_timer 294: 1973609 msmgpio elan-ktf3k 314: 679 msmgpio KEY_POWER

1
2
3
4
5
shell@flo:/ $ cat /proc/interrupts
            CPU0
  17:          0       GIC  dg_timer
294:    1973609   msmgpio  elan-ktf3k
314:        679   msmgpio  KEY_POWER

因为 Nexus 7 使用了 ELAN 的触屏控制器,所以结果中的 elan-ktf3k 就是触屏的中断请求信息,其中 294 是中断号,1973609 是触发的次数(手指单击时会产生两次中断,但滑动时会产生上百次中断)。

为了简化这里不考虑优先级问题,以 ARMv7 架构的处理器为例,当中断发生时,CPU 会停下当前运行的程序,保存当前执行状态(如 PC 值),进入 IRQ 状态),然后跳转到对应的中断处理程序执行,这个程序一般由第三方内核驱动来实现,比如前面提到的 Nexus 7 的驱动源码在这里 touchscreen/ektf3k.c。

这个驱动程序将读取 I²C 总线中传来的位置数据,然后通过内核的 input_report_abs 等方法记录触屏按下坐标等信息,最后由内核中的input 子模块将这些信息都写进 /dev/input/event0 这个设备文件中,比如下面展示了一次触摸事件所产生的信息:

130|shell@flo:/ $ getevent -lt /dev/input/event0 [ 414624.658986] EV_ABS ABS_MT_TRACKING_ID 0000835c [ 414624.659017] EV_ABS ABS_MT_TOUCH_MAJOR 0000000b [ 414624.659047] EV_ABS ABS_MT_PRESSURE 0000001d [ 414624.659047] EV_ABS ABS_MT_POSITION_X 000003f0 [ 414624.659078] EV_ABS ABS_MT_POSITION_Y 00000588 [ 414624.659078] EV_SYN SYN_REPORT 00000000 [ 414624.699239] EV_ABS ABS_MT_TRACKING_ID ffffffff [ 414624.699270] EV_SYN SYN_REPORT 00000000

1
2
3
4
5
6
7
8
9
130|shell@flo:/ $ getevent -lt /dev/input/event0
[  414624.658986] EV_ABS       ABS_MT_TRACKING_ID   0000835c
[  414624.659017] EV_ABS       ABS_MT_TOUCH_MAJOR   0000000b
[  414624.659047] EV_ABS       ABS_MT_PRESSURE      0000001d
[  414624.659047] EV_ABS       ABS_MT_POSITION_X    000003f0
[  414624.659078] EV_ABS       ABS_MT_POSITION_Y    00000588
[  414624.659078] EV_SYN       SYN_REPORT           00000000
[  414624.699239] EV_ABS       ABS_MT_TRACKING_ID   ffffffff
[  414624.699270] EV_SYN       SYN_REPORT           00000000

挑战四:Hybrid App 化

现在 Hybrid App 架构应用很火啊 _ (:3」∠)_,不搞一下都不好意思说自己是做 H5的。这里所说的 Hybrid App 可不是那种内置打包的 html 源码那种,而是直接去服务端请求 html 文档那种,可能会使用离线缓存。有的人以为如果要使用 Hybrid 架构,就不能使用 SPA 的方式,其实 Hybrid 架构更应该使用 SPA。

遇到的几个问题,我简单列举一下:

  • 客户端通过 url 传参

    如果通过 http get 请求的 query 参数进行传参,会导致命中不到 html 文档缓存,所以通过 SPA 的 hash query 传参,可以规避这个问题。

  • 与其他 html 页面进行跳转

    这种场景下,进入新页面和返回旧页面导致 webview 会重新加载本地的 html 文档缓存,视觉体验很不爽,即使页面使用了离线缓存,而 SPA 可以规避这个问题。

  • 使用了离线缓存的页面需要支持代码多版本化

    由于采用了非覆盖性资源发布方式,所以需要仍然保留旧的代码一段时间,以防止用户使用旧的 html 文档访问某些按需加载功能或清除了本地缓存数据而拿不到旧版本代码。

  • js 和 css 资源 离线化

    由于离线缓存的资源需要先在 manifest 文件声明,你也不可能总是手动去维护需要引用的 js 和 css 资源,并且那些按需加载的功能也会因此失去按需加载的意义。所以需要将 js 和 css 缓存到 localstorage,直接省去这一步维护操作。至于用户清除 localstorage,参考第三点解决方案。

  • 图标资源离线化

    将图标文件进行 base64 编码后存入 css 文件,方便离线使用。

五、SVG transform skew斜切

先来了解下CSS中的斜切,斜切,如果单纯切一个方向,我们可以看成把矩形变成了平行四边形,其总面积不变化。

以纯X轴变换举例,skewX(-45deg)则下面这样子(灰色方块为原始位置):

小鱼儿主页高手论坛 23

skewX(45deg)则下面这样子:小鱼儿主页高手论坛 24

对于SVG的skew斜切变换,表现效果原理是一样的。但是,使用的语法却相当有意思。

在前面的一些变换中,例如位移、缩放之类是不支持translateXscaleX这种CSS常见用法的,但是这里的skew却有点让人哭笑不得:不支持skew(x[, y])这种语法,而只能是skewX或者skewY.

别问我为什么?我只是大自然的搬运工,我不生产语法。

因此,没有:

JavaScript

<del datetime="2015-10-10T12:49:32 00:00">transform="skew(45, 0)"</del>

1
<del datetime="2015-10-10T12:49:32 00:00">transform="skew(45, 0)"</del>

只有:

CSS

transform="skewX(45)"

1
transform="skewX(45)"

同样的,由于变换中心点的差异,CSS实现的变换和SVG属性变换往往最后的位置是不一样的:

小鱼儿主页高手论坛 25

不仅如此,如果元素的中心点不是就是SVG的左上角,则skewX(α1) skewX(α2)的最终位置和skewX(α1 α2)是不一样的(位移和旋转不会这样子)。

您可以狠狠地点击这里:CSS SVG transform skew斜切差异及连续斜切差异demo

正如demo所示,CSS的和SVG的位置差异很大:小鱼儿主页高手论坛 26

SVG的连续变换和一次性变换的位置也是不一样的:小鱼儿主页高手论坛 27

可能有人要疑问,为何连续斜切变换和一次性变换位置会不一样?其实原因很简单,因为斜切的角度和元素偏移大小并不是线性的,比方说,从70到80度和80度到90度之间的位移大小(虽然都是10度的变化区间)是显然不是一个档次的。因此,分开多次连续斜切最终的坐标偏移要比一次性偏移来得小。

最后,和缩放一样,你想要让SVG元素中心点斜切,可以先translate偏移,在skew变换。就不重复举例演示了。

No CSS Reset 思想

Jonathan Snook是第一个提出No CSS Reset思想,其核心是Less is more,少即是多,不提倡使用暴力归零的方法。

玉伯后来也在《Reset CSS研究》文章中阐述说明,其实 Eric Meyer 并不期望大家下载他的 CSS Reset 后直接就拿去用,而是应该按照自己的需求,适量裁剪和修改后再使用。

后来YUI更新了cssreset,还配套有 cssfonts 和 cssbase。cssreset只负责清除默认样式,而CSS fonts 和 CSS base 则将一些元素的默认样式重设回来,这就消除了之前的争议,这一又迅速成为大家的通用解决方法了。

YUI 提供的cssfonts.css

CSS

/* YUI 3.18.1 (build f7e7bcb) Copyright 2014 Yahoo! Inc. All rights reserved. Licensed under the BSD License. */ /** * Percents could work for IE, but for backCompat purposes, we are using keywords. * x-small is for IE6/7 quirks mode. */ body { font:13px/1.231 arial,helvetica,clean,sans-serif; *font-size:small; /* for IE */ *font:x-small; /* for IE in quirks mode */ } /** * Nudge down to get to 13px equivalent for these form elements */ select, input, button, textarea { font:99% arial,helvetica,clean,sans-serif; } /** * To help tables remember to inherit */ table { font-size:inherit; font:100%; } /** * Bump up IE to get to 13px equivalent for these fixed-width elements */ pre, code, kbd, samp, tt { font-family:monospace; *font-size:108%; line-height:100%; } /* YUI CSS Detection Stamp */ #yui3-css-stamp.cssfonts { display: none; }

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
/*
YUI 3.18.1 (build f7e7bcb)
Copyright 2014 Yahoo! Inc. All rights reserved.
Licensed under the BSD License.
http://yuilibrary.com/license/
*/
 
/**
* Percents could work for IE, but for backCompat purposes, we are using keywords.
* x-small is for IE6/7 quirks mode.
*/
body {
font:13px/1.231 arial,helvetica,clean,sans-serif;
*font-size:small; /* for IE */
*font:x-small; /* for IE in quirks mode */
}
 
/**
* Nudge down to get to 13px equivalent for these form elements
*/
select,
input,
button,
textarea {
font:99% arial,helvetica,clean,sans-serif;
}
 
/**
* To help tables remember to inherit
*/
table {
font-size:inherit;
font:100%;
}
 
/**
* Bump up IE to get to 13px equivalent for these fixed-width elements
*/
pre,
code,
kbd,
samp,
tt {
font-family:monospace;
*font-size:108%;
line-height:100%;
}
 
/* YUI CSS Detection Stamp */
#yui3-css-stamp.cssfonts { display: none; }

从操作系统 GUI 到浏览器

前面提到 Linux 内核已经完成了对硬件的抽象,其它程序只需要通过监听 /dev/input/event0 文件的变化就能知道用户进行了哪些触摸操作,不过如果每个程序都这么做实在太麻烦了,所以在图像操作系统中都会包含 GUI 框架来方便应用程序开发,比如 Linux 下著名的 X。

但 Android 并没有使用 X,而是自己实现了一套 GUI 框架,其中有个 EventHub 的服务会通过 epoll 方式监听 /dev/input/ 目录下的文件,然后将这些信息传递到 Android 的窗口管理服务(WindowManagerService)中,它会根据位置信息来查找相应的 app,然后调用其中的监听函数(如 onTouch 等)。

就这样,我们解答了第一个问题,不过由于时间有限,这里省略了很多细节,想进一步学习的读者推荐阅读以下书籍。

挑战五:性能优化

@前端农民工 在 别处 已经说得很清楚了,直接传送门过去看吧,这里不罗嗦了。

 

1 赞 2 收藏 评论

小鱼儿主页高手论坛 28

六、其他居中变换处理

像缩放、斜切这些SVG变换,想要如CSS transform-origin:50% 50%一样的中心点变换效果,需要事先位移,我们有没有其他办法呢?

这里有两个思路可供大家参考下。

1. 原始中心位置乃SVG左上角
拿45度旋转举例,我们可以把元素默认就放在中心点和SVG左上角重合的位置上,参见下面的gif演示:小鱼儿主页高手论坛 29

于是,我们原来的3步曲就变成了2步曲:

CSS

translate(140 105) rotate(45) translate(-140 -105) → translate(140 105) rotate(45)

1
translate(140 105) rotate(45) translate(-140 -105) → translate(140 105) rotate(45)

2. 通过viewBox调整
viewBox可以用来改变SVG画布的视区,这个我之前专门撰文介绍过,是SVG学习必备被深入理解的基础知识,参见:“理解SVG的viewport,viewBox,preserveAspectRatio”一文。

我们可以把元素默认挂在左上角,然后,通过viewBox做手脚,让元素呈现的位置并不是真正的左上角,例如应用viewBox='-140 -105 280 210',则变化如下示意图:

小鱼儿主页高手论坛 30

此时,我们只需要让元素旋转就可以了,无需额外的做translate位移,见下gif:小鱼儿主页高手论坛 31

国产 CSS Reset

这是YUI最新更新的一次版本V3.18.1,但是很尴尬的发现,YUI 提供的 cssfonts 和 cssbase 只考虑了西欧文字,对汉字的支持却不多,这就导致很多用户只使用了cssreset,而没有使用其他两个。

据说nake和adiaos两大运动品牌到天朝后,有些运动科技会缩水,但是万万没想到,万能的代码到了天朝也是会缩水的。 – -!

于是乎,有些大牛不甘心,不仅厌倦了国内抄来抄去的CSS Reset,也受够了只考虑西欧洲字体,不考虑汉字的缺陷,大厂们就开始摸索制定属于自己的CSS Reset,比如2009年阿里Kissy框架 (源码连接已失效,主页留纪念) 的第一份CSS Reset:

CSS

/* KISSY CSS Reset 理念:清除和重置是紧密不可分的 特色:1.适应中文 2.基于最新主流浏览器 维护:玉伯(lifesinger@gmail.com), 正淳(ragecarrier@gmail.com) */ /* 清除内外边距 */ body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, /* structural elements 结构元素 */ dl, dt, dd, ul, ol, li, /* list elements 列表元素 */ pre, /* text formatting elements 文本格式元素 */ fieldset, lengend, button, input, textarea, /* form elements 表单元素 */ th, td { /* table elements 表格元素 */ margin: 0; padding: 0; } /* 设置默认字体 */ body, button, input, select, textarea { /* for ie */ /*font: 12px/1 Tahoma, Helvetica, Arial, "宋体", sans-serif;*/ font: 12px/1 Tahoma, Helvetica, Arial, "5b8b4f53", sans-serif; /* 用 ascii 字符表示,使得在任何编码下都无问题 */ } h1 { font-size: 18px; /* 18px / 12px = 1.5 */ } h2 { font-size: 16px; } h3 { font-size: 14px; } h4, h5, h6 { font-size: 100%; } address, cite, dfn, em, var { font-style: normal; } /* 将斜体扶正 */ code, kbd, pre, samp, tt { font-family: "Courier New", Courier, monospace; } /* 统一等宽字体 */ small { font-size: 12px; } /* 小于 12px 的中文很难阅读,让 small 正常化 */ /* 重置列表元素 */ ul, ol { list-style: none; } /* 重置文本格式元素 */ a { text-decoration: none; } a:hover { text-decoration: underline; } abbr[title], acronym[title] { /* 注:1.ie6 不支持 abbr; 2.这里用了属性选择符,ie6 下无效果 */ border-bottom: 1px dotted; cursor: help; } q:before, q:after { content: ''; } /* 重置表单元素 */ legend { color: #000; } /* for ie6 */ fieldset, img { border: none; } /* img 搭车:让链接里的 img 无边框 */ /* 注:optgroup 无法扶正 */ button, input, select, textarea { font-size: 100%; /* 使得表单元素在 ie 下能继承字体大小 */ } /* 重置表格元素 */ table { border-collapse: collapse; border-spacing: 0; } /* 重置 hr */ hr { border: none; height: 1px; } /* 让非ie浏览器默认也显示垂直滚动条,防止因滚动条引起的闪烁 */ html { overflow-y: scroll; }

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
/* KISSY CSS Reset
理念:清除和重置是紧密不可分的
特色:1.适应中文 2.基于最新主流浏览器
维护:玉伯(lifesinger@gmail.com), 正淳(ragecarrier@gmail.com)
*/
 
/* 清除内外边距 */
body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, /* structural elements 结构元素 */
dl, dt, dd, ul, ol, li, /* list elements 列表元素 */
pre, /* text formatting elements 文本格式元素 */
fieldset, lengend, button, input, textarea, /* form elements 表单元素 */
th, td { /* table elements 表格元素 */
    margin: 0;
    padding: 0;
}
 
/* 设置默认字体 */
body,
button, input, select, textarea { /* for ie */
    /*font: 12px/1 Tahoma, Helvetica, Arial, "宋体", sans-serif;*/
    font: 12px/1 Tahoma, Helvetica, Arial, "5b8b4f53", sans-serif;
    /* 用 ascii 字符表示,使得在任何编码下都无问题 */
}
 
h1 { font-size: 18px; /* 18px / 12px = 1.5 */ }
h2 { font-size: 16px; }
h3 { font-size: 14px; }
h4, h5, h6 { font-size: 100%; }
 
address, cite, dfn, em, var { font-style: normal; } /* 将斜体扶正 */
code, kbd, pre, samp, tt { font-family: "Courier New", Courier, monospace; } /* 统一等宽字体 */
small { font-size: 12px; } /* 小于 12px 的中文很难阅读,让 small 正常化 */
 
/* 重置列表元素 */
ul, ol { list-style: none; }
 
/* 重置文本格式元素 */
a { text-decoration: none; }
a:hover { text-decoration: underline; }
 
abbr[title], acronym[title] { /* 注:1.ie6 不支持 abbr; 2.这里用了属性选择符,ie6 下无效果 */
border-bottom: 1px dotted;
cursor: help;
}
 
q:before, q:after { content: ''; }
 
/* 重置表单元素 */
legend { color: #000; } /* for ie6 */
fieldset, img { border: none; } /* img 搭车:让链接里的 img 无边框 */
/* 注:optgroup 无法扶正 */
button, input, select, textarea {
    font-size: 100%; /* 使得表单元素在 ie 下能继承字体大小 */
}
 
/* 重置表格元素 */
table {
border-collapse: collapse;
border-spacing: 0;
}
 
/* 重置 hr */
hr {
    border: none;
    height: 1px;
}
/* 让非ie浏览器默认也显示垂直滚动条,防止因滚动条引起的闪烁 */
html { overflow-y: scroll; }

 

记得玉伯在写完第一版本的CSS Reset后,在文章的结尾还是千叮咛,万嘱咐说:

请记住:永远不存在万能解决方案,永远没有银弹。
因此我的建议和 Eric 是一样的:请根据具体需求,适量裁剪和修改后再使用。

扩展学习

  • 《计算机体系结构》
  • 《计算机体系结构:量化研究方法》
  • 《计算机组成与设计:硬件/软件接口》
  • 《编码》
  • 《CPU自制入门》
  • 《操作系统概念》
  • 《ARMv7-AR 体系结构参考手册》
  • 《Linux内核设计与实现》
  • 《精通Linux设备驱动程序开发》

七、结束语

本文介绍的内容实际上都还是非常基本的。实际SVG应用的时候,可能是多个变换参杂在一起,所以,如果本文介绍的几个基本变换都没搞清楚,到时候,想必是想破脑袋都不明白怎么元素跑这里了,怎么变成这样了!

本文的这些知识点虽然基本,但是相当重要的。再加上,不同的变换方法的语法细节还不一样。有的自带偏移,有的需要手动偏移等等;不同变换的前后位置不同,甚至同一变换分开连续变换和一次性变换的结果都不一样等等;都要求大家要细心耐心阅读。

本文内容和结构参考自:Transforms on SVG Elements. 但要比原文要精炼很多,同时,每一个变换都有亲自实践认证,因此,从品质上讲,可能还要略高一筹。

对了,矩阵matrix没有细说过,这个可以参考我之前的文章:“理解CSS3 transform中的Matrix(矩阵)”,一脉相承的。

我也是初学者,出错在所难免,欢迎指正!

感谢阅读,欢迎交流!小鱼儿主页高手论坛 32

1 赞 收藏 评论

小鱼儿主页高手论坛 33

CSS Reset 替代品 Normalize.css

我们把历史拉回到今天,时过境迁,CSS Reset 逐渐淡出的前沿前端的视野,被取而代之就是Normalize.css,关于对CSS Reset 与 Normalize.css的区别?可以引用知乎上 张小核桃 的一个回答:

CSS Reset 是革命党,CSS Reset 里最激进那一派提倡不管你小子有用没用,通通给我脱了那身衣服,凭什么你 body 出生就穿一圈 margin,凭什么你姓 h 的比别人吃得胖,凭什么你 ul 戴一胳膊珠子。于是 *{margin:0;} 等等运动,把人家全拍扁了。看似是众生平等了,实则是浪费了资源又占不到便宜,有求于人家的时候还得贱贱地给加回去,实在需要人家的默认样式了怎么办?人家锅都扔炉子里烧了,自己看着办吧。

Normalize.css 是改良派。他们提倡,各个元素都有其存在的道理,简单粗暴地一视同仁是不好的。body 那一圈确实挤压了页面的生存空间,那就改掉。士农工商,谁有谁的作用,给他们制定个规范,确保他们在任何浏览器里都干好自己的活儿。

下一章节会对Normalize.css进行简单的介绍,关于两者的差异区别可以看问答平台的问题:
使用normalize.css遇到的问题?
Normalize.css 和 Reset CSS 有什么本质区别没?

第二个问题:浏览器如何向网卡发送数据?

Normalize.css 简单介绍

关于对Github的介绍,这里引用 咀嚼之味 针对 官方介绍 翻译的的 中文版本。

从浏览器到浏览器内核

前面提到操作系统 GUI 将输入事件传递到了浏览器中,在这过程中,浏览器可能会做一些预处理,比如 Chrome 会根据历史统计来预估所输入字符对应的网站,比如输入了「ba」,根据之前的历史发现 90% 的概率会访问「www.baidu.com 」,因此就会在输入回车前就马上开始建立 TCP 链接甚至渲染了,这里面还有很多其它策略,感兴趣的读者推荐阅读 High Performance Networking in Chrome。

接着是输入 URL 后的「回车」,这时浏览器会对 URL 进行检查,首先判断协议,如果是 http 就按照 Web 来处理,另外还会对这个 URL 进行安全检查,然后直接调用浏览器内核中的对应方法,比如 WebView 中的 loadUrl 方法。

在浏览器内核中会先查看缓存,然后设置 UA 等 HTTP 信息,接着调用不同平台下网络请求的方法。

需要注意浏览器和浏览器内核是不同的概念,浏览器指的是 Chrome、Firefox,而浏览器内核则是 Blink、Gecko,浏览器内核只负责渲染,GUI 及网络连接等跨平台工作则是浏览器实现的

简要概述

Normalize.css 是@necolas和@jon_neal 两位大牛花了几百个小时来研究不同浏览器的默认样式的差异而得出的结晶,感谢前辈们的贡献。

Normalize.css 只是一个很小的CSS文件,但它在默认的HTML元素样式上提供了跨浏览器的高度一致性。相比于传统的CSS Reset,Normalize.css是一种现代的、为HTML5准备的优质替代方案。Normalize.css现在已经被用于Twitter Bootstrap、HTML5 Boilerplate、GOV.UK、Rdio、CSS Tricks 以及许许多多其他框架、工具和网站上。

目前Normalize.css 已经成为了CSS Reset的替代方案是无可争议的事情了。国内著名的AliceUI,AmazeUI 框架都是基于或者借鉴Normalize.css进行的制定化版本。

可以从这里下载:
Github:

HTTP 请求的发送

因为网络的底层实现是和内核相关的,所以这一部分需要针对不同平台进行处理,从应用层角度看主要做两件事情:通过 DNS 查询 IP、通过 Socket 发送数据,接下来就分别介绍这两方面的内容。

做了那些事

Normalize.css做了以下几件事:

  • Preserves useful defaults, unlike many CSS resets.
    保护有用的浏览器默认样式而不是完全去掉它们
  • Normalizes styles for a wide range of elements
    一般化的样式:为大部分HTML元素提供
  • Corrects bugs and common browser inconsistencies
    修复浏览器自身的bug并保证各浏览器的一致性
  • Improves usability with subtle improvements
    优化CSS可用性:用一些小技巧
  • Explains what code does using detailed comments
    解释代码:用注释和详细的文档来

DNS 查询

应用程序可以直接调用 Libc 提供的 getaddrinfo() 方法来实现 DNS 查询。

DNS 查询其实是基于 UDP 来实现的,这里我们通过一个具体例子来了解它的查找过程,以下是使用 dig trace fex.baidu.com 命令得到的结果(省略了一些):

; <<>> DiG 9.8.3-P1 <<>> trace fex.baidu.com ;; global options: cmd . 11157 IN NS g.root-servers.net. . 11157 IN NS i.root-servers.net. . 11157 IN NS j.root-servers.net. . 11157 IN NS a.root-servers.net. . 11157 IN NS l.root-servers.net. ;; Received 228 bytes from 8.8.8.8#53(8.8.8.8) in 220 ms com. 172800 IN NS a.gtld-servers.net. com. 172800 IN NS c.gtld-servers.net. com. 172800 IN NS m.gtld-servers.net. com. 172800 IN NS h.gtld-servers.net. com. 172800 IN NS e.gtld-servers.net. ;; Received 503 bytes from 192.36.148.17#53(192.36.148.17) in 185 ms baidu.com. 172800 IN NS dns.baidu.com. baidu.com. 172800 IN NS ns2.baidu.com. baidu.com. 172800 IN NS ns3.baidu.com. baidu.com. 172800 IN NS ns4.baidu.com. baidu.com. 172800 IN NS ns7.baidu.com. ;; Received 201 bytes from 192.48.79.30#53(192.48.79.30) in 1237 ms fex.baidu.com. 7200 IN CNAME fexteam.duapp.com. fexteam.duapp.com. 300 IN CNAME duapp.n.shifen.com. n.shifen.com. 86400 IN NS ns1.n.shifen.com. n.shifen.com. 86400 IN NS ns4.n.shifen.com. n.shifen.com. 86400 IN NS ns2.n.shifen.com. n.shifen.com. 86400 IN NS ns5.n.shifen.com. n.shifen.com. 86400 IN NS ns3.n.shifen.com. ;; Received 258 bytes from 61.135.165.235#53(61.135.165.235) in 2 ms

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
; <<>> DiG 9.8.3-P1 <<>> trace fex.baidu.com
;; global options: cmd
.           11157   IN  NS  g.root-servers.net.
.           11157   IN  NS  i.root-servers.net.
.           11157   IN  NS  j.root-servers.net.
.           11157   IN  NS  a.root-servers.net.
.           11157   IN  NS  l.root-servers.net.
;; Received 228 bytes from 8.8.8.8#53(8.8.8.8) in 220 ms
 
com.            172800  IN  NS  a.gtld-servers.net.
com.            172800  IN  NS  c.gtld-servers.net.
com.            172800  IN  NS  m.gtld-servers.net.
com.            172800  IN  NS  h.gtld-servers.net.
com.            172800  IN  NS  e.gtld-servers.net.
;; Received 503 bytes from 192.36.148.17#53(192.36.148.17) in 185 ms
 
baidu.com.      172800  IN  NS  dns.baidu.com.
baidu.com.      172800  IN  NS  ns2.baidu.com.
baidu.com.      172800  IN  NS  ns3.baidu.com.
baidu.com.      172800  IN  NS  ns4.baidu.com.
baidu.com.      172800  IN  NS  ns7.baidu.com.
;; Received 201 bytes from 192.48.79.30#53(192.48.79.30) in 1237 ms
 
fex.baidu.com.      7200    IN  CNAME   fexteam.duapp.com.
fexteam.duapp.com.  300 IN  CNAME   duapp.n.shifen.com.
n.shifen.com.       86400   IN  NS  ns1.n.shifen.com.
n.shifen.com.       86400   IN  NS  ns4.n.shifen.com.
n.shifen.com.       86400   IN  NS  ns2.n.shifen.com.
n.shifen.com.       86400   IN  NS  ns5.n.shifen.com.
n.shifen.com.       86400   IN  NS  ns3.n.shifen.com.
;; Received 258 bytes from 61.135.165.235#53(61.135.165.235) in 2 ms

可以看到这是一个逐步缩小范围的查找过程,首先由本机所设置的 DNS 服务器(8.8.8.8)向 DNS 根节点查询负责 .com 区域的域务器,然后通过其中一个负责 .com 的服务器查询负责 baidu.com 的服务器,最后由其中一个 baidu.com 的域名服务器查询 fex.baidu.com 域名的地址。

可能你在查询某些域名的时会发现和上面不一样,最底将看到有个奇怪的服务器抢先返回结果。。。

这里为了方便描述,忽略了很多不同的情况,比如 127.0.0.1 其实走的是 loopback,和网卡设备没关系;比如 Chrome 会在浏览器启动的时预先查询 10 个你有可能访问的域名;还有 Hosts 文件、缓存时间 TTL(Time to live)的影响等。

优势对比

前面讲到CSS Reset的核心作用就是清零,而且过于暴力;那么作为后者Normalize.css,到底有什么优势可以完全取代前者呢?

1.Normalize.css 保护了有价值的默认值
Reset通过为几乎所有的元素施加默认样式,强行使得元素有相同的视觉效果。 相比之下,Normalize.css保持了许多默认的浏览器样式。 这就意味着你不用再为所有公共的排版元素重新设置样式。 当一个元素在不同的浏览器中有不同的默认值时,Normalize.css会力求让这些样式保持一致并尽可能与现代标准相符合。

2.Normalize.css 修复了浏览器的bug
它修复了常见的桌面端和移动端浏览器的bug。这往往超出了Reset所能做到的范畴。 关于这一点,Normalize.css修复的问题包含了HTML5元素的显示设置、预格式化文字的font-size问题、在IE9中SVG的溢出、许多出现在各浏览器和操作系统中的与表单相关的bug。

3.Normalize.css 修复了浏览器的bug
使用Reset最让人困扰的地方莫过于在浏览器调试工具中大段大段的继承链。在Normalize.css中就不会有这样的问题,因为在我们的准则中对多选择器的使用时非常谨慎的,我们仅会有目的地对目标元素设置样式。

4.Normalize.css 是模块化的
这个项目已经被拆分为多个相关却又独立的部分,这使得你能够很容易也很清楚地知道哪些元素被设置了特定的值。因此这能让你自己选择性地移除掉某些永远不会用到部分(比如表单的一般化)。

5.Normalize.css 拥有详细的文档
Normalize.css的代码基于详细而全面的跨浏览器研究与测试。这个文件中拥有详细的代码说明并在Github Wiki中有进一步的说明。这意味着你可以找到每一行代码具体完成了什么工作、为什么要写这句代码、浏览器之间的差异,并且你可以更容易地进行自己的测试。

这个项目的目标是帮助人们了解浏览器默认是如何渲染元素的,同时也让人们很容易地明白如何改进浏览器渲染。

通过 Socket 发送数据

有了 IP 地址,就可以通过 Socket API 来发送数据了,这时可以选择 TCP 或 UDP 协议,具体使用方法这里就不介绍了,推荐阅读 Beej’s Guide to Network Programming。

HTTP 常用的是 TCP 协议,由于 TCP 协议的具体细节到处都能看到,所以本文就不介绍了,这里谈一下 TCP 的 Head-of-line blocking 问题:假设客户端的发送了 3 个 TCP 片段(segments),编号分别是 1、2、3,如果编号为 1 的包传输时丢了,即便编号 2 和 3 已经到达也只能等待,因为 TCP 协议需要保证顺序,这个问题在 HTTP pipelining 下更严重,因为 HTTP pipelining 可以让多个 HTTP 请求通过一个 TCP 发送,比如发送两张图片,可能第二张图片的数据已经全收到了,但还得等第一张图片的数据传到。

为了解决 TCP 协议的性能问题,Chrome 团队去年提出了 QUIC 协议,它是基于 UDP 实现的可靠传输,比起 TCP,它能减少很多来回(round trip)时间,还有前向纠错码(Forward Error Correction)等功能。目前 Google Plus、 Gmail、Google Search、blogspot、Youtube 等几乎大部分 Google 产品都在使用 QUIC,可以通过 chrome://net-internals/#spdy 页面来发现。

虽然目前除了 Google 还没人用 QUIC,但我觉得挺有前景的,因为优化 TCP 需要升级系统内核(比如 Fast Open)。

浏览器对同一个域名有连接数限制,大部分是 6,我以前认为将这个连接数改大后会提升性能,但实际上并不是这样的,Chrome 团队有做过实验,发现从 6 改成 10 后性能反而下降了,造成这个现象的因素有很多,如建立连接的开销、拥塞控制等问题,而像 SPDY、HTTP 2.0 协议尽管只使用一个 TCP 连接来传输数据,但性能反而更好,而且还能实现请求优先级。

另外,因为 HTTP 请求是纯文本格式的,所以在 TCP 的数据段中可以直接分析 HTTP 的文本,如果发现。。。

本文由小鱼儿玄机30码发布于小鱼儿主页高手论坛,转载请注明出处:看得出它的认可程度之高,让读者领悟它们之间

关键词: 小鱼儿玄机30码