致爱好者 —— 索尼(Sony)Xperia 1 II 简单使用感想

受 Covid-19 疫情影响,今年很多事情都不同以往。在2月底发布之后三个多月,Xperia 1 II 才终于在部分市场以软件未完成的形式上市,大陆行货则至今仍遥遥无期。从6月首发入手港版 Xperia 1 II 至今也有近两个月,在此简单聊聊使用感想。

时隔多年,再次选择了白色机身的 Xperia

本文基于在香港地区销售的 Xperia 1 II 写成,型号 XQ-AT52。本机支持中国移动联通电信的 4G 网络。理论上仅能完美支持中国联通的 5G 网络。这两年 5G 是一个热点话题,Xperia 1 II 又是索尼的第一台 5G 智能手机,在此多讲几句。个人认为目前 5G 网络能提供的性能提升还不能抵消额外的费用与耗电问题,尤其是自己日常生活中99%的场景不是不需要高速移动网络(如开车时),就是有更加稳定高速的 WLAN 环境,因此对港版型号不支持 5G 并不在意。事实上,因为不用手机打游戏,也不需要高速下载大量文件,LTE+ 上百兆比特的速率对自己的需求来讲已经绰绰有余。即使没有费用因素,5G 以更高能耗换来的性能提升对自己也不是必须。即使在一线城市,5G 信号要达到目前 4G 的水准恐怕也还需要时日,费用问题和芯片功耗也不见得会在短时间改善。再考虑到手机升级换代的频率不会太低,忽略 Xperia 1 II 在大陆的 5G 网络问题符合自己的实际情况。据称由于网络制式问题,这次行货型号可能会在硬件上有改动,无法通过软件通刷港版硬件。如果 5G 网络是刚需,或担心之后几年 4G 网络的通信质量被限制,建议等待几个月后上市能更完整支持国内 5G 网络的行货型号。

本文内容基于2020年8月提供的软件版本 58.0.A.3.88。出于兴趣写了近十年的业余“测评”,如今网络上专业的不专业的,客观的不客观的测评越来越多,更重要的是智能手机在十多年飞速发展后已经彻底进入了瓶颈期,每年写的文字越来越公式化,乐趣越来越少。于是从这次开始,更多会分享主观的使用感受,站在一个见证 Xperia 10年发展衰弱,试行错误的爱好者的角度,提供一些个人的看法和评论。

顺便一提,官方产品名发音为 Xperia One Mark Two。虽说符合相机部门的命名传统,如 Alpha Seven Mark Two 或 RX-100 Mark Five,但距离大众接受流行渐行渐远。就算这次中文用户能省略 Xperia 1 这一品牌与型号名,单独施以爱称“马克兔”,明年的 Mark Three 又会如何呢(估计会和相机一样,被称为 X1M3 或 1M3 吧,笑)。

2020/10/17 更新

Xperia 1 II 和 Xperia 5 II 的大陆行货版本在比其他地区晚了5个月后终于姗姗来迟。型号为 XQ-AT72 的新版 Xperia 1 II 硬件上内存从8GB增加至12GB,新增镜面绿色。网络上国行 Xpeira 1 II 完整支持中国大陆三大运营商的 5G 网络并支持 5G/4G 双待(Xperia 5 II 支持除了中移动 NSA 外的其他 5G 网络)。系统上,国行新增了对微信指纹支付的支持。虽然从生态上来看这不是一件好事,但确实可以增加一些潜在的国内销量吧。港台版本的 Xperia 1 II 也同时新增了 12GB 内存的高性能版和镜面绿色配色。

致爱好者

智能手机已经进入了发展瓶颈。一边,价格亲民的中低端机型已经能很好的满足普通人基本的通信与娱乐需求,Andriod 发展初期低端机性能明显不足的问题已经改善。另一边,在屏幕与相机等方面积极采用高规格硬件的高端型号价格不断攀升,与中低端机型拉开更大差距。由于多种原因,在全球销量一路断崖式下跌的索尼移动,在几次失败的尝试后,最终从去年开始选择了主打高端型号,以满足小众发烧友和品牌粉丝的发展路线,推出 Xperia 1。今年的 Xperia 1 II 是该路线的延续,不但彻底解决前代大量体验问题,更进一步加大力度讨好目标用户。

先说结论。作为目标用户,不得不说,Xperia 1 II 深得我意。Xperia 1 II 是迄今为止 Xperia 系列最高峰,历代体验标杆。

致静态摄影爱好者——源于 Alpha 相机团队的多项软硬件技术,搭配蔡司镜头与 T* 镀膜,提供独一无二的拍摄性能和体验,以及系列传统二段式独立相机快门键

致电影录制爱好者——增强的 Cinema Pro 软件提供更好的电影拍摄与剪辑体验

致电影鉴赏爱好者——显示效果业界一流的 21:9 4K HDR OLED 显示屏,且支持创作家模式以呈现作品原本风格

致音乐欣赏爱好者——LDAC 高解析度蓝牙音频技术,以及业界少见的 3.5mm 耳机接口(笑)

致手机游戏爱好者——游戏模式增加包括电力直供模式等多项新功能,提高重度玩家的游戏体验

致 Xperia 爱好者——最新型旗舰处理器与高速闪存、识别迅速准确的侧面指纹、在高端机型中高于平均的续航能力、支持电池寿命保护与无线充电、精致的做工与外形设计、相近规格产品中轻薄的尺寸与重量、稳定无广告且少有海外软件兼容问题的系统、完整 Google 服务支持

Xperia 1 II 并非完美无缺,但对于能够接受 Xperia 系列一贯的精简系统,不依赖很多国产手机厂商额外定制的本土化软件功能的老用户来说,Xperia 1 II 出色地实现了设计目标,提供了综合水准很高的使用体验。

致静态摄影爱好者

