LoginSignup
1

More than 1 year has passed since last update.

Vega でクリスマスツリー

FUJITSU アドベントカレンダー23日目の記事です。

はじめに

Vega はjsonでデータや描画の設定を記述することで、視覚化できるツールです。いろんなグラフを表現できますが、今回はグラフでなくクリスマスツリーをVegaで表現してみたいと思います。

出来上がったもの

image.png

Online Editor
Gist

中身

データとしては、「幹」「葉っぱ」「星」「白いライン」「丸い飾り」で構成しています。
それぞれ、抜粋しながらポイントを書いておきます。

rect(四角形)を描画してます。

  "data": [
    {"name": "tree", "values": [{"x": 0, "y": 0}]},
  ],
...
  "marks": [
    {
      "type": "rect",
      "from": {"data": "tree"},
      "encode": {
        "update": {
          "x": {"scale": "xscale", "signal": "datum.x - 0.8"},
          "x2": {"scale": "xscale", "signal": "datum.x + 0.8"},
          "y": {"scale": "yscale", "value": 10},
          "y2": {"scale": "yscale", "value": 0},
          "fill": {"value": "#864A2b"}
        }
      }
    },

葉っぱ

高さ(y)とサイズ(size)を変えて、緑色の三角形を並べて表現しています。

"data": [
{
      "name": "leaves",
      "values": [
        {"x": 0, "y": 15, "size": 18000},
        {"x": 0, "y": 20, "size": 15000},
        {"x": 0, "y": 25, "size": 13000},
        {"x": 0, "y": 30, "size": 10000},
        {"x": 0, "y": 36, "size": 6000}
      ]
 },
...
"marks": [
    {
      "type": "symbol",
      "from": {"data": "leaves"},
      "encode": {
        "update": {
          "x": {"scale": "xscale", "field": "x"},
          "y": {"scale": "yscale", "field": "y"},
          "size": {"field": "size"},
          "shape": {"value": "triangle"},
          "fill": {"value": "green"}
        }
      }
    },
]

中身(x=0)に高さ(y)を調整し、星形を作ります。
星形は、SVG pathで表現しています。

"data": [
    {"name": "star", "values": [{"x": 0, "y": 42, "size": 1000}]
],
...
"marks":[
    {
      "type": "symbol",
      "from": {"data": "star"},
      "encode": {
        "enter": {"fill": {"value": "#939597"}, "stroke": {"value": "#652c90"}},
        "update": {
          "x": {"scale": "xscale", "field": "x"},
          "y": {"scale": "yscale", "field": "y"},
          "size": {"field": "size"},
          "shape": {
            "value": "M0,.5L.6,.8L.5,.1L1,-.3L.3,-.4L0,-1L-.3,-.4L-1,-.3L-.5,.1L-.6,.8L0,.5Z"
          },
          "fill": {"value": "yellow"}
        }
      }
    },
]

白いライン

layerによって、group化することで、一つのデータセットから複数の斜め上にいく線を表現しています。
本来は、葉のうえだけ描画するのが正しいですが、白色にすることで背景色と同一にしごまかしています。

"data":[
    {
      "name": "lines",
      "values": [
        {"x": -4, "y": 10, "layer": 1},
        {"x": 4, "y": 20, "layer": 1},
        {"x": -4, "y": 20, "layer": 2},
        {"x": 4, "y": 30, "layer": 2},
        {"x": -4, "y": 30, "layer": 3},
        {"x": 4, "y": 40, "layer": 3}
      ]
    },
],
...
"marks": [
    {
      "type": "group",
      "from": {"facet": {"data": "lines", "name": "facet", "groupby": "layer"}},
      "marks": [
        {
          "type": "line",
          "from": {"data": "facet"},
          "encode": {
            "update": {
              "x": {"scale": "xscale", "field": "x"},
              "y": {"scale": "yscale", "field": "y"},
              "strokeWidth": {"value": 5},
              "stroke": {"value": "white"}
            }
          }
        }
      ]
    },
]

丸い飾り

横の位置(x)と高さ(y)をツリーの上に来るように配置し、飾りの色はxとyを掛けた値をcとして、pastelカラーで振り分けるように、color スケールをつくって表現します。

"data":[
    {
      "name": "bolls",
      "values": [
        {"x": -2, "y": 15},
        {"x": 2, "y": 12},
        {"x": -1, "y": 25},
        {"x": 1.2, "y": 20},
        {"x": -0.8, "y": 10},
        {"x": 0.4, "y": 32},
        {"x": -0.6, "y": 38}
      ],
      "transform": [{"type": "formula", "as": "c", "expr": "datum.x * datum.y"}]
    }
],
"scales": [
    {
      "name": "color",
      "domain": {"data": "bolls", "field": "c"},
      "range": {"scheme": "pastel1"}
    }
],
...
"marks": [
    {
      "type": "symbol",
      "from": {"data": "bolls"},
      "encode": {
        "update": {
          "x": {"scale": "xscale", "field": "x"},
          "y": {"scale": "yscale", "field": "y"},
          "size": {"value": 150},
          "fill": {"scale": "color", "field": "c"}
        }
      }
    }
]

おわりに

急遽思いついて試してみましたが思った以上にクリスマスツリーになりました。

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
What you can do with signing up
1