概略
CytoscapeJSでノードの幅を文字の幅で取りたい時があります。
その時は以下のようにwidthを設定することで設定すれば可能です。
cytoscape({
container: /** target dom */,
elements: {/** 略 */},
style: [
{
selector: 'node',
css: {
label: 'data(name)',
width: 'label', // これ
shape: 'round-rectangle',
'text-valign': 'center',
'text-halign': 'center'
}
},
],
});
しかしconsoleをみたとき、以下のようなワーニングが出てしまいます。
今回はワーニングを出さず同じ結果を出すことを目指します。
install
npm i cytoscape @types/cytoscape
やりかた
const getCharacterWidthInCanvas = (
target: cytoscape.NodeCollection | cytoscape.EdgeCollection
): number => {
const labelWidthPadding = 10;
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d')!;
const fontStyle = target.style('font-style');
const fontSize = target.style('font-size');
const fontFamily = target.style('font-family');
const fontWeight = target.style('font-weight');
ctx.font = fontStyle + ' ' + fontWeight + ' ' + fontSize + ' ' + fontFamily;
return ctx.measureText(target.data('name')).width + labelWidthPadding;
}
cytoscape({
container: /** target dom */,
elements: {/** 略 */},
style: [
{
selector: 'node',
css: {
label: 'data(name)',
width: getCharacterWidthInCanvas, // ここで使う
shape: 'round-rectangle',
'text-valign': 'center',
'text-halign': 'center'
}
},
],
});
にっこり。
表示領域はcanvasを用いているため、measureText()で文字幅を取得します。
しかし実際に表示しているcanvas DOMに値を突っ込むことはできないため、別途canvasを生成してそこで measureText()
を走らせます。
CanvasRenderingContext2D.fontの形式で設定するわけですが、そのために各ノードのstyleを取得します。
fontStyle
, fontWeight
, fontSize
, fontFamily
を見てみましょう。
console.log([fontStyle, fontSize, fontFamily, fontWeight]);
// ['normal', '16px', 'Helvetica Neue, Helvetica, sans-serif', 'normal']
できていますね。
少しパディングをつけて完成です。