1、Flutter 之图像绘制原理

2、Widget、Element、RenderObjectcss

3、Flutter UI 更新流程html

4、build 流程分析前端

5、layout 流程分析react

6、Paint 绘制(1)编程

7、Paint 绘制(2)canvas

8、composite 流程分析浏览器

9、Flutter 小实践bash

在界面上显示一个宽为 300、高为 200 矩形, 以下图所示服务器

前端实现方式不少 (1)domweex

<html>
<style type='text/css'>
    .demo {
        width: 300px;
        height: 200px;
        background: #f00;
    }
</style>
<body>
    <div class='demo'></div>
</body>
</html>
复制代码

html文本描述了页面应该有哪些功能,css告诉浏览器该长什么样 浏览器引擎经过解析html和css,翻译成一些列的预约义UI控件 而后UI控件去调用操做系统绘图指令去绘制图像展示给用户

(2) canvas

<html>
<body>
    <script>
        var c= document.createElement("canvas");
        var ctx=c.getContext("2d");
        ctx.fillStyle="#FF0000";
        ctx.fillRect(0,0,300,200);
        document.body.append(c);
    </script>
</body>
</html>
复制代码

能够经过画布绘制,如以上代码所示, 经过建立 canvas 节点,获取 canvas 绘制上下文,调用相关 API, 即可绘制一个矩形,并 append 到 body 节点中。

一、图形绘制原理

显示器(屏幕)是由一个个物理显示单元(像素点)组成,而每个像素点能够发出多种颜色,显示器成相的原理就是在不一样的物理像素点上显示不一样的颜色,最终构成完整的图像。图形计算和绘制都是由相应的硬件来完成,操做系统通常屏蔽了这些底层硬件操做指令,提供一些封装后的API供操做系统之上的应用调用,可是对于应用开发者来讲,直接调用这些操做系统提供的API是比较复杂和低效的,所以几乎全部用于开发GUI程序的编程语言都会在操做系统之上再封装一层,将操做系统原生API封装在一个编程框架和模型中,而后定义一种简单的开发规则来开发GUI应用程序,而这一层抽象,就是所谓的“UI”系统,如Android SDK正是封装了Android操做系统API,提供了一个“UI描述文件XML+Java操做DOM”的UI系统,而iOS的UIKit 对View的抽象也是同样的,他们都将操做系统API抽象成一个基础对象(如用于2D图形绘制的Canvas),而后再定义一套规则来描述UI,如UI树结构,UI操做的单线程原则等。

二、跨端应用

Weex

上图是weex 工做流程图,WEEX框架中核心的部分是JavaScript Runtime。当JSBundle从服务器端下载完成以后,WEEX在Android、iOS和Web端会运行一个JavaScript引擎来执行JSBundle,同时向各终端的渲染层发送渲染指令,并调度客户端的渲染引擎实现视图渲染、事件绑定和处理用户交互等操做。

ReactNative

上图为 reactnative 流程架构图,和 weex 相似, reactNative 全部的标签也不是真实控件,JS 代码中所生成存的 dom,最后都是由 Native 端解析,再获得对应的Native控件渲染。

不论是 Weex 仍是 ReactJS,自身是不直接绘制UI的,而是调用原生组件执行页面渲染操做。Bridges则是用来绘制指令给原生组件进行绘制

Flutter

与 React Native 和 WEEX 使用原生组件渲染界面不一样,Flutter并不须要使用原生组件来渲染界面,而是使用自带的渲染引擎(Engine层)来绘制页面组件。

以下图所示,Flutter框架主要由 Framework 层和 Engine 层组成,其中 Engine 层 其以Skia做为其2D渲染引擎,有本身的UI绘制机制。

在 Flutter 中,也有 Canvas 的概念,Engine 层向 Dart 层的暴露了 Canvas, PictureRecorder 等接口,利用它们能够绘制任何本身想显示的东西~如如下代码,相似 js 中调用 canvas 相似

void main() {
// 获取绘制图层
OffsetLayer rootLayer = new OffsetLayer();
PictureLayer pictureLayer = PictureLayer(Rect.zero);
rootLayer.append(pictureLayer);
// 绘制图形
pictureLayer.picture =
   createSolidRectanglePicture(Color(0xFFFF0000), 300, 200);
rootLayer.updateSubtreeNeedsAddToScene();
SceneBuilder sceneBuilder = SceneBuilder();
rootLayer.addToScene(sceneBuilder);
Scene scene = sceneBuilder.build();
window.onDrawFrame = () {
 // 将绘制的图层输送到GPU
 window.render(scene);
};
window.scheduleFrame();
}
复制代码

简单地讲,flutter 提供一张画布、咱们能够在画布上天马星空,绘制任何本身想绘制的东西

三、Vsync 更新机制

Vsync 相关概念

在计算机系统中,CPU、GPU和显示器以一种特定的方式协做:CPU将计算好的显示内容提交给 GPU,GPU渲染后放入帧缓冲区,它们是图像生产者,往帧缓冲区(BufferQueue) 不断填充数据, 显示器能够理解为消费者,从帧缓冲区取帧数据(BufferQueue)中获取数据, 负责把渲染后的内容呈现到屏幕上。

为了更新显示画面,显示器是以固定的频率刷新(从GPU取数据),好比有一部手机屏幕的刷新频率是 60Hz。当一帧图像绘制完毕后准备绘制下一帧时,显示器会发出一个垂直同步信号(如VSync), 60Hz的屏幕就会一秒内发出 60次这样的信号, 这个信号是用来同步 CPU、GPU 和显示器的工做的,即提示 CPU 和 GPU 进行下一帧工做的信号, Android系统每隔16.6ms发出VSYNC信号,来通知界面进行输入、动画、绘制等动做

为何须要 Vsync

Refresh Rate:表明了屏幕在一秒内刷新屏幕的次数,这取决于硬件的固定参数,例如60Hz Frame Rate:表明了GPU在一秒内绘制操做的帧数,例如30fps,60fps

若是没有 Vsync 机制,容易产生如下两种状况

(1)供过于求 如今的显卡一般能够将CS的帧率渲染到120以上,即120FPS。可一般咱们使用的显示器只能达到60HZ的刷新率。显然,即便显卡在1秒内将画面变化了120次,但显示器只有展现其中60幅的能力。这种时候,咱们感知的流畅度实际上是60FPS,显卡在显示器两次刷新的一个周期内,输出了两帧画面,前一帧就会被看成无效帧丢弃、多余的帧是无效帧,对画面效果提高没有任何做用。

(2)供不该求

若是图像生成的速率低于图像消费速率,即供不该求的状况下,容易产生卡顿的现象,如上图中:

第一个 16ms:Display显示第0帧,CPU处理完第一帧后,GPU紧接其后处理继续第一帧

第二个16ms:由于早在上一个16ms时间内,第1帧已经由CPU,GPU处理完毕。故Display能够直接显示第1帧。显示没有问题。但在本16ms期间,CPU和GPU却并未及时去绘制第2帧数据,而是在本周期快结束时,CPU/GPU才去处理第2帧数据

第三个16ms: 此时Display应该显示第2帧数据,但因为CPU和GPU尚未处理完第2帧数据,故Display只能继续显示第一帧的数据,结果使得第1帧多画了一次

Vsync 机制是起到一个协调做用,显卡在渲染每一帧以前会等待垂直同步信号,只有显示器完成了一次刷新时,发出垂直同步信号,显卡才会渲染下一帧,确保刷新率和帧率保持同步,以达到供需平衡的效果,防止卡顿现象

Flutter Vsync 流程

更多可参考 www.jianshu.com/p/75139692b…

相关文章
相关标签/搜索