在一些市场,Xperia 1 II 最大的产品亮点是“口袋中的 Alpha 相机”。Xperia 1 II 最具代表性且不可替代的特长确实在这套软硬结合的相机系统上。

Xperia 1 II 与 Alpha 系列旗舰型号 Alpha 9 的合成照片是相机功能的官方宣传亮点——即使两者性能有天壤之别

硬件上,Xperia 1 II 延续了去年 Xperia 1 才姗姗来迟的三摄像头组合,提供了三颗12.2MP的摄像头和一颗帮助对焦的 3D iToF 红外测距传感器。与一些厂商为了背景虚化而采用 ToF 传感器不同,Xperia 1 II 的 ToF 传感器为对焦而设计,以实现弱光场景下0.03秒的高速对焦性能。这是 Xperia 1 II 为了对焦性能而作的独特设计。

标准镜头比 Xperia 1 更广角,长焦镜头则更望远。除超广角镜头外,另两颗都支持光学数字混合防抖

传感器方面,和 Xperia 1 不同,参照35mm下大三元的焦段,这次三颗镜头的焦段分别为 16mm(F2.2)、24mm(F1.7) 和 70mm(F2.4)。镜头则首次采用了蔡司(ZEISS)镜头和蔡司减少光线反射的 T* 镀膜,以提供有蔡司风格的色彩与虚化风格。其中标准镜头和长焦镜头支持光学与电子混合防抖。

首次采用来自 ZEISS 的高性能镜头与 T* 镀膜,看来索尼自己也认为 Z 系列时自家的 G 镜头并没有宣传效果

这次 24mm 主摄传感器为 1/1.7” 大尺寸,相比 Xperia 1 的 1/2.6” 大幅提升,像素尺寸高达1.8μm(Xperia 1 为 1.4μm)。除了华为在 P40 系列上使用的惊人的 1/1.28” 50MP Ultra Vision 主摄传感器,能够在4像素合一时提供2.44μm 的像素尺寸(单像素1.22μm),Xperia 1 II 的主摄像素尺寸与三星 Galaxy S20 系列的一致,并高于 iPhone 11 Pro 系列的1.4μm。此外,主摄 F1.7 的明亮镜头则小幅领先同级对手的 F1.9 或 F1.8,入光量更大。尽管像素尺寸和镜头光圈并非一切,Xperia 1 II 这次至少在规格上没有明显短板。

配合 BIONZ™ X for mobile,Xperia 1 II 最终实现了相比 Xperia 1 约1.5倍的感光性能。Exmor™ RS 或许因为不再有独特优势,宣传上被弱化

Xperia 1 II 在相机软件方面也积极引入源自 Alpha 的技术。

  • 运用 AI 技术,世界首创每秒60帧的 AF/AE 自动对焦/自动曝光计算,并实现最终每秒20张的 AF/AE 连拍,为拍摄运动物体提供了业界顶级的对焦与连拍能力。实际使用中,Xperia 1 II 的连续对焦连拍效果非常震撼,使抓拍精彩瞬间有了更多可能(顺便,连快门音都和 Alpha 相近,笑)
  • 高精度实时人眼/动物眼 AF,帮助时刻准确对焦拍摄对象(仅支持 24mm 主摄)
眼部对焦相当于是人脸对焦的更精准版本,但似乎并没有概念上的突破,一直以来都觉得更像是以趣味性而非功能性为卖点
  • 双重相片二极管对焦
  • 覆盖率70%的247点相位对焦。为 Xperia 1 的4倍
  • 增强的摄影后期工作流程:通过 Imaging Edge Mobile 软件遥控相机,以 5G 或 WiFi 6 传输作品、并以 D50 / D55 照片印刷色彩标准在 Xperia 1 II 的 4K HDR OLED 屏幕上回放
Alpha 在屏幕方面规格不激进的原因找到了

不过, Xperia 1 II 最让自己心动的软件功能当属 Photography Pro(下称 Photo Pro)。

Xperia 摄影新乐趣,兼具专业手动设置,以及,仪式感

简言之,PhotoPro 提供了与 Alpha 或 RX-100 相机类似的手动设置界面,以及专为触摸屏优化的设置菜单。近期发布的首次搭载触摸屏的 Alpha 7s III 也使用了这套新菜单。

Photo Pro 允许用户在不离开取景界面的同时修改各类拍摄参数,还支持 Alpha 相机上的 AF-ON 与 AEL 等高级功能,让摄影师和摄影爱好者能最大程度发挥自己的创作灵感。

