Zdieľať cez


Zvýraznenie údajových bodov vo vizuáloch služby Power BI

Tento článok popisuje, ako zvýrazniť údaje vo vizuáloch Power BI.

Ak je prvok vybratý, predvolene sa pole v objekte dataView vyfiltruje tak, values aby zobrazovalo len vybraté hodnoty. values Pri filtrovaní poľa sa vo všetkých ostatných vizuáloch na stránke zobrazia len vybraté údaje.

Ak nastavíte vlastnosť v súbore supportsHighlight na true, výsledkom bude celé nefiltrované values pole spolu s poľom highlightscapabilities.json . Pole highlights má rovnakú dĺžku ako pole hodnoty a všetky nevybrané hodnoty sú nastavené na nullhodnotu . Keď je táto vlastnosť povolená, príslušné údaje vo vizuáli sa zvýraznia porovnaním values poľa s poľom highlights .

V príklade si všimnite, že:

  • Bez podpory zvýraznenia je výber jedinou hodnotou v values poli a jediným pruhom v zobrazení údajov.
  • S podporou zvýraznenia sú všetky hodnoty v values poli. Pole highlights obsahuje null hodnotu nezvýraznených prvkov. V zobrazení údajov sa zobrazia všetky pruhy a zvýraznený pruh je iná farba.

Môžu existovať aj viaceré výbery a čiastočné zvýraznenia. Zvýraznené hodnoty sa zobrazujú v zobrazení údajov.

Poznámka

Priradenie zobrazenia tabuľkového údajov nepodporuje funkciu zvýraznení.

Zvýraznenie údajových bodov s priradením zobrazenia kategorických údajov

V prípade vizuálov s priradením zobrazenia kategorických údajov pridajte "supportsHighlight": true do capabilities.json súboru položku . Napríklad:

{
    "dataRoles": [
        {
            "displayName": "Category",
            "name": "category",
            "kind": "Grouping"
        },
        {
            "displayName": "Value",
            "name": "value",
            "kind": "Measure"
        }
    ],
    "dataViewMappings": [
        {
            "categorical": {
                "categories": {
                    "for": {
                        "in": "category"
                    }
                },
                "values": {
                    "for": {
                        "in": "value"
                    }
                }
            }
        }
    ],
    "supportsHighlight": true
}

Po odstránení nepotrebného kódu vyzerá predvolený zdrojový kód vizuálu ako v nasledujúcom príklade:

"use strict";

// ... default imports list

import { FormattingSettingsService } from "powerbi-visuals-utils-formattingmodel";

import DataViewCategorical = powerbi.DataViewCategorical;
import DataViewCategoryColumn = powerbi.DataViewCategoryColumn;
import PrimitiveValue = powerbi.PrimitiveValue;
import DataViewValueColumn = powerbi.DataViewValueColumn;

import { VisualFormattingSettingsModel } from "./settings";

export class Visual implements IVisual {
    private target: HTMLElement;
    private formattingSettings: VisualFormattingSettingsModel;
    private formattingSettingsService: FormattingSettingsService;

    constructor(options: VisualConstructorOptions) {
        console.log('Visual constructor', options);
        this.formattingSettingsService = new FormattingSettingsService();
        this.target = options.element;
        this.host = options.host;
    }

    public update(options: VisualUpdateOptions) {
        this.formattingSettings = this.formattingSettingsService.populateFormattingSettingsModel(VisualFormattingSettingsModel, options.dataViews);
        console.log('Visual update', options);

    }

    // Returns properties pane formatting model content hierarchies, properties and latest formatting values, Then populate properties pane. 
    // This method is called once every time we open properties pane or when the user edit any format property. 
    public getFormattingModel(): powerbi.visuals.FormattingModel {
        return this.formattingSettingsService.buildFormattingModel(this.formattingSettings);
    }
}

Importujte požadované rozhrania na spracovanie údajov zo služby Power BI:

import DataViewCategorical = powerbi.DataViewCategorical;
import DataViewCategoryColumn = powerbi.DataViewCategoryColumn;
import PrimitiveValue = powerbi.PrimitiveValue;
import DataViewValueColumn = powerbi.DataViewValueColumn;

Vytvorte koreňový div prvok pre hodnoty kategórií:

export class Visual implements IVisual {
    private target: HTMLElement;
    private formattingSettings: VisualFormattingSettingsModel;
    private formattingSettingsService: FormattingSettingsService;

    private div: HTMLDivElement; // new property

    constructor(options: VisualConstructorOptions) {
        console.log('Visual constructor', options);
        this.formattingSettingsService = new FormattingSettingsService();
        this.target = options.element;
        this.host = options.host;

        // create div element
        this.div = document.createElement("div");
        this.div.classList.add("vertical");
        this.target.appendChild(this.div);

    }
    // ...
}

Pred vykreslením nových údajov vymažte obsah prvkov div:

// ...
public update(options: VisualUpdateOptions) {
    this.formattingSettings = this.formattingSettingsService.populateFormattingSettingsModel(VisualFormattingSettingsModel, options.dataViews);
    console.log('Visual update', options);

    while (this.div.firstChild) {
        this.div.removeChild(this.div.firstChild);
    }
    // ...
}

Získajte kategórie a hodnoty mierky z dataView objektu:

public update(options: VisualUpdateOptions) {
    this.formattingSettings = this.formattingSettingsService.populateFormattingSettingsModel(VisualFormattingSettingsModel, options.dataViews);
    console.log('Visual update', options);

    while (this.div.firstChild) {
        this.div.removeChild(this.div.firstChild);
    }

    const dataView: DataView = options.dataViews[0];
    const categoricalDataView: DataViewCategorical = dataView.categorical;
    const categories: DataViewCategoryColumn = categoricalDataView.categories[0];
    const categoryValues = categories.values;

    const measures: DataViewValueColumn = categoricalDataView.values[0];
    const measureValues = measures.values;
    const measureHighlights = measures.highlights;
    // ...
}

Kde categoryValues je pole hodnôt kategórií, measureValues je pole miery a measureHighlights sú zvýraznené časti hodnôt.

Poznámka

Ak sú hodnoty measureHighlights vlastnosti menšie ako hodnoty categoryValues vlastnosti, hodnota bola čiastočne zvýraznená.

Vyčíslite categoryValues pole a načítajte zodpovedajúce hodnoty a zvýraznenia:

// ...
const measureHighlights = measures.highlights;

categoryValues.forEach((category: PrimitiveValue, index: number) => {
    const measureValue = measureValues[index];
    const measureHighlight = measureHighlights && measureHighlights[index] ? measureHighlights[index] : null;
    console.log(category, measureValue, measureHighlight);

});

Vytvorte div prvky a p na zobrazenie a vizualizáciu hodnôt zobrazenia údajov v rámci platformy DOM vizuálu:

categoryValues.forEach((category: PrimitiveValue, index: number) => {
    const measureValue = measureValues[index];
    const measureHighlight = measureHighlights && measureHighlights[index] ? measureHighlights[index] : null;
    console.log(category, measureValue, measureHighlight);

    // div element. it contains elements to display values and visualize value as progress bar
    let div = document.createElement("div");
    div.classList.add("horizontal");
    this.div.appendChild(div);

    // div element to visualize value of measure
    let barValue = document.createElement("div");
    barValue.style.width = +measureValue * 10 + "px";
    barValue.style.display = "flex";
    barValue.classList.add("value");

    // element to display category value
    let bp = document.createElement("p");
    bp.innerText = category.toString();

    // div element to visualize highlight of measure
    let barHighlight = document.createElement("div");
    barHighlight.classList.add("highlight")
    barHighlight.style.backgroundColor = "blue";
    barHighlight.style.width = +measureHighlight * 10 + "px";

    // element to display highlighted value of measure
    let p = document.createElement("p");
    p.innerText = `${measureHighlight}/${measureValue}`;
    barHighlight.appendChild(bp);

    div.appendChild(barValue);

    barValue.appendChild(barHighlight);
    div.appendChild(p);
});

