Power BI カスタムビジュアル開発 : ColorUtils で色の管理をする

# ColorUtils 

`ColorUtils` は Power BI カスタムビジュアルで使う色の操作を簡単にするユーティリティです。例えば、シリーズで使う多くの色を自動で生成したり、アイテムクリックに伴って使うようなハイライト色、背景を透過するような色、また 2 つのグラフが重なった領域の色を取得するような便利な関数が提供されます。

# インストール

以下手順で追加。

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

```shell
npm install powerbi-visuals-utils-colorutils --save
```
2\. tsconfig.json の files に型情報を追加。

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

3\. pbiviz.json の externalJS に追加。

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

# 機能

- [ColorHelper](#colorhelper] : チャートの値によって異なる色を生成する
- [ColorUtils](#colorutils) : 色のフォーマット変換

# ColorHelper

`ColorHelper` を使うと様々な異なる色を、容易に生成することができます。

`powerbi.extensibility.utils.color.ColorHelper` モジュールは以下の機能を提供します。

- [getColorForSeriesValue](#getcolorforseriesvalue)
- [getColorForMeasure](#getcolorformeasure)
- [normalizeSelector](#normalizeselector)

## getColorForSeriesValue

この関数はシリーズの色を生成。明示的な指定がない場合や、既定の色がない場合、引数の値を利用してカラースケールより色を割り当てる。自動で色を割り当てたい場合は、既定の色を指定しない。

```typescript
getColorForSeriesValue(objects: IDataViewObjects, value: PrimitiveValue): string
```

### getColorForSeriesValue の例

まず Capabilities.json の objects に色を保持するオブジェクトとプロパティを指定。

```json:capabilities.json
...
"objects": {
    "dataColor": {
        "displayName": "データの色",
        "properties": {
            "fill": {
                "displayName": "既定の色",
                "type": {
                    "fill": {
                        "solid": {
                            "color": true
                        }
                    }
                }
            }
        }
    }
}
...
```

visual.ts にて必要なモジュールをインポートし、色を取得する場所で関数を実行。ここでは既定値をして 'green' を指定。値がない場合は緑となる。自動割り当てをしたい場合は、色を指定しない。

```typescript:visual.ts
import ColorHelper = powerbi.extensibility.utils.color.ColorHelper;
...

public update(options: VisualUpdateOptions) {
    let groups = options.dataViews[0].categorical.values.grouped();
    let colorHelper: ColorHelper = new ColorHelper(
        this.host.colorPalette,
        {
            objectName: "dataColor",
            propertyName: "fill"
        },
        "green");
       
    grouped.foreach((group)=>{
        colorHelper.getColorForSeriesValue(group.objects, group.name);
    });
...
```

## getColorForMeasure

この関数はメジャーに対して色々を設定。

```typescript
getColorForMeasure(objects: IDataViewObjects, measureKey: any): string
```

### getColorForMeasure の例

まず Capabilities.json の objects に色を保持するオブジェクトとプロパティを指定。

```json:capabilities.json
...
"objects": {
    "dataColor": {
        "displayName": "データの色",
        "properties": {
            "fill": {
                "displayName": "既定の色",
                "type": {
                    "fill": {
                        "solid": {
                            "color": true
                        }
                    }
                }
            }
        }
    }
}
...
```

visual.ts にて必要なモジュールをインポートし、色を取得する場所で関数を実行。ここでは既定値をして 'green' を指定。値がない場合は緑となる。自動割り当てをしたい場合は、色を指定しない。

```typescript
import ColorHelper = powerbi.extensibility.utils.color.ColorHelper;

export class YourVisual implements IVisual {
...

public update(options: VisualUpdateOptions): {
    const objects: DataViewObjects = options.dataViews[0].categorical.categories[0].objects[0],
    let colorHelper: ColorHelper = new ColorHelper(
        this.host.colorPalette,
        {
            objectName: "dataColor",
            propertyName: "fill"
        },
        "green");

    colorHelper.getColorForMeasure(objects, ""); 
...    
}
```

## normalizeSelector

この関数は selector に対して measure を取り除いたものを返します。

```typescript
static normalizeSelector(selector: Selector, isSingleSeries?: boolean): Selector;
```

### normalizeSelector の例

```typescript
import ISelectionId = powerbi.visuals.ISelectionId;
import ColorHelper = powerbi.extensibility.utils.color.ColorHelper;

let selectionId: ISelectionId = ...;

ColorHelper.normalizeSelector(selectionId.getSelector(), false);
```

normalizeSelector は動的なシリーズを使うチャートにおいて色がカテゴリ単位で設定される場合、シリーズからメジャーの selector (metadata 部分) を取り除いて selector を返します。詳細は [ソースコード](https://github.com/Microsoft/powerbi-visuals-utils-colorutils/blob/37309fe961741f6ede9075eb91fd41ebc9e5060e/src/colorHelper.ts#L75) を確認してください。



# ColorUtils
`colorUtils` は色のフォーマット変換に関する関数を提供します。

`powerbi.extensibility.utils.color` モジュールは以下の機能を提供します。

- [hexToRGBString](#hextorgbstring)
- [rotate](#rotate)
- [parseColorString](#parsecolorstring)
- [calculateHighlightColor](#calculatehighlightcolor)
- [createLinearColorScale](#createlinearcolorscale)
- [shadeColor](#shadecolor)
- [rgbBlend](#rgbblend)
- [channelBlend](#channelblend)
- [hexBlend](#hexblend)

## hexToRGBString

HEX を RGB に変換。

```typescript
function hexToRGBString(hex: string, transparency?: number): string
```

### hexToRGBString の例

```typescript
import ColorUtility = powerbi.extensibility.utils.color;

ColorUtility.hexToRGBString('#112233'); // "rgb(17,34,51)"
```

## rotate
RGB をローテーションします。

```typescript
function rotate(rgbString: string, rotateFactor: number): string
```

### rotate の例

```typescript
import ColorUtility = powerbi.extensibility.utils.color;

ColorUtility.rotate("#CC0000", 0.25); // #66CC00
```

## parseColorString
色を指定する文字列を RGB に変換

```typescript
function parseColorString(color: string): RgbColor
```

### parseColorString の例

```typescript
import ColorUtility = powerbi.extensibility.utils.color;

ColorUtility.parseColorString('#09f'); // {R: 0, G: 153, B: 255 }

ColorUtility.parseColorString('rgba(1, 2, 3, 1.0)');// {R: 1, G: 2, B: 3, A: 1.0 }
```

## calculateHighlightColor

lumianceThreshold と delta 値から指定した RGB のハイライト色を取得

```typescript
function calculateHighlightColor(rgbColor: RgbColor, lumianceThreshold: number, delta: number): string
```

### calculateHighlightColor の例

```typescript
import ColorUtility = powerbi.extensibility.utils.color;

let yellow = "#FFFF00",
    yellowRGB = ColorUtility.parseColorString(yellow);

ColorUtility.calculateHighlightColor(yellowRGB, 0.8, 0.2); // '#CCCC00'
```

## createLinearColorScale

リニアカラースケールに対して指定した数値の色を取得

```typescript
function createLinearColorScale(domain: number[], range: string[], clamp: boolean): LinearColorScale
```

### createLinearColorScale の例

```typescript
import ColorUtility = powerbi.extensibility.utils.color;

let scale = ColorUtility.createLinearColorScale(
    [0, 1, 2, 3, 4],
    ["red", "green", "blue", "black", "yellow"],
    true);

scale(1); // green
scale(10); // yellow
```

## shadeColor

HEX を数値に変換し、RGB のパーセント数値を取得。その数値を元に色に対して適用し、'#' 付きの色情報を取得。

```typescript
function shadeColor(color: string, percent: number): string
```

### shadeColor の例

```typescript
import ColorUtility = powerbi.extensibility.utils.color;

ColorUtility.shadeColor('#000000', 0.1); // '#1a1a1a'
ColorUtility.shadeColor('#FFFFFF', -0.5); // '#808080'
ColorUtility.shadeColor('#00B8AA', -0.25); // '#008a80'
ColorUtility.shadeColor('#00B8AA', 0); // '#00b8aa' (変化なし)
```

## rgbBlend

RGB 色を透過率を使って背景色にオーバーレイした色を取得。

```typescript
function rgbBlend(foreColor: RgbColor, opacity: number, backColor: RgbColor): RgbColor
```

### rgbBlend の例

```typescript
import ColorUtility = powerbi.extensibility.utils.color;

ColorUtility.rgbBlend({R: 100, G: 100, B: 100}, 0.5, {R: 200, G: 200, B: 200}); // {R: 150, G: 150, B: 150}
```

## channelBlend

2 色を混ぜた値を透過率を使用して取得

```typescript
function channelBlend(foreChannel: number, opacity: number, backChannel: number): number
```

### channelBlend の例

```typescript
import ColorUtility = powerbi.extensibility.utils.color;

ColorUtility.channelBlend(0, 1, 255); // 0
ColorUtility.channelBlend(128, 1, 255); // 128
ColorUtility.channelBlend(255, 0, 0); // 0
ColorUtility.channelBlend(88, 0, 88); // 88
```

## hexBlend

HEX 色を透過率を使って背景色にオーバーレイした色を取得。

```typescript
function hexBlend(foreColor: string, opacity: number, backColor: string): string
```

### hexBlend の例

```typescript
import ColorUtility = powerbi.extensibility.utils.color;

let yellow = "#FFFF00",
    black = "#000000",
    white = "#FFFFFF";

ColorUtility.hexBlend(yellow, 0.5, white); // "#FFFF80"
ColorUtility.hexBlend(white, 0.5, yellow); // "#FFFF80"

ColorUtility.hexBlend(yellow, 0.5, black); // "#808000"
ColorUtility.hexBlend(black, 0.5, yellow); // "#808000"
```

# まとめ

RGB と HEX ともに対応している事や、背景色や 2 色が混じった際の色を簡単に計算できるので、とても便利です。明示的に色を苦労して指定している場合は、こちらのユーティリティーを使ってみてください。

[目次へ戻る](https://qiita.com/kenakamu/items/f57ab7f73d6ea10bc9d9)

# 参照
[ColorUtil](https://github.com/Microsoft/powerbi-visuals-utils-colorutils)
[Installation Guide](./docs/usage/installation-guide.md)
[Usage Guide](./docs/usage/usage-guide.md)