Photo Pro 大体提供了以下功能:

  • 拍摄模式
    • Auto 自动模式(全自动调节参数)
    • P 编程自动模式(自动设定快门速度与 ISO)
    • S 快门速度优先模式(手动设置快门速度,自动设置 ISO)
    • M 手动曝光模式(手动设置快门速度与 ISO 以控制曝光,用于烟火或星空等特殊场景
  • 对焦功能
    • AF-C/S
    • 手动对焦
    • AF-ON
    • 人脸/眼部 AF ON / OFF
    • 对焦提示音
    • 对焦区域可视化
  • 白平衡
    • 自定义白平衡
    • 白平衡微调
    • AEL
    • DRO/ HDR
  • 其他
    • 低速/高速连拍与延迟拍摄
    • 3:2 照片比例
    • RAW 格式保存(单张照片约24MB,无法与连拍/HDR 同时启用)
    • 界面显示选项
    • 直方图
    • 水准仪等

熟悉索尼相机的用户相比可以很快上手,充分利用 Photo Pro 的各项功能。把 Photo Pro 设置为实体相机快门键长按启动的默认相机或许是个不错的主意。而半按快门 AEL 则是其他厂商无法提供的便捷功能。

Photo Pro 之所以令人满意,是因为它不但提供了丰富的手动拍摄选项,还维持了高水准的性能。配合 Xperia 1 II 的高通骁龙 865 处理器,以及 UFS3.0 高速闪存,以及更好的软硬件搭配,无论何时,Photo Pro 都保证了小于一秒的冷启动速度、JPEG + DRO 模式下数百张无压力的连拍能力、可以忽略不计的照片保存时间。在忍受了 Xperia 1 时而需要数秒冷启动且保存速度堪忧的相机软件后,Xperia 1 II 总算做到了一款旗舰产品应有的拍照体验。在手机上用 Lightroom 编辑 RAW 格式照片并同步到 Adobe Creative Cloud 则让 RAW 后期处理列入拍摄设备的能力范围,即使没有 PC 也能在拍摄作品后立即对原片做复杂的调整和修复。

最后简单谈谈画质,虽然这反而或许是手机摄影相对不那么关键的部分。毕竟真的亟需优质画质的场合,手机绝不是最佳选项。对于 24mm 的标准镜头,在光线充足时,Xperia 1 II 的成像没有比前代明显提升,主要是 Photo Pro 的 HDR 模式明显改善了光线对比强烈时的曝光效果。在弱光环境下,Xperia 1 II 体现出了硬件优势,画面明显干净很多。作为卖点的蔡司镜头仍然会在画面边缘存在一定畸变和画质下降,不过畸变在没有参照物时并不容易被察觉,画质下降也只有在需要局部裁剪放大时才会成为一个问题。总的来讲,这颗主摄的成像效果对得起它的宣传,是 Xperia 相机画质的正常进步。

Xperia 1 II 的广角与长焦镜头则比较平庸,与标准镜头的画质差距明显,在弱光环境下画质下降严重,与动辄高倍光学变焦的竞争对手相比甚至变焦能力也无法同台竞争,只能说是聊胜于无。或许其他两颗镜头的画质会成为明年 Mark III 的重点提升方向吧。不知何日才能重新看到十多年前索尼爱立信曾经在手机上使用过的光学变焦镜头。

ISO250 – 1/250 主摄像头。仅压缩。色彩还原自然一直是 Xperia 系列的特征。不过新的主摄镜头比过去更容易背景虚化,有时反而蛇足
ISO320 – 1/15 主摄像头。原尺寸约1/16区域局部裁剪。Lightroom RAW 格式后期。一方面,更高素质的主传感器和 RAW 格式保存,后期的余地明显增加。在光线不足时 Xperia 1 II 的表现比去年更上一层。另一方面,12MP 像素在裁剪时力不从心的问题也被暴露
ISO64 – 1/1000 主摄像头。仅压缩。也许是心理作用,也许是配合蔡司镜头做了调整,Xperia 1 II 拍摄的照片的色调和以往机型相比总有种说不出的微妙差异

致电影录制爱好者

Xperia 1 II 的另一项特色软件是从前代延续的 Cinematography Pro(下称 Cinema Pro)。

Cinema Pro 允许用户以 CineAlta 独有的 Look(滤镜,分别为 VENICE CS ・Opaque/Blue60Yellow60 ・Bright/Blue20Yellow60 ・Warm/Yellow80 ・Strong/Blue100 ・Cool/Blue60・Soft/Yellow40 ・Soft Monochrome)来录制 4K HDR 10bit 视频,或 2K 10bit HDR 120帧高帧率视频,并提供了水准仪与手动对焦等多种高级功能。

Xperia 1 II 除了软件功能优化,还专门对风噪抑制做了加强。

实话说,电影录制爱好者或许会因为 CineAlta 的名声,在使用 Cinema Pro 拍摄24帧的 21:9 电影时感到额外的乐趣。作为对此无感的普通人,很怀疑这个软件能够在 Xperia 上存在多久。目前看来,它更像是产品设计理念的一种象征罢了。

致电影鉴赏爱好者

和去年一样,Xperia 1 II 继续搭载了一块赏心悦目的高品质屏幕。

适合观影的 21:9 CinemaWide 屏幕比例、业界最高分辨率的 4K HDR OLED、X1™ for mobile 图像处理引擎、4K SDR 内容升格都是保留项目。这次就不再赘述。

新增的 90Hz 软件高刷新率在减少残影方面的效果比较微妙,它通过改进屏幕响应速度并调节像素亮度来模拟更高刷新率。效果有时能感知,有时则不能。主要在网页滚动等场景下会有一些差异。这或许是软件实现的极限,毕竟屏幕的硬件刷新率依然是 60Hz。虽然高刷新率屏幕如今成了高端产品竞相宣传的特性,但它确实不属于人人都有的需求,而且会带来耗电增加的副作用。比较好的做法也许是在后续产品中硬件支持高刷,但默认软件启用普通刷新率,让对刷新率有要求的用户可以各取所需。

创作家模式在 Xperia 1 II 上健在。引用之前的描述,在应用支持时,Xperia 1 II 能够以 HDR 高动态亮度范围、BT.2020 色域、D65 白平衡点、10bit 色深(软件模拟 8bit 硬件至近似 10bit 效果)的规格播放内容,还原电影导演在拍摄影片时的原始视觉效果,直接感受创作者想要传递的情感。对于优秀的作品,每一个场景都融入了创作者有意识的设计,强行用算法调整画面效果绝非最佳做法,甚至可能损害作品的完整性。Xperia 1 的创作家模式则为解决这一问题而生。目前,创作家模式会在 Netflex 与 CineaPro 两个应用中自动启用,用户也可手动选择切换。

创作家模式以索尼专有算法来表现以专业规格制作的视频内容,呈现更贴近创作者理念的视觉效果

从硬件上来看,Xperia 1 II 与 Xperia 1 使用了相同规格的屏幕。但或许是得益于软件改进,Xperia 1 II 无论是日常使用时屏幕显示的通透感和色彩表现力,都明显优于 Xperia 1,令人甚至怀疑这是否是因为 Xperia 1 使用一年多的屏幕自然老化才造成了如此差距。另,Xperia 1 II 的白平衡默认仍使用冷色调,算是遵从了所谓部分用户更偏好冷色调的说法来设置出厂白平衡。

由于硬件没有改变,Xperia 1 II 的最高亮度依然平庸,在室外亮度增强模式下也只有约650尼特的亮度,在阳光直射时可视性依然一般,如果长期在剧烈阳光下室外活动,需要多评估一下对屏幕最高亮度的需求。

主观上来讲,和以往一样,Xperia 1 II 的屏幕显示效果远好于其它一些厂家的高端机,色彩方面 OLED 容易出现的味精感,或是特殊像素排列造成的模糊感,在 Xperia 1 II 上都很难发现。如果追求屏幕效果,Xperia 依然是和 iPhone、Galaxy 同级的少数选项之一。更何况,没有刘海和挖孔的屏幕,才不会在观看宽屏电影时不可避免地缺失一块画面,不是吗?

致音乐欣赏爱好者

Xperia 1 II 搭载了极为罕见而先进的 3.5mm 耳机插孔(笑)。

Xperia 高端机型在取消耳机孔数代后,又把它改了回来。声道干扰比上代减少90%,仅为 20dB。过去的数字音频升格技术 DSEE HX 结合 AI 算法,改名为 DSEE Ultimate,在使用有线耳机时,能更好地将各类音源的码率提升至 HiRes 水准。尽管自己是蓝牙耳机支持者,但不得不承认 Xperia 1 II 和有线耳机 XBA-N3 的搭配,比支持 LDAC 高解析度蓝牙音频的同价位蓝牙耳机,有更好的主观听感,并且,无需充电。除了 LDAC,Xperia 1 II 的蓝牙新支持 aptX Adaptive,延迟较以往更低。

据访谈介绍,Xperia 1 II 的音响调教继续得到索尼音乐的专业支持。屡获殊荣的资深调教工程师 Mark Wilder 两次参与 Xperia 1 II 的音频调教研讨会并提出建议,最后对其音质表现表示肯定。

此外,支持 Dolby Atmos 的正面双扬声器位置得到改善,下方扬声器也能从屏幕正面发声。驱动单元则重新开发,推力和低音表现都比上代提升。不过对于很少使用外放的人来讲,这是无关紧要的改进。

致手机游戏爱好者

Xperia 1 II 虽然不是游戏手机,但也有专门的游戏模式,并联手堡垒之夜或 Call of Duty:Mobile 等游戏对其 21:9 的屏幕比例做了优化,能显示更广阔的视野。

Xperia 的游戏增强模式主要做了以下几方面的工作:性能优化、游戏录制、免干扰、防误触、直接供电。

虽然不用手机玩游戏,但已经听说直接供电模式下,由于不会对电池充电,手机的温度会较通常更低,不容易触及软件设置的温度墙而降频处理器来保护设备。该功能不但可以减少游戏因处理器性能受限而引发卡顿,还能减少电池因高温导致的寿命缩减,如果需要高负荷长时间使用非游戏类应用,想必也能发挥效果。

致 Xperia 爱好者

Xperia 1 II 的基础功能是 Xperia 系列的新高峰。

最新的高通骁龙 865 芯片组、8G内存、256GB UFS 3 高速闪存的组合使运行任何程序都流畅快速。支持最大1.7Gbps的 4G 下行速率与 3.4Gbps 的 5G 下行速率。没有减去 IP58 防水能力和 MicroSD 卡扩展,增加无线充电的情况下,机身重量还能控制在同级较轻的 181g + 7.9mm 厚,宽度也仅有72mm。看着这两年竞争对手频繁推出重量超过200g的产品,为当年索尼因 Xperia XZ2 Premium 而在网络上背负半斤骂名感到可惜。

一个可喜的改善是,Xperia 1 因专利问题而使用的与电源分离的小尺寸侧面指纹模块终于被替换回了过去的整合式指纹开关,识别率也恢复到了 Xperia XZ Premium 的水平,在绝大多数时候都能迅速识别解锁。Xperia 1 底部略有些割手的 USB 口问题也因为新的边框倒角设计而被解决。

4000mAh 的系列高端机型最大电池容量,提供100小时的 4G 待机时间和85小时的 5G 待机时间。支持 21W PD 快充,能在30分钟内充电50%。同时系列传统的电池长寿技术能智能学习用户的充电习惯,避免过充,让电池性能在两年内不会显著衰减。索尼与苹果三星一样,似乎对快充技术从不激进,峰值充电功率距离国产厂商越来越远。所幸自己这么多年来哪怕一次也没有遇到过需要手机短时间充电的情况,所以对快充需求实在无感。

一个多月的实际使用来看,4000mAh 电池按个人使用习惯(白天约2小时蓝牙音乐、一小时通信与一小时网页浏览等亮屏操作,大部分时间 WiFi 连接),可以在工作日下班时剩余70%左右的电量,即使手机使用较多,通常也不会低于50%。这一数字比之前容量不到 3500mAh 的机型有可感知的差距。仅针对自己来讲,电池焦虑恐怕很难再会出现。

外形设计方面,传承当年 Xperia Z2 神韵的具有高级感的边框设计,相比 Xperia 1,Xperia 1 II 更充满了 Xperia 的个性,每次拿起手中,都会满心欢喜。索尼没有在 Xperia XZ2/XZ3 设计语言的不归路上越走越远,总算做到了至少取悦了 Xperia 的爱好者们。

就这样,Xperia 1 II 几乎全方位地改进了上一代存在的或严重或细节的问题,无论任何一个方面来看,体验都可谓系列最佳。可以说,Xperia 1 II 是一台能让 Xperia 爱好者重燃希望的机型,或许会和 Xperia XZ Premium 一样成为一代名机。

2020/10/17 更新

使用四个月后的初步结论是,Xperia 1 II 在系统稳定性、发热与续航控制、相机性能等影响使用体验的重点方面做得很不错,在 Xperia 系列历史上应该可以位列第一。中等强度使用下也不会有续航不足一天的焦虑、相机的启动、对焦、保存速度在使用一段时间后依然在比较理想的状态。即使类原生 Android 系统在国内软件生态下难免水土不服,Xperia 1 II 也靠电池和性能的升级,总算是一定程度上缓解了问题。

Xperia 1 II 也并非没有缺憾。在网络上有见到说白色机型后盖内部可能发生掉漆(这台还没发现)、非居中的摄像头突起导致在桌面上平方时不稳(虽然目前绝大多数手机都如此设计)、耳机孔和 USB 孔或许会在长期使用后接触不良(Xperia 的通病,暂时不对 Xperia 1 II 能彻底解决这个问题乐观)、Xperia 自带的特色软件继续被去除(Movie Creator 可以通过 APK 安装、相册不再被支持只能使用性能功能都更强但缺乏特色的 Google Photo、LifeLog 结束服务,等等)、在原生 Android 系统基础上做的增强过少,一些用户喜爱的其他厂商早已默认提供的定制功能不得不自己安装额外的软件才能拥有,甚至最终无法实现、一些软件,尤其是游戏,至今没有对 21:9 屏幕比例进行优化,等。

今后使用过程中发现更多的问题,会持续更新和补充。

【图文内容不定期更新】

本文相关图片版权属于各版权所有人

解决 HTML Canvas 元素在高像素密度/高分辨率屏幕上显示模糊的问题

最近在使用 HTML Canvas 元素时发现通过 fillText() 绘制的文字明显发虚,像是以低分辨率渲染后放大所致,再仔细一检查,发现事实上包括 fillRect() 在内的其他图案也都存在相同的问题。

初步推测和显示设备使用了较高的 DPI 有关,随进行了一番搜索,在 Stackoverflow 、Medium 等站点都有一些提问和回答。然而意外的是,自己能找到的一些解答,至少在自己这边并不能解决问题。

经过摸索,找到了能够解决自己问题的办法,分享于此,以便后人。

以下为 Angular component 代码片段,语言为 TypeScript。

@ViewChild('canvas', { static: true }) canvas: ElementRef; // Canvas 元素
@ViewChild('canvasDiv', { static: true }) canvasDiv: ElementRef; // Canvas 元素的父元素,一个 div
private ctx: CanvasRenderingContext2D; // Canvas context

private dpiRatio: number; // DPI 缩放比例
private canvasDivWidth: number;  // 父元素宽度

……

this.dpiRatio = window.devicePixelRatio;

this.canvasDivWidth = this.canvasDiv.nativeElement.offsetWidth;

// 分别设置 canvas 的宽度和样式宽度,canvas 的显示尺寸将会减半
this.ctx = this.canvas.nativeElement.getContext('2d');
this.ctx.canvas.width = this.canvasWidth * this.dpiRatio;
this.ctx.canvas.style.width = this.canvasWidth + 'px';

// 在绘制时考虑缩放因素
this.ctx.font = 12 * this.dpiRatio + 'px Roboto';
this.ctx.fillText('HIDPI文字', x  * this.dpiRatio, y * this.dpiRatio);

一个悬而未决的问题是,canvas context 本身的 transfer 函数似乎不能做到整体的放大,因此这里作为临时方案暂时在绘制每一个图形时都乘以了缩放倍率。这里应该有更好的办法,不过限于时间,暂且搁置。

Angular 9+ 升级小记 —— 应付 MSAL-Angular 与 ngx-restangular 的兼容性问题

之前几次升级 Angular 版本的经历总体还算顺利,因此原本对 Angular 8 升级到 9 的过程也比较乐观。虽然 Angular 9 开始将默认启动新的 Angular Ivy,但考虑到已经正式发布数月,甚至 Android 10 都已问世,自己的项目又没有用特别冷门的依赖,依然没有担心会遇到问题。可惜墨菲定律无处不在,最后还是花了比想象中更多的时间完成升级。

为此,本文简单介绍自己在从 Angular 8 升级到 9 最终到 10 时遇到的问题及相应的解决方法,仅供参考。

首先,Angular 官方文档提供了详细的升级说明,建议在升级项目前首先通览相关文档,了解可能存在的问题。可以从下面的链接找到升级到 Angular 10 的最新信息。

https://angular.io/guide/updating-to-version-10

下面是自己在升级时实际操作的几个主要步骤:

  • 更新 Angular 8 相关依赖至最新版
    • ng update @angular/core@8 @angular/cli@8
    • ng build –prod –aot
    • 确认变更
  • 更新 @azure/msal-angular 至最新版 1.0.0
    • 安装 1.0.0 版并为新版的接口变化修改代码(1)
    • ng build –prod –aot
    • 确认变更
  • 升级至 Angular 9,检查并乎略一些依赖版本问题
    • ng update @angular/core@9 @angular/cli@9 –force(2)
    • ng build –prod –aot
    • 确认变更
    • 升级 Angular Material
      • ng update @angular/material@9
      • 检查 Angular Material 引用问题(3)
    • 增加 ngcc 作为 postinstall 脚本(4)
    • ng build –prod –aot
    • 确认变更
    • ng add @angular/localize (5)
    • ng serve –ssl 启动并检查应用基本功能
  • 升级至 Angular 10,检查并乎略一些依赖版本问题
    • ng update @angular/core @angular/cli –force
    • 临时手段解决 ngx-restangular 编译问题(6)
    • ng build –prod –aot
    • 确认变更
    • ng update @angular/material
    • ng build –prod –aot
    • 确认变更
    • ng serve –ssl 启动并检查应用基本功能
  • 大功告成

以下具体说明上述步骤中的一些关键操作。

(1)MSAL Angular 代码更改

在升级 Angular 9 之前,自己的项目使用 MSAL Angular 0.1.4 实现对 Microsoft 账户或 ADD 的验证。当时该库的文档和范例代码质量就差强人意,缺少说明和链接失效比比皆是。更重要的是,该库并不兼容 Angular Ivy,这也是没有更早升级 Angular 9 的原因之一。等着 MSAL Angular 花了几个月的时间终于正式发布 1.0.0 版本才开始升级,依然遇到几个问题:

  • 方法接口变化,getUser() 改为 getAccount(),displayableId 成员取消
  • 服务初始化方式变化,结构虽然较过去清晰,但文档和示例代码不足,甚至还有语法拼写错误
  • 请求验证成功后返回的 payload 格式发生变化,token 变量改为 rawIdToken
  • loginRedirect() 似乎不再正常工作,仍需进一步排查原因

无论如何,能够兼容 Angular 9 已经不易,总比 ngx-restangular 那样根本无法成功编译要好些。MSAL Angular 已经两个月没有新版本发布,不知今后的更新是否能解决一些问题。

(2)升级至 Angular 9

这步本身没有什么问题,不过需要检查一些报警的依赖版本冲突。自己的项目中主要是 tslib 已经到了 2.0 而 Angular 9 要求 1.10.0,以及 Angular http 停在了大版本7。确认没有问题后就以 –force 参数强制升级。

(3)检查 Angular Material 引用问题

新版本 Angular Material 要求每个引用都明确指定具体组件,如:

 import { MatSpinner } from '@angular/material/progress-spinner';

而不允许在一句引用中同时引入多个组件,如:

import { MatSpinner, MatSnackBar } from '@angular/material';

正常情况下 ng update 会自动更正代码,不过自己在操作时似乎遇到一些问题,没有顺利完成,只好收到批量做了一些处理。

(4)增加 ngcc 作为 postinstall 脚本

在 package.json 中增加 “postinstall”: “ngcc” 有助于避免可能的库兼容问题。参见 ngcc 的和 ModuleWithProviders 迁移的相关说明。

(5)增加 @angular/localize

如果项目中使用了 Angular 自带的 i18n 功能,可能需要执行 ng add @angular/localize 添加必要的依赖。不过这并非必要步骤,可以在遇到提示时才采取行动。

(6)解决 ngx-restangular 5.0.0 编译问题

很可惜,ngcc 不是银弹。至少,它无法解决 ngx-restangular 的兼容问题。

ngx-restangular 是自己项目中使用的主要第三方库之一,帮助使用 REST API 的使用。这个项目本身算不上太活跃,但基本功能还算充分。可惜的是,半年没有更新的它,果然无法在 Ivy 下正确编译,报错如下:

ERROR in node_modules/ngx-restangular/lib/ngx-restangular.module.d.ts:8:97 - error TS2314: Generic type 'ModuleWithProviders<T>' requires 1 type argument(s).

static forRoot(providers?: any[], configFunction?: (provider: any, ...arg: any[]) => void): ModuleWithProviders;

搜索尝试一些方法无果后,不得已手动修改库文件,增加类型 <RestangularModule> 在 node_modules/ngx-restangular/lib/ngx-restangular.module.d.ts 第八行末尾:

static forRoot(providers?: any[], configFunction?: (provider: any, ...arg: any[]) => void): ModuleWithProviders<RestangularModule>;

在 CI 管道中,则暂时每次都在 ng build 之前以 sed 命令完成代码更改:

sed -i 's/ModuleWithProviders;/ModuleWithProviders<RestangularModule>;/g' node_modules/ngx-restangular/lib/ngx-restangular.module.d.ts

于是,暂时绕过了编译错误。ngx-restangular 的功能本身倒似乎没有问题,可以正常工作。

经过功能确认和测试后,一个 Angular 8 应用终于顺利升级为了 Angular 10 应用。尽管并非一帆风顺,但 Ivy 确实明显提升了编译性能并减小了体积,总管没有白费功夫。如有需要,还可以参考 AngularGo GitHub 地址),了解升级过程中的配置与代码更改。

