Skip to content

动态模版简介

0JARVIS0 edited this page Oct 13, 2020 · 1 revision

在大部分场景预设好、海报不需要即时编辑的情况下,静态模版已经足够满足我们的大部分海报绘制需求了。但是当面临海报的自由度要求高,信息可选项多,甚至需要从用户处即时获取信息或需要用户直接手动操作海报中元素以完善海报信息的时候,交互体验往往会变差,要么不得不为了一些小的修改频繁修改静态模版的整个结构,大量的时间将会被浪费在重绘并没有作出修改操作的 view,要么就只能等所有修改都做好,然后一次性重绘,用户无法在编辑后马上看到自己的改动造成的影响。有没有什么办法让这种场景下的海报更新操作更为友好呢?如果只重新绘制需要被更新的 view,而其他的 view 都保持不变,是不是就能最大程度改善这一问题呢?基于上述原因,我们提出了动态模版这一与静态模版相对的概念。

动态模版对比静态模版的区别是,我们可以在使用动态模版时,通过向 action 传入单个 view 用以更新模版。在这个过程中,我们只会做必要的重绘操作,而不是每次都把整个模版刷新,从而减少绘制时间,提升交互体验。

静态模版工作流程

静态模版工作流程

动态模版工作流程

动态模版工作流程

而为了实现以上能力,painter 对 palette 做了分层操作。

顾名思义,分层操作就是将模版切割为多个小的模版,分别渲染。这么做的好处就是如果需要对单个 view 进行重绘,painter 只会重绘对应层级的 canvas,绘制在其他层级的内容完全不需要感知到有这次操作。绘制内容的减少,将会大大缩短重绘完成的时间。在决定分层后,我们考虑过几种分层方法:

  1. 每个 view 都作为一个单独的层级:这种方式能最大限度的分割模版,后续更新也能确保每次最多重绘一个 view,还能保持层级不变。但问题是这种分割方式会导致 painter 创建的 pen 对象暴增。由于我们无法预估使用者会创建出多么复杂的模版,层级越多,造成的开销越大。除此之外,在小程序上使用如此多的 canvas 也会导致问题。我们尝试过将示例中的模版按照这种方式绘制,在 ios 上表现尚可,但在 android 上会绘制失败。考虑到官方也建议减少 android 上的画布规模防止 crash,这个方案就此废弃。
  2. 为需要更新的 view 单独做一个操作层:这种方式就是简单粗暴的把需要更新的 view 从模版中切出来,绘制在一个单独的层级上,接下来的修改都只重绘这个操作层。这种方式的 canvas 数量可控,不会造成太大的浪费,同时也能保证更新的最小化。但每次选择新的 view 更新,我们都需要做一遍“把 view 切出来”这个操作,这相比重绘整个模版不见得有优化,除此之外,这个切分操作由于要在两个 canvas 上同时绘制,如果绘制结束的时间不一致,就会导致样式问题,譬如,操作层先绘制好了,背景层还没有,结果页面上刚被切换掉的 view 消失了(这时其实还出现了两个当前需要操作的 view,但是由于重叠问题,不会还是显示一个),又譬如,背景层绘制好了,操作层还没有,画布上当前需要操作的 view 不见了(此时刚被切换的 view 又出现了两个)。最重要的是,这种方式无法在操作时保证 view 的原层级,而我们的目标是在操作时看起来 view 还在它原来应该待的位置,因此我们继续探索新的方案。
  3. 在方案 2 的基础上拓展,将背景层再拆分成两个层级——top 与 bottom:这种三层式的划分方式每次会将相比更新的 view 原本层级更高的绘制到 top 层,而层级更低的则绘制到 bottom 层。这样在方案 2 的基础上,还能保证操作时原层级不被修改,相对而言是更为合理的做法。而方案 2 中每次切换更新的 view,因绘制时间不可控导致的视觉问题,在这种分层方案中能以调节绘制顺序的方式合理避开:如果新切换的 view 比原本的层级要高,则从 bottom 向上绘制,如果新切换的 view 比原本的层级要低,则从 top 向下绘制。利用绘制完成前的视觉残留,能做到类似无缝切换的效果。

view切换时的绘制流程

当然,这种分层的问题也很明显——当频繁更新同一个 view 的时候,只有第一次分层的操作会较大,后续操作都会比直接更新 palette 要小的多,但如果频繁更新不同的 view,分层操作反而会比直接刷新整个模版开销更大。因此在使用时,建议根据具体的场景,酌情选用。

我们刚才也说了,动态模版的优势在于频繁对同一 view 进行更新操作时,能减少开销,那么什么情况下容易产生对某一 view 的频繁刷新呢?举几个例子:位置拖动、拖动缩放。painter 预先对拖动、缩放和删除事件做了处理。

在 painter 中,当你使用了动态模版,除了分层的三层 canvas 之外,还将创建一个 front canvas。这个 canvas 位于整个绘制的最顶层,且绑定了各类手指触碰事件。当用户的触碰事件发生时,front 层将在被选中 view 位置绘制选择框,用以标记选中 view 的位置。同时,选中框上还会有缩放与删除的 icon。当用户的触碰事件被监听到发生在缩放 icon 内,则会进行缩放操作,在删除 icon 内,则会删除该 view,除此之外的位置,如果操作为拖动操作,则会拖动该 view,如果为点击操作,则会点选中对应位置的 view(如没有 view,就取消选中)多个 view 在同一位置重叠时,多次点击还可以切换选中的 view;选中框样式可以通过 customActionStyle 属性传入,具体使用方法请查看上方组件文档。而这些操作,你也可以在示例中体验到。

Clone this wiki locally