API de mise en forme d’objet (préversion)
mise en forme sur objet permet aux utilisateurs de modifier rapidement et facilement le format des visuels en sélectionnant directement les éléments qu’ils souhaitent modifier. Lorsqu’un élément est sélectionné, le volet de mise en forme navigue automatiquement et développe le paramètre de mise en forme spécifique de l’élément sélectionné. Pour plus d’informations sur la mise en forme sur l’objet, consultez mise en forme d’objet dans Power BI Desktop.
Pour ajouter ces fonctionnalités à votre visuel, chaque visuel doit fournir une option de style de sous-sélection et un raccourci pour chaque région sous-sélectionnable.
Note
- Les visuels qui prennent en charge la mise en forme sur objet doivent implémenter l’API getFormattingModel disponible à partir de la version 5.1 de l’API.
- Si vous utilisez powerbi-visuals-utils-formattingmodel, utilisez la version 6.0.0 au moins.
Créer une expérience sur l’objet
Utilisez le service de sous-sélection lorsque l’utilisateur sélectionne un élément sous-désélectionnable pour envoyer Power BI à la sous-sélection. Fournissez les styles et raccourcis de sous-sélection à l’aide de l’API de sous-sélection . L’assistance de sous-sélection peut être utilisée pour simplifier le processus.
Mode Format
Le mode Format est un nouveau mode où l’utilisateur peut activer et désactiver onObject
mise en forme en mode création. Le visuel est mis à jour avec l’état du mode de format dans les options de mise à jour. Les options de mise à jour incluent également la sous-sélection actuellement sous-sélectionnée comme CustomVisualSubSelection
.
Comment implémenter l’API de mise en forme sur l’objet
Fichier de fonctionnalités
Dans le fichier capabilites.json, ajoutez les propriétés suivantes pour déclarer que le visuel prend en charge la mise en forme sur objet :
{
"supportsOnObjectFormatting": true,
"enablePointerEventsFormatMode": true,
}
Interface IVisual
Le visuel doit implémenter l’interface VisualOnObjectFormatting
dans le cadre de l’interface IVisual.
VisualOnObjectFormatting contient trois méthodes :
getSubSelectionStyles
Chaque visuel est requis pour implémenter une méthode getSubSelectionStyles
, appelée lorsqu’un élément subselectable est sous-sélectionné. La méthode getSubSelectionStyles
est fournie avec les éléments sous-sélectionnés actuels sous la forme d’un tableau CustomVisualSubSelection
et doit retourner un objet SubSelectionStyles
ou undefined
.
Il existe trois catégories de styles de sous-sélection qui couvrent la plupart des scénarios :
- SMS
- Texte numérique
- Forme
Chaque objet SubSelectionStyles
offre une expérience différente à l’utilisateur pour modifier le style d’un élément.
getSubSelectionShortcuts
Pour fournir davantage d’options à l’utilisateur, le visuel doit implémenter la méthode getSubSelectionShortcuts
. Cette méthode retourne VisualSubSelectionShortcuts
ou undefined
. En outre, si SubSelectionShortcuts
sont fournies, un VisualNavigateSubSelectionShortcut
doit également être fourni afin que lorsqu’un utilisateur désélectionne un élément et que le volet de mise en forme est ouvert, le volet défile automatiquement vers la carte appropriée.
Il existe plusieurs raccourcis de sous-sélection pour modifier l’état visuel. Chacun définit un élément de menu dans le menu contextuel avec l’étiquette appropriée.
Sub-Selection menu Disambiguation : le menu désambiguation on-Object fournit une méthode permettant aux utilisateurs de sélectionner leur sous-sélection souhaitée lorsqu’il n’est pas clair quel élément visuel est en cours de sous-sélection. Cela se produit souvent lorsque l’utilisateur désélectionne l’arrière-plan du visuel. Pour que le menu ambiguïté présente davantage de sous-sélections, le visuel doit fournir toutes les sous-sélections via la méthode getSubSelectables
.
getSubSelectables
Pour fournir des sous-sélections au menu ambiguïté, le visuel doit implémenter la méthode getSubSelectables
. Cette méthode est fournie sous forme d’argument filterType
facultatif, de type SubSelectionStylesType
et retourne un tableau de CustomVisualSubSelection
ou de undefined
.
Si le HTMLSubSelectionHelper
est utilisé pour créer une sous-sélection, la méthode HTMLSubSelectionHelper.getSubSelectables() peut être utilisée pour collecter des éléments sous-sélectionnables à partir du DOM.
Sub-Selection Modification directe du texte : avec la mise en forme sur l’objet, vous pouvez double-cliquer sur le texte d’un élément sous-élu pour le modifier directement.
Pour fournir une fonctionnalité de modification directe, vous devez fournir un RectangleSubSelectionOutline
avec la propriété cVDirectEdit appropriée remplie avec un objet SubSelectableDirectEdit. Le plan peut être fourni sous la forme d’un plan personnalisé ou, si vous utilisez le HTMLSubSelectionHelper
vous pouvez utiliser l’attribut SubSelectableDirectEdit
. (Consultez les attributs fournis par htmlSubSelectionHelper)
L’ajout d’une modification directe pour un point de données spécifique (à l’aide de sélecteurs) n’est pas encore pris en charge.
Interface FormattingId
L’interface suivante permet de référencer les raccourcis et styles subSelection
.
interface FormattingId {
objectName: string;
propertyName: string;
selector?: powerbi.data.Selector;
}
- objectName : nom de l’objet tel qu’il est déclaré dans la capabilities.json.
- propertyName : nom de propriété d’un objet tel qu’il est déclaré dans la capabilities.json.
- sélecteur : si le point de données a un selectionId, utilisez selectionId.getSelector(), ce sélecteur doit être identique à celui fourni pour la tranche de modèle de mise en forme.
Exemples
Dans cet exemple, nous créons un visuel personnalisé qui a deux objets, colorSelector
et directEdit
. Nous utilisons le HTMLSubSelectionHelper
à partir des utils onobjectFormatting
, pour gérer la plupart du travail de sous-sélection.
Pour plus d’informations, consultez utilitaires sur objet.
Tout d’abord, nous créons des cartes pour le volet mise en forme et fournissons sous-sélectionShortcuts et styles pour chaque sous-sélection.
Définir les objets
Définissez les objets et déclarez que le visuel prend en charge la mise en forme OnObject dans l'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,
Générer les cartes de mise en forme
Générez leurs cartes de mise en forme à l’aide des utils formattingModel.
Paramètres de carte de sélecteur de couleurs
class ColorSelectorCardSettings extends Card {
name: string = "colorSelector";
displayName: string = "Data Colors";
slices = [];
}
Ajoutez une méthode à la mise en formeSetting afin de pouvoir remplir dynamiquement les tranches de l’objet colorSelector (nos points de données).
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(),
}));
});
}
}
Nous transmettons le sélecteur du point de données spécifique dans le champ sélecteur. Ce sélecteur est celui utilisé lors de l’implémentation des API Get du OnObject.
Modifier directement les paramètres de carte
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];
}
Utiliser des attributs d’assistance de sous-sélection
Ajoutez les attributs HTMLSubSelectionHelper
à nos objets. Pour afficher les attributs fournis par HTMLSubSelectionHelper, consultez la documentation sur l’utilisation de l’objet.
Pour l’attribut 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)
L'
HTMLSubSelectionHelper
utilise l’attributSubSelectableDirectEditAttr
pour fournir la référence directEdit du plan directEdit. Par conséquent, une modification directe démarre lorsqu’un utilisateur double-clique sur l’élément.Pour le 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)
Définir des références
Définissez l’interface suivante pour simplifier les exemples :
Note
La cardUid
que vous fournissez doit être la même que celle fournie pour l’API getFormattingModel. Par exemple, si vous utilisez powerbi-visuals-utils-formattingmodel, fournissez le cardUid
en tant que Visual-cardName-card, où cardName est le nom que vous avez attribué à cette carte dans les paramètres du modèle de mise en forme. Sinon, fournissez-le en tant que Visual-cardUid que vous avez affecté à cette carte.
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;
}
Dans le cadre de cet exemple, créez une énumération pour les noms d’objets :
const enum BarChartObjectNames {
ColorSelector = 'colorSelector',
DirectEdit = 'directEdit'
}
- Références pour l’objet
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'
}
};
- Pour
colorSelector
:
const colorSelectorReferences: References = {
cardUid: 'Visual-colorSelector-card',
groupUid: 'colorSelector-group',
fill: {
objectName: BarChartObjectNames.ColorSelector,
propertyName: 'fill'
}
};
Implémenter des API
Nous allons maintenant implémenter les API get pour la mise en forme onObject et les fournir dans visualOnObjectFormatting :
Dans le code du constructeur, fournissez les méthodes get dans 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(); } } }
Implémentez les raccourcis et le style getSubSelection pour 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' } ]; }
Le raccourci ci-dessus retourne un élément de menu pertinent dans le menu contextuel et ajoute les fonctionnalités suivantes :
- VisualShortcutType.Navigate : lorsqu’un utilisateur sélectionne sur l’une des barres (point de données) et que le volet de mise en forme est ouvert, le volet de mise en forme fait défiler jusqu’à la carte de sélecteur de couleurs et l’ouvre.
- VisualShortcutType.Reset : ajoute un raccourci de réinitialisation au menu contextuel. Elle est activée si la couleur de remplissage a été modifiée.
private getColorSelectorStyles(subSelections: CustomVisualSubSelection[]): SubSelectionStyles { const selector = subSelections[0].customVisualObjects[0].selectionId?.getSelector(); return { type: SubSelectionStylesType.Shape, fill: { label: 'Fill', reference: { ...colorSelectorReferences.fill, selector }, }, }; }
Lorsqu’un utilisateur clique avec le bouton droit sur une barre, les éléments suivants s’affichent :
Lors de la modification de la couleur :
Raccourcis de sous-section
Pour implémenter les raccourcis et les styles de sous-sélection pour 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'
}
];
}
Ce raccourci ajoute un élément de menu approprié dans le menu contextuel et ajoute les fonctionnalités suivantes :
- VisualShortcutType.Reset : ajoute une réinitialisation à l’élément par défaut au menu contextuel, lorsque l’une des propriétés fournies dans les modifications de tableau relatedResetFormattingIds.
- VisualShortcutType.Toggle : ajoute des options Delete au menu contextuel. Lorsque vous cliquez sur le bouton bascule, le bouton bascule de la carte directEdit est désactivé.
- VisualShortcutType.Picker : ajoute une option dans le menu contextuel pour choisir entre droite et gauche, car nous avons ajouté la tranche de position dans la carte de mise en forme de la directEdit.
- VisualShortcutType.Navigate : lorsque le volet de format est ouvert et que l’utilisateur sélectionne l’élément directEdit, le volet de format fait défiler et ouvre la carte 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'
}
}
}
Nous avons fourni les propriétés pertinentes à mesure que nous les avons ajoutées dans le formattingSettings.
L’image suivante illustre l’apparence de l’interface utilisateur lorsque vous cliquez avec le bouton droit sur l’élément directEdit :
Localisation
Le visuel doit gérer la localisation et fournir des chaînes localisées.
Ressources GitHub
- Toutes les interfaces de mise en forme d’objet sont disponibles (lien à fournir une fois l’API publiée) dans on-object-formatting-api.d.ts
- Nous vous recommandons d’utiliser [on object utils], qui incluent le [HTMLSubSelectionHelper](lien à fournir une fois l’API publiée)
- Vous trouverez un exemple d’un visuel personnalisé SampleBarChart qui utilise l’API version 5.8.0 et implémente la prise en charge de la mise en forme sur l’objet à l’aide des utils d’objets à l’adresse (lien à fournir une fois l’API publiée)