LoginSignup
0
2

More than 5 years have passed since last update.

Power BI カスタムビジュアル開発 : SVGUtils で SVG を扱う

Posted at

SVGUtils

SVGUtils は SVG の扱いを容易にする機能を提供します。カスタムビジュアルではグラフの描写に SVG を多用するためうまく使うと開発が楽になります。

インストール

以下手順で追加。

1. npm コマンドでインストール。

npm install powerbi-visuals-utils-svgutils --save

2. tsconfig.json の files に型情報を追加。

tsconfig.json
{
  "compilerOptions": {
  ...
  },
  "files": [
    ..., 
    "node_modules/powerbi-visuals-utils-svgutils/lib/index.d.ts"
  ]
}

3. pbiviz.json の externalJS に追加。

pbiviz.json
{
  ...
  "externalJS": [
    ...,
    "node_modules/powerbi-visuals-utils-svgutils/lib/index.js"
  ],
  ...
}

機能

CssConstants

CssConstants モジュールはクラスセレクターの操作を容易にする機能を提供。

powerbi.extensibility.utils.svg.CssConstants モジュールは以下の機能を提供

CreateClassAndSelector

指定した名前で ClassAndSelector インスタンスを作成。作成したインスタンスの .class プロパティを使ってクラスを付与し、.selector をセレクターとして利用。

function createClassAndSelector(className: string): ClassAndSelector;

CreateClassAndSelector の例

import CssConstants = powerbi.extensibility.utils.svg.CssConstants;

export class Visual implements IVisual {
    ...
    private barClassAndSelector: CssConstants.ClassAndSelector;

    constructor(options: VisualConstructorOptions) {
        ...
        this.barClassAndSelector = CssConstants.createClassAndSelector('bar');
    }