Použite požadované štýly pre prvky na používanie flexboxa definujte farby pre prvky div:

div.vertical {
    display: flex;
    flex-direction: column;
}

div.horizontal {
    display: flex;
    flex-direction: row;
}

div.highlight {
    background-color: blue
}

div.value {
    background-color: red;
    display: flex;
}

Výsledkom je nasledujúce zobrazenie vizuálu:

The visuals with categorical data view mapping and highlight

Zvýraznenie údajových bodov s priradením zobrazenia maticovými údajmi

Pre vizuály s priradením zobrazenia maticových údajov pridajte "supportsHighlight": true do capabilities.json súboru položku . Napríklad:

{
    "dataRoles": [
        {
            "displayName": "Columns",
            "name": "columns",
            "kind": "Grouping"
        },
        {
            "displayName": "Rows",
            "name": "rows",
            "kind": "Grouping"
        },
        {
            "displayName": "Value",
            "name": "value",
            "kind": "Measure"
        }
    ],
    "dataViewMappings": [
        {
            "matrix": {
                "columns": {
                    "for": {
                        "in": "columns"
                    }
                },
                "rows": {
                    "for": {
                        "in": "rows"
                    }
                },
                "values": {
                    "for": {
                        "in": "value"
                    }
                }
            }
        }
    ],
    "supportsHighlight": true
}

Vzorové údaje na vytvorenie hierarchie pre priradenie zobrazenia maticového údajov:

Row1 (Riadok1) Riadok2 Riadok3 Stĺpec 1 Stĺpec 2 Stĺpec 3 Hodnoty
R1 R11 R111 C1 C11 C111 1
R1 R11 R112 C1 C11 C112 2
R1 R11 R113 C1 C11 C113 3
R1 R12 R121 C1 C12 C121 4
R1 R12 R122 C1 C12 C122 5
R1 R12 R123 C1 C12 C123 6
R1 R13 R131 C1 C13 C131 7
R1 R13 R132 C1 C13 C132 8
R1 R13 R133 C1 C13 C133 9
R2 R21 R211 C2 C21 C211 10
R2 R21 R212 C2 C21 C212 11
R2 R21 R213 C2 C21 C213 12
R2 R22 R221 C2 C22 C221 13
R2 R22 R222 C2 C22 C222 14
R2 R22 R223 C2 C22 C223 16
R2 R23 R231 C2 C23 C231 17
R2 R23 R232 C2 C23 C232 18
R2 R23 R233 C2 C23 C233 19

Vytvorte projekt predvoleného vizuálu a použite ukážku capabilities.json súboru.

Po odstránení nepotrebného kódu vyzerá predvolený zdrojový kód vizuálu ako v nasledujúcom príklade:

"use strict";

// ... default imports

import { FormattingSettingsService } from "powerbi-visuals-utils-formattingmodel";
import { VisualFormattingSettingsModel } from "./settings";

export class Visual implements IVisual {
    private target: HTMLElement;
    private formattingSettings: VisualFormattingSettingsModel;
    private formattingSettingsService: FormattingSettingsService;

    constructor(options: VisualConstructorOptions) {
        console.log('Visual constructor', options);
        this.formattingSettingsService = new FormattingSettingsService();
        this.target = options.element;
        this.host = options.host;
    }

    public update(options: VisualUpdateOptions) {
        this.formattingSettings = this.formattingSettingsService.populateFormattingSettingsModel(VisualFormattingSettingsModel, options.dataViews);
        console.log('Visual update', options);

    }

   /**
     * Returns properties pane formatting model content hierarchies, properties and latest formatting values, Then populate properties pane.
     * This method is called once every time we open properties pane or when the user edit any format property. 
     */
    public getFormattingModel(): powerbi.visuals.FormattingModel {
        return this.formattingSettingsService.buildFormattingModel(this.formattingSettings);
    }
}

