Использование диаграммы

ChartUtils — это набор интерфейсов и методов для создания осей, меток данных и условных обозначений в визуальных элементах Power BI.

Установка

Чтобы установить пакет, выполните следующую команду в каталоге с текущим визуальным элементом:

npm install powerbi-visuals-utils-chartutils --save

Вспомогательный помощник оси

Вспомогательный элемент оси (axis объект в utils) предоставляет функции для упрощения манипуляций, имеющих ось.

Модуль предоставляет следующие функции:

getRecommendedNumberOfTicksForXAxis

Эта функция возвращает рекомендуемое количество тиков в соответствии с шириной диаграммы.

function getRecommendedNumberOfTicksForXAxis(availableWidth: number): number;

Пример:

import { axis } from "powerbi-visuals-utils-chartutils";
// ...
axis.getRecommendedNumberOfTicksForXAxis(1024);

// returns: 8

getRecommendedNumberOfTicksForYAxis

Эта функция возвращает рекомендуемое количество галок в соответствии с высотой диаграммы.

function getRecommendedNumberOfTicksForYAxis(availableWidth: number);

Пример:

import { axis } from "powerbi-visuals-utils-chartutils";
// ...
axis.getRecommendedNumberOfTicksForYAxis(100);

// returns: 3

getBestNumberOfTicks

Возвращает оптимальное количество галок на основе минимального значения, максимального значения, метаданных измерения и максимального числа галок.

function getBestNumberOfTicks(
  min: number,
  max: number,
  valuesMetadata: DataViewMetadataColumn[],
  maxTickCount: number,
  isDateTime?: boolean
): number;

Пример:

import { axis } from "powerbi-visuals-utils-chartutils";
// ...
var dataViewMetadataColumnWithIntegersOnly: powerbi.DataViewMetadataColumn[] = [
  {
    displayName: "col1",
    isMeasure: true,
    type: ValueType.fromDescriptor({ integer: true })
  },
  {
    displayName: "col2",
    isMeasure: true,
    type: ValueType.fromDescriptor({ integer: true })
  }
];
var actual = axis.getBestNumberOfTicks(
  0,
  3,
  dataViewMetadataColumnWithIntegersOnly,
  6
);

// returns: 4

getTickLabelMargins

Эта функция возвращает поля для меток галочки.

function getTickLabelMargins(
  viewport: IViewport,
  yMarginLimit: number,
  textWidthMeasurer: ITextAsSVGMeasurer,
  textHeightMeasurer: ITextAsSVGMeasurer,
  axes: CartesianAxisProperties,
  bottomMarginLimit: number,
  properties: TextProperties,
  scrollbarVisible?: boolean,
  showOnRight?: boolean,
  renderXAxis?: boolean,
  renderY1Axis?: boolean,
  renderY2Axis?: boolean
): TickLabelMargins;

Пример:

import { axis } from "powerbi-visuals-utils-chartutils";
// ...

axis.getTickLabelMargins(
  plotArea,
  marginLimits.left,
  TextMeasurementService.measureSvgTextWidth,
  TextMeasurementService.estimateSvgTextHeight,
  axes,
  marginLimits.bottom,
  textProperties,
  /*scrolling*/ false,
  showY1OnRight,
  renderXAxis,
  renderY1Axis,
  renderY2Axis
);

// returns:  xMax, yLeft, yRight, stackHeigh;

isOrdinal

Проверяет, имеет ли строка значение NULL, не определена или пуста.

function isOrdinal(type: ValueTypeDescriptor): boolean;

Пример:

import { axis } from "powerbi-visuals-utils-chartutils";
// ...
let type = ValueType.fromDescriptor({ misc: { barcode: true } });
axis.isOrdinal(type);

// returns: true

isDateTime

Проверяет, имеет ли значение тип DateTime.

function isDateTime(type: ValueTypeDescriptor): boolean;

Пример:

import { axis } from "powerbi-visuals-utils-chartutils";
// ...

axis.isDateTime(ValueType.fromDescriptor({ dateTime: true }));

// returns: true

getCategoryThickness

Использует масштаб D3 для получения фактической толщины категории.

