整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

拥有了“猛男粉”的iPhone 13,值得等等党们换

拥有了“猛男粉”的iPhone 13,值得等等党们换新吗?

国网友可算把iPhone 13盼来了。


去年iPhone 12系列作为苹果的5G手机开端,有太多不想做第一批吃螃蟹的人;一个王守义十三香的梗,给了“等等党”们一个自洽的借口,为iPhone 13苦等一年。


今天凌晨,库克终于带着它身现直播间。你的等待究竟是“物有所值”还是“终究错付”,终于要揭晓了。


杨景怡 刘冬宇 | 作者

李拓 | 编辑

放大灯团队 | 策划



iPhone 13系列:要不咱别等了?


与去年iPhone 12如出一辙,iPhone 13依然有iPhone 13 mini、iPhone 13、iPhone 13 Pro和iPhone 13 Pro Max四款产品。它们的尺寸也没有变化,iPhone 13 mini和iPhone 13 Pro Max的屏幕尺寸分别为5.4寸和6.7寸,而另外两款则为6.1寸。


如果你也看完了发布会的全过程,也许会发现苹果拥有了更多颜色,并且机型的颜色更难记了——以至于当iPhone 13和iPhone 13 Pro发布颜色时,你可能已经对颜色感到疲劳。它们总共有多达9种颜色,其中iPhone 13五种、13 Pro四种,没有任何重复与交集。


苹果对颜色的审美也不是一成不变的,但总的说来,这届iPhone远没有12系列那么“雷人”。iPhone 13和mini取消了去年颇具人气的绿色和不太见得到的紫色,新增了粉色;去年被吐槽成塑料拖鞋的蓝色,今年更灰了一点,看起来就两个字:高级。



头顶上的iPhone 13 Pro系列,也没了“地才蓝”,新增了一个熟悉的金色,它看起来几乎就是iPhone Xs的金色的翻版(当时就有不少吐槽的声音,“科技以换壳为本”之类的),以及另一个全新的浅蓝色“远峰蓝”——由于整体结构的相似性,如果不买这两种颜色,围观群众很可能看不出来你用的是iPhone 13 Pro不用怀疑,这个新增的浅蓝色,很快就能成为今年最抢手的新iPhone


回到实在的事情上,看看iPhone 13系列有什么技术升级。


更小的“刘海”。郭明錤老师预测过了,它可能让你的观看体验好那么一点点,但这不是什么根本性的改变。多出的一点点显示面积,苹果并没有为它安排什么新图标、新功能,一切照旧。



但特别地,更新后的Face ID功能将可以正常识别佩戴口罩或者眼镜起雾的用户。希望这项功能可以在冬天到来前上线。毕竟这一代iPhone仍然没有屏下指纹,而大冬天里摘下口罩的滋味可不怎么好受。


更大容量的电池。这也早就被剧透了。实际上,iPhone 13全系列相对上代,续航提升从1.5小时(13 mini、13 Pro)到2.5小时(13、13 Pro Max)。


更快的主芯片A15。5nm制程、150亿个晶体管、2大核+4小核架构、更强的人工智能芯片。但需要特别注意,这届苹果给13和Pro系列的芯片做了差异化处理,13搭载4核心GPU,13 Pro搭载5核心GPU。其中的性能差异,根据发布会上的信息,4核的比竞品快30%,5核的比竞品快50%,我们用计算器做了个简单的算术题,这两款GPU的性能差异大概是15%。不过,具体差异,还需要等待实际测试结果。


更多的影像算法。电影模式视频给中国手机厂商们好好上了一课:人工智能开始学习运镜,知道画面中什么是重要的,应该聚焦在哪里,焦点应该如何跟随主角的目光变化而变化——如果这套自动化的程序失效了,那还应该记录下图像中的深度信息,让后期调整可以变焦虚化,这一切都应该在手机中完成。当然还有更多算法,天文摄影、摄影风格、夜间模式、智能HDR4等。


剩下的提升,两部手机就走上了不同的升级路线。总的说来,就是iPhone 13几乎就是iPhone 12 Pro采用的技术下放,且换上了更好的处理器,诚意满满;而iPhone 13 Pro,则补上了几个用户期待已久的新技术,并且继续将服务于创作者的能力,作为差异化的体现。


先说iPhone 13。它的这些关键升级,其实都是去年iPhone 12 Pro的参数下放。


比如XDR屏幕,最高典型亮度800nit、HDR亮度1200nit,与iPhone 12 Pro完全相同,而比12系列的625nit亮度高出28%,这就成了某种显而易见的升级。


