共用方式為


物件上格式化 API (預覽)

物件格式設定 可讓使用者直接選取想要修改的元素,快速且輕鬆地修改視覺效果的格式。 選取專案時,格式窗格會自動巡覽並展開所選元素的特定格式設定。 如需有關物件格式的詳細資訊,請參閱 Power BI Desktop 中的 物件格式設定

若要將這些功能新增至視覺效果,每個視覺效果都必須為每個可選取的區域提供子選取樣式選項和快捷方式。

注意

  • 支援物件格式設定的視覺效果必須實作可從 API 5.1 版取得 getFormattingModel API
  • 如果您使用 powerbi-visuals-utils-formattingmodel,請至少使用 6.0.0 版。

建立物件上的體驗

當使用者選取可選取的元素來傳送 Power BI 子選取時,請使用子選取服務。 使用 子選取 API提供子選取樣式和快捷方式。 子選擇協助程式 可用來簡化程式。

格式模式

格式模式是新的模式,用戶可以在撰寫模式中開啟和關閉 onObject 格式設定。 視覺效果會以更新選項中的格式模式狀態進行更新。 更新選項也包含目前子選取的子選取為 CustomVisualSubSelection

如何實作物件上的格式化 API

功能檔案

capabilites.json 檔案中,新增下列屬性來宣告視覺效果支援物件格式設定:

{
  "supportsOnObjectFormatting": true,
  "enablePointerEventsFormatMode": true,
}

IVisual 介面

視覺效果需要實作 VisualOnObjectFormatting 介面作為 IVisual 介面的一部分。

VisualOnObjectFormatting 包含三種方法:

getSubSelectionStyles

每個視覺效果都需要實作 getSubSelectionStyles 方法,這個方法會在子選取的元素被子選取時呼叫。 getSubSelectionStyles 方法會以目前的子選取專案作為 CustomVisualSubSelection 陣列提供,而且預期會傳回 SubSelectionStyles 物件或 undefined

子選取樣式有三種類別,涵蓋大部分案例:

  • 發簡訊
  • 數值文字
  • 形狀

每個 SubSelectionStyles 物件都會為使用者提供修改項目樣式的不同體驗。

getSubSelectionShortcuts

若要為使用者提供更多選項,視覺效果必須實作 getSubSelectionShortcuts 方法。 這個方法會傳回 VisualSubSelectionShortcutsundefined。 此外,如果提供 SubSelectionShortcuts,也必須提供 VisualNavigateSubSelectionShortcut,以便在用戶子選取專案且格式窗格已開啟時,窗格會自動捲動至適當的卡片。

有數個子選取快捷方式可修改視覺狀態。 每個項目都會使用適當的標籤,在操作功能表中定義功能表項。

Sub-Selection 釐清功能表: [On-Object disambiguation] 功能表提供一種方法,讓使用者在不清楚要選取哪個視覺元素時選取其所需的子選取。 當使用者子選取視覺效果的背景時,通常會發生這種情況。 若要讓不明確的功能表呈現更多子選取專案,視覺效果必須透過 getSubSelectables 方法提供所有子選取專案。

getSubSelectables

若要提供區分功能表的子選取專案,視覺效果必須實作 getSubSelectables 方法。 這個方法會提供選擇性 filterType 自變數,類型為 SubSelectionStylesType,並傳回 CustomVisualSubSelectionundefined的陣列。 如果要使用 HTMLSubSelectionHelper 來建立子選取區,HTMLSubSelectionHelper.getSubSelectables() 方法可用來從 DOM 收集可選取的元素。

Sub-Selection 直接文字編輯: 使用 On-Object 格式設定,您可以按兩下可選取的子元素的文字,直接編輯它。 若要提供直接編輯功能,您必須提供具有填入 SubSelectableDirectEdit 對象的適當 cVDirectEdit 屬性的 RectangleSubSelectionOutline。 大綱可以做為自定義大綱提供,或者,如果您使用 HTMLSubSelectionHelper 可以使用 SubSelectableDirectEdit 屬性。 (請參閱 HTMLSubSelectionHelper 所提供的屬性)

尚不支援為特定數據點新增直接編輯(使用選取器)。

FormattingId 介面

下列介面可用來參考 subSelection 快捷方式和樣式。

