React / Ant Design Pro 实现Canvas画布实时自适应
如何实现canvas根据父容器进行自适应?
Ant Design的组件都提供了强大的自适应能力,为了对齐父组件,镶嵌在Ant Design组件里的canvas也需要能根据父级容器进行自适应的能力,页面高度一般不用做自适应,因为即使太多内容页面太长,也会出现滚动条,所以问题不大,问题在于宽度,屏幕尺寸各不同,如果宽度不够,元素就会被挤变形或者换行
步骤:
首先,固定canvas的height,对于width
1、实时获取父组件的尺寸
2、实时修改canvas的尺寸
1
这里使用一个npm的包,可以很轻松的实时获取某节点的尺寸:
npm install resize-observer-polyfill --save-dev
用法 :首先在父节点下创建一个div,父节点,div,canvas的关系如下:
<父组件> <div> <Canvas></Canvas> </div> </父组件>
然后,利用ref读到DOM节点,如下
<父组件> <div ref={this.refHandle}> <Canvas></Canvas> </div> </父组件>
constructor(props) { super(props); this.state = { cvWidth: null } }
refHandle = (cw) => { // containerWrap if (cw) { const ro = new ResizeObserver((entries, observer) => { // eslint-disable-next-line no-restricted-syntax for (const entry of entries) { const { left, top, width, height } = entry.contentRect; // console.log('Element:', entry.target); // console.log(`Element's size: ${width}px x ${height}px`); // console.log(`Element's paddings: ${top}px ; ${left}px`); console.log(`Element's size: ${width} x ${height} `); this.setState({ cvWidth: width }) } }); ro.observe(cw); } };
{ cvWidth && <Canvas cvWidth={cvWidth } /> }
2 在Canvas组件里
使用以下生命周期,为了避免不必要的渲染,当新旧cvWidth一样时不进行重新渲染
componentWillReceiveProps
componentWillReceiveProps(nextProps) { const { ...data } = this.props const { ...newData } = nextProps if (data.cvWidth !== newData.cvWidth) { this.canvas.width = newData.cvWidth this.canvasRender(newData) } }
this.canvas是我创建的canvas实例,canvasRender是我的canvas画图函数,你可以换成你自己的,最后在this.canvas开头加一行
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
防止图像重叠
PS:我的父组件,使用了Row+Col,并且Col使用了span,因此一开始Row+Col就有宽度
另外,如果要实现宽高自适应,请参考G2+bizcharts的源码,先看bizcharts的Chart组件