比如摄像头,主摄1200万像素/1.7微米,F/1.6光圈、7P镜片、传感器位移防抖,这几乎完全重现了iPhone 12 Pro Max那颗主摄,根据Macworld的报道,它们就是同一颗镜头[1],而超广角镜头也如出一辙。



又比如存储容量。相对上代iPhone 12,iPhone 13存储空间直接翻倍,与iPhone 12 Pro系列拉平。而翻倍容量并没有带来价格的显著提升,这代128G比上代64G便宜,这代256G跟上代128G一个价,新增的512G,它的确是会贵一点了,消费升级不可避免嘛。


所以该如何总结iPhone 13?它是上代Pro的翻版,一样的影像和显示素质、更大的存储空间、更亲民的价格,和更新的芯片——库克在稳定地推动产品迭代,它没有踩爆牙膏管,但仍然诚意满满,这次13的确香。


另外,在iPhone 13发布后,iPhone 12 Pro在苹果官网上直接下架,而iPhone 12则降价,面向中端手机市场销售。


再说iPhone 13 Pro系列。苹果缺席已久的高刷新屏幕,这次终于在iPhone 13 Pro系列登场,还拥有了1000nit的夸张亮度。


除此之外,iPhone 13 Pro的三摄像头系统则迎来了又一轮升级:主摄的单像素尺寸和底片面积继续扩大(1.7微米→1.9微米),更大的F/1.5光圈,光线捕捉能力提高至2.2倍;超广角镜头的光圈扩大,光线捕捉能力提高92%。


某种程度上说,Pro系列定位高端的原因只有一个:它的创作能力。的确,现在已经走到第三代的iPhone Pro,与当年iPhone X系列的“高端”是完全不同的路线,当年iPhone X用全面屏、Face ID等横空出世的新技术,让高端系列成为未来感满满的新鲜玩具,而iPhone 13与Pro的差异,影像能力能占七成,剩下屏幕、材质等随便分分。



最后,总结下iPhone 13系列的售价——



值得注意的是,苹果未来不会再推出5.4英寸手机。这意味着本次发布的iPhone 13 mini将成为小屏手机的“绝唱”。


这一代还是下一代,等等党该做出选择了。


iPad & iPad mini:

并没有完全再见的边框


库克首先带来了平平无奇的新款iPad。它额头下巴还在,Home键也在,搭载A13仿生芯片,前置摄像头升级至拥有1200万像素的122°超广角镜头,显然是为疫情期间的学生和上班族做出的针对性优化。


iPad mini迎来重大升级,彻底改头换面。


此次发布的iPad mini没有用传统的数字编号,而是直接被称作“新款iPad mini”,换上了类似iPad Pro的Liquid视网膜全面屏,也因此拿掉了过时的Home键,用户可以在顶部按钮用指纹解锁,看起来像是iPad Air的缩小版——它也有与iPad Air相同的黑边,并且由于iPad mini尺寸更小,黑边所占比例相应更大,让视觉感受略显突兀。



不过得益于全面屏的使用,iPad mini能在机身大小几乎不发生变化的同时,屏幕尺寸从前代的7.9寸增加至8.3寸,重量也减小到293克。颜色方面,也有深空灰、星光色、粉色和紫色四种可选。


此外,新款iPad mini用上了与iPhone 13同款的A15芯片,采用了USB-C接口并配备了横向立体声扬声器,用来打游戏和刷剧再合适不过了。


新iPad mini有64GB和256GB两款可选,连接方式也有无线版和5G蜂窝版两种,普通的Wi-Fi版64G售价3799元,256G售价4999元,9月24日发售,9月16日上午9点开始接受订购。


这个价格直接实现了消费升级,要知道上代iPad mini同样64G起售价只要2999元,如果看看更大尺寸的iPad Air,全面屏后价格同样不太亲切——库克找到了在平板电脑上财富新密码:更好看,就得更贵


iPad作为平板行业中的王者,2020年靠iPad Pro和iPad Air取得了巨大的成功。据IDC的数据,2020年全年,苹果的平板电脑市场份额以32.5%位居世界第一,远超份额为19.1%、排名第二的三星。[2]



Apple Watch Series 7


Apple Watch连续6年不变的外观,终于在Series 7上发生了变化,但并非如此前爆料所言,使用直角边框和扁平的屏幕,反而是维持一贯的圆弧形机身设计,边角甚至因表镜增厚变得更加圆润。



不过,由于Apple Watch 7的边框比上一代窄了40%,缩小至1.7mm,提升了20%的显示面积和70%的显示亮度。



可别小看这20%,据苹果的介绍,Apple Watch 7屏幕能显示的文本比上一代提升50%。你甚至可以在Apple Watch上进行全键盘输入。



