Find everything you need to get certified on Fabric—skills challenges, live sessions, exam prep, role guidance, and more. Get started
Hello Everyone,
I have developed the pie chart custom visual by taking the reference from the PowerBI-visuals-sampleBarChart.
Pie chart has been created and default color has been assigned to each slice using the colorPallete.
However, I am struggling with the implementation of functionality for updation of color of Piechart's slices from formatting Pane. Selected color from the formatting Pane is not updated in the visual.
Black is selected for the "West" region. However, color is not updated.
Please find out the code:
visual.ts:
import FormattingSettingsColorPicker = formattingSettings.ColorPicker;
import * as d3 from "d3";
import { axisBottom, axisLeft, scaleLinear, scaleBand } from "d3";
import powerbi from "powerbi-visuals-api";
import { formattingSettings, FormattingSettingsService } from "powerbi-visuals-utils-formattingmodel";
import "./../style/visual.less";
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import IVisual = powerbi.extensibility.visual.IVisual;
import DataView = powerbi.DataView;
import IVisualHost = powerbi.extensibility.visual.IVisualHost;
type Selection<T extends d3.BaseType, U = any, V extends d3.BaseType = any, W = any> = d3.Selection<T, U, V, W>;
import { Card, ColorPicker, Slice } from "powerbi-visuals-utils-formattingmodel/lib/FormattingSettingsComponents";
import { TextProperties } from "powerbi-visuals-utils-formattingutils/lib/src/interfaces";
import { valueFormatter } from "powerbi-visuals-utils-formattingutils";
import {createTooltipServiceWrapper, ITooltipServiceWrapper} from "powerbi-visuals-utils-tooltiputils";
import ISelectionManager = powerbi.extensibility.ISelectionManager;
import { dataViewObjects} from "powerbi-visuals-utils-dataviewutils";
import IColorPalette = powerbi.extensibility.IColorPalette;
import { VisualSettings } from "./settings";
import ISandboxExtendedColorPalette = powerbi.extensibility.ISandboxExtendedColorPalette;
import DataViewCategoryColumn = powerbi.DataViewCategoryColumn;
import DataViewObjectPropertyIdentifier = powerbi.DataViewObjectPropertyIdentifier;
import Fill = powerbi.Fill;
import { legend, legendInterfaces } from 'powerbi-visuals-utils-chartutils';
import ILegend = legendInterfaces.ILegend;
import LegendPosition = legendInterfaces.LegendPosition;
import positionChartArea = legend.positionChartArea;
import createLegend = legend.createLegend;
import ISelectionId = powerbi.visuals.ISelectionId;
export interface PieChartDataPoint {
category: string;
color: string;
data:any;
selectionId: ISelectionId;
slice:string;
size:number;
}
function getColumnColorByIndex(
category: DataViewCategoryColumn,
index: number,
colorPalette: ISandboxExtendedColorPalette,
): string {
if (colorPalette.isHighContrast) {
return colorPalette.background.value;
}
const defaultColor: Fill = {
solid: {
color: colorPalette.getColor(`${category.values[index]}`).value,
}
};
const prop: DataViewObjectPropertyIdentifier = {
objectName: "colorSelector",
propertyName: "fill"
};
let colorFromObjects: Fill;
if(category.objects?.[index]){
colorFromObjects = dataViewObjects.getValue(category?.objects[index], prop);
}
return colorFromObjects?.solid.color ?? defaultColor.solid.color;
}
function createSelectorDataPoints(options: VisualUpdateOptions, host: IVisualHost): PieChartDataPoint[] {
console.log("createSelectorDataPoints function called");
const pieChartDataPoints: PieChartDataPoint[] = [];
let viewport = options.viewport;
let dataView = options.dataViews;
console.log("dataView", dataView);
console.log("dataView length", dataView.length);
let data = dataView[0];
console.log("data[0]", data);
let categorical = data.categorical;
let categories = categorical.categories;
let values = categorical.values;
console.log("categorical", values);
let slice = categories[0];
let size = values[0];
let xValues = slice.values;
let sizeValues = size.values;
console.log("xValues",xValues)
const colorPalette: ISandboxExtendedColorPalette = host.colorPalette;
for (let i = 0; i < xValues.length; i++) {
let slice = xValues[i].toString();
let size = +sizeValues[i];
const color = colorPalette.getColor(slice).value;
const selectionId: ISelectionId = host.createSelectionIdBuilder()
.withCategory(categories[0], i)
.createSelectionId();
pieChartDataPoints.push({
slice,
size,
color,
selectionId,
data,
category: slice
});
}
console.log("pieChartDataPoints", pieChartDataPoints);
return pieChartDataPoints;
}
export class Visual implements IVisual {
private textNode: Text;
private formattingSettingsService: FormattingSettingsService;
private selectionManager: ISelectionManager;
private formattingSettings: VisualSettings;
private svg: Selection<SVGGraphicsElement>
private parentGroup: Selection<SVGElement>;
private pieGroup: Selection<SVGElement>;
private tooltipServiceWrapper: ITooltipServiceWrapper;
private host: IVisualHost;
private legend: ILegend;
private colorPalette: IColorPalette;
private pieDatapoints: PieChartDataPoint[];
static margins = { top: 30, right: 30, bottom: 30, left: 30 };
constructor(options: VisualConstructorOptions) {
console.log('Visual constructor', options);
this.formattingSettingsService = new FormattingSettingsService();
this.svg = d3.select(options.element).append('svg').classed('pie', true);
this.parentGroup = this.svg.append('g').attr('class', 'parent');
this.pieGroup = this.parentGroup.append('g').attr('class', 'dots');
this.host = options.host;
this.colorPalette = options.host.colorPalette;
this.selectionManager = options.host.createSelectionManager();
this.tooltipServiceWrapper = createTooltipServiceWrapper(this.host.tooltipService, options.element);
}
public update(options: VisualUpdateOptions) {
this.formattingSettings = this.formattingSettingsService.populateFormattingSettingsModel(VisualSettings, options.dataViews);
this.pieDatapoints = createSelectorDataPoints(options, this.host);
this.formattingSettings.initColors(this.pieDatapoints);
let viewport = options.viewport;
this.svg.attr('height', viewport.height).attr('width', viewport.width);
this.parentGroup.attr('transform', 'translate(' + viewport.width / 2 + ',' + viewport.height / 2 + ')');
let radius = Math.min(viewport.width, viewport.height) / 4;
let pie = d3.pie<PieChartDataPoint>().value(function (d) {
console.log("arcd",d.size);
return d.size;
});
let g = this.pieGroup.selectAll(".arc")
.data(pie(this.pieDatapoints))
.enter();
let arc = g.selectAll("arc")
.data(pie(this.pieDatapoints))
.enter();
console.log("arc",arc);
let path = d3.arc()
.outerRadius(radius)
.innerRadius(0);
arc.append("path")
.attr("d", function (d) { return path(d as any); })
.attr("fill", function (d) {
return d.data.color;
})
}
public getFormattingModel(): powerbi.visuals.FormattingModel {
return this.formattingSettingsService.buildFormattingModel(this.formattingSettings);
}
}
Settings.ts:
"use strict";
import { formattingSettings } from "powerbi-visuals-utils-formattingmodel";
import FormattingSettingsCard = formattingSettings.Card;
import FormattingSettingsColorPicker = formattingSettings.ColorPicker;
import FormattingSettingsModel = formattingSettings.Model;
import FormattingSettingsSlice = formattingSettings.Slice;
import { ColorHelper } from "powerbi-visuals-utils-colorutils";
import {PieChartDataPoint} from "./visual";
import { Visual } from "./visual";
import { Card, ColorPicker, Slice } from "powerbi-visuals-utils-formattingmodel/lib/FormattingSettingsComponents";
export class ColorSelectorCardSettings extends Card {
name: string = "colorSelector";
displayName: string = "Data Colors";
slices: Slice[] = [];
}
export class VisualSettings extends FormattingSettingsModel {
colorSelector = new ColorSelectorCardSettings();
cards: Card[] = [this.colorSelector];
public initColors(dataPoints:PieChartDataPoint[]) {
const slices:Slice[]=this.colorSelector.slices;
if (dataPoints) {
dataPoints.forEach(dataPoint => {
slices.push(new ColorPicker({
name: "fill",
displayName: dataPoint.slice,
value: { value: dataPoint.color },
selector: dataPoint.selectionId.getSelector(),
}));
});
}
console.log("slices",slices)
}
}
Capabilities.json:
{
"dataRoles": [
{
"displayName": "Slice",
"name": "slice",
"kind": "Grouping"
},
{
"displayName": "Value",
"name": "size",
"kind": "Measure"
}
],
"dataViewMappings": [
{
"categorical": {
"categories": {
"select": [
{
"for": { "in": "slice" }
}
]
},
"values": {
"select": [
{
"bind": {
"to": "size"
}
}
]
}
}
}
],
"objects": {
"colorSelector": {
"properties": {
"fill": {
"type": { "fill": { "solid": { "color": true } } }
}
}
}
},
"privileges": []
}
Basically, I am having difficulties in implementing logic for updating the color after selection from the color Picker. However, still I am unaware if I miss something more.
arc.append("path")
.attr("d", function (d) { return path(d as any); })
.attr("fill", function (d) {
return ordScale(d.data.slice).toString();
})
Thank You!
Solved! Go to Solution.
I have managed to fix the issue:
I have managed to fix the issue:
Check out the September 2024 Power BI update to learn about new features.
Learn from experts, get hands-on experience, and win awesome prizes.
User | Count |
---|---|
27 | |
11 | |
8 | |
6 | |
6 |