cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
vichus
Helper V
Helper V

Creating Legend for a Pie Chart.

Hi guys, I'm developing a Pie chart and trying to create a legend for it.But the code snippet doesn't seem to do anything. please Help.

Here's my code: 
visual.ts

 

module powerbi.extensibility.visual {
    "use strict";
    


    interface Data 
    {        
    quantity: number;
    category: string;
    color:string;
    selectionId:ISelectionId;
    }

    interface PieChartArc {
        datapoints: Data[];
        setting: pieChartSettings;
        dataview: DataView[];
    }
    
    interface pieChartSettings
    {
        Legend :
        {
            show: boolean;
        };
    }

    interface LegendValues
    {
        category:string;
        color:string;
        selection:ISelectionId;
    }

    function visualTransform(options:VisualUpdateOptions,host:IVisualHost) : PieChartArc
    {
        let dataViews= options.dataViews;

        let defaultSetting : pieChartSettings = {
            Legend:{
                show:false,
            }
        };

        let viewModel: PieChartArc=
        {
            datapoints:[],
            setting : defaultSetting,
            dataview: dataViews
        };


        if (!dataViews
            || !dataViews[0]
            || !dataViews[0].categorical
            || !dataViews[0].categorical.categories
            || !dataViews[0].categorical.categories[0].source
            || !dataViews[0].categorical.values)
            return viewModel;
            
        let categorical=dataViews[0].categorical;
        let category=categorical.categories[0];
        let dataValue=categorical.values[0];
        
        let pieChartData: Data[]=[];
        let colorPalette: IColorPalette=host.colorPalette;
        let objects= dataViews[0].metadata.objects
            let pieChartSetting: pieChartSettings={
                Legend:{
                    show: getValue<boolean>(objects,'Legend','show',defaultSetting.Legend.show)
                }
            }
        for(let i=0;i<Math.max(category.values.length,dataValue.values.length);i++)
        {
            pieChartData.push({
           quantity: <string>category.values[i],
           color: colorPalette.getColor(<string>category.values[i]).value,
           selectionId: host.createSelectionIdBuilder()
                         .withCategory(category, i)
                        .createSelectionId()    
            });
            console.log(pieChartData[i].color);

        }
        return {
            datapoints: pieChartData,
            setting: pieChartSetting,
            dataview:dataViews
        };
    }
    
    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 selectionManager:ISelectionManager;
        private svg: d3.Selection<SVGElement>;
        private legend:d3.Selection<SVGElement>;
        private g: any;
        private pie: any;
        private color: string;
        private tooltipServiceWrapper: ITooltipServiceWrapper;
        private pieSettings: pieChartSettings;
        static data: DataView[];
        
        static config=
        
        {
        solidOpacity:1,
        transparentOpacity:0.5,
        };

        constructor(options: VisualConstructorOptions) {
            console.log('Visual constructor', options);
            
            this.target = options.element;
            this.host=options.host;
            this.selectionManager=options.host.createSelectionManager();
            this.legend=d3.select(options.element);
            let svg=this.svg=d3.select(options.element)
                                .append('svg')
                                .classed("pieChart",true)
                                ;
            
            this.pieChartContainer=svg.append('g').classed('pieChartContainer',true);//.attr('transform','translate('+100+',' +100+')');  
            this.tooltipServiceWrapper = createTooltipServiceWrapper(this.host.tooltipService, options.element);                      
        }