价格方面,苹果只透露了起售价为399美元,至于不同尺寸以及不同材质的详细价格,或许要等到发售才能知晓,但何时发售仍是个未知数。


彭博社此前文章就提到,新屏幕因工艺复杂,以致量产出现问题,Apple Watch 7或许会因此限量供应。情况确实如此,苹果并未说明该产品的具体发售时间,官网只显示会在“秋末发售”。但按照郭明錤的说法,如今量产问题已经解决,立讯精密已经在加紧安排生产线出货,Apple Watch 7想必也不会让人等待太久。


Apple Watch 7为什么值得期待?不光因为它充电速度更快——从0充到80%只需要45分钟,比前代快了33%;也不完全是它的配色和表带更多——拥3种材质共8种不同配色和数不清的官配表带。而是它在运动场景的一系列创新。



因传感器和App的更新,新款Apple Watch配合专用的App,能够检测数十种体育项目,包括深蹲、跨步、骑行、游泳,甚至还有自动记录冲浪信息、网球发球速度和高尔夫球击球数据等,其心率检测和血氧测量等功能也得以优化。


不过,此前呼声很大的体温和血糖监测功能,并未在此代Apple Watch 7上推出。今年6月在国内获得批准的心电图功能,至今也未在国内开放使用,Apple Watch 7也很难豁免。



我们对苹果还剩下什么期待?


作为苹果首代5G手机,iPhone 12大获成功——7个月卖出1亿台,和当年的iPhone 6一样火。[3]


iPhone 12系列手机大获成功后,郭明錤毫不掩饰其对iPhone 13的看好,曾在2020年11月、2021年6月、2021年9月的研报中多次提及,iPhone 13系列出货量将超过iPhone 12系列。最近一篇报告中,他表示iPhone 13出货量比去年同期iPhone 12增长10%以上。[4]


Loup Ventures联合创始人Gene Munster也在研究报告中提到,由于三年及三年以上的旧iPhone数量达到4亿部,iPhone 13依旧会大卖。[5]摩根士丹利和IDC也给出了相同的观点。[6]


除了产品本身的因素外,iPhone 13还占尽天时。


竞争对手骁龙888翻车,极大地影响了Android阵营各品牌高端手机的销量。据2021年京东618大促首天(6月1日)的销售数据。销量前12的手机型号中,只有小米11搭载的是骁龙888芯片。


图片来源[7]


不愿意妥协的安卓用户只有两个选择:要么退而求其次,选择骁龙870手机;要么选择性能差不多的A14或者麒麟9000。但如今,华为暂无麒麟芯片,可苹果的芯片已经迭代到A15了。


A15芯片的生产也历经坎坷。


中国台湾的芯片行业先后遭遇缺水、断电、起火等事故困扰。在开始制造A15芯片后,台积电又传出5nm产线污染,所幸未对A15的生产造成实质影响。


好景不长,9月2日台积电宣布全面涨价。虽然作为VVVIP客户的苹果享受到了3%的最低涨幅,但日经新闻报道称,苹果依然会将上涨的成本转嫁给消费者。


那我们该不该换iPhone 13呢?


按照苹果三年一次的“重新设计周期”,处于同一周期内的连续三代iPhone将会维持基本相同的外观设计,仅在配置和细节上做一些升级——iPhone 12作为新周期中的第一个系列,这也意味着,你不会在今天发布的iPhone13和明年发布的iPhone 14上看到什么颠覆性的变化。


好处也是有的。毕竟在经过iPhone 12在5G上的验证后,苹果的5G手机已经足够成熟。而5G基站在未来全面铺开,5G信号从室外覆盖到室内,拥有一部支持5G的手机还很有必要。


如果你还在使用更早的机型,甚至是还带着指纹识别的旧手机,iPhone 13确实是一个不错的选择。但如果你更关注设计理念,或者觉得性能够用就行,那手持iPhone 12的你可以努努力,坚持到2023年的下一轮——即便iPhone 13在配置升级上诚意满满,把13变成了小Pro,但它在用户体验上其实也难以实现某种跨越,这是种“稳”,而我们期待苹果每年都带来突破性的升级、彻底颠覆一遍用户的体验,也不现实。


对数码爱好者来说,今年的科技春晚“苹苹淡淡”,但对普通用户来说,最合适就是最好的。



文章来源:放大灯(ID:guokr233)

References:

[1] iPhone 13 and 13 Pro: The five most important things you need to know

https://www.macworld.com/article/234814/iphone-13-features-specs-price-release.html

[2] Worldwide Tablet Shipments Return to Growth in 2020, Fueled by Unprecedented Demand, According to IDC

