PBI中使用SVG自定义折线缩略图

1. 目的驱动

在学习别人做的报表的时候,我有看到如下图所示的效果。
PBI中使用SVG自定义折线缩略图_第1张图片
我个人觉得这个趋势图比较有意思,于是就研究了一下是如何画出来的。
经研究发现,这个就是用SVG画出来的。
前面介绍SVG的时候提到过,SVG可以用来画一些自定义的图表。
这里我们主要就学习如何用SVG画折线图
图中所示的折线图的含义是:每类电影票房趋势的变化(by year)
即:X轴——year,Y轴——每年该类电影票房总值。

2. 理解设计原理

由于是缩略图,我们肯定不能按照真实的year和票房来展现X、Y轴。
而需要对X、Y轴进行一些处理,让缩略图显示得更加美观。

对X、Y轴的处理主要就是:计算相对位置(当前值在整个区间内的比例)
X轴:以最小年份作为X轴的起点,最大年份作为X轴的终点,然后计算当前年份在整个区间内的百分比位置。Y轴同理。

比如X轴:假设某电影的上映年限为2000年-2020年,如果当前年份为2010年,那么2010年就应该在整个X轴的50%的位置。
Y轴同理:假设某电影的票房区间(最大值-最小值)(by year)为一亿,而当前年份的票房高出最低票房三千万,则该年的Y坐标就应该在整个Y轴的30%的位置。

:必须理解 “相对位置” 的概念,才能知道图是何如画出来的。

1. SVG折线图基本属性

折线图的简单示例:

<svg xmlns='http://www.w3.org/2000/svg'
	 viewBox='0 0 500 500'>
<polyline
		  fill='none'
		  stroke='red'
		  stroke-width='4'
		  points='0,40 40,40 40,80 80,80 80,120 120,120 120,160'/>
</svg>

1. 标签

画简单的折线图,我们只需要用到两个标签。

  1. … 标签最基本的标签,画任何类型的图都需要在外面嵌套…标签;
  2. 标签:专门画折线图的标签。

2.标签的属性

  1. 每个标签会有一些基本的属性(在PBI中使用SVG时,属性值必须用单引号引起来)。
  2. 每个属性之间用空格进行分隔(可以换行)。

标签属性说明:

  • xmlns:说明这段代码所遵从的标准;
  • viewBox:设置可视窗口的大小;
  • fill:设置图形填充颜色;
  • stroke:设置图形边框的颜色;
  • stroke-width:设置图形边框的宽度;
  • points:画折线图的点位信息,每个点位用空格隔开,SVG会按顺序将各个点连接起来;
    如:points=‘0,40 40,40 40,80 80,80 80,120 120,120 120,160’
    代表依次从点1(0,40)到点2(40,40)到点3(40,80)…,直到最后一个点,绘制折线图。

3. 显示折线图

可以在 SVG图形展示 中查看SVG的图形形状 (将代码粘贴到文本框中,然后运行即可)。
前面的SVG代码就可以绘制出下面的折线图:
PBI中使用SVG自定义折线缩略图_第2张图片

2. 图标大小设定

为了整个图片的呈现美观,我们需要先对SVG图标的大小进行设计。
这里,我们将整个SVG图标的大小设计成 100*100 的大小(如果没有特殊要求,我们一般采用100*100的大小)。

3. 确定X、Y轴的值

X轴:
求出年份的最大值和最小值
计算 (当前年份-最小年份) 占整个年份区间内的比例

如:年份区间为:2000至2020,当前年份为2010。
[(2010-2000)/(2020-2000)]*100%=50%。
则当前年份的X坐标应该在整个X轴的50%的位置。

③ 对②中计算出来的比例值乘以100放大,并以此值作为X坐标;(因为②中得到的比例范围为0-1,乘以100,刚好是0-100的范围)

如:②中举例年份的X坐标为50。

Y轴:
Y轴和X轴的步骤一样。
① 求出该类电影票房的最大值和最小值(by year);
② 计算 (当前年份票房-最小票房) 占整个票房区间的比例;
③ 对②中计算出来的值乘以100放大,并以此值作为Y坐标。

4. 具体实现

1. 先建一个计算票房总值的度量值

