Power BI仪表板中的风格与开发人员工具预览选项不同

时间:2015-11-02 10:54:24

标签: d3.js svg typescript powerbi bullet-chart

首先尝试使用功能BI自定义图形,原谅我的一些不一致。

我正在尝试编辑子弹图“ BulletChartbySQLBI ”,以便它可以满足我的需求,但我似乎无法弄清楚为什么样式应用于开发。导入仪表板,颜色和文本格式时,工具preview不会停留。

+问题

我遇到的另一个问题是我似乎无法将标题放在主栏的顶部,以便我可以将文本放在那里,我尝试使用CSS样式,但没有成功,然后尝试改变svg的绘制方式,使文本显示在顶部,但也没有成功。

代码开发于:https://app.powerbi.com/devTools

数据预览:SimpleGauge(单一+分类)

module powerbi.visuals {

//Model
export interface BulletCharttestBI4ALL {
    label: string;
    label2: string;
    showLabel: boolean;
    color: string;
    color2: string;
    states: number[];
    value: number;
    target: number;
    comparison: number;
    min: number;
    max: number;
    selector: data.Selector;
    toolTipInfo: TooltipDataItem[];
}

export var bulletChartProps = {   //PROPRIEDADES para o power BI  // Replicar  linha 187  e  427
    general: {
        fill: <DataViewObjectPropertyIdentifier>{ objectName: 'Cores', propertyName: 'fill' },
        fill2: <DataViewObjectPropertyIdentifier>{ objectName: 'Cores', propertyName: 'fill2' },
    },
    label: {
        show: <DataViewObjectPropertyIdentifier>{ objectName: 'Titulo', propertyName: 'show' },
        text: <DataViewObjectPropertyIdentifier>{ objectName: 'Titulo', propertyName: 'text' },
        text2: <DataViewObjectPropertyIdentifier>{ objectName: 'Titulo', propertyName: 'text2' }
    },
};

//Visual
export class BulletCharttestBI4ALL1 implements IVisual {

    //Variables
    private svg: D3.Selection;
    private svgBullet: D3.Selection;
    private svgTitle: D3.Selection;
    private svgSubtitle: D3.Selection;

    private dataView: DataView;
    private data: BulletCharttestBI4ALL;

    public static getDefaultData(): BulletCharttestBI4ALL {
        return {
            color: '#36bba3',
            color2: 'lightsteelblue',
            label: 'YTD stuff',
            label2: '2015',
            showLabel: true,
            states: [],
            min: 0,
            max: 100,
            value: 0,
            target: 0,
            comparison: 0,
            toolTipInfo: [],
            selector: SelectionId.createNull().getSelector()
        };
    }

    //Capabilities
    public static capabilities: VisualCapabilities = {
        dataRoles: [
             {
                name: 'Y',
                kind: VisualDataRoleKind.Measure,
                displayName: data.createDisplayNameGetter('Role_DisplayName_Value'),
            }, {
                name: 'ComparisonValue',
                kind: VisualDataRoleKind.Measure,
                displayName: 'Comparison Value',
            }, {
                name: 'TargetValue',
                kind: VisualDataRoleKind.Measure,
                displayName: data.createDisplayNameGetter('Role_DisplayName_TargetValue'),
            }, {
                name: 'MinValue',
                kind: VisualDataRoleKind.Measure,
                displayName: data.createDisplayNameGetter('Role_DisplayName_MinValue'),
            }, {
                name: 'MaxValue',
                kind: VisualDataRoleKind.Measure,
                displayName: data.createDisplayNameGetter('Role_DisplayName_MaxValue'),

            }, {
                name: 'QualitativeState1Value',
                kind: VisualDataRoleKind.Measure,
                displayName: 'Qualitative State 1',
            }, {
                name: 'QualitativeState2Value',
                kind: VisualDataRoleKind.Measure,
                displayName: 'Qualitative State 2',
            }, {
                name: 'QualitativeState3Value',
                kind: VisualDataRoleKind.Measure,
                displayName: 'Qualitative State 3',
            }
        ],
        objects: {

            general: {
                displayName: data.createDisplayNameGetter('Visual_General'),
                properties: {
                    fill: {
                        displayName: 'Main Color',
                        type: { fill: { solid: { color: true } } }
                    },
                    fill2: {
                        displayName: 'Comparison Color',
                        type: { fill: { solid: { color: true } } }
                    },
                },
            },

            label: {
                displayName: "Label",
                properties: {
                    show: {
                        displayName: data.createDisplayNameGetter('Visual_Show'),
                        type: { bool: true }
                    },
                    text: {
                        displayName: 'Label',
                        type: { text: true }
                    },
                    text2: {
                        displayName: 'Sub Label',
                        type: { text: true }
                    },
                },
            },
        },
        dataViewMappings: [{
            conditions: [
                { 'Y': { max: 1 }, 'ComparisonValue': { max: 1 }, 'TargetValue': { max: 1 }, 'MinValue': { max: 1 }, 'MaxValue': { max: 1 }, 'QualitativeState1Value': { max: 1 }, 'QualitativeState2Value': { max: 1 }, 'QualitativeState3Value': { max: 1 } },
            ],
            categorical: {
                values: {
                    select: [
                        { bind: { to: 'Y' } },
                        { bind: { to: 'ComparisonValue' } },
                        { bind: { to: 'TargetValue' } },
                        { bind: { to: 'MaxValue' } },
                        { bind: { to: 'QualitativeState1Value' } },
                        { bind: { to: 'QualitativeState2Value' } },
                        { bind: { to: 'QualitativeState3Value' } },
                    ]
                },
            },
        }],
        suppressDefaultTitle: true,
    };