function getCategoryThickness(scale: any): number;

Пример:

import { axis } from "powerbi-visuals-utils-chartutils";
// ...

let range = [0, 100];
let domain = [0, 10];
let scale = d3.scale
  .linear()
  .domain(domain)
  .range(range);
let actualThickness = axis.getCategoryThickness(scale);

invertOrdinalScale

Эта функция инвертирует порядковый масштаб. Если x < scale.range()[0], возвращается scale.domain()[0]. В противном случае он возвращает наибольший элемент в scale.domain(), который <имеет значение = x.

function invertOrdinalScale(scale: d3.scale.Ordinal<any, any>, x: number);

Пример:

import { axis } from "powerbi-visuals-utils-chartutils";
// ...

let domain: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
  pixelSpan: number = 100,
  ordinalScale: d3.scale.ordinal = axis.createOrdinalScale(
    pixelSpan,
    domain,
    0.4
  );

axis.invertOrdinalScale(ordinalScale, 49);

// returns: 4

findClosestXAxisIndex

Эта функция находит и возвращает ближайший индекс оси x.

function findClosestXAxisIndex(
  categoryValue: number,
  categoryAxisValues: AxisHelperCategoryDataPoint[]
): number;

Пример:

import { axis } from "powerbi-visuals-utils-chartutils";
// ...

/**
 * Finds the index of the category of the given x coordinate given.
 * pointX is in non-scaled screen-space, and offsetX is in render-space.
 * offsetX does not need any scaling adjustment.
 * @param {number} pointX The mouse coordinate in screen-space, without scaling applied
 * @param {number} offsetX Any left offset in d3.scale render-space
 * @return {number}
 */
private findIndex(pointX: number, offsetX?: number): number {
    // we are using mouse coordinates that do not know about any potential CSS transform scale
    let xScale = this.scaleDetector.getScale().x;
    if (!Double.equalWithPrecision(xScale, 1.0, 0.00001)) {
        pointX = pointX / xScale;
    }
    if (offsetX) {
        pointX += offsetX;
    }

    let index = axis.invertScale(this.xAxisProperties.scale, pointX);
    if (this.data.isScalar) {
        // When we have scalar data the inverted scale produces a category value, so we need to search for the closest index.
        index = axis.findClosestXAxisIndex(index, this.data.categoryData);
    }

    return index;
}

diffScaled

Эта функция вычисляет и возвращает дифф значений в масштабе.

function diffScaled(
  scale: d3.scale.Linear<any, any>,
  value1: any,
  value2: any
): number;

Пример:

import { axis } from "powerbi-visuals-utils-chartutils";
// ...

var scale: d3.scale.Linear<number, number>,
    range = [0, 999],
    domain = [0, 1, 2, 3, 4, 5, 6, 7, 8, 999];

scale = d3.scale.linear()
    .range(range)
    .domain(domain);

return axis.diffScaled(scale, 0, 0));

// returns: 0

createDomain

Эта функция создает домен значений для оси.

function createDomain(
  data: any[],
  axisType: ValueTypeDescriptor,
  isScalar: boolean,
  forcedScalarDomain: any[],
  ensureDomain?: NumberRange
): number[];

Пример:

import { axis } from "powerbi-visuals-utils-chartutils";
// ...

var cartesianSeries = [
  {
    data: [
      { categoryValue: 7, value: 11, categoryIndex: 0, seriesIndex: 0 },
      {
        categoryValue: 9,
        value: 9,
        categoryIndex: 1,
        seriesIndex: 0
      },
      {
        categoryValue: 15,
        value: 6,
        categoryIndex: 2,
        seriesIndex: 0
      },
      { categoryValue: 22, value: 7, categoryIndex: 3, seriesIndex: 0 }
    ]
  }
];

var domain = axis.createDomain(
  cartesianSeries,
  ValueType.fromDescriptor({ text: true }),
  false,
  []
);

// returns: [0, 1, 2, 3]

getCategoryValueType

Эта функция получает ValueType столбец категории. Значение по умолчанию — если Text тип отсутствует.