box_office_sum = sum('movie_metadata'[box office])

2. 计算Year最小值和最大值

VAR XMinDate = MIN('movie_metadata'[year])
VAR XMaxDate = MAX('movie_metadata'[year])

3. 计算每年票房的最小值和最大值

VAR YMinValue = MINX(VALUES('movie_metadata'[year]),CALCULATE([box_office_sum]))
VAR YMaxValue = MAXX(VALUES('movie_metadata'[year]),CALCULATE([box_office_sum]))

4. 计算X、Y值并存入临时表

VAR SparklineTable = ADDCOLUMNS(
    SUMMARIZE('movie_metadata','movie_metadata'[year]),
        "X",INT(100 * DIVIDE('movie_metadata'[year]- XMinDate , XMaxDate - XMinDate)),
        "Y",INT(100 * DIVIDE([box_office_sum] - YMinValue,YMaxValue - YMinValue)))

5.将X、Y值连接起来

从前面的polyline标签的points属性的介绍中,我们知道,points属性是由多个点组成的,每个点用空格隔开
即points属性的格式如下:

points='0,40 40,40 40,80 80,80 80,120 120,120 120,160'

第4步中,我们得到的数据格式如下:
PBI中使用SVG自定义折线缩略图_第3张图片

要将第4步中的表格数据格式转换成points属性需要的文本格式
我们可以使用下面的语句:

VAR Lines = CONCATENATEX(SparklineTable,[X] & "," & 100-[Y]," ", [year])

使用concatenatex()函数将X、Y值用逗号连接起来,然后将多行的数据用空格来隔开,并用 [year] 来正序排列X、Y值

注:使用“100-[Y]”的原因:使用SVG画图时,它的坐标系是从左上角开始的;而我们一般画图时的坐标系是从左下角开始的,所以Y值需要用整个画布的大小,减去原来的Y值,得到新的Y值,作为SVG画图的Y坐标(相当于将图片" 上下颠倒 ")。
SVG画图时的坐标系:
PBI中使用SVG自定义折线缩略图_第4张图片

注:concatenatex()函数详解:理解 CONCATENATEX

6. 完整度量值

1. box_office_sum

box_office_sum = sum('movie_metadata'[box office])

2. Box_office_sparkline

Box_office_sparkline = 

// Static line color - use %23 instead of # for Firefox compatibility
VAR LineColor = "%234A588A"

// "Date" field used in this example along the X axis
VAR XMinDate = MIN('movie_metadata'[year])
VAR XMaxDate = MAX('movie_metadata'[year])

// Obtain overall min and overall max measure values when evaluated for each date
VAR YMinValue = MINX(VALUES('movie_metadata'[year]),CALCULATE([box_office_sum]))
VAR YMaxValue = MAXX(VALUES('movie_metadata'[year]),CALCULATE([box_office_sum]))

// Build table of X & Y coordinates and fit to 100 x 100 viewbox
VAR SparklineTable = ADDCOLUMNS(
    SUMMARIZE('movie_metadata','movie_metadata'[year]),
        "X",INT(100 * DIVIDE('movie_metadata'[year]- XMinDate , XMaxDate - XMinDate)),
        "Y",INT(100 * DIVIDE([box_office_sum] - YMinValue,YMaxValue - YMinValue)))

// Concatenate X & Y coordinates to build the sparkline
VAR Lines = CONCATENATEX(SparklineTable,[X] & "," & 100-[Y]," ", [year])

// Add to SVG, and verify Data Category is set to Image URL for this measure
VAR SVGImageURL = IF(HASONEVALUE('movie_metadata'[type]),
    "data:image/svg+xml;utf8," & 
    "" &
     "",
     BLANK())
RETURN if(isblank(sum('movie_metadata'[box office])),blank(),SVGImageURL)

写完度量值后,还需要将度量值的数据类型改成“图像 URL”,否则只能显示SVG源代码,无法解析成图片。

注:原始数据格式如下:
PBI中使用SVG自定义折线缩略图_第5张图片
想要自己练习的小伙伴可以按照这个格式,生成测试数据来练习。
或者**直接私信我,要原始数据文档和 .pbix 文件。**

你可能感兴趣的:(Power,BI,学习)