    //One time setup
    public init(options: VisualInitOptions): void {
        this.svg = d3.select(options.element.get(0))
            .append('svg')
            .classed('bullet', true);

        this.svgBullet = this.svg
            .append('g');

        var labels = this.svgBullet
            .append('g')
            .style('text-anchor', 'end')
            .style("position", "relative")
            .style("z-index", "9999");

        this.svgTitle = labels
            .append('text')
            .attr("dx", "-1em")       //localizaçaõ do texto
            .classed('title', true);

        this.svgSubtitle = labels
            .append('text')
            .attr('dy', '1em')         //localizaçaõ do texto
            .classed('subtitle', true);
    }

    //Convert the dataview into its view model
    public static converter(dataView: DataView): BulletCharttestBI4ALL {

        var data: BulletCharttestBI4ALL = BulletCharttestBI4ALL1.getDefaultData();

        if (dataView.categorical) {

            if (dataView.metadata) {
                var objects = dataView.metadata.objects;

                if (objects) {
                    data.color = DataViewObjects.getFillColor(objects, bulletChartProps.general.fill, data.color);
                    data.color2 = DataViewObjects.getFillColor(objects, bulletChartProps.general.fill2, data.color2);
                    data.label = DataViewObjects.getValue(objects, bulletChartProps.label.text, data.label);
                    data.label2 = DataViewObjects.getValue(objects, bulletChartProps.label.text2, data.label2);
                    data.showLabel = DataViewObjects.getValue(objects, bulletChartProps.label.show, data.showLabel);
                }

                var toolTipItems = [];

                var values = dataView.categorical.values;

                if (values && dataView.metadata.columns) {
                    for (var i = 0; i < values.length; i++) {

                        var col = dataView.metadata.columns[i];
                        var value = values[i].values[0] || 0;
                        if (col && col.roles) {

                            var pushToTooltips = false;

                            if (col.roles['Y']) {
                                data.value = value;
                                pushToTooltips = true;

                            } else if (col.roles['MaxValue']) {
                                data.max = value;
                            } else if (col.roles['TargetValue']) {
                                data.target = value;
                                pushToTooltips = true;
                            } else if (col.roles['ComparisonValue']) {
                                data.comparison = value;
                                pushToTooltips = true;
                            } else if (col.roles['QualitativeState1Value'] || col.roles['QualitativeState2Value'] || col.roles['QualitativeState3Value']) {
                                if (value)
                                    data.states.push(value);
                            }

                            if (value && pushToTooltips)
                                toolTipItems.push({ value: value, metadata: values[i] });
                        }
                    }
                }

                if (toolTipItems.length > 0) {
                    data.toolTipInfo = TooltipBuilder.createTooltipInfo({
                        objectName: 'general',
                        propertyName: 'formatString',
                    }, null, null, null, null, toolTipItems);
                }
            }
        }

        return data;
    }