Importujte požadované rozhrania na spracovanie údajov zo služby Power BI:

import DataViewMatrix = powerbi.DataViewMatrix;
import DataViewMatrixNode = powerbi.DataViewMatrixNode;
import DataViewHierarchyLevel = powerbi.DataViewHierarchyLevel;

Vytvorte dva div prvky pre rozloženie vizuálu:

constructor(options: VisualConstructorOptions) {
    // ...
    this.rowsDiv = document.createElement("div");
    this.target.appendChild(this.rowsDiv);

    this.colsDiv = document.createElement("div");
    this.target.appendChild(this.colsDiv);
    this.target.style.overflowY = "auto";
}

Skontrolujte údaje v metóde update a ubezpečte sa, že vizuál načíta údaje:

public update(options: VisualUpdateOptions) {
    this.formattingSettings = this.formattingSettingsService.populateFormattingSettingsModel(VisualFormattingSettingsModel, options.dataViews);
    console.log('Visual update', options);

    const dataView: DataView = options.dataViews[0];
    const matrixDataView: DataViewMatrix = dataView.matrix;

    if (!matrixDataView ||
        !matrixDataView.columns ||
        !matrixDataView.rows ) {
        return
    }
    // ...
}

Pred vykreslením nových údajov vymažte obsah div prvkov:

public update(options: VisualUpdateOptions) {
    // ...

    // remove old elements
    // to better performance use D3js pattern:
    // https://d3js.org/#enter-exit
    while (this.rowsDiv.firstChild) {
        this.rowsDiv.removeChild(this.rowsDiv.firstChild);
    }
    const prow = document.createElement("p");
    prow.innerText = "Rows";
    this.rowsDiv.appendChild(prow);

    while (this.colsDiv.firstChild) {
        this.colsDiv.removeChild(this.colsDiv.firstChild);
    }
    const pcol = document.createElement("p");
    pcol.innerText = "Columns";
    this.colsDiv.appendChild(pcol);
    // ...
}

Vytvorte treeWalker funkciu na prechádzania štruktúrou maticových údajov:

public update(options: VisualUpdateOptions) {
    // ...
    const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement)  => {

    }
    // ...
}

Kde matrixNode je aktuálny uzol, levels sú stĺpce metaúdajov tejto úrovne hierarchie, div – nadradený prvok pre podriadené prvky HTML.

je treeWalker rekurzívna funkcia, je potrebné vytvoriť div prvok a p pre text ako hlavičku a vyvolať funkciu pre podriadené prvky uzla:

public update(options: VisualUpdateOptions) {
    // ...
    const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement)  => {
        // ...

        if (matrixNode.children) {
            const childDiv = document.createElement("div");
            childDiv.classList.add("vertical");
            div.appendChild(childDiv);

            const p = document.createElement("p");
            const level = levels[matrixNode.level]; // get current level column metadata from current node
            p.innerText = level.sources[level.sources.length - 1].displayName; // get column name from metadata

            childDiv.appendChild(p); // add paragraph element to div element
            matrixNode.children.forEach((node, index) => treeWalker(node, levels, childDiv, ++levelIndex));
        }
    }
    // ...
}

Vyvolajte funkciu pre koreňové prvky stĺpca a riadka štruktúry zobrazenia maticových údajov:

public update(options: VisualUpdateOptions) {
    // ...
    const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement)  => {
        // ...
    }
    // ...
    // remove old elements
    // ...

    // ...
    const rowRoot: DataViewMatrixNode = matrixDataView.rows.root;
    rowRoot.children.forEach((node) => treeWalker(node, matrixDataView.rows.levels, this.rowsDiv));

    const colRoot = matrixDataView.columns.root;
    colRoot.children.forEach((node) => treeWalker(node, matrixDataView.columns.levels, this.colsDiv));
}