interface FormattingId {
            objectName: string;
            propertyName: string;
            selector?: powerbi.data.Selector;
        }
  • objectName:對象名稱,如 在 capabilities.json中宣告。
  • propertyName:對象的屬性名稱,如 capabilities.json中所宣告。
  • selector:如果 datapoint 有 selectionId,請使用 selectionId.getSelector(),此選取器必須與格式化模型配量所提供的相同。

例子

在這裡範例中,我們會建置具有兩個 物件的自定義視覺效果,colorSelectordirectEdit。 我們使用來自 onobjectFormatting 公用程式的 HTMLSubSelectionHelper 來處理大部分的子選取作業。 如需詳細資訊,請參閱 物件上的公用程式

首先,我們會建置格式化窗格的卡片,並提供 子SelectionShortcuts樣式, 每個子選擇。

定義物件

定義物件,並宣告視覺效果支援 capabilities.json中的 OnObject 格式:

"objects": {
      "directEdit": {
      "properties": {
        "show": {
          "displayName": "Show",
          "type": {
            "bool": true
          }
        },
        "textProperty": {
          "displayName": "Text",
          "type": {
            "text": true
          }
        },
        "fontFamily": {
          "type": {
            "formatting": {
              "fontFamily": true
            }
          }
        },
        "fontSize": {
          "type": {
            "formatting": {
              "fontSize": true
            }
          }
        },
        "bold": {
          "type": {
            "bool": true
          }
        },
        "italic": {
          "type": {
            "bool": true
          }
        },
        "underline": {
          "type": {
            "bool": true
          }
        },
        "fontColor": {
          "displayName": "Font Color",
          "type": {
            "fill": {
              "solid": {
                "color": true
              }
            }
          }
        },
        "background": {
          "displayName": "Background",
          "type": {
            "fill": {
              "solid": {
                "color": true
              }
            }
          }
        },
        "position": {
          "displayName": "Position",
          "type": {
            "enumeration": [
              { "displayName": "Left", "value": "Left" }, { "displayName": "Right", "value": "Right" }
            ]
          }
        }
      }
    },
    "colorSelector": {
      "displayName": "Data Colors",
      "properties": {
        "fill": {
          "displayName": "Color",
          "type": {
            "fill": {
              "solid": {
                "color": true
              }
            }
          }
        }
      }
    },
   },
  "supportsOnObjectFormatting": true,
  "enablePointerEventsFormatMode": true,

建置格式化卡片

使用 formattingModel utils建置其格式設定卡片。

色彩選取器卡片設定

class ColorSelectorCardSettings extends Card {
    name: string = "colorSelector";
    displayName: string = "Data Colors";
    slices = [];
}

將方法新增至 formattingSetting,以便我們可以動態填入 colorSelector 物件的配量(我們的數據點)。

populateColorSelector(dataPoints: BarChartDataPoint[]) {
        let slices: formattingSettings.ColorPicker[] = this.colorSelector.slices;
        if (dataPoints) {
            dataPoints.forEach(dataPoint => {
                slices.push(new formattingSettings.ColorPicker({
                    name: "fill",
                    displayName: dataPoint.category,
                    value: { value: dataPoint.color },
                    selector: dataPoint.selectionId.getSelector(),
                }));
            });
        }
    }

我們會在選取器欄位中傳遞特定數據點的選取器。 這個選取器是實作 OnObject 取得 API 時所使用的選取器。

直接編輯卡片設定