Die Alltägliche

No. 17

这次的构想是居家办公途中听到呼喊而回头望向后方的瞬间

_

又是一年。于是今年也再度拿起画笔,趁着悬而未立,趁着多少还能确保一些能够自己支配的业余时间,再随着自己的性子去做些什么,留下些什么。画画有意思的地方在于可以随心所欲,暂时享受造物主的特权。

回想起来,上次把笔记本电脑作为道具画在画里竟然已经是九年之前。这次也算是回归初心。Surface Laptop 2 的宣传语是 A touch above ordinary,倒也恰好与标题契合。画的另一个小道具 Xperia 1 是最近一年的主力机,爱不释手。

过去一年是神奇的一年。非要说的话,或许是在过去很多年里,在今后很多年内,都很不寻常。为一些坏的情况做了准备,但最坏的情况最终竟也没有发生。对一些好的结果有所期望,但最好的结果似乎也不会实现。失望、希望、踌躇、前进。既然总有些事无法克服,那就只好尽量与之和平共处。不知不觉中,可能已经习惯了这样的状态。

迄今为止都在拼命地向前冲刺,告诉自己说,要做的更好,要变得更好。但怎样才算是更好,又怎样才能界定呢。是世俗意义的成功,还是想象中的自我实现?年初的时候还跟朋友聊到说,仍以为自己不是特别普通。实际又如何呢。也许,更多是一种相信,一份期待吧。对幻想中的美好。

