wechat-miniprogram / minigame-canvas-engine

轻量级canvas2d渲染引擎,开放数据域开发解决方案。
https://wechat-miniprogram.github.io/minigame-canvas-engine/
MIT License
274 stars 64 forks source link

display: none 属性支持 #29

Open yuanzm opened 1 year ago

yuanzm commented 1 year ago

Layout.init阶段核心仅仅是根据xml和css创建了节点树,Layout.init之后是执行 Layout.layout执行渲染

之所以将 layout 单独抽象为一个函数,是因为 layout 应当是可以重复调用的,比如改变了一个元素的尺寸,实际上节点树是没变的,仅仅是需要重新计算布局,然后渲染

一个完整的 layout 分成下面的几步:

  1. 执行画布清理,因为布局变化页面需要重绘,这里没有做很高级的剔除等操作,一律清除重画,实际上性能已经很好;
  2. 节点树都含有 style 属性,css-layout 能够根据这些信息计算出最终布局,详情可见 https://www.npmjs.com/package/css-layout
  3. 经过 Layout 计算,节点树带上了 layout、lastLayout、shouldUpdate 布局信息,但这些信息并不是能够直接用的比如 layout.top 是指在一个父容器内的 top,最终要实现渲染,实际上要递归加上父容器的 top这样每次 repaint 的时候只需要直接使用计算好的值即可,不需要每次都递归计算这一步称为 layoutChildren,目的在于将 css-layout 进一步处理为可以渲染直接用的布局信息;
    1. renderChildren:执行渲染;
  4. bindEvents:执行事件绑定;

其中步骤2 css-layout 并不会理解 display: none属性,要实现这个属性,应当是从节点树中临时剔除然后重新计算布局,同时要考虑 display: block 重置回去的场景。

yuanzm commented 1 year ago

参照Yoga的实现是将布局属性全部置空 https://github.com/facebook/yoga/blob/main/yoga/Yoga.cpp#L1822

Layout里面,计算布局是直接作用于整个节点树,思路上可能是·动态设置display:none的时候将布局属性暂存 -> 重新计算布局 ->display: block -> 暂存属性重新使用->重新计算布局。