Vygenerujte vlastnosť selectionID pre uzly a tlačidlá Vytvoriť na zobrazenie uzlov:

public update(options: VisualUpdateOptions) {
    // ...
    const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement)  => {
        const selectionID: ISelectionID = this.host.createSelectionIdBuilder()
            .withMatrixNode(matrixNode, levels)
            .createSelectionId();

        let nodeBlock = document.createElement("button");
        nodeBlock.innerText = matrixNode.value.toString();

        nodeBlock.addEventListener("click", (event) => {
            // call select method in the selection manager
            this.selectionManager.select(selectionID);
        });

        nodeBlock.addEventListener("contextmenu", (event) => {
            // call showContextMenu method to display context menu on the visual
            this.selectionManager.showContextMenu(selectionID, {
                x: event.clientX,
                y: event.clientY
            });
            event.preventDefault();
        });
        // ...
    }
    // ...
}

Hlavným krokom zvýraznenia je vytvorenie ďalšieho poľa hodnôt.

Objekt koncového uzla má dve vlastnosti pre pole hodnoty, hodnotu a zvýraznenie:

JSON.stringify(options.dataViews[0].matrix.rows.root.children[0].children[0].children[0], null, " ");
{
 "level": 2,
 "levelValues": [
  {
   "value": "R233",
   "levelSourceIndex": 0
  }
 ],
 "value": "R233",
 "identity": {
  "identityIndex": 2
 },
 "values": {
  "0": {
   "value": null,
   "highlight": null
  },
  "1": {
   "value": 19,
   "highlight": 19
  }
 }
}

Kde value predstavuje hodnotu uzla bez použitia výberu z iného vizuálu, udáva časť údajov, highlight ktorá bola zvýraznená.

Poznámka

Ak je hodnota menšia highlight ako hodnota value, potom value sa čiastočne zvýraznilo.

Pridajte kód na spracovanie values poľa uzla, ak je uvedené:

public update(options: VisualUpdateOptions) {
    // ...
    const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement)  => {
        // ...

        if (matrixNode.values) {
            const sumOfValues = Object.keys(matrixNode.values) // get key property of object (value are 0 to N)
                .map(key => +matrixNode.values[key].value) // convert key property to number
                .reduce((prev, curr) => prev + curr) // sum of values

            let sumOfHighlights = sumOfValues;
            sumOfHighlights = Object.keys(matrixNode.values) // get key property of object (value are 0 to N)
                .map(key => matrixNode.values[key].highlight ? +matrixNode.values[key].highlight : null ) // convert key property to number if it exists
                .reduce((prev, curr) => curr ? prev + curr : null) // convert key property to number

            // create div container for value and highlighted value
            const vals = document.createElement("div");
            vals.classList.add("vertical")
            vals.classList.replace("vertical", "horizontal");
            // create paragraph element for label
            const highlighted = document.createElement("p");
            // Display complete value and highlighted value
            highlighted.innerText = `${sumOfHighlights}/${sumOfValues}`;

            // create div container for value
            const valueDiv = document.createElement("div");
            valueDiv.style.width = sumOfValues * 10 + "px";
            valueDiv.classList.add("value");

            // create div container for highlighted values
            const highlightsDiv = document.createElement("div");
            highlightsDiv.style.width = sumOfHighlights * 10 + "px";
            highlightsDiv.classList.add("highlight");
            valueDiv.appendChild(highlightsDiv);

            // append button and paragraph to div containers to parent div
            vals.appendChild(nodeBlock);
            vals.appendChild(valueDiv);
            vals.appendChild(highlighted);
            div.appendChild(vals);
        } else {
            div.appendChild(nodeBlock);
        }

        if (matrixNode.children) {
            // ...
        }
    }
    // ...
}

Výsledkom je vizuál s tlačidlami a hodnotami, ako highlighted value/default valuenapríklad .

Animation selecting data points on the visual, with matrix data views mapping and highlight.