ไฮไลต์จุดข้อมูลใน Power BI VisualsHighlight data points in Power BI Visuals

โดยค่าเริ่มต้นเมื่อใดก็ตามที่มีการเลือกองค์ประกอบ อาร์เรย์ values ในวัตถุ dataView จะถูกกรองให้เป็นเพียงค่าที่เลือกเท่านั้นBy default whenever an element is selected the values array in the dataView object will be filtered to just the selected values. ซึ่งจะทำให้วิชวลอื่น ๆ ทั้งหมดในหน้าแสดงเป็นเพียงข้อมูลที่เลือกเท่านั้นIt will cause all other visuals on the page to display just the selected data.

ไฮไลต์ dataview ในลักษณะตามค่าเริ่มต้น

หากคุณตั้งค่าคุณสมบัติ supportsHighlight ใน capabilities.json เป็น true คุณจะได้รับอาร์เรย์ values แบบไม่มีการกรองเต็มรูปแบบพร้อมกับอาร์เรย์ highlightsIf you set the supportsHighlight property in your capabilities.json to true, you'll receive the full unfiltered values array along with a highlights array. อาร์เรย์ highlights จะมีความยาวเท่ากับอาร์เรย์ค่าและค่าที่ไม่ได้เลือกจะถูกตั้งค่าเป็น nullThe highlights array will be the same length as the values array and any non-selected values will be set to null. เมื่อเปิดใช้งานคุณสมบัตินี้แล้ว จึงเป็นความรับผิดชอบของวิชวลในการไฮไลต์ข้อมูลที่เหมาะสมโดยการเปรียบเทียบอาร์เรย์ values กับอาร์เรย์ highlightsWith this property enabled it's the visual's responsibility to highlight the appropriate data by comparing the values array to the highlights array.

' dataview ' สนับสนุนการไฮไลต์

ในตัวอย่าง คุณจะสังเกตเห็นว่ามี 1 แถบที่ถูกเลือกIn the example, you'll notice that 1 bar is selected. และเป็นเฉพาะค่าในอาร์เรย์ไฮไลต์And it's the only value in the highlights array. นอกจากนี้ สิ่งสำคัญคือต้องทราบว่าอาจมีตัวเลือกหลายรายการและการไฮไลต์บางส่วนด้วยIt's also important to note that there could be multiple selections and partial highlights. ค่าที่ไฮไลต์ไว้จะแสดงในมุมมองข้อมูลThe highlighted values will be presented in the data view.

หมายเหตุ

การแมปมุมมองข้อมูลแบบตารางไม่สนับสนุนคุณลักษณะการไฮไลท์Table data view mapping doesn't support the highlights feature.

ไฮไลต์จุดข้อมูลด้วยการแมปมุมมองข้อมูลตามประเภทHighlight data points with categorical data view mapping

วิชวลที่มีการแมปมุมมองข้อมูลตามประเภทมีcapabilities.jsonพร้อมด้วย"supportsHighlight": trueพารามิเตอร์ The visuals with categorical data view mapping have capabilities.json with "supportsHighlight": true parameter. ตัวอย่างเช่น:For example:

{
    "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
}

รหัสแหล่งข้อมูลของวิชวลเริ่มต้นหลังจากลบรหัสที่ไม่จำเป็นจะมีลักษณะดังนี้:The default visual source code after removing unnecessary code will look like this:

"use strict";

// ... default imports list

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

import { VisualSettings } from "./settings";

export class Visual implements IVisual {
    private target: HTMLElement;
    private settings: VisualSettings;

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

    }

    public update(options: VisualUpdateOptions) {
        this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);
        console.log('Visual update', options);

    }

    private static parseSettings(dataView: DataView): VisualSettings {
        return <VisualSettings>VisualSettings.parse(dataView);
    }

    /**
     * This function gets called for each of the objects defined in the capabilities files and allows you to select which of the
     * objects and properties you want to expose to the users in the property pane.
     *
     */
    public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] | VisualObjectInstanceEnumerationObject {
        return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options);
    }
}

นำเข้าอินเทอร์เฟสที่จำเป็นเพื่อประมวลผลข้อมูลจาก Power BI:Import required interfaces to process data from Power BI:

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

สร้างองค์ประกอบdivระดับสูงสำหรับค่าหมวดหมู่:Create root div element for category values:

export class Visual implements IVisual {
    private target: HTMLElement;
    private settings: VisualSettings;

    private div: HTMLDivElement; // new property

    constructor(options: VisualConstructorOptions) {
        console.log('Visual constructor', options);
        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);

    }
    // ...
}