https://www.idc.com/getdoc.jsp?containerId=prUS47423721

[3] iPhone 12 Series Sales Cross 100 Million Mark Within 7 Months of Launch

https://www.counterpointresearch.com/zh-hans/iphone-12-series-sales-cross-100-million-mark-within-7-months-launch/

[4] https://9to5mac.com/2021/09/12/kuo-iphone-13-to-drop-64gb-storage-size-pro-models-to-offer-1tb-option/

[5] Gene Munster previews next Tuesday's Apple event

https://www.ped30.com/2021/09/10/apple-preview-gene-munster/

[6] 蘋果iPhone中國需求火熱、摩根士丹利:iPhone 13銷量看旺

https://www.bnext.com.tw/article/64593/iphone13-demand-rise-in-china

[7] https://www.gamersky.com/tech/202106/1393729.shtml


说过CSS in JS,还有JS in CSS?

CSS in JS

CSS in JS是一种解决css问题想法的集合,而不是一个指定的库。从CSS in JS的字面意思可以看出,它是将css样式写在JavaScript文件中,而不需要独立出.css.less之类的文件。将css放在js中使我们更方便的使用js的变量模块化tree-shaking。还解决了css中的一些问题,譬如:更方便解决基于状态的样式更容易追溯依赖关系生成唯一的选择器来锁定作用域。尽管CSS in JS不是一个很新的技术,但国内的普及程度并不高。由于Vue和Angular都有属于他们自己的一套定义样式的方案,React本身也没有管用户怎样定义组件的样式,所以CSS in JS在React社区的热度比较高。

目前为止实现CSS in JS的第三方库有很多:点击这里。像JSS、styled-components等。在这里我们就不展开赘述了,这篇文章的重点是JS in CSS

JS in CSS又是什么

在上面我们提到CSS in JS就是把CSS写在JavaScript中,那么JS in CSS我们可以推断出就是可以在CSS中使用JavaScript脚本,如下所示。可以在CSS中编写Paint API的功能。还可以访问:ctx,geom。甚至我们还可以编写自己的css自定义属性等。这些功能的实现都基于CSS Houdini。

.el {
  --color: cyan;
  --multiplier: 0.24;
  --pad: 30;
  --slant: 20;
  --background-canvas: (ctx, geom)=> {
    let multiplier=var(--multiplier);
    let c=`var(--color)`;
    let pad=var(--pad);
    let slant=var(--slant);

    ctx.moveTo(0, 0);
    ctx.lineTo(pad + (geom.width - slant - pad) * multiplier, 0);
    ctx.lineTo(pad + (geom.width - slant - pad) * multiplier + slant, geom.height);
    ctx.lineTo(0, geom.height);
    ctx.fillStyle=c;
    ctx.fill();
  };
  background: paint(background-canvas);
  transition: --multiplier .4s;
}
.el:hover {
  --multiplier: 1;
}

Houdini 解决了什么问题

CSS 与 JS的标准制定流程对比

在如今的Web开发中,JavaScript几乎占据了项目代码的大部分。我们可以在项目开发中使用ES 2020、ES2021、甚至提案中的新特性(如:Decorator),即使浏览器尚未支持,也可以编写Polyfill或使用Babel之类的工具进行转译,让我们可以将最新的特性应用到生产环境中(如下图所示)。



而CSS就不同了,除了制定CSS标准规范所需的时间外,各家浏览器的版本、实战进度差异更是旷日持久(如下图所示),最多利用PostCSS、Sass等工具來帮我们转译出浏览器能接受的CSS。开发者们能操作的就是通过JS去控制DOMCSSOM来影响页面的变化,但是对于接下來的LayoutPaintComposite就几乎没有控制权了。为了解决上述问题,为了让CSS的魔力不再受到浏览器的限制,Houdini就此诞生。

CSS Polyfill

我们上文中提到JavaScript中进入提案中的特性我们可以编写Polyfill,只需要很短的时间就可以讲新特性投入到生产环境中。这时,脑海中闪现出的第一个想法就是CSS Polyfill,只要CSS的Polyfill 足够强大,CSS或许也能有JavaScript一样的发展速度,令人可悲的是编写CSS Polyfill异常的困难,并且大多数情况下无法在不破坏性能的情况下进行。这是因为JavaScript是一门动态脚本语言。它带来了极强的扩展性,正是因为这样,我们可以很轻松使用JavaScript做出JavaScript的Polyfill。但是CSS不是动态的,在某些场景下,我们可以在编译时将一种形式的CSS的转换成另一种(如PostCSS)。如果你的Polyfill依赖于DOM结构或者某一个元素的布局、定位等,那么我们的Polyfill就无法编译时执行,而需要在浏览器中运行了。不幸的是,在浏览器中实现这种方案非常不容易。

