柱图教程

手把手教你制作一个带有Tooltip提示的框的柱图!

1. 准备数据

柱图需要两个信息,维度和每个维度的柱子,在数据视图中制作一个包含一个维度一个数值的结果,如下图表示每日这个渠道的用户访问量,可提供三个在图表视图引用的变量:

  • $DATA_VIEWS[0],代表“访问数据集”
  • $X_FIELDS[0][0].id,代表“发送时间”维度中的值
  • $Y_FIELDS[0][0].id,代表“会话量”数值中的值

2. 画图数据

有了数据,但是画图不能直接用数值结果,比如收入10亿,在图中怎么画?换个角度,需要将数据转换为图中的位置,如用20个像素代表10亿。展示柱图确定柱子的宽度和高度,这就用到了scale,坐标比例尺,将原始数据转换为画图可用的数据。

  • 宽度——现在有6个维度,也就是6个柱子,每个宽度一样,所以每个珠子的宽度应该是"图表的宽度"/6
  • 高度——每个柱子的高度由数字决定,应当在图表高度中按照数值大小分布,分布方式有很多种,如线性分布,按照数值比例获取占高度的大小
"scales": [
    {
      "name": "xscale",
      "type": "band",
      "domain": {"data": "ds0", "field": "x0"},
      "range": "width"
    },
    {
      "name": "yscale",
      "domain": {"data": "ds0", "field": "y0"},
      "nice": true,
      "range": "height"
    }
  ],

定义两个scale分别代表宽度坐标(xscale)和高度坐标(yscale),每个scale需要有个唯一的名字name,之后使用时会调用这个名字。

其中宽度坐标需要均分图表宽度,转换类型设置为等分组band,代表按照维度个数平分图表的宽度;如宽度为600时,第一个维度的坐标将为[0-100]domain为转换坐标的数据来源,上图中使用第一个数据集和其第一个维度字段。range为目标范围,如上图代表将“width”图表宽度设为目标值,分组将等分这个值。

高度坐标没有设置type,默认为linear,线性分布,可理解为按原值占比获取其在高度目标值的占比,。目标范围设为“height“图表高度。数据使用数据集的第一个数值“会话量”。这里用的nice属性为Vega提供的美化语法,可将转换结果进行一定程度处理,使结果更易理解,达到更好的展示效果,如[0, 94.345]自动转换为[0, 100]

range中使用的“width”“height“为Vega的预置的内部变量,可直接引用图表的宽度和高度;用户也可以手动指定值域数组,如[0, 400]and [200, 0]。当typeband时,range可以指定每个柱子的步长,步长=柱子宽度+边距,如设定步长为60,最终柱图总长=60*6=360。当typeordinal时,range还可以指定一个长数组,指定自定义的颜色序列(如RGB十进制"#ffa804")。

domain可使用数据视图中数据集结果或数组及各种外部JSON数据,如CSV等。数据转换默认支持处理数值为零的数据,可以通过设置"zero": false,取消该特性。

比例尺转出的图表数据与原始数据结构对应,使用时需要按照原始数据结构对应,如在画图数据中使用y0代表使用第一个数值字段转换出的画图坐标。

3. 图形