嗯。加油。

要再厉害一点。

Du bist besonders.

_

_

_

One more thing…

Ver. Hoodie

Angular on Azure Web App Service (IIS)

部署于 Azure App Service 的 Web App 事实上运行于 IIS (Internet Information Services),因此也可以通过 web.config 文件来配置它的行为。

由于 Angular 是一种 SPA Web 框架,需要对 IIS 做一些额外的 URL Rewrite 配置,才能在浏览器刷新页面时依然成功载入内容,参见以下代码。

规则 Index Rule 的作用是把所有匹配的 HTTP 请求全都重定向至 “/” 路径,之后 Angular 自己的路由(Routes)将会继续工作,完成内容的载入和跳转。可以参考此处了解如何实现 lazy loading 。

staticContent 节点则定义了允许的 mimeType,否则直接访问 contentType 为 application/json 等类型的请求将返回 404 Not Found。

复旦大学校歌

刘大白 词
丰子恺 曲

歌词:
复旦复旦旦复旦,巍巍学府文章焕,
学术独立思想自由,政罗教网无羁绊,
无羁绊前程远,向前,向前,向前进展。
复旦复旦旦复旦,日月光华同灿烂。
复旦复旦旦复旦,师生一德精神贯,
巩固学校维护国家,先忧后乐交相勉,
交相勉前程远,向前,向前,向前进展。
复旦复旦旦复旦,日月光华同灿烂。
复旦复旦旦复旦,沪滨屹立东南冠,
作育国士恢廓学风,震欧铄美声名满,
声名满前程远,向前,向前,向前进展。
复旦复旦旦复旦,日月光华同灿烂。