    public update(options: VisualUpdateOptions) {
    ...
    this.bars = this.barContainer
        .selectAll(this.barClassAndSelector.selectorName)
        .data(this.viewModel.dataPoints);
    this.bars.enter()
        .append('rect')
        .classed(this.barClassAndSelector.className, true);
...

manipulation

manipulation は SVG で利用できる transform プロパティの値を作成する機能を提供。これによりマジックストリングを減らすことが可能。

powerbi.extensibility.utils.svg モジュールは以下の機能を提供。

translate

translate プロパティ用の文字列を作成

function translate(x: number, y: number): string

translate の例

import svg = powerbi.extensibility.utils.svg;

svg.translate(100, 100); // translate(100,100)

translateXWithPixels

translateX をピクセル単位で作成。

function translateXWithPixels(x: number): string

translateXWithPixels の例

import svg = powerbi.extensibility.utils.svg;

svg.translateXWithPixels(100); // translateX(100px)

translateWithPixels

ピクセル単位での translate 文字列を作成。

function translateWithPixels(x: number, y: number): string

translateWithPixels の例

import svg = powerbi.extensibility.utils.svg;

svg.translateWithPixels(100, 100); // translate(100px,100px)

translateAndRotate

translate と rotate の文字列を作成。

function translateAndRotate(x: number, y: number, px: number, py: number, angle: number): string

translateAndRotate の例

import svg = powerbi.extensibility.utils.svg;

svg.translateAndRotate(100, 100, 50, 50, 35); // translate(100,100) rotate(35,50,50)

scale

CSS 用の scale プロパティを作成。

function scale(scale: number): string

scale の例

import svg = powerbi.extensibility.utils.svg;

svg.scale(50); // scale(50)

createArrow

Arrow を作成。

function createArrow(width: number, height: number, rotate: number): { path: string; transform: string; };

createArrow の例

import svg = powerbi.extensibility.utils.svg;

let arrow = svg.createArrow(10, 20, 5);

this.svg.append('path')
    .attr("d",arrow.path)
    .attr("transform", arrow.transform);

Rect

Rect は四角形 (Rectangle) の操作を行う機能を提供。

powerbi.extensibility.utils.svg.shapes.Rect モジュールは以下の機能を提供。

getOffset

Rectangle のオフセットを確認。

function getOffset(rect: IRect): IPoint;

getOffset の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.getOffset({ left: 25, top: 25, width: 100, height: 100 });

/* returns: {
    x: 25,
    y: 25
}*/

getSize

Rectangle のサイズを確認。

function getSize(rect: IRect): ISize;

getSize の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.getSize({ left: 25, top: 25, width: 100, height: 100 });

/* returns: {
    width: 100,
    height: 100
}*/

setSize

rectangle のサイズを変更。

function setSize(rect: IRect, value: ISize): void;

setSize の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

let rectangle = { left: 25, top: 25, width: 100, height: 100 };

Rect.setSize(rectangle, { width: 250, height: 250 });

// rectangle === { left: 25, top: 25, width: 250, height: 250 }

right

rectangle の右位置を確認。

function right(rect: IRect): number;

right の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.right({ left: 25, top: 25, width: 100, height: 100 });

// returns: 125

bottom

rectangle の下位置を確認。

function bottom(rect: IRect): number;

bottom の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.bottom({ left: 25, top: 25, width: 100, height: 100 });

// returns: 125

topLeft

rectangle の左上を確認。

function topLeft(rect: IRect): IPoint;

topLeft の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.topLeft({ left: 25, top: 25, width: 100, height: 100 });

// returns: { x: 25, y: 25 }

topRight

rectangle の右上を確認。

function topRight(rect: IRect): IPoint;

topRight の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.topRight({ left: 25, top: 25, width: 100, height: 100 });

// returns: { x: 125, y: 25 }

bottomLeft

rectangle の左下を確認。

function bottomLeft(rect: IRect): IPoint;

bottomLeft の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.bottomLeft({ left: 25, top: 25, width: 100, height: 100 });

// returns: { x: 25, y: 125 }

bottomRight

rectangle の右下を確認。

function bottomRight(rect: IRect): IPoint;

bottomRight の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.bottomRight({ left: 25, top: 25, width: 100, height: 100 });

// returns: { x: 125, y: 125 }

clone

rectangle をコピー

function clone(rect: IRect): IRect;

clone の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.clone({ left: 25, top: 25, width: 100, height: 100 });

/* returns: {
    left: 25, top: 25, width: 100, height: 100}
*/

toString

rectangle を文字列をとして表現

function toString(rect: IRect): string;

toString の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.toString({ left: 25, top: 25, width: 100, height: 100 });

// returns: {left:25, top:25, width:100, height:100}

offset

rectangle に指定したオフセットを適用。

function offset(rect: IRect, offsetX: number, offsetY: number): IRect;

offset の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.offset({ left: 25, top: 25, width: 100, height: 100 }, 50, 50);

/* returns: {
    left: 75,
    top: 75,
    width: 100,
    height: 100
}*/

add

1 つ目の rectangle に 2 つ目の rectangle を追加。

function add(rect: IRect, rect2: IRect): IRect;

add の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.add(
    { left: 25, top: 25, width: 100, height: 100 },
    { left: 50, top: 50, width: 75, height: 75 });

/* returns: {
    left: 75,
    top: 75,
    height: 175,
    width: 175
}*/

getClosestPoint

指定した rectangle に近いポイント (IPoint) を確認。

function getClosestPoint(rect: IRect, x: number, y: number): IPoint

getClosestPoint の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.getClosestPoint({ left: 0, top: 0, width: 100, height: 100 }, 50, 50);

/* returns: {
    x: 50,
    y: 50
}*/

equal

2 つの rectangle が同じか確認。

function equal(rect1: IRect, rect2: IRect): boolean

equal の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.equal(
    { left: 0, top: 0, width: 100, height: 100 },
    { left: 50, top: 50, width: 100, height: 100 });

// returns: false

equalWithPrecision

小数点の精度レベルで 2 つの rectangle が同じか確認。

function equalWithPrecision(rect1: IRect, rect2: IRect): boolean

equalWithPrecision の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.equalWithPrecision(
    { left: 0, top: 0, width: 100, height: 100 },
    { left: 50, top: 50, width: 100, height: 100 });

// returns: false

isEmpty

rectangle が空か確認。

function isEmpty(rect: IRect): boolean

isEmpty の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.isEmpty({ left: 0, top: 0, width: 0, height: 0 });

// returns: true

containsPoint

rectangle がポイント (IPoint) を含むか確認。

function containsPoint(rect: IRect, point: IPoint): boolean

containsPoint の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.containsPoint({ left: 0, top: 0, width: 100, height: 100 }, { x: 50, y: 50 });

// returns: true

isIntersecting

2 つの rectangle が交差しているか確認。

function isIntersecting(rect1: IRect, rect2: IRect): boolean

isIntersecting の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.isIntersecting(
    { left: 0, top: 0, width: 100, height: 100 },
    { left: 0, top: 0, width: 50, height: 50 });

// returns: true

intersect

2 つの rectangle が交差する領域を確認。

function intersect(rect1: IRect, rect2: IRect): IRect

intersect の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.intersect(
    { left: 0, top: 0, width: 100, height: 100 },
    { left: 0, top: 0, width: 50, height: 50 });

/* returns: {
    left: 0,
    top: 0,
    width: 50,
    height: 50
}*/

combine

2 つの rectangle を重ねた合計を確認。

function combine(rect1: IRect, rect2: IRect): IRect

combine の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.combine(
    { left: 0, top: 0, width: 100, height: 100 },
    { left: 0, top: 0, width: 50, height: 120 });

/* returns: {
    left: 0,
    top: 0,
    width: 100,
    height: 120
}*/

getCentroid

rectangle の中心点を取得。

function getCentroid(rect: IRect): IPoint

getCentroid の例

import Rect = powerbi.extensibility.utils.svg.shapes.Rect;

Rect.getCentroid({ left: 0, top: 0, width: 100, height: 100 });

/* returns: {
    x: 50,
    y: 50
}*/

pointer

pointer はポインターの位置を確認する機能を提供。

powerbi.extensibility.utils.svg モジュールは以下の機能を提供。

getCoordinates

現在のポインター位置を返す。

function getCoordinates(rootNode: Element, isPointerEvent: boolean): number[]

getCoordinates の例

import svg = powerbi.extensibility.utils.svg;

let bodySelection = d3.select("body");

bodySelection
    .append("div")
    .style({
        width: "100px",
        height: "100px",
        "background-color": "green"
    })
    .on("click", () => {
        svg.getCoordinates(bodySelection.node(), true);
    });

// Div をクリックした時点の位置を返す

まとめ

高度なビジュアルでは多くの SVG 要素が含まれ、重なっているもののハンドルなども必要となってきます。

目次に戻る

参考

SVGUtils

0
2
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
2