问题描述
前置条件
使用了Angular页面缓存
使用了ResizeObserver监听zrender宿主dom尺寸,如果尺寸发生变化则调用zrenderIns.resize()
元素设置了culling: true
路由A: zrender绘制页面,路由B: 常规配置页面
复现步骤
2024-10-01.08.12.31.mov
第一次页面加载路由A,渲染没有问题
切换至路由B
切回路由A
绘制元素消失
问题分析
refresh执行中会判断元素如果设置为culling则会判断是否在可视区域中,不在则不会渲染。而之前切换页面时会导致zrender宿主dom的尺寸变为长宽为0, 所以无论如何判断元素都不会渲染
而调用resize函数后, 源码确实会计算当前视窗尺寸但是没有设置_width 和 _height 这两个私有属性
if ( this . _width !== width || height !== this . _height ) {
domRoot . style . width = width + 'px' ;
domRoot . style . height = height + 'px' ;
for ( let id in this . _layers ) {
if ( this . _layers . hasOwnProperty ( id ) ) {
this . _layers [ id ] . resize ( width , height ) ;
}
}
this . refresh ( true ) ;
}
this . _width = width ;
this . _height = height ;
这段代码会使用_width和_height
const repaint = ( repaintRect ?: BoundingRect ) => {
const scope : BrushScope = {
inHover : false ,
allClipped : false ,
prevEl : null ,
viewWidth : this . _width ,
viewHeight : this . _height
} ;
for ( i = start ; i < layer . __endIndex ; i ++ ) {
const el = list [ i ] ;
if ( el . __inHover ) {
needsRefreshHover = true ;
}
this . _doPaintEl ( el , layer , useDirtyRect , repaintRect , scope , i === layer . __endIndex - 1 ) ;
if ( useTimer ) {
// Date.now can be executed in 13,025,305 ops/second.
const dTime = Date . now ( ) - startTime ;
// Give 15 millisecond to draw.
// The rest elements will be drawn in the next frame.
if ( dTime > 15 ) {
break ;
}
}
}
Line 215 永真
if (
this . ignore
// Ignore invisible element
|| this . invisible
// Ignore transparent element
|| this . style . opacity === 0
// Ignore culled element
|| ( this . culling
&& isDisplayableCulled ( this , viewWidth , viewHeight )
)
// Ignore scale 0 element, in some environment like node-canvas
// Draw a scale 0 element can cause all following draw wrong
// And setTransform with scale 0 will cause set back transform failed.
|| ( m && ! m [ 0 ] && ! m [ 3 ] )
) {
return false ;
可能方案
前置
this . _width = width ;
this . _height = height ;
临时方案
再调用一遍refrsh(true)进行全部刷新 😭
(this.zrenderIns.painter.refresh as EtSafeAny)(true); Ts 语法还报错 可以的话这玩意也修复下
问题描述
前置条件
复现步骤
2024-10-01.08.12.31.mov
问题分析
refresh执行中会判断元素如果设置为culling则会判断是否在可视区域中,不在则不会渲染。而之前切换页面时会导致zrender宿主dom的尺寸变为长宽为0, 所以无论如何判断元素都不会渲染
而调用resize函数后, 源码确实会计算当前视窗尺寸但是没有设置_width 和 _height 这两个私有属性
zrender/src/canvas/Painter.ts
Lines 870 to 884 in 247e119
这段代码会使用_width和_height
zrender/src/canvas/Painter.ts
Lines 413 to 440 in 247e119
Line 215 永真
zrender/src/graphic/Displayable.ts
Lines 208 to 223 in 247e119
可能方案
前置
zrender/src/canvas/Painter.ts
Lines 883 to 884 in 247e119
临时方案
再调用一遍refrsh(true)进行全部刷新 😭
(this.zrenderIns.painter.refresh as EtSafeAny)(true); Ts 语法还报错 可以的话这玩意也修复下