AngularGo —— 一个开源 Angular SPA 模板

在接触 Angular 后,这些年工作业余也用 Angular 做了若干实际项目。不过,由于 Angular 在国内的流行度不高,各种原创内容和参考资料也相对较少。虽然网络上也能找到各种各样的技术文章,官方的文档也很全面,但总的来讲,信息还是有些分散。

很惭愧,几年里没有做什么特别有技术含量的工作。 只是提炼出一个很基础的模板,帮助开发者快速创建一个 SPA(Single Page Application)站点,或是供对 Android 感兴趣的读者了解 Android 的语法和基本的框架机制。该模板先分享于此 —— AngularGo on GitHub

该模板基于目前最新的 Angular 8,且会持续跟进更新。在 Angular CLI 自动创建的范例项目的基础上,目前版本的 AngularGo 还包含以下内容:

  • Angular 8 以及相关依赖的最新版本配置
  • 一种可能的源文件结构示例
  • 一种与 Cordova 共享代码库的可能方式
  • 基础 Angular 组件及依赖注入的使用范例
  • 基础 Angular Material 控件的使用范例
  • 支持桌面和移动设备的抽屉式侧滑菜单
  • 支持 lazy loading 的 app-routing 全局路由
  • 支持 authentication guard 的模块路由
  • 支持 bearer token 验证的 Restangular 初始化及 service 用例
  • 基于 HttpClient 的用户注册与登录 API 调用
  • 基于 scss 的 Angular Material 样式(尚未采用 BEM 命名规则)
  • Azure Application Insights 集成
  • 适用于 Windows server/ Azure App Service 的 web.config 配置