function getCategoryValueType(
  data: any[],
  axisType: ValueTypeDescriptor,
  isScalar: boolean,
  forcedScalarDomain: any[],
  ensureDomain?: NumberRange
): number[];

Пример:

import { axis } from "powerbi-visuals-utils-chartutils";
// ...

var cartesianSeries = [
  {
    data: [
      { categoryValue: 7, value: 11, categoryIndex: 0, seriesIndex: 0 },
      {
        categoryValue: 9,
        value: 9,
        categoryIndex: 1,
        seriesIndex: 0
      },
      {
        categoryValue: 15,
        value: 6,
        categoryIndex: 2,
        seriesIndex: 0
      },
      { categoryValue: 22, value: 7, categoryIndex: 3, seriesIndex: 0 }
    ]
  }
];

axis.getCategoryValueType(
  cartesianSeries,
  ValueType.fromDescriptor({ text: true }),
  false,
  []
);

// returns: [0, 1, 2, 3]

createAxis

Эта функция создает ось D3, включая масштабирование. Может быть вертикальным или горизонтальным, а также датой, числом или текстом.

function createAxis(options: CreateAxisOptions): IAxisProperties;

Пример:

import { axis } from "powerbi-visuals-utils-chartutils";
import { valueFormatter } from "powerbi-visuals-utils-formattingutils";
// ...

var dataPercent = [0.0, 0.33, 0.49];

var formatStringProp: powerbi.DataViewObjectPropertyIdentifier = {
  objectName: "general",
  propertyName: "formatString"
};
let metaDataColumnPercent: powerbi.DataViewMetadataColumn = {
  displayName: "Column",
  type: ValueType.fromDescriptor({ numeric: true }),
  objects: {
    general: {
      formatString: "0 %"
    }
  }
};

var os = axis.createAxis({
  pixelSpan: 100,
  dataDomain: [dataPercent[0], dataPercent[2]],
  metaDataColumn: metaDataColumnPercent,
  formatString: valueFormatter.getFormatString(
    metaDataColumnPercent,
    formatStringProp
  ),
  outerPadding: 0.5,
  isScalar: true,
  isVertical: true
});

applyCustomizedDomain

Эта функция задает настраиваемый домен, но он не изменяется, если ничего не задано.

function applyCustomizedDomain(customizedDomain: any[], forcedDomain: any[]): any[];

Пример:

import { axis } from "powerbi-visuals-utils-chartutils";
// ...

let customizedDomain = [undefined, 20],
  existingDomain = [0, 10];

axis.applyCustomizedDomain(customizedDomain, existingDomain);

// returns: {0:0, 1:20}

combineDomain

Эта функция объединяет принудительный домен с фактическим доменом, если задано одно из значений. Принудительный домен является первым приоритетом. Расширяет домен, если требуется любая эталонная точка.

function combineDomain(
  forcedDomain: any[],
  domain: any[],
  ensureDomain?: NumberRange
): any[];

Пример:

import { axis } from "powerbi-visuals-utils-chartutils";
// ...

let forcedYDomain = this.valueAxisProperties
  ? [this.valueAxisProperties["secStart"], this.valueAxisProperties["secEnd"]]
  : null;

let xDomain = [minX, maxX];

axis.combineDomain(forcedYDomain, xDomain, ensureXDomain);

powerOfTen

Эта функция указывает, является ли число мощностью 10.

function powerOfTen(d: any): boolean;

Пример:

import { axis } from "powerbi-visuals-utils-chartutils";
// ...

axis.powerOfTen(10);

// returns: true

DataLabelManager

Помогает DataLabelManager создавать и поддерживать метки. Он упорядочивает элементы метки с помощью точки привязки или прямоугольника. Столкновения могут быть автоматически обнаружены для изменения положения или скрытия элементов.

Класс DataLabelManager предоставляет следующие методы:

hideCollidedLabels

Этот метод упорядочивает положение меток и видимость на холсте в соответствии с размерами меток и перекрывающимися.

function hideCollidedLabels(
  viewport: IViewport,
  data: any[],
  layout: any,
  addTransform: boolean = false
  hideCollidedLabels?: boolean
): LabelEnabledDataPoint[];

