API de formatação no objeto (versão prévia)
formatação no objeto permite que os usuários modifiquem com rapidez e facilidade o formato dos visuais selecionando diretamente os elementos que desejam modificar. Quando um elemento é selecionado, o painel de formato navega automaticamente e expande a configuração de formatação específica para o elemento selecionado. Para obter mais informações sobre a formatação no objeto, consulte Formatação no objeto no Power BI Desktop.
Para adicionar essas funcionalidades ao visual, cada visual precisa fornecer uma opção de estilo de subseleção e um atalho para cada região subelecionável.
Nota
- Os visuais que dão suporte à formatação no objeto precisam implementar a API getFormattingModel
que está disponível na versão 5.1 da API. - Se você estiver usando powerbi-visuals-utils-formattingmodel, use pelo menos a versão 6.0.0.
Criar uma experiência no objeto
Use o serviço de subseleção quando o usuário selecionar um elemento subselecionável para enviar ao Power BI a subseleção. Forneça os estilos de subseleção e os atalhos usando a API de subseleção . O auxiliar de subseleção pode ser usado para simplificar o processo.
Modo de formato
O modo de formato é um novo modo em que o usuário pode ativar e desativar onObject
formatação quando estiver no modo de criação. O visual é atualizado com o status do modo de formato nas opções de atualização. As opções de atualização também incluem a subSeleção subselecionária atualmente como CustomVisualSubSelection
.
Como implementar a API de formatação no objeto
Arquivo de funcionalidades
No arquivo capabilites.json, adicione as seguintes propriedades para declarar que o visual dá suporte à formatação no objeto:
{
"supportsOnObjectFormatting": true,
"enablePointerEventsFormatMode": true,
}
Interface IVisual
O visual precisa implementar a interface VisualOnObjectFormatting
como parte da interface IVisual.
VisualOnObjectFormatting contém três métodos:
getSubSelectionStyles
Cada visual é necessário para implementar um método getSubSelectionStyles
, que é chamado quando um elemento subelecionável é subselecionado. O método getSubSelectionStyles
é fornecido com os elementos subselecionados atuais como uma matriz de CustomVisualSubSelection
e deve retornar um objeto SubSelectionStyles
ou undefined
.
Há três categorias de estilos de subseleção que abrangem a maioria dos cenários:
- Texto
- Texto numérico
- Forma
Cada objeto SubSelectionStyles
fornece uma experiência diferente para o usuário para modificar o estilo de um elemento.
getSubSelectionShortcuts
Para fornecer mais opções para o usuário, o visual deve implementar o método getSubSelectionShortcuts
. Esse método retorna VisualSubSelectionShortcuts
ou undefined
. Além disso, se SubSelectionShortcuts
forem fornecidos, um VisualNavigateSubSelectionShortcut
também deverá ser fornecido para que, quando um usuário subseleciona um elemento e o painel de formato estiver aberto, o painel role automaticamente para o cartão apropriado.
Há vários atalhos de subseleção para modificar o estado visual. Cada um define um item de menu no menu de contexto com o rótulo apropriado.
Sub-Selection Menu Desambiguação: o menu de desambiguação On-Object fornece um método para os usuários selecionarem a subseleção desejada quando não estiver claro qual elemento visual está sendo subselecionado. Isso geralmente acontece quando o usuário subseleciona a tela de fundo do visual. Para que o menu disâmbguo apresente mais subseleções, o visual deve fornecer todas as subseleções por meio do método getSubSelectables
.
getSubSelectables
Para fornecer subeleções ao menu de desambiguação, o visual precisa implementar o método getSubSelectables
. Esse método recebe um argumento filterType
opcional, do tipo SubSelectionStylesType
e retorna uma matriz de CustomVisualSubSelection
ou undefined
.
Se o HTMLSubSelectionHelper
estiver sendo utilizado para criar uma subseleção, o método HTMLSubSelectionHelper.getSubSelectables() pode ser usado para coletar elementos subselecionáveis do DOM.
Sub-Selection Edição direta de texto: com formatação on-object, você pode clicar duas vezes no texto de um elemento subelegível para editá-lo diretamente.
Para fornecer recursos de edição direta, você precisa fornecer uma RectangleSubSelectionOutline
com a propriedade cVDirectEdit apropriada preenchida com um objeto SubSelectableDirectEdit. A estrutura de tópicos pode ser fornecida como uma estrutura de tópicos personalizada ou, se você estiver usando o HTMLSubSelectionHelper
poderá usar o atributo SubSelectableDirectEdit
. (Consulte os atributos fornecidos pelo HTMLSubSelectionHelper)
Ainda não há suporte para a adição de uma edição direta para um ponto de dados específico (usando seletores).
Interface FormattingId
A interface a seguir é usada para fazer referência aos atalhos e estilos subSelection
.
interface FormattingId {
objectName: string;
propertyName: string;
selector?: powerbi.data.Selector;
}
- objectName: o nome do objeto conforme declarado no capabilities.json.
- propertyName: o nome da propriedade de um objeto conforme declarado no capabilities.json.
- seletor: se o ponto de dados tiver uma selectionId, use selectionId.getSelector(), esse seletor deverá ser o mesmo fornecido para a fatia do modelo de formatação.
Exemplos
Neste exemplo, criamos um visual personalizado que tem dois objetos, colorSelector
e directEdit
. Usamos o HTMLSubSelectionHelper
do onobjectFormatting
utils para lidar com a maior parte do trabalho de subSeleção.
Para obter mais informações, consulte utils no objeto.
Primeiro, criamos cartões para o painel de formatação e fornecemos estilos de subSelectionShortcuts e para cada subeleção.
Definir os objetos
Defina os objetos e declare que o visual dá suporte à Formatação OnObject no 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,
Criar os cartões de formatação
Crie seus cartões de formatação usando os utils formattingModel.
Configurações do cartão seletor de cores
class ColorSelectorCardSettings extends Card {
name: string = "colorSelector";
displayName: string = "Data Colors";
slices = [];
}
Adicione um método à formattingSetting para que possamos preencher as fatias dinamicamente para o objeto colorSelector (nossos pontos de dados).
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(),
}));
});
}
}
Passamos o seletor do ponto de dados específico no campo seletor. Esse seletor é o usado ao implementar as APIs get do OnObject.
Configurações de cartão de edição direta
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];
}
Usar atributos auxiliares de subseleção
Adicione os atributos HTMLSubSelectionHelper
aos nossos objetos. Para ver quais atributos o HTMLSubSelectionHelper fornece, verifique a documentação sobre objeto utils.
Para o atributo 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)
O
HTMLSubSelectionHelper
usa o atributoSubSelectableDirectEditAttr
para fornecer a referência directEdit da estrutura de tópicos directEdit, de modo que uma edição direta é iniciada quando um usuário clica duas vezes no elemento.Para o 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)
Definir referências
Defina a interface a seguir para simplificar os exemplos:
Nota
O cardUid
fornecido deve ser o mesmo fornecido para a API getFormattingModel. Por exemplo, se você estiver usando powerbi-visuals-utils-formattingmodel, forneça o cardUid
como cartão Visual-cardName, em que o cardName é o nome atribuído a esse cartão nas configurações do modelo de formatação. Caso contrário, forneça-o como o Visual-cardUid atribuído a esse cartão.
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;
}
Para a finalidade deste exemplo, crie uma enumeração para os nomes de objetos:
const enum BarChartObjectNames {
ColorSelector = 'colorSelector',
DirectEdit = 'directEdit'
}
- Referências para o objeto
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'
}
};
- Para
colorSelector
:
const colorSelectorReferences: References = {
cardUid: 'Visual-colorSelector-card',
groupUid: 'colorSelector-group',
fill: {
objectName: BarChartObjectNames.ColorSelector,
propertyName: 'fill'
}
};
Implementar APIs
Agora, vamos implementar as APIs get para a formatação onObject e fornecê-las no visualOnObjectFormatting:
No código do construtor, forneça os métodos get no 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(); } } }
Implemente os atalhos e o estilo getSubSelection para o 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' } ]; }
O atalho acima retorna um item de menu relevante no menu de contexto e adiciona as seguintes funcionalidades:
- VisualShortcutType.Navigate: quando um usuário seleciona em uma das barras (ponto de dados) e o painel de formatação está aberto, o painel de formato rola até o cartão seletor de cores e o abre
- VisualShortcutType.Reset: adiciona um atalho de redefinição ao menu de contexto. Ele será habilitado se a cor de preenchimento tiver sido alterada.
private getColorSelectorStyles(subSelections: CustomVisualSubSelection[]): SubSelectionStyles { const selector = subSelections[0].customVisualObjects[0].selectionId?.getSelector(); return { type: SubSelectionStylesType.Shape, fill: { label: 'Fill', reference: { ...colorSelectorReferences.fill, selector }, }, }; }
Quando um usuário clica com o botão direito do mouse em uma barra, o seguinte aparece:
Ao alterar a cor:
Atalhos de subseção
Para implementar os atalhos e estilos de subSeleção para o 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'
}
];
}
Esse atalho adiciona um item de menu relevante no menu de contexto e adiciona as seguintes funcionalidades:
- VisualShortcutType.Reset: adiciona uma redefinição ao item padrão ao menu de contexto, quando uma das propriedades fornecidas na matriz relatedResetFormattingIds é alterada.
- VisualShortcutType.Toggle: adiciona opções de exclusão ao menu de contexto. Quando clicado, o botão de alternância para o cartão directEdit é desativado.
- VisualShortcutType.Picker: adiciona uma opção no menu de contexto para escolher entre Direita e Esquerda, já que adicionamos a fatia de posição no cartão de formatação para o directEdit.
- VisualShortcutType.Navigate: quando o painel de formato é aberto e o usuário seleciona o elemento directEdit, o painel de formato rola e abre o cartão 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'
}
}
}
Fornecemos as propriedades relevantes à medida que as adicionamos nas formatttingSettings.
A imagem a seguir ilustra a aparência da interface do usuário ao clicar com o botão direito do mouse no elemento directEdit:
Localização
O visual deve manipular a localização e fornecer cadeias de caracteres localizadas.
Recursos do GitHub
- Todas as interfaces de formatação de objeto podem ser encontradas (link a ser fornecido depois que a API é lançada) no on-object-formatting-api.d.ts
- É recomendável usar o [on object utils], que incluem o [HTMLSubSelectionHelper](link a ser fornecido depois que a API for liberada)
- Você pode encontrar um exemplo de um visual personalizado SampleBarChart que usa a API versão 5.8.0 e implementa o suporte para a formatação no objeto usando os utils de objeto no (link a ser fornecido depois que a API é liberada)
Conteúdo relacionado
- de API de Subseleção
- utils no objeto