class DirectEditSettings extends Card {
    displayName = 'Direct Edit';
    name = 'directEdit';
    private minFontSize: number = 8;
    private defaultFontSize: number = 11;
    show = new formattingSettings.ToggleSwitch({
        name: "show",
        displayName: undefined,
        value: true,
    });
    topLevelSlice = this.show;
    textProperty = new formattingSettings.TextInput({
        displayName: "Text Property",
        name: "textProperty",
        value: "What is your quest?",
        placeholder: ""
    });
    position = new formattingSettings.ItemDropdown({
        name: 'position',
        items: [{ displayName: 'Left', value: 'Left' }, { displayName: 'Right', value: 'Right' }],
        value: { displayName: 'Right', value: 'Right' }
    });
    font = new formattingSettings.FontControl({
        name: "font",
        displayName: 'Font',
        fontFamily: new formattingSettings.FontPicker({
            name: "fontFamily",
            displayName: "Font Family",
            value: "Segoe UI, wf_segoe-ui_normal, helvetica, arial, sans-serif"
        }),
        fontSize: new formattingSettings.NumUpDown({
            name: "fontSize",
            displayName: "Font Size",
            value: this.defaultFontSize,
            options: {
                minValue: {
                    type: powerbi.visuals.ValidatorType.Min,
                    value: this.minFontSize,
                }
            }
        }),
        bold: new formattingSettings.ToggleSwitch({
            name: 'bold',
            displayName: "Font Size",
            value: true
        }),
        italic: new formattingSettings.ToggleSwitch({
            name: 'italic',
            displayName: "Font Size",
            value: true
        }),
        underline: new formattingSettings.ToggleSwitch({
            name: 'underline',
            displayName: "Font Size",
            value: true
        })
    });
    fontColor = new formattingSettings.ColorPicker({
        name: "fontColor",
        displayName: "Color",
        value: { value: "#000000" }
    });
    background = new formattingSettings.ColorPicker({
        name: "background",
        displayName: "Color",
        value: { value: "#FFFFFF" }
    });
    slices = [this.show, this.textProperty, this.font, this.fontColor, this.background, this.position];
}

使用子選取協助程序屬性

HTMLSubSelectionHelper 屬性新增至物件。 若要查看 HTMLSubSelectionHelper 提供哪些屬性,請檢查 物件公用程式檔

  • 針對 directEdit 屬性:

    import {
       HtmlSubSelectableClass, HtmlSubSelectionHelper, SubSelectableDirectEdit as SubSelectableDirectEditAttr,
       SubSelectableDisplayNameAttribute, SubSelectableObjectNameAttribute, SubSelectableTypeAttribute 
    } from 'powerbi-visuals-utils-onobjectutils';
    
    const DirectEdit: powerbi.visuals.SubSelectableDirectEdit = {
        reference: {
            objectName: 'directEdit',
            propertyName: 'textProperty'
        },
        style: SubSelectableDirectEditStyle.Outline,
    };
    private visualDirectEditSubSelection = JSON.stringify(DirectEdit);
    
    this.directEditElement
                .classed('direct-edit', true)
                .classed('hidden', !this.formattingSettings.directEditSettings.show.value)
                .classed(HtmlSubSelectableClass, options.formatMode && this.formattingSettings.directEditSettings.show.value)
                .attr(SubSelectableObjectNameAttribute, 'directEdit')
                .attr(SubSelectableDisplayNameAttribute, 'Direct Edit')
                .attr(SubSelectableDirectEditAttr, this.visualDirectEditSubSelection)
    

    HTMLSubSelectionHelper 會使用 SubSelectableDirectEditAttr 屬性來提供 directEdit 大綱的 directEdit 參考,因此當使用者按兩下元素時,就會開始直接編輯。

    顯示子選取協助程序運作方式的螢幕快照。

  • 針對 colorSelector:

    barSelectionMerged
              .attr(SubSelectableObjectNameAttribute, 'colorSelector')
              .attr(SubSelectableDisplayNameAttribute, (dataPoint: BarChartDataPoint) => this.formattingSettings.colorSelector.slices[dataPoint.index].displayName)
              .attr(SubSelectableTypeAttribute, powerbi.visuals.SubSelectionStylesType.Shape)
              .classed(HtmlSubSelectableClass, options.formatMode)
    
    

定義參考

定義下列介面以簡化範例:

注意

您提供的 cardUid 應該與 getFormattingModel API 所提供的 cardUid 相同。 例如,如果您使用 powerbi-visuals-utils-formattingmodel,請在格式化模型設定中提供 cardUid 做為 Visual-cardName-card-card,其中 cardName 是您指派給此卡片的名稱。 否則,請提供它作為您指派給此卡片 Visual-cardUid

interface References {
    cardUid?: string;
    groupUid?: string;
    fill?: FormattingId;
    font?: FormattingId;
    fontColor?: FormattingId;
    show?: FormattingId;
    fontFamily?: FormattingId;
    bold?: FormattingId;
    italic?: FormattingId;
    underline?: FormattingId;
    fontSize?: FormattingId;
    position?: FormattingId;
    textProperty?: FormattingId;
}

針對此範例的目的,請為物件名稱建立列舉:

const enum BarChartObjectNames {
    ColorSelector = 'colorSelector',
    DirectEdit = 'directEdit'
}
  • directEdit 物件的參考:
const directEditReferences: References = {
    cardUid: 'Visual-directEdit-card',
    groupUid: 'directEdit-group',
    fontFamily: {
        objectName: BarChartObjectNames.DirectEdit,
        propertyName: 'fontFamily'
    },
    bold: {
        objectName: BarChartObjectNames.DirectEdit,
        propertyName: 'bold'
    },
    italic: {
        objectName: BarChartObjectNames.DirectEdit,
        propertyName: 'italic'
    },
    underline: {
        objectName: BarChartObjectNames.DirectEdit,
        propertyName: 'underline'
    },
    fontSize: {
        objectName: BarChartObjectNames.DirectEdit,
        propertyName: 'fontSize'
    },
    fontColor: {
        objectName: BarChartObjectNames.DirectEdit,
        propertyName: 'fontColor'
    },
    show: {
        objectName: BarChartObjectNames.DirectEdit,
        propertyName: 'show'
    },
    position: {
        objectName: BarChartObjectNames.DirectEdit,
        propertyName: 'position'
    },
    textProperty: {
        objectName: BarChartObjectNames.DirectEdit,
        propertyName: 'textProperty'
    }
};
  • 針對 colorSelector
const colorSelectorReferences: References = {
    cardUid: 'Visual-colorSelector-card',
    groupUid: 'colorSelector-group',
    fill: {
        objectName: BarChartObjectNames.ColorSelector,
        propertyName: 'fill'
    }
};

實作 API

現在讓我們實作 onObject 格式的取得 API,並在 visualOnObjectFormatting 中提供它們:

  1. 在建構函式程序代碼中,提供 visualOnObjectFormatting 中的 get 方法:

    public visualOnObjectFormatting: powerbi.extensibility.visual.VisualOnObjectFormatting;
    constructor(options: VisualConstructorOptions) {
            this.subSelectionHelper = HtmlSubSelectionHelper.createHtmlSubselectionHelper({
                     hostElement: options.element,
                     subSelectionService: options.host.subSelectionService,
                     selectionIdCallback: (e) => this.selectionIdCallback(e),
                });
    
     this.visualOnObjectFormatting = {
                    getSubSelectionStyles: (subSelections) => this.getSubSelectionStyles(subSelections),
                    getSubSelectionShortcuts: (subSelections, filter) => this.getSubSelectionShortcuts(subSelections, filter),
                    getSubSelectables: (filter) => this. getSubSelectables(filter)
                }
       }
    
    private getSubSelectionStyles(subSelections: CustomVisualSubSelection[]): powerbi.visuals.SubSelectionStyles | undefined {
            const visualObject = subSelections[0]?.customVisualObjects[0];
            if (visualObject) {
                switch (visualObject.objectName) {
                    case BarChartObjectNames.ColorSelector:
                        return this.getColorSelectorStyles(subSelections);
                     case BarChartObjectNames.DirectEdit:
                        return this.getDirectEditStyles();
                }
            }
        }
    
    private getSubSelectionShortcuts(subSelections: CustomVisualSubSelection[], filter: SubSelectionShortcutsKey | undefined):    VisualSubSelectionShortcuts | undefined {
            const visualObject = subSelections[0]?.  customVisualObjects[0];
            if (visualObject) {
                switch (visualObject.objectName) {
                    case BarChartObjectNames.ColorSelector:
                        return this.getColorSelectorShortcuts(subSelections);
                    case BarChartObjectNames.DirectEdit:
                        return this.getDirectEditShortcuts();
                }
            }
        }
    
  2. 實作 colorSelector 的 getSubSelection 快捷方式和樣式:

    private getColorSelectorShortcuts(subSelections:  CustomVisualSubSelection[]): VisualSubSelectionShortcuts   {
            const selector = subSelections[0].customVisualObjects[0].selectionId?.getSelector();
            return [
                {
                    type: VisualShortcutType.Reset,
                    relatedResetFormattingIds: [{
                        ...colorSelectorReferences.fill,
                        selector
                    }],
                },
                {
                    type: VisualShortcutType.Navigate,
                    destinationInfo: { cardUid: colorSelectorReferences.cardUid },
                    label: 'Color'
                }
            ];
        }
    

    上述快捷方式會傳回操作功能表中的相關功能表項,並新增下列功能:

    • VisualShortcutType.Navigate:當用戶選取其中一個橫條(數據點),且格式化窗格已開啟時,格式窗格會捲動至色彩選取器卡片並開啟它
    • VisualShortcutType.Reset:將重設快捷方式新增至操作功能表。 如果填滿色彩已變更,則會啟用它。
    private getColorSelectorStyles(subSelections: CustomVisualSubSelection[]): SubSelectionStyles {
            const selector = subSelections[0].customVisualObjects[0].selectionId?.getSelector();
            return {
                type: SubSelectionStylesType.Shape,
                fill: {
                    label: 'Fill',
                    reference: {
                        ...colorSelectorReferences.fill,
                     selector
                    },
                },
            };
        }
    

