Forum Discussion
Creating a Pie chart visual with Static Data.
Hi guys. I'm trying to create a pie chart power Bi visual for practicing custom visual creation.I have followed the tutorial given in the github repo for the environment setup and now is currently on the first step , ie creating visual with static data.
The visual is being built and served correctly.But when I insert the visual in the powerBi service,all i get is a blank screen.
Can someone help? I'm new to d3 and TypeScript, so there may be a chance that I may have made some silly mistakes.
Here's my code:
module powerbi.extensibility.visual {
"use strict";
interface Data
{
quantity: number;
category: string;
}
export class PieChart implements IVisual {
private target: HTMLElement;
private settings: VisualSettings;
private textNode: Text;
private pieChartContainer:d3.Selection<SVGElement>;
private arc:any;
private host:IVisualHost;
private svg:d3.Selection<SVGElement>;
private g:any;
private pie:any;
private color:string;
constructor(options: VisualConstructorOptions) {
console.log('Visual constructor', options);
this.target = options.element;
this.host=options.host;
let svg=this.svg=d3.select(options.element)
.append('svg')
.classed("pieChart",true);
this.pieChartContainer=svg.append('g').classed('pieChartContainer',true);
}
public update(options: VisualUpdateOptions) {
this.settings = PieChart.parseSettings(options && options.dataViews && options.dataViews[0]);
let testData: Data[] = [
{
quantity: 25,
category: 'a'
},
{
quantity: 50,
category: 'b'
},
{
quantity: 100,
category: 'c'
},
{
quantity: 200,
category: 'd'
},
{
quantity: 300,
category: 'e'
}];
let width=options.viewport.width;
let height=options.viewport.height;
let radius=Math.min(width,height)/2;
this.svg.attr({
width:width,
height:height,
});
let colourValues = d3.scale.category20c();
this.arc=d3.svg.arc()
.innerRadius(0)
.outerRadius(radius-20);
this.pie = d3.layout.pie<Data>().value((d: Data):number => d.quantity);
let fill = (d=> colourValues(d.category));
let tf = d => `translate(${this.arc.centroid(d)})`;
let text = d => d.data.category;
this.svg.append('g')
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
this.g=this.svg.selectAll('.arc')
.data(this.pie(testData))
.enter()
.append('g')
.attr('class', 'arc')
.data(this.pie(testData));
this.g.append('path')
.attr('d', this.arc)
.attr('fill', fill)
.style("stroke","black")
.style("stroke-width","0.8")
.on("mouseover",d=>
{
d3.select(d)
.attr('fill','blue')
.style('opacity','0.6')
.attr('d',this.arc)
.style("stroke","black")
.style("stroke-width","3");
this.color=d.getAttribute('fill');
})
.on("mouseout",d=>
{
d3.select(d)
.attr('fill',colourValues(this.color))
.style("opacity","1")
.attr('d',this.arc)
.style("stroke-width","0.8");
}).append("svg:title");
//.html(d=>'<p>Quantity :'+d=>d. + '</p>');
this.g.append('text').attr('transform', tf).text(text);
}
private static parseSettings(dataView: DataView): VisualSettings {
return VisualSettings.parse(dataView) as VisualSettings;
}
/**
* This function gets called for each of the objects defined in the capabilities files and allows you to select which of the
* objects and properties you want to expose to the users in the property pane.
*
*/
public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] | VisualObjectInstanceEnumerationObject {
return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options);
}
}
}Please take a look at this fixed version:
module powerbi.extensibility.visual { "use strict"; interface Data { quantity: number; category: string; } export class PieChart implements IVisual { private target: HTMLElement; private settings: VisualSettings; private textNode: Text; private pieChartContainer: d3.Selection<SVGElement>; private arc: any; private host: IVisualHost; private svg: d3.Selection<SVGElement>; private g: any; private pie: any; private color: string; constructor(options: VisualConstructorOptions) { debugger; console.log('Visual constructor', options); this.target = options.element; this.host = options.host; let svg = this.svg = d3.select(options.element) .append('svg') .classed("pieChart", true); this.pieChartContainer = svg .append('g') .classed('pieChartContainer', true); } public update(options: VisualUpdateOptions) { console.log(options); this.settings = PieChart.parseSettings(options && options.dataViews && options.dataViews[0]); let testData: Data[] = [ { quantity: 25, category: 'a' }, { quantity: 50, category: 'b' }, { quantity: 100, category: 'c' }, { quantity: 200, category: 'd' }, { quantity: 300, category: 'e' }]; let width = options.viewport.width; let height = options.viewport.height; let radius = Math.min(width, height) / 2; this.svg.attr({ width: width, height: height, }); let colourValues = d3.scale.category20c(); this.arc = d3.svg.arc() .innerRadius(0) .outerRadius(radius - 20); this.pie = d3.layout.pie<Data>().value((d: Data): number => d.quantity); let fill = (d => colourValues(d.category)); let tf = d => `translate(${this.arc.centroid(d)})`; let text = d => d.data.category; this.pieChartContainer.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')'); this.g = this.pieChartContainer.selectAll('.arc') .data(this.pie(testData)) .enter() .append('g') .attr('class', 'arc') .data(this.pie(testData)); this.g.append('path') .attr('d', this.arc) .attr('fill', fill) .style("stroke", "black") .style("stroke-width", "0.8") .on("mouseover", d => { d3.select(d) .attr('fill', 'blue') .style('opacity', '0.6') .attr('d', this.arc) .style("stroke", "black") .style("stroke-width", "3"); this.color = d.getAttribute('fill'); }) .on("mouseout", d => { d3.select(d) .attr('fill', colourValues(this.color)) .style("opacity", "1") .attr('d', this.arc) .style("stroke-width", "0.8"); }).append("svg:title"); //.html(d=>'<p>Quantity :'+d=>d. + '</p>'); this.g.append('text').attr('transform', tf).text(text); } private static parseSettings(dataView: DataView): VisualSettings { return VisualSettings.parse(dataView) as VisualSettings; } /** * This function gets called for each of the objects defined in the capabilities files and allows you to select which of the * objects and properties you want to expose to the users in the property pane. * */ public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] | VisualObjectInstanceEnumerationObject { return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options); } } }Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals
10 Replies
- AnonymousNot applicable
Hi guys. I'm trying to create a pie chart power Bi visual for practicing custom visual creation.I have followed the tutorial given in the github repo for the environment setup and now is currently on the first step , ie creating visual with static data.
The visual is being built and served correctly.But when I insert the visual in the powerBi service,all i get is a blank screen.
Can someone help? I'm new to d3 and TypeScript, so there may be a chance that I may have made some silly mistakes.
Here's my code:module powerbi.extensibility.visual { "use strict"; interface Data { quantity: number; category: string; } export class PieChart implements IVisual { private target: HTMLElement; private settings: VisualSettings; private textNode: Text; private pieChartContainer:d3.Selection<SVGElement>; private arc:any; private host:IVisualHost; private svg:d3.Selection<SVGElement>; private g:any; private pie:any; private color:string; constructor(options: VisualConstructorOptions) { console.log('Visual constructor', options); this.target = options.element; this.host=options.host; let svg=this.svg=d3.select(options.element) .append('svg') .classed("pieChart",true); this.pieChartContainer=svg.append('g').classed('pieChartContainer',true); } public update(options: VisualUpdateOptions) { this.settings = PieChart.parseSettings(options && options.dataViews && options.dataViews[0]); let testData: Data[] = [ { quantity: 25, category: 'a' }, { quantity: 50, category: 'b' }, { quantity: 100, category: 'c' }, { quantity: 200, category: 'd' }, { quantity: 300, category: 'e' }]; let width=options.viewport.width; let height=options.viewport.height; let radius=Math.min(width,height)/2; this.svg.attr({ width:width, height:height, }); let colourValues = d3.scale.category20c(); this.arc=d3.svg.arc() .innerRadius(0) .outerRadius(radius-20); this.pie = d3.layout.pie<Data>().value((d: Data):number => d.quantity); let fill = (d=> colourValues(d.category)); let tf = d => `translate(${this.arc.centroid(d)})`; let text = d => d.data.category; this.svg.append('g') .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')'); this.g=this.svg.selectAll('.arc') .data(this.pie(testData)) .enter() .append('g') .attr('class', 'arc') .data(this.pie(testData)); this.g.append('path') .attr('d', this.arc) .attr('fill', fill) .style("stroke","black") .style("stroke-width","0.8") .on("mouseover",d=> { d3.select(d) .attr('fill','blue') .style('opacity','0.6') .attr('d',this.arc) .style("stroke","black") .style("stroke-width","3"); this.color=d.getAttribute('fill'); }) .on("mouseout",d=> { d3.select(d) .attr('fill',colourValues(this.color)) .style("opacity","1") .attr('d',this.arc) .style("stroke-width","0.8"); }).append("svg:title"); //.html(d=>'<p>Quantity :'+d=>d. + '</p>'); this.g.append('text').attr('transform', tf).text(text); } private static parseSettings(dataView: DataView): VisualSettings { return VisualSettings.parse(dataView) as VisualSettings; } /** * This function gets called for each of the objects defined in the capabilities files and allows you to select which of the * objects and properties you want to expose to the users in the property pane. * */ public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] | VisualObjectInstanceEnumerationObject { return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options); } } } - v-viigCommunity Champion
Hello Anonymous,
I'm wondering if you can clarify these items:
- Did you install d3 by executing npm i [email protected] --save?
- Did you include d3 into externalJS property of pbiviz.json? (example)
Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals
- AnonymousNot applicable
I'm using d3 3.5.17 and yes, i have included it into externalJS property.
- v-viigCommunity Champion
Your code actually works for me:
However, Pie chart is misplaced. I suppose that you should apply CSS transform-translate to fix position issue.
Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals