demo放在首位: https://dante.jdtj.top/gent/
我依赖pixijs,编写了一个用于canvas排版的库。
这里的排版不同于 html2canvas 之类的库,它们是生成一张图片,这里的排版是要整个页面用 canvas 绘制,包括动画、交互等等(类似 react-canvas,外国小红书搞出来的东西,已经凉了)
做这个东西,主要是优化长列表和增强交互效果。长列表的dom方案有虚拟列表只渲染可视区的节点,但是在快速滚动的时候,上下会留白。但是如果用canvas来处理,可以得到一个几乎完美的效果。举个例子:https://chart.caihongduoduo.com/chart?lotteryId=1000&lotteryL...(在手机上打开)。可以看到,canvas处理后的长列表非常流畅。
页面都用canvas排版后,能实现什么效果:
内部自带优化方案,解决海量节点渲染的性能问题。
两种优化办法:
其一:不在可视区的内容,跳过渲染。不影响它的节点对象,在它不被渲染时也可以对其属性进行操作
其二:对页面局部进行缓存,在页面重排重绘时,减少渲染
页面效果更丰富
一、封装补间动画方法,实现类似css动画的效果
/** * * @param params * name 动画名称 * duration 动画执行时长 ms * delay 延迟多久执行 * func 补间动画执行的 贝塞尔方法名 或者 动画模板名称 * attr{} 动画操作的属性 * callback 动画执行完毕后的回调 */ regKeyFrames(params)
二、在节点上调用```regCustomRender(canvas: HTMLCanvasElement)```后,会用传入的canvas覆盖节点本身的渲染,在结合```getSnapshoot('base64')```取得节点的渲染结果可以实现炫酷的效果。
这是demo的录屏:https://dante.jdtj.top/gent/demo.mp4
- 原滋原味的截图,不会有兼容问题和失真。但也要注意图像的跨域问题
页面如何便捷排版
节点
想要完全实现dom的排版体验比较困难。我目前实现了一套简单的排版方式:
Graph 暴露一个pixiJS的Graphics对象,充当"canvas"的角色
Text 文本
Image 图片
Input 输入框,对input进行包装,支持type = ['text', 'password', 'number']
Video 视频渲染
Select 下拉框
Option 下拉框的选项
ScrollY 纵向滚动容器,自动计算内容高度和滚动条
ScrollX 横向向滚动容器,自动计算内容宽度和滚动条
HorLinearLayout 横向线性布局,内部元素都是水平排列
VerLinearLayout 纵向线性布局,内部元素都是垂直排列
AbsoluteLayout" 绝对定位布局,内部元素基于AbsoluteLayout定位,AbsoluteLayout基于父级定位
FixedLayout 固定定位布局,内部元素基于FixedLayout定位,FixedLayout基于app挂载对象定位
这些个布局容器可以相互嵌套,虽然写法比较啰嗦,但已经可以实现大部分的页面布局。
属性
在属性上,也支持了%,px,calc,auto。这些里面最难实现的是auto。其他几个的子父级影响都可以认为是单向的,都是子级依赖父级的尺寸进行计算,而auto,它就需要子级尺寸变化时影响父级的尺寸,父级又会影响父级的父级和父级的子级,引起大量的计算。这样的影响,直到传递到尺寸不受影响的节点为止,因为它没有被这次重新计算改变尺寸,那么它就不会影响它的子级和父级,影响停止于此。
目前实现了以下的属性:
width
height
marginLeft
marginRight
marginTop
marginBottom
borderLeftWidth
borderRightWidth
borderTopWidth
borderBottomWidth
borderLeftColor
borderRightColor
borderTopColor
borderBottomColor
rotate 旋转角度 0-360
anchor 锚点,rotate和scale受它的影响
bgColor 背景色
top AbsoluteLayout,FixedLayout和他们的子节点可用。HorLinearLayout的子节点可用
bottom AbsoluteLayout,FixedLayout和他们的子节点可用。HorLinearLayout的子节点可用
left AbsoluteLayout,FixedLayout和他们的子节点可用。VerLinearLayout的子节点可用
right AbsoluteLayout,FixedLayout和他们的子节点可用。VerLinearLayout的子节点可用
id 通过getElementById找到节点
groupId 通过getElementsByGroupId找到节点组,类似getElementsByClassName
// text特有属性
lineHeight 行高
fontSize 字号
fontColor 文字颜色
text 文字内容
fontFamily
wordWrap
breakWords
其他
所有的节点都自带 overflow: hidden
效果