LoginSignup
0
0

Cytoscape.js: The style value of `label` is deprecated for `width`

Posted at

Cytoscape.jsでノードの横幅をラベル文字の横幅に合わせたい場合に使えたwidth: 'label'オプションが、v3.16から非推薦となっている1

cytoscape({
  style: [
    {
      selector: 'node',
      style: {
        shape: 'rectangle',
        width: 'label' // The style value of `label` is deprecated for `width`
      }
    }
  ]
})

さらに、このオプションでは図のようにラベルの前後にパディングがなく、見た目が悪い。

width: 'label'

マッパーの作成

ドキュメントには「プロパティの値を直接指定する代わりにマッパーを用いて動的にプロパティ値を指定することもできる2」とあるので、ラベル文字からキャンバスに描画された文字の横幅を取得するマッパーを作成する。

labelWidth.ts
import type { NodeCollection } from 'cytoscape'

const labelWidth = (node: NodeCollection): number => {
  const canvas = document.createElement('canvas')
  const context = canvas.getContext('2d')!
  context.font = ['style', 'weight', 'size', 'family']
    .map(style => node.style(`font-${style}`))
    .join(' ')
  const { width } = context.measureText(node.data('label'))
  const padding = 10

  return width + padding
}

export { labelWidth }
JavaScriptの場合
labelWidth.js
const labelWidth = node => {
  const canvas = document.createElement('canvas')
  const context = canvas.getContext('2d')
  context.font = ['style', 'weight', 'size', 'family']
    .map(style => node.style(`font-${style}`))
    .join(' ')
  const { width } = context.measureText(node.data('label'))
  const padding = 10

  return width + padding
}

node.data('label')labelの値は、elementsで定義したノードのラベルのプロパティ名に合わせて変更してください。

cytoscape({
  elements: [
    {
      data: {
        id: '1',
        label: 'node1' // ← このプロパティ名に合わせる
    }
  }]
})

マッパーの使用

widthオプションに作成したマッパーを指定する。

+ import { labelWidth } from 'labelWidth.ts'

  cytoscape({
    style: [
      {
        selector: 'node',
        style: {
          shape: 'rectangle',
-         width: 'label' // The style value of `label` is deprecated for `width`
+         width: labelWidth
        }
      }
    ]
  })

いい感じになった。

width: labelWidth

余談

ワーニングの文字列「The style value of label is deprecated for width」でググると、おそらくcytoscape/cytoscape.js#2713を参考にしたてあろう下記のようなマッパーがいくつかヒットしたが、自分で試したところ上手くいかなかった。

const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
const fontStyle = node.style('font-style')
const fontSize = node.style('font-size')
const fontFamily = node.style('font-family')
const fontWeight = node.style('font-weight')
context.font = fontStyle + ' ' + fontWeight + ' ' + fontSize + ' ' + fontFamily

調査したところ、原因は node.style()を適用する順番 にあることがわかった。
MDN Web docsによると、CSSのfontプロパティの値は次の順番で指定しなければならない3

font: font-style font-weight font-size font-family

上記コードにおいてcontext.fontの指定順は問題ないが、その前のnode.style()の適用においてもこの順番を守る必要があったようである。
つまり、次のように適用順番を修正すれば、上記コードでも正しく機能する。

  const canvas = document.createElement('canvas')
  const context = canvas.getContext('2d')
  const fontStyle = node.style('font-style')
+ const fontWeight = node.style('font-weight')
  const fontSize = node.style('font-size')
  const fontFamily = node.style('font-family')
- const fontWeight = node.style('font-weight')
  context.font = fontStyle + ' ' + fontWeight + ' ' + fontSize + ' ' + fontFamily
  1. Deprecate width:label & height:label

  2. Mappers

  3. font - CSS: カスケーディングスタイルシート | MDN

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0