如上图所示,是从浏览器获取到HTML到渲染在屏幕上的全过程,我们可以看到只有带颜色(粉色、蓝色)的部分是JavaScript可以控制的环节。首先我们根本无法控制浏览器解析HTML与CSS并将其转化为DOMCSSOM的过程,以及Cascade,Layout,Paint,Composite我们也无能为力。整个过程中我们唯一完全可控制的就是DOM,另外CSSOM部分可控。

CSS Houdini草案中提到,这种程度的暴露是不确定的、兼容性不稳定的以及缺乏对关键特性的支持的。比如,在浏览器中的 CSSOM 是不会告诉我们它是如何处理跨域的样式表,而且对于浏览器无法解析的 CSS 语句它的处理方式就是不解析了,也就是说——如果我们要用 CSS polyfill 让浏览器去支持它尚且不支持的属性,那就不能在 CSSOM 这个环节做,我们只能遍历一遍DOM,找到 <style><link rel="stylesheet"> 标签,获取其中的 CSS 样式、解析、重写,最后再加回 DOM 树中。令人尴尬的是,这样DOM树全部刷新了,会导致页面的重新渲染(如下如所示)。

即便如此,有的人可能会说:“除了这种方法,我们也别无选择,更何况对网站的性能也不会造成很大的影响”。那么对于部分网站是这样的。但如果我们的Polyfill是需要对可交互的页面呢?例如scrollresizemousemovekeyup等等,这些事件随时会被触发,那么意味着随时都会导致页面的重新渲染,交互不会像原本那样丝滑,甚至导致页面崩溃,对用户的体验也极其不好。

综上所述,如果我们想让浏览器解析它不认识的样式(低版本浏览器使用grid布局),然而渲染流程我们无法介入,我们也只能通过手动更新DOM的方式,这样会带来很多问题,Houdini的出现正是致力于解决他们。

Houdini API

Houdini是一组底层API,它公开了CSS引擎的各个部分,如下图所示展示了每个环节对应的新API(灰色部分各大浏览器还未实现),从而使开发人员能够通过加入浏览器渲染引擎的样式和布局过程来扩展CSS。Houdini是一群来自Mozilla,Apple,Opera,Microsoft,HP,Intel和Google的工程师组成的工作小组设计而成的。它们使开发者可以直接访问CSS对象模型(CSSOM),使开发人员可以编写浏览器可以解析为CSS的代码,从而创建新的CSS功能,而无需等待它们在浏览器中本地实现。

Properties & Values API

尽管当前已经有了CSS变量,可以让开发者控制属性值,但是无法约束类型或者更严格的定义,CSS Houdini新的API,我们可以扩展css的变量,我们可以定义CSS变量的类型,初始值,继承。它是css变量更强大灵活。

CSS变量现状:

.dom {
  --my-color: green;
  --my-color: url('not-a-color'); // 它并不知道当前的变量类型
  color: var(--my-color);
}

Houdini提供了两种自定义属性的注册方式,分别是在js和css中。

CSS.registerProperty({
  name: '--my-prop', // String 自定义属性名
  syntax: '<color>', // String 如何去解析当前的属性,即属性类型,默认 *
  inherits: false, // Boolean 如果是true,子节点将会继承
  initialValue: '#c0ffee', // String 属性点初始值
});

我们还可以在css中注册,也可以达到上面的效果

@property --my-prop {
  syntax: '<color>';
  inherits: false;
  initial-value: #c0ffee;
}

这个API中最令人振奋人心的功能是自定义属性上添加动画,像这样:transition: --multiplier 0.4s;,这个功能我们在前面介绍什么是js in css那个demo用使用过。我们还可以使用+使syntax属性支持一个或多个类型,也可以使用|来分割。更多syntax属性值:

属性值

描述

<length>

长度值

<number>

数字

<percentage>

百分比

<length-percentage>

长度或百分比,calc将长度和百分比组成的表达式

<color>

颜色

<image>

图像

<url>

网址

<integer>

整数

<angle>

角度

<time>

时间

<resolution>

分辨率

<transform-list>

转换函数

<custom-ident>

ident

Worklets

Worklets是渲染引擎的扩展,从概念上来讲它类似于Web Workers,但有几个重要的区别:

  1. 设计为并行,每个Worklets必须始终有两个或更多的实例,它们中的任何一个都可以在被调用时运行
  2. 作用域较小,限制不能访问全局作用域的API(Worklet的函数除外)
  3. 渲染引擎会在需要的时候调用他们,而不是我们手动调用