图形是Vega中最主要的元素,将可视化都拆解为图形的组合,如上面的柱图,每个柱子是一个矩形,共6个矩形,用到了marks属性:

  "marks": [
    {
      "type": "rect",
      "from": {"data":"ds0"},
      "encode": {
        "enter": {
          "x": {"scale": "xscale", "field": "x0", "offset": 1},
          "width": {"scale": "xscale", "band": 1, "offset": -1},
          "y": {"scale": "yscale", "field": "y0"},
          "y2": {"scale": "yscale", "value": 0}
        },
        "update": {
          "fill": {"value": "steelblue"}
        },
        "hover": {
          "fill": {"value": "red"}
        }
      }
    },

marks中可以有多个图形,每个图形可以设置自己的类型typerect代表使用矩形(rectangles)。有了图形,还要描述6个柱子根据什么数据画,使用from属性,说明数据来自第一个数据集,在BDP中通常使用数据视图中的数据集作为数据来源。如果不指定from会默认画一个图形。

图形的可视化属性在encode中设置,如颜色、大小,分为几个状态:

  • enter,图形第一次绘制,设置了柱图的位置和大小;
  • exit,图形被删除或移除时,本次没用到;
  • update,图形设置更新或改变,设置了柱图的颜色,创建后会首次进入更新状态;
  • hover,鼠标移动至图形上,设置了鼠标移动到柱子上需要改变的颜色;

这里看到颜色没在enter中设置而是在update中设置,这是因为hover设置了颜色改变,如果不设置在update中,鼠标经过柱子后将出现一个永久红色的柱子。

重点说明创建时如何画出基础图形:

          "x": {"scale": "xscale", "field": "x0", "offset": 1},
          "width": {"scale": "xscale", "band": 1, "offset": -1},
          "y": {"scale": "yscale", "field": "y0"},
          "y2": {"scale": "yscale", "value": 0}

画图形四要素,描述图形水平、垂直方向的起始和结束值,xwidth确定水平位置和每个柱子宽度,yy2决定了垂直位置和柱子高度:

  • x,每个图形起始位置,如柱图中每个柱子的的左侧坐标,画图数据使用定过的水平坐标"xscale"中的第一个维度x0"offset": 1第一个柱子前的偏移量,与其他柱子间隔1像素的样式保持一致;
  • width,每个维度所占的宽度,即柱子的宽度,使用已经计算好的"xscale"中的等宽长度。"band": 1代表使用比例尺计算的大小,可以设置0-1的小数代表使用比例尺结果的百分比结果,如"band": 0.5代表使用比例尺结果的一半;
  • yy2,柱子顶部的高度,类似xwidth,每个柱子垂直方向的起始位置和结束位置,也可以使用类似的height,这里由于每个柱子都是从水平线开始,使用y2将起始值固定为0。实际上Vega也不区分yy2哪个是起始值,只要设置了两个值系统会自动按照坐标大小调整位置。

除了标准的图形,Vega支持将图形嵌套分组,通过group属性,可以包含其他图形,如制作BDP中的对比拆分图。分组中可以自定义比例尺和坐标轴。

PS:坐标系起始值[0.0]在预览区域的的左上角。预览时发现图形并不是从预览区域的左下角开始,这是因为自定义图表默认启用了自动缩放大小,Vega默认为四周留了边距,可以使用"autosize": "none"取消自动缩放,注意关闭后在BDP仪表盘中调整图表大小将不影响可视化效果。

4. 坐标轴

柱图还有坐标轴,分为X轴和Y轴,包含刻度和值。

  "axes": [
    { "orient": "bottom", "scale": "xscale" },
    { "orient": "left", "scale": "yscale", "tickCount": 5,"offset": 6 }
  ],

简单的坐标轴只需要设置轴的方向和使用的图表数据,系统会自动生成坐标轴。这里指定X轴在底部使用通过日期维度转换出的画图数据;Y轴在左侧使用数值的画图数据,同时设置了"tickCount": 7默认分为7组刻度,并设置"offset": 6向右移动6个像素的偏移量。

5. 变量

变量是Vega中一种非常实用的属性,可以在发生事件或其他变量变化时,重新计算结果,柱图中的Tooltip提示框就需要用到变量实现。每个变量需要一个唯一的名称name和一个初始值,其他属性用于定义变量如何计算。

Tooltip内容通常为所在图形的值,位置在图形上方,所以为了在鼠标移动在某个柱子时需要根据这个柱子展示,需要一个记录当前柱子的变量,并根据这个属性绘制出提示文本框。

创建变量,先设置一个变量为“tooltip”,初始值为空,变动实际在两个事件,矩形rect的鼠标移入mouseover和移出mouseout事件;在鼠标移入时将变量赋值为鼠标所在矩形的数值对象"datum",鼠标移出时将变量值设回空值。这是一个Vega特殊的内置变量,代表当前的数据对象,在当前的事件中代表的数据包含这个柱子的日期和会话量,在Data中使用时可代表所在的完整数据集。

  "signals": [
    {
      "name": "tooltip",
      "value": {},
      "on": [
        {"events": "rect:mouseover", "update": "datum"},
        {"events": "rect:mouseout",  "update": "{}"}
      ]
    }
  ],

创建文本框,文本框也是一种图形,由于只在鼠标移动到某个柱子时展示,初始状态"enter"只设置基础属性,这些设置均相对之后确定的某个坐标点,对齐方式"align"设为居中,基准线"baseline"设为底部对齐,颜色为黑色。

确定位置,Tooltip应动态展示在柱子顶部的中间,使用"update"每次根据当前柱子的坐标,将文本框绘制在正上方,"x""y"坐标均使用处理好的水平和垂直的画图数据,从画图数据中获取某个柱子坐标时,需要通过原始数据的内容找到对应的转换结果,当移动至某个柱子时变量tooltip值为其的原始数据对象,"tooltip."+x0即引用了这个柱子的日期维度。为了能坐标点在每个柱子中间,获取水平画图数据时,缩放50%"band": 0.5;在垂直方向保留了-2的偏移量,与柱子分隔。

{
  "marks": [
    ...,
     {
      "type": "text",
      "encode": {
        "enter": {
          "align": {"value": "center"},
          "baseline": {"value": "bottom"},
          "fill": {"value": "#333"}
        },
        "update": {
          "x": {"scale": "xscale", "signal": "tooltip."+x0, "band": 0.5},
          "y": {"scale": "yscale", "signal": "tooltip."+y0, "offset": -2},
          "text": {"signal": "tooltip."+y0},
        }
      }
    }
  ]

6. 完整代码

尝试用你的数据创建柱图,练习引用其他数据集。

{

  "signals": [
    {
      "name": "tooltip",
      "value": {},
      "on": [
        {"events": "rect:mouseover", "update": "datum"},
        {"events": "rect:mouseout",  "update": "{}"}
      ]
    }
  ],

  "scales": [
    {
      "name": "xscale",
      "type": "band",
      "domain": {"data": "ds0", "field": "x0"},
      "range": "width"
    },
    {
      "name": "yscale",
      "domain": {"data": "ds0", "field": "y0"},
      "nice": true,
      "range": "height"
    }
  ],


  "axes": [
    { "orient": "bottom", "scale": "xscale" },
    { "orient": "left", "scale": "yscale", "tickCount": 7,"offset": 6  }
  ],


  "marks": [
    {
      "type": "rect",
      "from": {"data":"ds0"},
      "encode": {
        "enter": {
          "x": {"scale": "xscale", "field": "x0", "offset": 1},
          "width": {"scale": "xscale", "band": 1, "offset": -1},
          "y": {"scale": "yscale", "field": "y0"},
          "y2": {"scale": "yscale", "value": 0}
        },
        "update": {
          "fill": {"value": "steelblue"}
        },
        "hover": {
          "fill": {"value": "red"}
        }
      }
    },
    {
      "type": "text",
      "encode": {
        "enter": {
          "align": {"value": "center"},
          "baseline": {"value": "bottom"},
          "fill": {"value": "#333"}
        },
        "update": {
          "x": {"scale": "xscale", "signal": "tooltip."+"x0", "band": 0.5},
          "y": {"scale": "yscale", "signal": "tooltip."+"y0", "offset": -2},
          "text": {"signal": "tooltip."+"y0"},
        }
      }
    }
  ]
}

7. 更多用法

已经有了第一个自定义图表,Vega还有很多强大的可视化能力,下面简要介绍,点击查看官方文档,大家可以尝试做出有意思的效果:

支持的其他Mark

  • arc - 圆弧
  • area - 区域
  • image - 图片
  • group - 分组,包含其他图表
  • line - 线
  • path - 路径或多边形,使用SVG路径
  • rect - 矩形
  • rule - 简易的一根线,只需要起点和终点
  • shape - 任意图形,类似path
  • symbol - 预置图形,圆、方形等.
  • text - 文本框.
  • trail - 粗细可调整的线

支持的其他Scale

定量转化:

离散转化:

更多详细文档正在编写中,使用中遇到问题联系客服,或查看官方文档

results matching ""

    No results matching ""