   //Drawing the visual
    public update(options: VisualUpdateOptions) {
        if (!options.dataViews || !options.dataViews[0]) return;
        var dataView = this.dataView = options.dataViews[0];
        var viewport = options.viewport;

        this.data = BulletCharttestBI4ALL1.converter(dataView);

        var maxValue = Math.max(this.data.target, this.data.value, this.data.comparison, this.data.max);
        if (this.data.states.length === 0)
            this.data.states = [Math.ceil(maxValue) / 3, (Math.ceil(maxValue) / 3) * 2, Math.ceil(maxValue)];

        var sortedRanges = this.data.states.slice().sort(d3.descending);
        sortedRanges.unshift(maxValue+1);

        var titleWidth = TextMeasurementService.measureSvgTextWidth({ fontFamily: 'tahoma', fontSize: '16px', text: this.data.label });
        var showSubtitle = (this.data.label2.length > 0);
        var subtitleWidth = TextMeasurementService.measureSvgTextWidth({ fontFamily: 'tahoma', fontSize: '12px', text: this.data.label2 });
        var labelWidth = (this.data.showLabel ? Math.max(titleWidth, subtitleWidth) : 0);

        var height = 25;
        var width = viewport.width - 50;



        this.svg
            .attr({
                'height': 60,
                'width': viewport.width - 40
            });


         if (this.data.showLabel) {

            this.svgBullet.attr('transform', 'translate(' + (labelWidth + 20) + ',5)');

            this.svgTitle
                .attr("position", "absolute")
                .style('display', 'block')
                .attr("text-anchor", "middle")
                .attr('transform', 'translate(30,' + ((height / 2) + (showSubtitle ? 0 : 5)) + ')')
                .text(this.data.label)
                .style("z-index", "10000");


            if (showSubtitle) {
                this.svgSubtitle
                    .style('display', 'block')
                    .attr("position", "absolute")
                    .style("z-index", "10000")
                    .attr('transform', 'translate(30,' + ((height / 2) - 5) + ')')
                    .text(this.data.label2);
            } else {
                this.svgSubtitle.style('display', 'none');
            }



        } else {
                            this.svgBullet.attr('transform', 'translate(10,50)');
            this.svgTitle.style('display', 'none');
            this.svgSubtitle.style('display', 'none');
        }       





        //Scale on X-axis
        var scale = d3.scale.linear()
            .domain([0, Math.max(sortedRanges[0], this.data.target, this.data.value)])
            .range([0, width]);

        //Ranges
        var range = this.svgBullet.selectAll('rect.range')
            .data(sortedRanges);

        range.enter()
            .append('rect')
            .attr('class', function (d, i) { return 'range s' + i; });

        range
            .attr('x', 0)
            .attr('width', function (d) { return Math.abs(scale(d) - scale(0)); })
            .attr('height', height);

        //Comparison measure
        this.svgBullet.selectAll('rect.measure').remove();
        if (this.data.comparison > 0) {
            var comparison = this.svgBullet
                .append('rect')
                .classed('measure', true)
                .style('fill', this.data.color2);

            comparison
                .attr('width', scale(this.data.comparison))
                .attr('height', height)
                .attr('x', 0)
                .attr('y', height - 25);
        }

        //Main measure


        var measure = this.svgBullet
            .append('rect')
            .style("height", height)
            .classed('measure', true)
            .style("z-index", "0")
            .attr("position", "relative")
            .attr("z-index", "0")
            .style('fill', this.data.color);

        measure
            .attr('width', scale(this.data.value))
            .attr('height', height - 25)
            .attr('x', 0)
            .attr("z-index", "0")
            .attr('y', height - 25);

        //Target markers
        this.svgBullet.selectAll('line.marker').remove();
        var marker = this.svgBullet
            .append('line')
            .classed('marker', true);

        marker
            .attr('x1', scale(this.data.target))
            .attr('x2', scale(this.data.target))
            .attr('y1', height / 20)
            .attr('y2', height + 2);

        //Ticks
        var format = scale.tickFormat(10);

        var tick = this.svgBullet.selectAll('g.tick')
            .data(scale.ticks(10), function (d) {
                return this.textContent || format(d);
            });

        var tickEnter = tick.enter()
            .append('g')
            .attr('class', 'tick');

        tickEnter.append('line')
            .attr('y1', height)
            .attr('y2', height * 7 / 6);

        tickEnter
            .append('text')
            .attr('text-anchor', 'middle')
            .attr('dy', '1em')
            .attr('y', height * 7 / 6)
            .text(format);

        tickEnter
            .attr('transform', function (d) {
                return 'translate(' + scale(d) + ',0)';
            });

        var tickUpdate = tick.transition()
            .duration(0)
            .attr('transform', function (d) {
                return 'translate(' + scale(d) + ',0)';
            })
            .style('opacity', 1);

        tickUpdate.select('line')
            .attr('y1', height)
            .attr('y2', height * 7 / 6);

        tickUpdate.select('text')
            .attr('y', height * 7 / 6);

        tick.exit().transition()
            .duration(0)
            .attr('transform', function (d) {
                return 'translate(' + scale(d) + ',0)';
            })
            .style('opacity', 1e-6)
            .remove();

        TooltipManager.addTooltip(this.svgBullet, (tooltipEvent: TooltipEvent) => this.data.toolTipInfo);
    } 