Worklet是一个JavaScript模块,通过调用worklet的addModule方法(它是个Promise)来添加。比如registerLayout, registerPaint, registerAnimator 我们都需要放在Worklet中

//加载单个
await demoWorklet.addModule('path/to/script.js');

// 一次性加载多个worklet
Promise.all([
  demoWorklet1.addModule('script1.js'),
  demoWorklet2.addModule('script2.js'),
]).then(results=> {});

registerDemoWorklet('name', class {

  // 每个Worklet可以定义要使用的不同函数
  // 他们将由渲染引擎在需要时调用
  process(arg) {
    return !arg;
  }
});

Worklets的生命周期


  1. Worklet的生命周期从渲染引擎内开始
  2. 对于JavaScript,渲染引擎启动JavaScript主线程
  3. 然后他将启动多个worklet进程,并且可以运行。这些进程理想情况下是独立于主线程的线程,这样就不会阻塞主线程(但它们也不需要阻塞)
  4. 然后在主线程中加载我们浏览器的JavaScript
  5. 该JavaScript调用 worklet.addModule 并异步加载一个worklet
  6. 加载后,将worklet加载到两个或多个可用的worklet流程中
  7. 当需要时,渲染引擎将通过从加载的Worklet中调用适当的处理函数来执行Worklet。该调用可以针对任何并行的Worklet实例。

Typed OM

Typed OM是对现有的CSSOM的扩展,并实现 Parsing APIProperties & Values API相关的特性。它将css值转化为有意义类型的JavaScript的对象,而不是像现在的字符串。如果我们尝试将字符串类型的值转化为有意义的类型并返回可能会有很大的性能开销,因此这个API可以让我们更高效的使用CSS的值。

现在读取CSS值增加了新的基类CSSStyleValue,他有许多的子类可以更加精准的描述css值的类型:

子类

描述

CSSKeywordValue

CSS关键字和其他标识符(如inherit或grid)

CSSPositionValue

位置信息 (x,y)

CSSImageValue

表示图像的值属性的对象

CSSUnitValue

表示为具有单个单位的单个值(例如50px),也可以表示为没有单位的单个值或百分比

CSSMathValue

比较复杂的数值,比如有calc,min和max。这包括子类 CSSMathSum, CSSMathProduct, CSSMathMin, CSSMathMax, CSSMathNegateCSSMathInvert

CSSTransformValue

CSS transforms组成的CSSTransformComponent列表,其中包括CSSTranslate, CSSRotate, CSSScale, CSSSkew, CSSSkewX, CSSSkewY, CSSPerspectiveCSSMatrixComponent

使用Typed OM主要有两种方法:

  1. 通过attributeStyleMap设置和获取有类型的行间样式
  2. 通过computedStyleMap获取元素完整的Typed OM样式

使用attributeStyleMap设置并获取

myElement.attributeStyleMap.set('font-size', CSS.em(2));
myElement.attributeStyleMap.get('font-size'); // CSSUnitValue { value: 2, unit: 'em' }

myElement.attributeStyleMap.set('opacity', CSS.number(.5));
myElement.attributeStyleMap.get('opacity'); // CSSUnitValue { value: 0.5, unit: 'number' };

在线demo

使用computedStyleMap

.foo {
  transform: translateX(1em) rotate(50deg) skewX(10deg);
  vertical-align: baseline;
  width: calc(100% - 3em);
}
const cs=document.querySelector('.foo').computedStyleMap();

cs.get('vertical-align');
// CSSKeywordValue {
//  value: 'baseline',
// }

cs.get('width');
// CSSMathSum {
//   operator: 'sum',
//   length: 2,
//   values: CSSNumericArray {
//     0: CSSUnitValue { value: -90, unit: 'px' },
//     1: CSSUnitValue { value: 100, unit: 'percent' },
//   },
// }

cs.get('transform');
// CSSTransformValue {
//   is2d: true,
//   length: 3,
//   0: CSSTranslate {
//     is2d: true,
//     x: CSSUnitValue { value: 20, unit: 'px' },
//     y: CSSUnitValue { value: 0, unit: 'px' },
//     z: CSSUnitValue { value: 0, unit: 'px' },
//   },
//   1: CSSRotate {...},
//   2: CSSSkewX {...},
// }
复制代码

在线demo

Layout API

开发者可以通过这个API实现自己的布局算法,我们可以像原生css一样使用我们自定义的布局(像display:flex, display:table)。在 Masonry layout library 上我们可以看到开发者们是有多想实现各种各样的复杂布局,其中一些布局光靠 CSS 是不行的。虽然这些布局会让人耳目一新印象深刻,但是它们的页面性能往往都很差,在一些低端设备上性能问题犹为明显。

