Interfejs API formatowania obiektów (wersja zapoznawcza)
formatowanie obiektu on-object umożliwia użytkownikom szybkie i łatwe modyfikowanie formatu wizualizacji przez bezpośrednie wybranie elementów, które mają zostać zmodyfikowane. Po wybraniu elementu okienko formatowania automatycznie przechodzi i rozwija określone ustawienie formatowania dla wybranego elementu. Aby uzyskać więcej informacji na temat formatowania obiektów, zobacz formatowanie obiektów w programie Power BI Desktop.
Aby dodać te funkcje do wizualizacji, każda wizualizacja musi podać opcję stylu podwybierz i skrót dla każdego regionu, który można wybrać.
Nuta
- Wizualizacje, które obsługują formatowanie obiektów, muszą implementować getFormattingModel API, który jest dostępny z interfejsu API w wersji 5.1.
- Jeśli używasz modelu powerbi-visuals-utils-formattingmodel, użyj co najmniej wersji 6.0.0.
Tworzenie środowiska obiektu lokalnego
Użyj usługi podwybierz, gdy użytkownik wybierze element z możliwością wyboru podrzędnego, aby wysłać usługę Power BI jako podwybór. Podaj style i skróty podwybierz przy użyciu interfejsu API podwybierz . Pomocnik podwybierz może służyć do uproszczenia procesu.
Tryb formatowania
Tryb formatowania to nowy tryb, w którym użytkownik może włączyć i wyłączyć formatowanie onObject
w trybie tworzenia. Wizualizacja zostanie zaktualizowana o stan trybu formatowania w opcjach aktualizacji. Opcje aktualizacji obejmują również aktualnie wybrane podwybierz jako CustomVisualSubSelection
.
Jak zaimplementować interfejs API formatowania obiektów
Plik możliwości
W pliku capabilites.json dodaj następujące właściwości, aby zadeklarować, że wizualizacja obsługuje formatowanie obiektu lokalnego:
{
"supportsOnObjectFormatting": true,
"enablePointerEventsFormatMode": true,
}
Interfejs IVisual
Wizualizacja musi zaimplementować interfejs VisualOnObjectFormatting
w ramach interfejsu IVisual.
VisualOnObjectFormatting zawiera trzy metody:
getSubSelectionStyles
Każda wizualizacja jest wymagana do zaimplementowania metody getSubSelectionStyles
, która jest wywoływana, gdy podwybierze element jest wybierany. Metoda getSubSelectionStyles
jest dostarczana z bieżącymi elementami wybranymi jako tablica CustomVisualSubSelection
i oczekuje się, że zwróci obiekt SubSelectionStyles
lub undefined
.
Istnieją trzy kategorie stylów podwybierz, które obejmują większość scenariuszy:
- Tekst
- Tekst liczbowy
- Kształt
Każdy obiekt SubSelectionStyles
zapewnia użytkownikowi inne środowisko modyfikowania stylu elementu.
getSubSelectionShortcuts
Aby zapewnić więcej opcji dla użytkownika, wizualizacja musi zaimplementować metodę getSubSelectionShortcuts
. Ta metoda zwraca VisualSubSelectionShortcuts
lub undefined
. Ponadto w przypadku podania SubSelectionShortcuts
należy również podać VisualNavigateSubSelectionShortcut
, aby po wybraniu przez użytkownika elementu i otwarciu okienka formatowania okienko automatycznie przewijało się do odpowiedniej karty.
Istnieje kilka skrótów do podwybierz, aby zmodyfikować stan wizualizacji. Każdy z nich definiuje element menu w menu kontekstowym z odpowiednią etykietą.
Sub-Selection menu uściślania: menu uściślania obiektu on-object udostępnia metodę wyboru żądanego podwyboru, gdy nie jest jasne, który element wizualizacji jest wybierany. Dzieje się tak często, gdy użytkownik podwybierze tło wizualizacji. Aby niejednoznaczne menu przedstawiało więcej wyborów podsieciowych, wizualizacja musi dostarczyć wszystkie wybory podsieci za pośrednictwem metody getSubSelectables
.
getSubSelectables
Aby udostępnić wybory podrzędne do menu uściślania, wizualizacja musi zaimplementować metodę getSubSelectables
. Ta metoda jest udostępniana opcjonalny argument filterType
typu SubSelectionStylesType
i zwraca tablicę CustomVisualSubSelection
lub undefined
.
Jeśli HTMLSubSelectionHelper
jest używany do tworzenia podwybór, HTMLSubSelectionHelper.getSubSelectables() metody można użyć do zbierania elementów podrzędnych z modelu DOM.
Sub-Selection bezpośrednie edytowanie tekstu: za pomocą formatowania On-Object, możesz kliknąć dwukrotnie tekst elementu wybieranego podselektowego, aby bezpośrednio go edytować.
Aby zapewnić możliwość edycji bezpośredniej, należy podać RectangleSubSelectionOutline
z odpowiednią właściwością cVDirectEdit wypełniona obiektem SubSelectableDirectEdit. Konspekt można podać jako konspekt niestandardowy lub, jeśli używasz HTMLSubSelectionHelper
możesz użyć atrybutu SubSelectableDirectEdit
. (Zobacz atrybuty udostępniane przez element HTMLSubSelectionHelper)
Dodawanie bezpośredniej edycji dla określonego punktu danych (przy użyciu selektorów) nie jest jeszcze obsługiwane.
FormattingId, interfejs
Poniższy interfejs służy do odwołowania się do skrótów i stylów subSelection
.
interface FormattingId {
objectName: string;
propertyName: string;
selector?: powerbi.data.Selector;
}
- objectName: nazwa obiektu zadeklarowana w capabilities.json.
- propertyName: nazwa właściwości obiektu zadeklarowana w capabilities.json.
- selektor: jeśli punkt danych ma identyfikator selectionId, użyj selectionId.getSelector(), ten selektor musi być taki sam, jak w przypadku wycinka modelu formatowania.
Przykłady
W tym przykładzie utworzymy wizualizację niestandardową zawierającą dwa obiekty, colorSelector
i directEdit
. Używamy HTMLSubSelectionHelper
z narzędzia onobjectFormatting
do obsługi większości zadań podrzędnychWybierania.
Aby uzyskać więcej informacji, zobacz on-object utils.
Najpierw tworzymy karty dla okienka formatowania i udostępniamy subSelectionShortcuts i style dla każdego podwybór.
Definiowanie obiektów
Zdefiniuj obiekty i zadeklaruj, że wizualizacja obsługuje formatowanie OnObject w capabilities.json:
"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,
Tworzenie kart formatowania
Skompiluj karty formatowania przy użyciu narzędzi formatowaniaModel.
Ustawienia karty selektora kolorów
class ColorSelectorCardSettings extends Card {
name: string = "colorSelector";
displayName: string = "Data Colors";
slices = [];
}
Dodaj metodę do formatowaniaUstawienia, aby umożliwić dynamiczne wypełnianie wycinków dla obiektu colorSelector (naszych punktów danych).
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(),
}));
});
}
}
Przekazujemy selektor określonego punktu danych w polu selektora. Ten selektor jest używany podczas implementowania interfejsów API pobierania obiektu OnObject.
Ustawienia karty edycji bezpośredniej
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];
}
Używanie atrybutów pomocnika podwybierz
Dodaj atrybuty HTMLSubSelectionHelper
do naszych obiektów. Aby sprawdzić, które atrybuty zapewniają atrybuty elementu HTMLSubSelectionHelper, zapoznaj się z dokumentacją narzędzia obiektów .
Dla atrybutu 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
używa atrybutuSubSelectableDirectEditAttr
, aby podać odwołanie directEdit do konspektu directEdit, więc bezpośrednia edycja rozpoczyna się po dwukrotnym kliknięciu elementu przez użytkownika.Dla elementu 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)
Definiowanie odwołań
Zdefiniuj następujący interfejs, aby uprościć przykłady:
Nuta
Podany cardUid
powinien być taki sam jak podany dla interfejsu API getFormattingModel. Jeśli na przykład używasz modelu formatowania powerbi-visuals-utils, podaj cardUid
jako visual-cardName-card, gdzie cardName jest nazwą przypisaną do tej karty w ustawieniach modelu formatowania. W przeciwnym razie podaj go jako identyfikator Visual-cardUid przypisany do tej karty.
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;
}
W tym przykładzie utwórz wyliczenie dla nazw obiektów:
const enum BarChartObjectNames {
ColorSelector = 'colorSelector',
DirectEdit = 'directEdit'
}
- Odwołania do obiektu
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'
}
};
- Dla
colorSelector
:
const colorSelectorReferences: References = {
cardUid: 'Visual-colorSelector-card',
groupUid: 'colorSelector-group',
fill: {
objectName: BarChartObjectNames.ColorSelector,
propertyName: 'fill'
}
};
Implementowanie interfejsów API
Teraz zaimplementujmy interfejsy API pobierania dla formatowania onObject i podajmy je w obiekcie visualOnObjectFormatting:
W kodzie konstruktora podaj metody get w obiekcie visualOnObjectFormatting:
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(); } } }
Zaimplementuj skróty getSubSelection i styl dla elementu colorSelector:
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' } ]; }
Powyższy skrót zwraca odpowiedni element menu w menu kontekstowym i dodaje następujące funkcje:
- VisualShortcutType.Navigate: gdy użytkownik wybierze jeden z pasków (punkt danych), a okienko formatowania jest otwarte, okienko formatowania przewija kartę selektora kolorów i otwiera je
- VisualShortcutType.Reset: dodaje skrót resetowania do menu kontekstowego. Jest on włączony, jeśli kolor wypełnienia został zmieniony.
private getColorSelectorStyles(subSelections: CustomVisualSubSelection[]): SubSelectionStyles { const selector = subSelections[0].customVisualObjects[0].selectionId?.getSelector(); return { type: SubSelectionStylesType.Shape, fill: { label: 'Fill', reference: { ...colorSelectorReferences.fill, selector }, }, }; }
Gdy użytkownik kliknie prawym przyciskiem myszy pasek, zostanie wyświetlone następujące polecenie:
Podczas zmieniania koloru:
Skróty podsekcji
Aby zaimplementować skróty i style subSelection dla elementu directEdit:
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'
}
];
}
Ten skrót dodaje odpowiedni element menu w menu kontekstowym i dodaje następujące funkcje:
- VisualShortcutType.Reset: dodaje reset do domyślnego elementu w menu kontekstowym, gdy jedna z właściwości podanych w relatedResetFormattingIds zmienia tablicę.
- VisualShortcutType.Toggle: dodaje opcje Usuwania do menu kontekstowego. Po kliknięciu przełącznik directEdit karty jest wyłączony.
- VisualShortcutType.Picker: dodaje opcję w menu kontekstowym, aby wybrać między prawą i lewą, ponieważ dodaliśmy wycinek pozycji na karcie formatowania dla directEdit.
- VisualShortcutType.Navigate: po otwarciu okienka formatowania użytkownik wybiera element directEdit, okienko formatowania przewija i otwiera kartę 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'
}
}
}
Udostępniliśmy odpowiednie właściwości, gdy dodaliśmy je w formacieSettings.
Na poniższej ilustracji przedstawiono wygląd interfejsu użytkownika po kliknięciu prawym przyciskiem myszy elementu directEdit:
Lokalizacji
Wizualizacja powinna obsługiwać lokalizację i udostępniać zlokalizowane ciągi.
Zasoby usługi GitHub
- Wszystkie interfejsy formatowania obiektów można znaleźć w pliku (link do udostępnienia po wydaniu interfejsu API) w on-object-formatting-api.d.ts
- Zalecamy użycie narzędzia [on object utils], które obejmują element [HTMLSubSelectionHelper](link do udostępnienia po wydaniu interfejsu API)
- Przykład wizualizacji niestandardowej SampleBarChart korzystających z interfejsu API w wersji 5.8.0 i implementuje obsługę formatowania obiektów przy użyciu narzędzi obiektów w witrynie (link do udostępnienia po wydaniu interfejsu API)
Powiązana zawartość
- interfejsu API podwybór
- narzędzia lokalne obiektów