为Power BI自定义视觉创建图例

时间:2017-10-24 13:55:00

标签: d3.js svg powerbi

我正在尝试创建一个功能BI自定义视觉效果。我正在创建一个饼图。 正在显示饼图视觉。 我已将Legend定义为布尔属性,并且当show值的Legend属性设置为true时,当前正尝试为饼图呈现图例。 但即使settings.Legend.showtrue,也会显示无传奇。

我正在使用d3.js来创建视觉效果。 有人可以帮忙吗?

这是我的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:<number>dataValue.values[i],
       category:<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
        }];
    }

}
}

这是我的能力.json

{
"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
                }
            }  
            ]
     }        
]
}

0 个答案:

没有答案