ล้างเนื้อหาขององค์ประกอบ div ก่อนที่จะแสดงข้อมูลใหม่:Clear content of div elements before rendering new data:

// ...
public update(options: VisualUpdateOptions) {
    this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);
    console.log('Visual update', options);

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

รับค่าหมวดหมู่และหน่วยวัดจากวัตถุ dataView:Get categories and measure values from dataView object:

public update(options: VisualUpdateOptions) {
    this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);
    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;
    // ...
}

โดยที่ categoryValues คืออาร์เรย์ของค่าหมวดหมู่ measureValues เป็นอาร์เรย์ของหน่วยวัดและ measureHighlights คือส่วนที่ไฮไลต์ของค่าWhere categoryValues is an array of category values, measureValues is an array of measures, and measureHighlights is highlighted parts of values.

หมายเหตุ

ค่าของคุณสมบัติ measureHighlights อาจน้อยกว่าค่าของคุณสมบัติ categoryValuesValues of measureHighlights property can be less that values of categoryValues property. หมายความว่ามีการไฮไลต์ค่าบางส่วนIn means that value was higlighted partially.

ระบุอาร์เรย์ categoryValues และรับค่าและไฮไลต์ที่สอดคล้องกัน:Enumerate categoryValues array and get corresponding values and highlights:

// ...
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);

});

สร้างองค์ประกอบ div และ p เพื่อแสดงและดูภาพค่ามุมมองข้อมูลใน DOM ของวิชวล:Create div and p elements to display and visualize data view values in visual DOM:

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

ใช้ลักษณะที่จำเป็นสำหรับองค์ประกอบเพื่อใช้ flex box และกำหนดสีสำหรับองค์ประกอบ div:Apply required styles for elements to use flex box and define colors for div elements:

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

ในผลลัพธ์ คุณควรมีมุมมองของวิชวลดังต่อไปนี้In the result, you should have the following view of the visual.

วิชวลที่มีการแมปมุมมองข้อมูลตามประเภทและการไฮไลต์

ไฮไลต์จุดข้อมูลด้วยการแมปมุมมองข้อมูลแบบเมทริกซ์Highlight data points with matrix data view mapping

วิชวลที่มีการแมปมุมมองข้อมูลแบบเมทริกซ์มีcapabilities.jsonพร้อมด้วย"supportsHighlight": trueพารามิเตอร์ The visuals with matrix data view mapping have capabilities.json with "supportsHighlight": true parameter. ตัวอย่างเช่น:For example:

{
    "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
}

ข้อมูลตัวอย่างในการสร้างลำดับชั้นสำหรับการแมปมุมมองข้อมูลแบบเมทริกซ์:The sample data to create hierarchy for matrix data view mapping:

Row1Row1 Row2Row2 Row3Row3 คอลัมน์ 1Column1 คอลัมน์2Column2 คอลัมน์3Column3 มูลค่าValues
R1R1 R11R11 R111R111 C1C1 C11C11 C111C111 11
R1R1 R11R11 R112R112 C1C1 C11C11 C112C112 22
R1R1 R11R11 R113R113 C1C1 C11C11 C113C113 33
R1R1 R12R12 R121R121 C1C1 C12C12 C121C121 44
R1R1 R12R12 R122R122 C1C1 C12C12 C122C122 55
R1R1 R12R12 R123R123 C1C1 C12C12 C123C123 66
R1R1 R13R13 R131R131 C1C1 C13C13 C131C131 77
R1R1 R13R13 R132R132 C1C1 C13C13 C132C132 88
R1R1 R13R13 R133R133 C1C1 C13C13 C133C133 99
R2R2 R21R21 R211R211 C2C2 C21C21 C211C211 1010
R2R2 R21R21 R212R212 C2C2 C21C21 C212C212 1111
R2R2 R21R21 R213R213 C2C2 C21C21 C213C213 1212
R2R2 R22R22 R221R221 C2C2 C22C22 C221C221 1313
R2R2 R22R22 R222R222 C2C2 C22C22 C222C222 1414
R2R2 R22R22 R223R223 C2C2 C22C22 C223C223 1616
R2R2 R23R23 R231R231 C2C2 C23C23 C231C231 1717
R2R2 R23R23 R232R232 C2C2 C23C23 C232C232 1818
R2R2 R23R23 R233R233 C2C2 C23C23 C233C233 1919

สร้างโครงการวิชวลเริ่มต้นและใช้ตัวอย่างของ capabilities.jsonCreate the default visual project and apply sample of capabilities.json.

รหัสแหล่งข้อมูลของวิชวลเริ่มต้นหลังจากลบรหัสที่ไม่จำเป็นจะมีลักษณะ:Default visual source code after removing unessesray code will look:

"use strict";

// ... default imports

import { VisualSettings } from "./settings";

export class Visual implements IVisual {
    private target: HTMLElement;
    private settings: VisualSettings;


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

    public update(options: VisualUpdateOptions) {
        this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);
        console.log('Visual update', options);

    }

    private static parseSettings(dataView: DataView): VisualSettings {
        return <VisualSettings>VisualSettings.parse(dataView);
    }

    /**
     * This function gets called for each of the objects defined in the capabilities files and allows you to select which of the
     * objects and properties you want to expose to the users in the property pane.
     *
     */
    public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] | VisualObjectInstanceEnumerationObject {
        return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options);
    }
}

นำเข้าอินเทอร์เฟสที่จำเป็นเพื่อประมวลผลข้อมูลจาก Power BI:Import required interfaces to process data from Power BI:

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

สร้างองค์ประกอบ div สองแบบสำหรับเค้าโครงวิชวล:Create two div elements for visual layout:

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

ตรวจสอบข้อมูลในวิธีการ update เพื่อให้แน่ใจว่าวิชวลได้รับข้อมูล:Check the data in update method, to ensure that visual gets data:

public update(options: VisualUpdateOptions) {
    this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);
    console.log('Visual update', options);

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

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

ล้างเนื้อหาขององค์ประกอบ div ก่อนที่จะแสดงข้อมูลใหม่:Clear content of div elements before render new data:

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

สร้างฟังก์ชัน treeWalker เพื่อสำรวจโครงสร้างข้อมูลแบบเมทริกซ์:Create treeWalker function to traverse matrix data structure:

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

    }
    // ...
}

โดยที่ matrixNode คือโหนดปัจจุบัน levels คือคอลัมน์เมตาดาต้าของระดับลำดับชั้นนี้ div - องค์ประกอบหลักสำหรับองค์ประกอบ HTML ย่อยWhere matrixNode is the current node, levels is metadata columns of this hierarchy level, div - parent element for child HTML elements.

treeWalker คือฟังก์ชันแบบเรียกใช้ซ้ำ จำเป็นต้องสร้างองค์ประกอบ div และ p สำหรับข้อความเป็นส่วนหัว และเรียกใช้ฟังก์ชันสำหรับองค์ประกอบย่อยของโหนด:The treeWalker is recursive function, need to create div element and p for text as header, and call the function for child elements of node:

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

เรียกใช้ฟังก์ชันสำหรับองค์ประกอบระดับสูงของคอลัมน์และแถวของโครงสร้างมุมมองข้อมูลแบบเมทริกซ์:Call the function for root elements of column and row of matrix data view structure:

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

สร้าง selectionID สำหรับโหนดและสร้างปุ่มเพื่อแสดงโหนด:Generate selectionID for nodes and Create buttons to display nodes:

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();
        });
        // ...
    }
    // ...
}

ขั้นตอนหลักของการใช้การไฮไลต์คือการประมวลผลอาร์เรย์เพิ่มเติมของค่าThe main step of using highlighting is to process additional array of values.

หากคุณตรวจสอบวัตถุของโหนดเทอร์มินัล คุณจะเห็นว่าอาร์เรย์ค่ามีคุณสมบัติสองอย่างคือ ค่าและไฮไลต์:If you inspect the object of terminal node, you can see that the values array has two properties - value and highlight:

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

โดยที่คุณสมบัติ value แสดงค่าของโหนดโดยไม่ต้องใช้ตัวเลือกจากวิชวลอื่น ๆ และคุณสมบัติการไฮไลต์แสดงให้เห็นว่าเป็นส่วนหนึ่งของข้อมูลที่ถูกไฮไลต์Where value property represents value of node without applying a selection from other visual, and highlight property indicates which part of data was highlighted.

หมายเหตุ

ค่าของคุณสมบัติ highlight อาจน้อยกว่าค่าของคุณสมบัติ valueValue of highlight property can be less that value of value property. หมายความว่ามีการไฮไลต์ค่าบางส่วนIn means that value was higlighted partially.

เพิ่มรหัสเพื่อประมวลผลอาร์เรย์ values ของโหนดถ้าแสดง:Add the code to process the values array of node if it is presented:

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) {
            // ...
        }
    }
    // ...
}

ด้วยเหตุนี้ คุณจะได้รับวิชวลที่มีปุ่มและค่า highlighted value/default valueAs the result you'll get the visual with buttons and values highlighted value/default value

วิชวลที่มีการแมปและการไฮไลต์มุมมองข้อมูลแบบเมทริกซ์

ขั้นตอนถัดไปNext steps