    //Make visual properties available in the property pane in Power BI
    public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {
        var enumeration = new ObjectEnumerationBuilder();

        if (!this.data)
            this.data = BulletCharttestBI4ALL1.getDefaultData();

        switch (options.objectName) {
            case 'general':
                enumeration.pushInstance({
                    objectName: 'general',
                    displayName: 'Cores das Barras',
                    selector: null,
                    properties: {
                        fill: this.data.color,       //PROPRIEDADES
                        fill2: this.data.color2
                    }
                });
                break;

            case 'label':
                enumeration.pushInstance({
                    objectName: 'label',
                    displayName: 'Título',
                    selector: null,
                    properties: {
                        show: this.data.showLabel,   //PROPRIEDADES
                        text: this.data.label,
                        text2: this.data.label2
                    }
                });
                break;



        }

        return enumeration.complete();
    }

    //Free up resources
    public destroy(): void {
        this.svg = null;
        this.svgTitle = this.svgSubtitle = this.svgBullet = null;
    }
}
}

如果有人可以开导我,我会很感激, 干杯

1 个答案:

答案 0 :(得分:1)

经过深思熟虑之后,我明白了。

对于第一部分,问题在于,power bi不允许您通过一些修改上传相同的图形,我不得不更改代码中的命名,以便它假定不同的图形。

第二部分是棘手的,在移动后我发现代码总是坏了,所以我认为再次调用标题就可以了,所以它确实如此!我隐藏了另一个标题,并在绘制了条形图后再次调用。

修订代码:

 module powerbi.visuals {

//Model
export interface BulletCharttestBI4ALL1 {
    label: string;
    label2: string;
    showLabel: boolean;
    color: string;
    color2: string;
    states: number[];
    value: number;
    target: number;
    comparison: number;
    min: number;
    max: number;
    selector: data.Selector;
    toolTipInfo: TooltipDataItem[];
}

export var bulletChartProps = {   //PROPRIEDADES para o power BI  // Replicar  linha 187  e  427
    general: {
        fill: <DataViewObjectPropertyIdentifier>{ objectName: 'Cores', propertyName: 'fill' },
        fill2: <DataViewObjectPropertyIdentifier>{ objectName: 'Cores', propertyName: 'fill2' },
    },
    label: {
        show: <DataViewObjectPropertyIdentifier>{ objectName: 'Titulo', propertyName: 'show' },
        text: <DataViewObjectPropertyIdentifier>{ objectName: 'Titulo', propertyName: 'text' },
        text2: <DataViewObjectPropertyIdentifier>{ objectName: 'Titulo', propertyName: 'text2' }
    },
};

//Visual
export class BulletCharttestBI4ALL2 implements IVisual {

    //Variables

    private svg: D3.Selection;
    private svgBullet: D3.Selection;
    private svgTitle: D3.Selection;
    private svgSubtitle: D3.Selection;


    private dataView: DataView;
    private data: BulletCharttestBI4ALL1;

    public static getDefaultData(): BulletCharttestBI4ALL1 {
        return {
            color: '#36bba3',
            color2: 'lightsteelblue',
            label: 'YTD stuff',
            label2: '2015',
            showLabel: true,
            states: [],
            min: 0,
            max: 100,
            value: 0,
            target: 0,
            comparison: 0,
            toolTipInfo: [],
            selector: SelectionId.createNull().getSelector()
        };
    }

    //Capabilities
    public static capabilities: VisualCapabilities = {
        dataRoles: [
             {
                name: 'Y',
                kind: VisualDataRoleKind.Measure,
                displayName: data.createDisplayNameGetter('Role_DisplayName_Value'),
            }, {
                name: 'ComparisonValue',
                kind: VisualDataRoleKind.Measure,
                displayName: 'Comparison Value',
            }, {
                name: 'TargetValue',
                kind: VisualDataRoleKind.Measure,
                displayName: data.createDisplayNameGetter('Role_DisplayName_TargetValue'),
            }, {
                name: 'MinValue',
                kind: VisualDataRoleKind.Measure,
                displayName: data.createDisplayNameGetter('Role_DisplayName_MinValue'),
            }, {
                name: 'MaxValue',
                kind: VisualDataRoleKind.Measure,
                displayName: data.createDisplayNameGetter('Role_DisplayName_MaxValue'),

            }, {
                name: 'QualitativeState1Value',
                kind: VisualDataRoleKind.Measure,
                displayName: 'Qualitative State 1',
            }, {
                name: 'QualitativeState2Value',
                kind: VisualDataRoleKind.Measure,
                displayName: 'Qualitative State 2',
            }, {
                name: 'QualitativeState3Value',
                kind: VisualDataRoleKind.Measure,
                displayName: 'Qualitative State 3',
            }
        ],
        objects: {

            general: {
                displayName: data.createDisplayNameGetter('Visual_General'),
                properties: {
                    fill: {
                        displayName: 'Main Color',
                        type: { fill: { solid: { color: true } } }
                    },
                    fill2: {
                        displayName: 'Comparison Color',
                        type: { fill: { solid: { color: true } } }
                    },
                },
            },

            label: {
                displayName: "Label",
                properties: {
                    show: {
                        displayName: data.createDisplayNameGetter('Visual_Show'),
                        type: { bool: true }
                    },
                    text: {
                        displayName: 'Label',
                        type: { text: true }
                    },
                    text2: {
                        displayName: 'Sub Label',
                        type: { text: true }
                    },
                },
            },
        },
        dataViewMappings: [{
            conditions: [
                { 'Y': { max: 1 }, 'ComparisonValue': { max: 1 }, 'TargetValue': { max: 1 }, 'MinValue': { max: 1 }, 'MaxValue': { max: 1 }, 'QualitativeState1Value': { max: 1 }, 'QualitativeState2Value': { max: 1 }, 'QualitativeState3Value': { max: 1 } },
            ],
            categorical: {
                values: {
                    select: [
                        { bind: { to: 'Y' } },
                        { bind: { to: 'ComparisonValue' } },
                        { bind: { to: 'TargetValue' } },
                        { bind: { to: 'MaxValue' } },
                        { bind: { to: 'QualitativeState1Value' } },
                        { bind: { to: 'QualitativeState2Value' } },
                        { bind: { to: 'QualitativeState3Value' } },
                    ]
                },
            },
        }],
        suppressDefaultTitle: true,
    };

    //One time setup
    public init(options: VisualInitOptions): void {
        this.svg = d3.select(options.element.get(0))
            .append('svg')
            .classed('bullet', true);

        this.svgBullet = this.svg
            .append('g');

        var labels = this.svgBullet
            .append('g')
            .style('text-anchor', 'end');

        this.svgTitle = labels
            .append('text')
            .attr("dx", "-1em")       //localizaçaõ do texto
            .classed('title', true);

        this.svgSubtitle = labels
            .append('text')
            .attr('dy', '1em')
            .classed('subtitle', true);
    }

    //Convert the dataview into its view model
    public static converter(dataView: DataView): BulletCharttestBI4ALL1 {

        var data: BulletCharttestBI4ALL1 = BulletCharttestBI4ALL2.getDefaultData();

        if (dataView.categorical) {

            if (dataView.metadata) {
                var objects = dataView.metadata.objects;

                if (objects) {
                    data.color = DataViewObjects.getFillColor(objects, bulletChartProps.general.fill, data.color);
                    data.color2 = DataViewObjects.getFillColor(objects, bulletChartProps.general.fill2, data.color2);
                    data.label = DataViewObjects.getValue(objects, bulletChartProps.label.text, data.label);
                    data.label2 = DataViewObjects.getValue(objects, bulletChartProps.label.text2, data.label2);
                    data.showLabel = DataViewObjects.getValue(objects, bulletChartProps.label.show, data.showLabel);
                }

                var toolTipItems = [];

                var values = dataView.categorical.values;

                if (values && dataView.metadata.columns) {
                    for (var i = 0; i < values.length; i++) {

                        var col = dataView.metadata.columns[i];
                        var value = values[i].values[0] || 0;
                        if (col && col.roles) {

                            var pushToTooltips = false;

                            if (col.roles['Y']) {
                                data.value = value;
                                pushToTooltips = true;

                            } else if (col.roles['MaxValue']) {
                                data.max = value;
                            } else if (col.roles['TargetValue']) {
                                data.target = value;
                                pushToTooltips = true;
                            } else if (col.roles['ComparisonValue']) {
                                data.comparison = value;
                                pushToTooltips = true;
                            } else if (col.roles['QualitativeState1Value'] || col.roles['QualitativeState2Value'] || col.roles['QualitativeState3Value']) {
                                if (value)
                                    data.states.push(value);
                            }

                            if (value && pushToTooltips)
                                toolTipItems.push({ value: value, metadata: values[i] });
                        }
                    }
                }

                if (toolTipItems.length > 0) {
                    data.toolTipInfo = TooltipBuilder.createTooltipInfo({
                        objectName: 'general',
                        propertyName: 'formatString',
                    }, null, null, null, null, toolTipItems);
                }
            }
        }

        return data;
    }

   //Drawing the visual
    public update(options: VisualUpdateOptions) {
        if (!options.dataViews || !options.dataViews[0]) return;
        var dataView = this.dataView = options.dataViews[0];
        var viewport = options.viewport;

        this.data = BulletCharttestBI4ALL2.converter(dataView);

        var maxValue = Math.max(this.data.target, this.data.value, this.data.comparison, this.data.max);
        if (this.data.states.length === 0)
            this.data.states = [Math.ceil(maxValue) / 3, (Math.ceil(maxValue) / 3) * 2, Math.ceil(maxValue)];

        var sortedRanges = this.data.states.slice().sort(d3.descending);
        sortedRanges.unshift(maxValue+1);

        var titleWidth = TextMeasurementService.measureSvgTextWidth({ fontFamily: 'tahoma', fontSize: '16px', text: this.data.label });
        var showSubtitle = (this.data.label2.length > 0);
        var subtitleWidth = TextMeasurementService.measureSvgTextWidth({ fontFamily: 'tahoma', fontSize: '12px', text: this.data.label2 });
        var labelWidth = (this.data.showLabel ? Math.max(titleWidth, subtitleWidth) : 0);

        var height = 25;
        var width = viewport.width - 50;


        this.svg      // Coloca conteúdo dentro das variaveis
            .attr({
                'height': 60,
                'width': viewport.width - 40
            });



         if (this.data.showLabel) {       // Coloca conteúdo dentro das variaveis

            this.svgBullet.attr('transform', 'translate(' + (labelWidth + 20) + ',5)');

            this.svgTitle
                .attr("position", "absolute")
                .style('display', 'block')
                .attr("text-anchor", "middle")
                .attr('transform', 'translate(30,' + ((height / 2) + (showSubtitle ? 0 : 5)) + ')')
              //  .text(this.data.label)
                .style("z-index", "10000");


            if (showSubtitle) {
                this.svgSubtitle
                    .style('display', 'block')
                    .attr("position", "absolute")
                    .style("z-index", "10000")
                    .attr('transform', 'translate(30,' + ((height / 2) - 2) + ')')
                    //.text(this.data.label2);
            } else {
                this.svgSubtitle.style('display', 'none');
            }



        } else {
            this.svgBullet.attr('transform', 'translate(10,50)');
            this.svgTitle.style('display', 'none');
            this.svgSubtitle.style('display', 'none');
        }  


        //Scale on X-axis
        var scale = d3.scale.linear()
            .domain([0, Math.max(sortedRanges[0], this.data.target, this.data.value)])
            .range([0, width]);

        //Ranges       (NÃO É USADO)
        var range = this.svgBullet.selectAll('rect.range')
            .data(sortedRanges);

        range.enter()
            .append("g")     //NB
            .append('rect')
            .attr('class', function (d, i) { return 'range s' + i; });

        range
            .attr('x', 0)
            .attr('width', function (d) { return Math.abs(scale(d) - scale(0)); })
            .attr('height', height);


        //Comparison measure       (NAO É UUSADO)
        this.svgBullet.selectAll('rect.measure').remove();
        if (this.data.comparison > 0) {
            var comparison = this.svgBullet
                .append("g")                  //NB
                .append('rect')
                .classed('measure', true)
                .style('fill', this.data.color2);

            comparison
                .attr('width', scale(this.data.comparison))
                .attr('height', height)
                .attr('x', 0)
                .attr('y', height - 25);
        }


        //Main measure      //  Barra principal
        var measure = this.svgBullet
            .append("g")    //NB
            .append('rect')
            .style("height", height)
            .classed('measure', true)
            .style('fill', this.data.color);


        measure        //  Barra principal
            .attr('width', scale(this.data.value))
            .attr('height', height - 25)
            .attr('x', 0)
            .attr("z-index", "0")
            .attr('y', height - 25);


         this.svgBullet        //Coloca texto em cima da barra   YEY!!!!!!!!!!!!!!!!!!!!!!!!!!!
            .append("text")
            .text(this.data.label)
            .attr("text-anchor", "middle")
            .attr('transform', 'translate(40,' + ((height / 1.4) + (showSubtitle ? 0 : 5)) + ')'); 


        //Target markers     TARGET
        this.svgBullet.selectAll('line.marker').remove();
        var marker = this.svgBullet
            .append('line')
            .classed('marker', true);

        marker
            .attr('x1', scale(this.data.target))
            .attr('x2', scale(this.data.target))
            .attr('y1', height / 20)
            .attr('y2', height + 2);

        //Ticks    (NAO USADO)
        var format = scale.tickFormat(10);

        var tick = this.svgBullet.selectAll('g.tick')
            .data(scale.ticks(10), function (d) {
                return this.textContent || format(d);
            });

        var tickEnter = tick.enter()
            .append('g')
            .attr('class', 'tick');

        tickEnter.append('line')
            .attr('y1', height)
            .attr('y2', height * 7 / 6);

        tickEnter
            .append('text')
            .attr('text-anchor', 'middle')
            .attr('dy', '1em')
            .attr('y', height * 7 / 6)
            .text(format);

        tickEnter
            .attr('transform', function (d) {
                return 'translate(' + scale(d) + ',0)';
            });

        var tickUpdate = tick.transition()
            .duration(0)
            .attr('transform', function (d) {
                return 'translate(' + scale(d) + ',0)';
            })
            .style('opacity', 1);

        tickUpdate.select('line')
            .attr('y1', height)
            .attr('y2', height * 7 / 6);

        tickUpdate.select('text')
            .attr('y', height * 7 / 6);

        tick.exit().transition()
            .duration(0)
            .attr('transform', function (d) {
                return 'translate(' + scale(d) + ',0)';
            })
            .style('opacity', 1e-6)
            .remove();

        TooltipManager.addTooltip(this.svgBullet, (tooltipEvent: TooltipEvent) => this.data.toolTipInfo);
    } 

    //Make visual properties available in the property pane in Power BI
    public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {
        var enumeration = new ObjectEnumerationBuilder();

        if (!this.data)
            this.data = BulletCharttestBI4ALL2.getDefaultData();

        switch (options.objectName) {
            case 'general':
                enumeration.pushInstance({
                    objectName: 'general',
                    displayName: 'Cores das Barras',
                    selector: null,
                    properties: {
                        fill: this.data.color,       //PROPRIEDADES
                        fill2: this.data.color2
                    }
                });
                break;

            case 'label':
                enumeration.pushInstance({
                    objectName: 'label',
                    displayName: 'Título',
                    selector: null,
                    properties: {
                        show: this.data.showLabel,   //PROPRIEDADES
                        text: this.data.label,
                        text2: this.data.label2
                    }
                });
                break;



        }

        return enumeration.complete();
    }

    //Free up resources
    public destroy(): void {
        this.svg = null;
        this.svgTitle = this.svgSubtitle = this.svgBullet = null;
    }
}
}