Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.
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); } } }
Solved! Go to Solution.
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
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); } } }
This topic is duplicate of that one.
Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals
Hello @Anonymous,
I'm wondering if you can clarify these items:
Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals
I'm using d3 3.5.17 and yes, i have included it into externalJS property.
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
I got it. Thank you for your patience.
By the way,which element should be given the transform-translate style?
I added it as a attribute for svg ,but no use.
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
Thanks @v-viig.
And consider this as a Humble request from my side, Please consider improving the current documentation for creating custom visuals. Beginners like me struggle a lot following the current documentation.
Yes, sure. Thank you for the feedback.
Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals
Could you please share your .json files?
Did you make any change to my code?
Is there a need to fill the data fields when using static data?
Thank You
Vishnu Suresh
Covering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City
Check out the April 2024 Power BI update to learn about new features.