AngularGo 还很初步,很多细节因水平有限和时间限制写得也比较粗糙,想必会有其他优秀的开源模板提供了更好的实现。从某种意义上来讲,该模板一方面是对自己经验得一个整理,同时期望能起到一个抛砖引玉的作用。希望对读者有帮助,也欢迎批评指教。

最终一致性(eventual consistency)引

一致性设计在分布式系统中是一个重要问题。如果一个系统同时使用多个子数据系统来存储与读取数据,就必须设计满足功能需求的一致性定义。如果系统对不同数据子系统进行操作的结果不一致,不但可能会使用户困惑,更可能引发更严重的数据问题或系统错误。一致性有多种级别,适用于不同的业务场景。对于金融等对数据一致性要求较高的行业,传统的事务可以提供较高的一致性保证。对于分布式系统等对性能(performance)和可用性(availability)要求较高的场景,牺牲一定的强一致性来换取更好的用户体验也可接受。最终一致性的具体行为根据实际需求不同,并无严格而精确的定义。本文仅作为一个引子,介绍最终一致性及与其相关的一些基本概念,方便读者对最终一致性有初步的认识,以便进一步阅读其他文章与资料,设计适合自身业务需求的系统数据一致性。

衍生数据系统

衍生数据(derived data)指的是可以由另一些数据通过某种可以复现的处理来再次生成的数据。通常,衍生数据用于加速读取数据库中的某些数据。索引(index)和缓存(cache)都是典型的衍生数据。如果衍生数据丢失,仍可以通过原始数据再次生成。

单个数据库系统中的索引属于其所存储数据的衍生数据。有时,数据库的索引可能会由于性能或成本考量而被维护在另一个系统之中,此时,该索引系统即为一种衍生数据系统。该索引系统中的数据可以通过数据库中存储的数据重新生成(即使往往开销过大而不实际),反之则不行。这种情况下,如何维护源数据库数据与索引数据库系统之间数据的一致性,值得系统设计者考虑。

事务与 ACID

事务(transaction)是一种传统的确保数据一致性的方式。在一个系统中,各种类型的错误都可能会破坏数据的一致性。网络问题、硬件故障、远程服务不可用等原因都会导致数据操作部分或彻底失败。

事务可以将一组数据读写操作合并为一组,构成一个逻辑单元,作为一个单独的数据操作执行。一次事务操作要么完全成功(提交),要么彻底失败(中止并回滚)。如果事务失败,它能被安全地再次执行。

ACID 是原子性(atomicity)、一致性(consistency)、隔离性(isolation)与持久性(durability)的首字母缩写,它通常用来描述事务的性质。

原子性减轻了多步操作中途出错时造成的问题。如果一此事务失败,原子性将确保没有数据发生变化,事务可以被安全地重新提交。

一致性事实上不是数据库的一种属性,而由具体的应用需求定义。一个应用程序可以借助原子性与隔离性来实现一致性,而这可能不仅仅是单个数据库系统的问题。一致性有多种等级,在此不具体展开介绍。

隔离性与竞争(race condition)及并发(concurrency)有关,用于解决多个事务同时执行时的相互干涉。

持久性在数据库系统中指数据应当在事务提交成功后能安全而长久地被保存,且不会因系统故障而丢失。

事务可以在很大程度上确保数据质量。然而,最近流行的 NoSQL 数据库大多不提供事务支持,以免它过高的性能开销损害它们试图提供的高可用性。 从事务的角度来看,数据存储与索引是不同的数据库对象。 许多数据库系统,包括微软 Azure Cosmos DB 等分布式数据库都提供了单对象事务支持,但并未提供完全的多对象事务支持。

异构分布式事务

异构分布式事务( heterogeneous distributed transaction)指的是事务的参与者可能由两种或多种不同的技术组成。例如,由不同供应商提供的数据库,各司其职的数据库与索引系统,甚至是消息分发系统等非数据库系统。异构分布式事务也需要满足提交(commit)的原子性,这比实现数据库内部的事务更为困难。

两阶段提交(2PC,Two-Phase Commit)是一种著名的强一致性保证。对于一次事务请求,所有子系统都将确保数据被写入或最新的数据被读取。对于由一个索引系统和一个数据库系统构成的异构分布式系统,在完成一次两阶段提交后,索引系统中存储的数据必然能反映数据库系统的最新情况,对数据库系统的更新操作也总会反应在索引系统中。

重试策略

重试(retry)即再次执行某一操作。在设计数据系统时,重试策略也是一个需要考虑的问题。不恰当的重试可能会导致以下问题:

  • 如果重试请求的响应因网络问题而没能返回,再次重试可能会使开销倍增
  • 如果问题在于系统超负载,重试可能会导致问题进一步恶化
  • 重试只能解决暂时性问题(如死锁、隔离性被违反/isolation violation,或短暂的网络故障等),因此在重试前有必要判断重试是否可能解决问题

因此,在设计重试策略时,超时、最大重试次数、两次重试之间的间隔等都需要纳入考虑。

最终一致性与BASE

与事务提供的 ACID 属性不同,最终一致性提供的一致性保证也被称为 BASE(Basic Available, Soft state, Eventual consistency)。BASE 确保如果系统之后没有更多的数据操作,最终对系统的所有访问都将返回相同的结果。BASE 更多地是确保系统使用可用,但在系统数据收敛之前,它可能返回不同的结果。 最终一致性的实际行为由具体应用定义,无法统一阐述。

采用最终一致性的数据系统通常不要求数据操作失败时执行回滚(rollback)。用户或系统日志将得知操作失败,但在另一次成功的操作之前,数据的不一致问题并不会被自动修复。

之所以最终一致性会出现,很大程度上是因为如今的网路应用常常要处理规模巨大的数据与请求。此时,更强的一致性往往并不现实,高可用性反而是更系统更核心的设计目标。

_

以上是讨论最终一致性之前可能需要了解的一些前置概念的简述,以帮助读者快速了解系统数据一致性设计时的一些主题,并能有目标地查阅更多资料与文献。水平有限,如果纰漏,欢迎批评指正。

Weißer Ritter

第16弹,「Weißer Ritter」。

_

许久没有拿起画笔,终于借着周末得闲,踩着参加工作整六年的点,完成了新作品。 前一阵写了防御性驾驶心得,趁热打铁,这次的画便以车作为主题。和以往一样,图文无关。

某人说,猫多可爱,还不如画猫。于是决定配上黑猫。黑猫安静、深邃、外冷内热,最重要是黑不溜秋没有花纹比较方便,比之前美短简单不少。

我也喜欢猫。

_

人们喜欢纪念整数,即使那也不过是人生中平常的一天。 离开校园之后,自己的时间似乎就开始加速。日复一日,转瞬即逝。至今还清楚记得六年前的情景。虽然之前已有实习,但正式开始为期数十年的人生新阶段,总会引人遐想。如此不加筛选地记着各种各样的细节,也不知到底算是负担还是财富。所以,偶尔也羡慕那些很容易忘记烦恼的人。

回望过去的这些年,对自己的行动力颇为惊讶。一方面,自己做了若干不寻常的决定,直接改变了自己的人生轨迹。每一次都在之前无法想象,以至于现在的生活在几年前从未曾设想过。那些选择并不容易,过程也并非事事如意,但现在想来自己在每一次选择时都并没有经历过多的犹豫,直到现在也并没有后悔,往好的方面可说是未留遗憾。这便是好的。另一方面,一切又似乎都按部就班。每个月的计划、每一年的目标、五年一期的中期规划,尽管遭遇到了大大小小的失败,也总结反思出不少经验与教训,一路坚持,到最后竟也没有和最初的预期发生太大的偏差。甚至今天再读自己当年的初心,也并没有任何的违和感。前一阵被吐槽说想法始终过于 naive,但我并不讨厌这个评价。这个世界总是需要有些人在某些事上 naive ,不是么。相比过分老成,也许还是保持天真,看到的世界会更有意思。

_

漫无目的地写下些有的没的,尚不成篇,像是在回答自己,又算不上是答案。那些只是引子。手指敲击着键盘,心中已思绪万千。回忆已似潮水涌上心头,每一段都很有画面感。回想起过去每天经过的路,回想起生活了六年的地方,回想起曾经的自己。

有轨电车,我有些想念。

_