        public update(options: VisualUpdateOptions) {
          //  let legendModel : LegendValues[] = legendTransform(options,this.host);
            let viewModel: PieChartArc = visualTransform(options, this.host);        
            let settings=this.pieSettings=viewModel.setting;
            let category=options.dataViews[0].categorical.categories[0];
            let dataValue=options.dataViews[0].categorical.values[0];
            let legend=this.legend;
            let legendEnumerate:LegendValues[];
           // shows legend
          if(settings.Legend.show)
            {  //this.svg.append("text").text("Hello");
            for(let i=0;i<category.values.length;++i)
            {   
                   legendEnumerate.push({
                       category:<string>category.values[i],
                       color:<string>dataValue.values[i],
                       selection:this.host.createSelectionIdBuilder()
                       .withCategory(category, i)
                      .createSelectionId()
                   });
                }
                let leg= this.legend.append('svg');
                   
                for(let i=0;i<Math.max(category.values.length,dataValue.values.length);++i)
                {
                     //  this.legend.html(legendEnumerate[i].category).attr("transform","translate(" + i*20 +",0)")             
                    
                   // leg.a
                   leg.append('circle')
                   .attr('cx',20)
                   .attr('cy',20)
                   .attr('r',8)
                   .attr('fill',legendEnumerate[i].color)
                   .attr("transform","translate(" + i*20 +",0)")
                   ;
                   leg.append('text')
                   .text(legendEnumerate[i].category)
                   .attr("transform","translate(" + i*30 +",0)")
                    ;
                    } 
                
    }
            PieChart.data=options.dataViews;
            let width=options.viewport.width;
            let height=options.viewport.height;
            let radius=Math.min(width,height)/2;
            this.svg.attr({
                width: width-20,
                height: height-20,
            
            });
            
            this.arc=d3.svg.arc()
            .innerRadius(0)
            .outerRadius(radius-20);
            this.pie = d3.layout.pie<Data>().value((d: Data):number => d.quantity).sort(null);
            let fill = ((d):string=> d.data.color);
            let tf   =  (d: Data) => `translate(${this.arc.centroid(d)})`;
            let text = d => d.data.category;
            this.svg.append('g');
           
            this.g=this.svg.selectAll('.arc')
                    .data(this.pie(viewModel.datapoints))
                    .enter()
                    .append('g')
                    .attr('class', 'arc')
                    .data(this.pie(viewModel.datapoints))
                   // .attr("fill",fill)
                    ;
                   
           let path= this.g.append('path')
                    .attr('d', this.arc)
                    .attr('fill',fill)
                    .attr('fill-opacity',1)
                    //.style("stroke","black")
                    .attr("stroke-width","0.8");           
                    this.g.append('text').attr('transform', tf).text(text).attr('fill',"white");
             
                    this.tooltipServiceWrapper.addTooltip(path, 
                    (tooltipEvent: TooltipEventArgs<number>) => PieChart.getTooltipData(tooltipEvent.data),
                    (tooltipEvent: TooltipEventArgs<number>) => null);
            let selectionManager = this.selectionManager;

                path.on("click",function(d)
                 {
                    // path.attr('fill','blue');
                    selectionManager.select(d.data.selectionId).then((ids: ISelectionId[])=>                    
                   {                     
                    path.attr('fill-opacity',ids.length>0? PieChart.config.transparentOpacity: PieChart.config.solidOpacity);
                    d3.select(this).attr('fill-opacity',PieChart.config.solidOpacity);
                        (<Event>d3.event).stopPropagation;
                    });
                });
                path.exit()
                    .remove();
                    
        }

        
        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);
        let objectName=options.objectName;
        let objectEnumeration:VisualObjectInstance[]=[];
        switch(objectName)
        {
            case 'Legend':
            objectEnumeration.push({
                objectName: objectName,
                properties:{
                    show:this.pieSettings.Legend.show,
                },
                selector: null
            });
        };

        return objectEnumeration;
        
        }

        private static getTooltipData(value: any): VisualTooltipDataItem[] {
            return [{
                displayName: PieChart.data[0].metadata.columns[1].displayName,
                value: value.value.toString(),
                color: value.data.color,
                header:value.data.category
            }];
        }

    }
    }

Here's my capabilities.json, currently only Legend is included in enumerateObjectInstances()

{
    "dataRoles": [
        {
            "displayName": "Category",
            "name": "category",
            "kind": "Grouping"
        },
        {
            "displayName": "Measure",
            "name": "measure",
            "kind": "Measure"
        }
    ],
    "objects": {        
        "dataPoint": {
            "displayName": "Data colors",
            "properties": {
                "defaultColor": {
                    "displayName": "Default color",
                    "type": {
                        "fill": {
                            "solid": {
                                "color": true
                            }
                        }
                    }
                },                
                "showAllDataPoints": {
                    "displayName": "Show all",
                    "type": {
                        "bool": true
                    }
                },
                "fill": {
                    "displayName": "Fill",
                    "type": {
                        "fill": {
                            "solid": {
                                "color": true
                            }
                        }
                    }
                },
                "fillRule": {
                    "displayName": "Color saturation",
                    "type": {
                        "fill": {}
                    }
                },
                 "fontSize": {
                    "displayName": "Text Size",
                    "type": {
                        "formatting": {
                            "fontSize": true
                        }
                    }
                }
            }
        },
        "Legend":{
            "displayName": "Legend",
            "properties": {
            "show" :{
                "displayName": "Legend",
                "type": {
                    "bool": true
                }
            }
        }
        }
    },
    "dataViewMappings": [
        {
            "categorical": {
                "categories": {
                    "for": {
                        "in": "category"
                    },
                    "dataReductionAlgorithm": {
                        "top": {}
                    }
                },
                "values": {
                    "select": [
                        {
                            "bind": {
                                "to": "measure"
                            }
                        }
                    ]
                }
            },
            "conditions":[
               { "category":{
                    "max":1
                    },
                "measure":{
                    "max":1
                    }
                }  
                ]
         }        
    ]
}

 

1 REPLY 1
v-viig
Community Champion
Community Champion

Hello @vichus

 

I'm sorry for the delay.

Have you already found out the root of issue?

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

Helpful resources

Announcements
PBI User Groups

Welcome to the User Group Public Preview

Check out new user group experience and if you are a leader please create your group!

MBAS Attendee Badge

Claim Your Badge & Digital Swag!

Check out how to claim yours today!

secondImage

Are You Ready?

Test your skills now with the Cloud Skills Challenge.

Top Solution Authors
Top Kudoed Authors