CSS Layout API 暴露了一个registerLayout方法给开发者,接收一个布局名(layout name)作为后面在 CSS中使用的属性值,还有一个包含有这个布局逻辑的JavaScript类。

my-div {
  display: layout(my-layout);
}
// layout-worklet.js
registerLayout('my-layout', class {
  static get inputProperties() { return ['--foo']; }
  
  static get childrenInputProperties() { return ['--bar']; }
  
  async intrinsicSizes(children, edges, styleMap) {}

  async layout(children, edges, constraints, styleMap) {}
});
await CSS.layoutWorklet.addModule('layout-worklet.js');

在线demo 目前浏览器大部分还不支持

Painting API

我们可以在CSS background-image中使用它,我们可以使用Canvas 2d上下文,根据元素的大小控制图像,还可以使用自定义属性。

await CSS.paintWorklet.addModule('paint-worklet.js');
registerPaint('sample-paint', class {
  static get inputProperties() { return ['--foo']; }

  static get inputArguments() { return ['<color>']; }

  static get contextOptions() { return {alpha: true}; }

  paint(ctx, size, props, args) { }
});

在线demo

Animation API

这个API让我们可以控制基于用户输入的关键帧动画,并且以非阻塞的方式。还能更改一个 DOM 元素的属性,不过是不会引起渲染引擎重新计算布局或者样式的属性,比如 transform、opacity 或者滚动条位置(scroll offset)。Animation API的使用方式与 Paint APILayout API略有不同我们还需要通过new一个WorkletAnimation来注册worklet。

// animation-worklet.js
registerAnimator('sample-animator', class {
  constructor(options) {
  }
  animate(currentTime, effect) {
    effect.localTime=currentTime;
  }
});
await CSS.animationWorklet.addModule('animation-worklet.js');

// 需要添加动画的元素
const elem=document.querySelector('#my-elem');
const scrollSource=document.scrollingElement;
const timeRange=1000;
const scrollTimeline=new ScrollTimeline({
  scrollSource,
  timeRange,
});

const effectKeyframes=new KeyframeEffect(
  elem,
  // 动画需要绑定的关键帧
  [
    {transform: 'scale(1)'},
    {transform: 'scale(.25)'},
    {transform: 'scale(1)'}
  ],
  {
    duration: timeRange,
  },
);
new WorkletAnimation(
  'sample-animator',
  effectKeyframes,
  scrollTimeline,
  {},
).play();

关于此API的更多内容点击这里

Parser API

允许开发者自由扩展 CSS 词法分析器。

解析规则:

const background=window.cssParse.rule("background: green");
console.log(background.styleMap.get("background").value) // "green"

const styles=window.cssParse.ruleSet(".foo { background: green; margin: 5px; }");
console.log(styles.length) // 5
console.log(styles[0].styleMap.get("margin-top").value) // 5
console.log(styles[0].styleMap.get("margin-top").type) // "px"

解析CSS:

const style=fetch("style.css")
        .then(response=> CSS.parseStylesheet(response.body));
style.then(console.log);

Font Metrics API

它将提供一些方法来测量在屏幕上呈现的文本元素的尺寸,将允许开发者控制文本元素在屏幕上呈现的方式。使用当前功能很难或无法测量这些值,因此该API将使开发者可以更轻松地创建与文本和字体相关的CSS特性。例如:

  • flex布局: align-items baseline特性。需要知道每一个flex盒子中第一个元素的基线位置。
  • 首字母: 需要知道每个字母的基线高度和字母最大的高度,以及换行内容的基线长度。
  • 单个字形的前进和后退。
  • 换行: 需要访问字体数据,文本的所有样式输入以及布局信息(可用的段落长度等)。
  • 元素中的每一个line boxes都需要一个基线。(line boxes代表包含众多inline boxes的这行)

Houdini 目前进展

Houdini 的蓝图

了解到这里,部分开发者可能会说:“我不需要这些花里胡哨的技术,并不能带收益。我只想简简单单地写几个页面,做做普通的Web App,并不想试图干预浏览器的渲染过程从而实现一些实验性或炫酷的功能。”如果这样想的话,我们不妨退一步再去思考。回忆下最近做过的项目,用于实现页面效果所使用到的技术,grid布局方式在考虑兼容老版本浏览器时也不得不放弃。我们想控制浏览器渲染页面的过程并不是仅仅为了炫技,更多的是为了帮助开发者们解决以下两个问题:

  1. 统一各大浏览器的行为
  2. JavaScript一样,在推出新的特性时,我们可以通过Polyfill的形式快速地投入生产环境中。

几年过后再回眸,当主流浏览器完全支持Houdini的时候。我们可以在浏览器上随心所欲的使用任何CSS属性,并且他们都能完美支持。像今天的grid布局在旧版本浏览器支持的并不友好的这类问题,那时我们只需要安装对应的Polyfill就能解决类似的问题。

如在文中发现有误之处,欢迎反馈、纠正。

TML是一种标记语言(包含一系列标签),用于描述网页的的内容和结构(HTML元素构成的树形结构)。当我们对HTML有了基本的认识后,就可以了解一下CSS了。

CSS即层叠样式表(Cascading Style Sheets),是一种样式语言,可以用来描述网页的视觉表现,即指定HTML元素的各种样式,比如字体,颜色,背景,位置等。这些统称为元素的样式属性,每个样式属性规定了元素某一方面的视觉表现,为了全面描述一个元素的视觉表现,往往需要为它指定多个样式属性。如:

样式声明的基本语法:属性名+冒号+属性值+分号

曾经,HTML也包办了页面的视觉表现,它使用一系列格式化标签指定元素的样式,如<b></b>中间的文字会以粗体显示。但这样做会导致页面结构变得复杂,文件变大等一些列问题。而CSS的出现使得结构和表现分离,即用CSS定义页面的表现,HTML只负责内容和结构。那么,CSS是怎样与HTML结合起来的呢?即怎样将一组样式应用到某个元素。有两种方式:

1.为这个元素设置style属性,该样式称为内联样式

内联样式:每个元素的样式写在每个元素的style属性里

2.将所有样式声明集中起来,形成样式表,统一管理。再通过某种机制(选择器)将其中的某些样式与元素关联起来。样式表可以写在HTML文件中,称为内部样式表;也可以单独保存为一个文件(拓展名为.css),称为外部样式表,然后HTML文件再引用这个外部样式表文件

  • 内部样式表

样式声明放入大括号{},前面的符号是选择器(selector),两者构成一条样式规则。一个样式表含有任意数量的样式规则。一个样式表即为一个style元素的内容。选择器种类很多,用各种标签表示的是元素选择器,会“选择”所有对应的元素并对其应用大括号中声明的样式。由此可见,样式表中的样式会被一些元素共用,这会节约代码,并可以实现一处修改多处生效,方便统一页面整体风格,同时提高代码的可维护性。但内部样式表仅会作用于该HTML文档。

  • 外部样式表

任何一个html文档都可以引用外部样式表,这实现了更高级别的代码共用,大大方便了整个网站的样式管理。外部样式表通过link元素的href属性引用。

外部样式表style1.css

外部样式表的引用

  • “.”开头的选择器是类选择器。通过设置元素的class属性指定了该元素所属的类别,这样类选择器就会“选择“它并对其应用样式。不同元素的class属性的值可以相同,因此一组样式可以被许多元素共用。

  • “#”开头的是id选择器。通过设置元素的id属性指定了该元素的id,相应的id选择器就会”选择“到它并对其应用样式。每个元素的id属性值必须唯一,因此,相应的样式只会被它独享。

此外,我们知道,不同的元素本身就自带一些样式,这些样式其实是浏览器默认的设置,或称浏览器缺省样式。

综上,样式一共有3个来源:

  • 浏览器缺省样式表

  • 文档样式表,包括内部样式表和外部样式表

  • 每个元素的style属性,即内联样式

对于某个元素,除了内联样式,样式表(包括浏览器默认的)中可能也会指定它的样式,所有这些样式会组合起来共同决定该元素的最终表现。如果对同一个样式属性的声明发生了冲突,即被赋予了不同的值,如上面的代码示例中,后3个li元素的字体颜色都被多次声明了不同的值,但最终只会有一个值生效。因为内联样式会覆盖文档样式表中的样式,文档样式表中的样式又会覆盖浏览器的默认设置。而且,样式表中,与最具体的选择器相关联的值会覆盖与不那么具体的选择器相关联的值,如id选择器比类选择器更具体,而类选择器比元素选择器更具体。

因此,上面的网页最终效果会是这样:

第一项被外部样式表中的元素选择器“li”命中,因此会被应用样式“color:gray;”,即字体颜色为灰色。第二项,同时被元素选择器“li”和类选择器“.list-item”命中,后者更具体,因此字体最终为粉红色。同理,第三项按照id选择器的样式显示为绿色,而第四项会按style属性里设置的样式显示,为蓝色。此即为“层叠样式表”的真谛。

快去试试HTML+CSS吧~