Пример:

let dataLabelManager = new DataLabelManager();
let filteredData = dataLabelManager.hideCollidedLabels(
  this.viewport,
  values,
  labelLayout,
  true,
  true
);

IsValid

Этот статический метод проверяет, является ли предоставленный прямоугольник допустимым, то есть имеет положительную ширину и высоту.

function isValid(rect: IRect): boolean;

Пример:

let rectangle = {
  left: 150,
  top: 130,
  width: 120,
  height: 110
};

DataLabelManager.isValid(rectangle);

// returns: true

DataLabelUtils

Предоставляет DataLabelUtils возможности для управления метками данных.

Метод предоставляет следующие функции, интерфейсы и классы:

getLabelPrecision

Эта функция вычисляет точность из предоставленного формата.

function getLabelPrecision(precision: number, format: string): number;

getLabelFormattedText

Эта функция возвращает точность формата из предоставленного формата.

function getLabelFormattedText(options: LabelFormattedTextOptions): string;

Пример:

import { dataLabelUtils } from "powerbi-visuals-utils-chartutils";
// ...

let options: LabelFormattedTextOptions = {
  text: "some text",
  fontFamily: "sans",
  fontSize: "15",
  fontWeight: "normal"
};

dataLabelUtils.getLabelFormattedText(options);

перечислениеDataLabels

Эта функция возвращает VisualObjectInstance для меток данных.

function enumerateDataLabels(
  options: VisualDataLabelsSettingsOptions
): VisualObjectInstance;

перечислитьCategoryLabels

Эта функция добавляет VisualObjectInstance для меток данных категории в объект перечисления.

function enumerateCategoryLabels(
  enumeration: VisualObjectInstanceEnumerationObject,
  dataLabelsSettings: VisualDataLabelsSettings,
  withFill: boolean,
  isShowCategory: boolean = false,
  fontSize?: number
): void;

createColumnFormatterCacheManager

Эта функция возвращает диспетчер кэша, предоставляющий быстрый доступ к отформатированным меткам.

function createColumnFormatterCacheManager(): IColumnFormatterCacheManager;

Пример:

import { dataLabelUtils } from "powerbi-visuals-utils-chartutils";
// ...

let value: number = 200000;

labelSettings.displayUnits = 1000000;
labelSettings.precision = 1;

let formattersCache = DataLabelUtils.createColumnFormatterCacheManager();
let formatter = formattersCache.getOrCreate(null, labelSettings);
let formattedValue = formatter.format(value);

// formattedValue == "0.2M"

Служба условных обозначений

Служба Legend предоставляет вспомогательные интерфейсы для создания условных обозначений Power BI и управления ими для визуальных элементов Power BI.

Модуль предоставляет следующие функции и интерфейсы:

createLegend

Эта вспомогательная функция упрощает создание пользовательских условных обозначений Power BI.

function createLegend(
  legendParentElement: HTMLElement, // top visual element, container in which legend will be created
  isScrollable: boolean = false, // indicates that legend could be scrollable or not
  legendPosition: LegendPosition = LegendPosition.Top // Position of the legend inside of legendParentElement container
): ILegend;

Пример:

public constructor(options: VisualConstructorOptions) {
    this.visualInitOptions = options;
    this.layers = [];

    var element = this.element = options.element;
    var viewport = this.currentViewport = options.viewport;
    var hostServices = options.host;

    //... some other init calls

    this.legend = createLegend(
        element,
        true);
}

ILegend

Этот интерфейс реализует все методы, необходимые для создания условных обозначений.

export interface ILegend {
  getMargins(): IViewport;
  isVisible(): boolean;
  changeOrientation(orientation: LegendPosition): void; // processing legend orientation
  getOrientation(): LegendPosition; // get information about current legend orientation
  drawLegend(data: LegendData, viewport: IViewport); // all legend rendering code is placing here
  /**
   * Reset the legend by clearing it
   */
  reset(): void;
}

drawLegend

Эта функция измеряет высоту текста с заданными свойствами текста SVG.

function drawLegend(data: LegendData, viewport: IViewport): void;

Пример:

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);
        }
    }
}