背景
-
svg
タグやcanvas
タグ等で、width
、height
属性を設定したい - けれど、それらをレンダリングする場所は、固定サイズでないため(CSSで
width: 100%
等)レンダリングするまで具体的なサイズが不明 - そのほか、コンテナー要素のサイズに応じて、自前でレイアウト計算したいことがある
解決策
- react-measureのコンポーネントのchildrenでサイズを計測したい要素をレンダリングする
- childrenとしてFunctionを設定すると、
measureRef
(サイズ計測対象のref
をreact-measeureに渡すためのもの)が引数で渡されてくる - サイズ計測したい要素の
ref
にmeasureRef
を設定する。
例
SVGで指定の間隔の罫線を描くコンポーネント。DIV(.grid-inner)のサイズを計測し、その中にDIVと同サイズのSVGを生成し、SVGで罫線を描く
- 要素のサイズはstateで持つ
- サイズ変化時に
onResize: (contentRect) => void
が呼ばれる。contentRect
に計測したサイズが入ってくるので、サイズをsetStateして再レンダリングさせる
import * as React from "react";
import _ = require("underscore");
import Measure from "react-measure";
export interface GridProps {
size: number;
}
export class Grid extends React.Component<GridProps, {}> {
state = {
width: 0,
height: 0
}
render() {
const { size } = this.props;
const { width, height } = this.state;
return <div className="grid">
<Measure bounds onResize={(contentRect) => { this.setState({ ...contentRect.bounds }) }}>
{({ measureRef }) =>
<div ref={measureRef} className="grid-inner">
<svg width={width} height={height}>
<g>
{_.range(size, height, size).map((y) => {
return <line x1={0} y1={y}
x2={width} y2={y}
className="grid-line" />
})}
</g>
</svg>
</div>
}
</Measure>
</div>
}
}
.grid {
width: 100%;
height: 100%;
}
.grid-inner {
width: 100%;
height: 100%;
}