ChartUtils
ChartUtils
はカスタムビジュアルを作るためのインターフェースのセットです。軸の管理や凡例の操作、データのラベルの管理などが行えるなど、ビジュアルに関する重要な機能を提供します。
インストール
以下手順で追加。
1. npm コマンドでインストール。
npm install powerbi-visuals-utils-chartutils --save
2. tsconfig.json の files に型情報を追加。
{
"compilerOptions": {
...
},
"files": [
...,
"node_modules/powerbi-visuals-utils-chartutils/lib/index.d.ts"
]
}
3. pbiviz.json の externalJS に追加。
{
...
"externalJS": [
...,
"node_modules/powerbi-visuals-utils-chartutils/lib/index.js"
],
...
}
4. デザインの情報を style/visual.less に追加。
@import (less) "node_modules/powerbi-visuals-utils-interactivityutils/lib/index.css";
@import (less) "node_modules/powerbi-visuals-utils-chartutils/lib/index.css";
...
機能
- Axis Helper : チャートの軸の管理
- Legend Service : 凡例作成用のサービス
- DataLabelUtils : データに対するラベル作成と管理
Axis Helper
Axis Helper
はチャートの軸の操作を簡単にします。
powerbi.extensibility.utils.chart.axis
モジュールは多くの機能を提供するため、以下にいくつかよく使うものを紹介します。
- getRecommendedNumberOfTicksForYAxis
- getRecommendedNumberOfTicksForXAxis
- getBestNumberOfTicks
- getCategoryValueType
- isOrdinal
- isDateTime
- getCategoryThickness
- createOrdinalScale
getRecommendedNumberOfTicksForYAxis
チャート領域の高さによって最適な Y 軸の項目数を返す。
function getRecommendedNumberOfTicksForYAxis(availableWidth: number)
getRecommendedNumberOfTicksForYAxis の例
import axis = powerbi.extensibility.utils.chart.axis;
public update(options: VisualUpdateOptions) {
...
let yAxis = d3.svg.axis()
.scale(yAxisScale)
.orient('left')
.ticks(axis.getRecommendedNumberOfTicksForYAxis(options.viewport.height));
...
getRecommendedNumberOfTicksForXAxis
チャート領域の幅によって最適な X 軸の値の項目数を返す。
function getRecommendedNumberOfTicksForXAxis(availableWidth: number): number;
getRecommendedNumberOfTicksForXAxis の例
import axis = powerbi.extensibility.utils.chart.axis;
public update(options: VisualUpdateOptions) {
...
let xAxis = d3.svg.axis()
.scale(xScale)
.ticks(axis.getRecommendedNumberOfTicksForXAxis(width))
.orient('bottom');
...
getBestNumberOfTicks
最小値、最大値、メジャーの値、項目数の最大から最適な項目数を返す。
function getBestNumberOfTicks(min: number, max: number, valuesMetadata: DataViewMetadataColumn[], maxTickCount: number, isDateTime?: boolean): number;
getBestNumberOfTicks の例
import axis = powerbi.extensibility.utils.chart.axis;
public update(options: VisualUpdateOptions) {
...
let yAxis = d3.svg.axis()
.scale(yAxisScale)
.orient('left')
.ticks(axis.getBestNumberOfTicks(
this.viewModel.dataMin,
this.viewModel.dataMax,
options.dataViews[0].metadata.columns,
6)
);
...
contains
元の文字列が指定した文字列を含むか確認する。
function contains(source: string, substring: string): boolean;
contains の例
import axis = powerbi.extensibility.utils.chart.axis;
axis.contains("Microsoft Power BI Visuals", "Power BI"); // true
getCategoryValueType
カテゴリー列のタイプ (ValueType) を返す。タイプがない場合はテキスト型として処理。
function getCategoryValueType(metadataColumn: DataViewMetadataColumn, isScalar?: boolean): ValueType;
getCategoryValueType の例
import axis = powerbi.extensibility.utils.chart.axis;
public update(options: VisualUpdateOptions) {
...
let categorySource = options.dataViews[0].categorical.categories[0].source;
let categoryType = axis.getCategoryValueType(categorySource, true);
...
isOrdinal
type がテキスト、ブーリアン、バーコードまたは郵便番号か確認。詳細はソースコードを参照。
function isOrdinal(type: ValueTypeDescriptor): boolean;
isOrdinal の例
import axis = powerbi.extensibility.utils.chart.axis;
public update(options: VisualUpdateOptions) {
...
let categorySource = options.dataViews[0].categorical.categories[0].source;
let categoryType = axis.getCategoryValueType(categorySource, true);
axis.isOrdinal(categoryType);
...
isDateTime
type が日付型か確認。
function isDateTime(type: ValueTypeDescriptor): boolean;
isDateTime の例
import axis = powerbi.extensibility.utils.chart.axis;
public update(options: VisualUpdateOptions) {
...
let categorySource = options.dataViews[0].categorical.categories[0].source;
let categoryType = axis.getCategoryValueType(categorySource, true);
axis.isDateTime(categoryType);
...
getCategoryThickness
実際のカテゴリの幅を取得。
function getCategoryThickness(scale: any): number;
getCategoryThickness の例
import axis = powerbi.extensibility.utils.chart.axis;
let range = [0, 100];
let domain = [0, 10];
let scale = d3.scale.linear().domain(domain).range(range);
let actualThickness = axis.getCategoryThickness(scale);
createOrdinalScale
D3 の OrdinalScale を作成。
function createOrdinalScale(pixelSpan: number, dataDomain: any[], outerPaddingRatio?: number, innerPaddingRatio?: number, useRangePoints?: boolean): d3.scale.Ordinal<any, any>;
createOrdinalScale の例
import axis = powerbi.extensibility.utils.chart.axis;
public update(options: VisualUpdateOptions) {
...
let xScale = axis.createOrdinalScale(
options.viewport.width,
this.viewModel.dataPoints.map(d => d.category)
);
...
Legend service
Legend service
を使うとカスタムビジュアルに凡例を簡単に表示できます。
powerbi.visuals
モジュールは以下の機能を提供します。
createLegend
凡例オブジェクトの作成。描写は別途必要。
function createLegend(
legendParentElement: HTMLElement, // 凡例を配置する親エレメント
interactive: boolean, // 凡例がインタラクティブか指定
interactivityService: IInteractivityService, // 凡例をクリックした際のインタラクションのハンドルをするサービス
isScrollable: boolean = false, // 凡例でスクロールを使うか
legendPosition: LegendPosition = LegendPosition.Top // 凡例の位置
): ILegend;
createLegend の例
import legend = powerbi.extensibility.utils.chart.legend;
...
export class Visual implements IVisual {
private seriesLegend: legend.ILegend;
public init(options: VisualConstructorOptions) {
...
this.interactivityService = createInteractivityService(options.host);
this.seriesLegend= legend.createLegend(
options.element,
options.interactivity && options.interactivity.isInteractiveLegend,
this.interactivityService,
true,
legend.LegendPosition.Left);
}
...
ILegend
凡例の操作に必要な関数を定義したインターフェース
export interface ILegend {
getMargins(): IViewport;
isVisible(): boolean;
changeOrientation(orientation: LegendPosition): void;
getOrientation(): LegendPosition;
drawLegend(data: LegendData, viewport: IViewport): any;
/**
* Reset the legend by clearing it
*/
reset(): void;
}
drawLegend
SVG 上に凡例を描写
function drawLegend(data: LegendData, viewport: IViewport): void;
drawLegend の例
以下の例では表示する凡例データがある場合、設定から取得した位置に凡例を表示。データが無ければ上部に配置して表示しない。
private renderLegend(): void {
if (!this.isInteractive) {
let legendObjectProperties = this.data.legendObjectProperties;
if (legendObjectProperties) {
let legendData = this.data.legendData;
LegendData.update(legendData, legendObjectProperties);
let position = <string>legendObjectProperties[legendProps.position];
if (position)
this.legend.changeOrientation(LegendPosition[position]);
this.legend.drawLegend(legendData, this.parentViewport);
} else {
this.legend.changeOrientation(LegendPosition.Top);
this.legend.drawLegend({ dataPoints: [] }, this.parentViewport);
}
}
}
DataLabelUtils
DataLabelUtils
データラベルの管理を行うユーティリティー
powerbi.extensibility.utils.chart.dataLabel.utils
モジュールは以下の機能を提供
- drawDefaultLabelsForDataPointChart
- getLabelFormattedText
- enumerateDataLabels
- enumerateCategoryLabels
- createColumnFormatterCacheManager
drawDefaultLabelsForDataPointChart
データ用のラベルを描写
function drawDefaultLabelsForDataPointChart(
data: any[], // ラベル用のデータ
context: d3.Selection<any>, // ラベルを表示する領域
layout: ILabelLayout, // ラベルのデータや位置などのレイアウト
viewport: IViewport, // Viewport
isAnimator?: boolean, // アニメーションの有無
animationDuration?: number, // アニメーション時間
hasSelection?: boolean, // 選択されたアイテムの透過率設定
hideCollidedLabels?: Boolean // 重なるラベルを非表示にするか指定
): d3.selection.Update<any>;
drawDefaultLabelsForDataPointChart の例
データポイントが座標の情報など必要なものを持っている前提。
import dataLabelUtils = powerbi.extensibility.utils.chart.dataLabel.utils;
dataLabelUtils.drawDefaultLabelsForDataPointChart(
this.viewModel.dataPoints,
this.svg,
this.getLayout(),
this.viewport,
true,
1,
false,
false);
// データラベル用のレイアウトを返す
private getLayout(): dataLabel.ILabelLayout {
return {
labelText: (dataGroup: BarChartDataPoint) => {
return dataLabelUtils.getLabelFormattedText({
label: dataGroup.value,
maxWidth: this.viewport.width,
});
},
labelLayout: {
x: (d: BarChartDataPoint) => {
return d.x;
},
y: (d: BarChartDataPoint) => {
return d.y;
}
},
filter: (dataGroup: BarChartDataPoint) => {
return true; // フィルターはせず、すべてのデータを返す
},
style: {
"fill": "black",
"font-family": "helvetica,arial,sans-serif"
},
};
}
getLabelFormattedText
ラベルのフォーマットオプションの取得
function getLabelFormattedText(options: LabelFormattedTextOptions): string
getLabelFormattedText の例
import dataLabelUtils = powerbi.extensibility.utils.chart.dataLabel.utils;
let options: LabelFormattedTextOptions = {
text: 'some text',
fontFamily: 'sans',
fontSize: '15',
fontWeight: 'normal',
};
dataLabelUtils.getLabelFormattedText(options);
まとめ
軸や凡例を描写するのは結構面倒なため、このユーティリティーは使い方を覚えればとても役に立ちます。是非試してください。