當使用者以滑鼠右鍵按下列時,會出現下列專案:

當使用者以滑鼠右鍵按下列時,使用者介面的螢幕快照。

變更顏色時:

變更色彩的螢幕快照。

子區段快捷方式

若要實作 directEdit 的子Selection 快捷方式和樣式:

private getDirectEditShortcuts(): VisualSubSelectionShortcuts {
        return [
            {
                type: VisualShortcutType.Reset,
                relatedResetFormattingIds: [
                    directEditReferences.bold,
                    directEditReferences.fontFamily,
                    directEditReferences.fontSize,
                    directEditReferences.italic,
                    directEditReferences.underline,
                    directEditReferences.fontColor,
                    directEditReferences.textProperty
                ]
            },
            {
                type: VisualShortcutType.Toggle,
                relatedToggledFormattingIds: [{
                    ...directEditReferences.show,
                }],
                ...directEditReferences.show,
                disabledLabel: 'Delete',
            },
            {
                type: VisualShortcutType.Picker,
                ...directEditReferences.position,
                label: 'Position'
            },
            {
                type: VisualShortcutType.Navigate,
                destinationInfo: { cardUid: directEditReferences.cardUid },
                label: 'Direct edit'
            }
        ];
    }

此快捷方式會在操作功能表中新增相關的功能表項,並新增下列功能:

  • VisualShortcutType.Reset:當 relatedResetFormattingIds 陣列中提供的其中一個屬性變更時,會將重設新增至默認專案至操作功能表。
  • VisualShortcutType.Toggle:將 [刪除] 選項新增至操作功能表。 按兩下時,會關閉 directEdit 卡片的切換開關。
  • VisualShortcutType.Picker:在操作功能表中新增一個選項,以在右至左之間挑選,因為我們在 directEdit的格式設定卡片中新增位置配量。
  • VisualShortcutType.Navigate:開啟格式窗格,且用戶選取 directEdit 元素時,格式窗格會捲動並開啟 directEdit 卡片。
private getDirectEditStyles(): SubSelectionStyles {
        return {
            type: powerbi.visuals.SubSelectionStylesType.Text,
            fontFamily: {
                reference: {
                    ...directEditReferences.fontFamily
                },
                label: 'font family'
            },
            bold: {
                reference: {
                    ...directEditReferences.bold
                },
                label: 'bold'
            },
            italic: {
                reference: {
                    ...directEditReferences.italic
                },
                label: 'italic'
            },
            underline: {
                reference: {
                    ...directEditReferences.underline
                },
                label: 'underline'
            },
            fontSize: {
                reference: {
                    ...directEditReferences.fontSize
                },
                label: 'font size'
            },
            fontColor: {
                reference: {
                    ...directEditReferences.fontColor
                },
                label: 'font color'
            },
            background: {
                reference: {
                    objectName: 'directEdit',
                    propertyName: 'background'
                },
                label: 'background'
            }
        }
    }

我們在 formattingSettings 中新增相關屬性時提供了相關屬性。

下圖說明在 directEdit 元素上按下滑鼠右鍵時 UI 的外觀:

直接編輯介面的螢幕快照。

地方化

視覺效果應該處理當地語系化並提供當地語系化字串。

GitHub 資源

  • 您可以在 on-object-formatting-api.d.ts 中找到所有物件格式設定介面的連結(在 API 發行後提供的連結)
  • 我們建議使用 [on object utils],其中包含 [HTMLSubSelectionHelper](在 API 發行后提供的連結)
  • 您可以找到使用 API 5.8.0 版的自定義視覺效果範例 SampleBarChart,並使用 上的物件公用程式實作 對 物件格式設定的支援(在 API 發行後提供的連結)