First try at power BI Custom graphics, pardon me for some inconsistencies.
I'm trying to edit the Bullet Chart "BulletChartbySQLBI", so that it can meet my needs, but i cant seem to figure out why that the styling applied in dev. tools preview does not stay when importing to the dashboard, colors and text formatting.
+ Question
Another problem that i have is that i can't seem to place the title on top of the main bar, so that i can place the text there, i tried to use css styling, with no success, and then tried to change the way that the svg is drawn so that the text appears on top, but also with no success.
Code developed in: https://app.powerbi.com/devTools
Data Preview: SimpleGauge(Single+Categorical)
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;
}
}
}
If someone could enlighten me, i would appreciate it, Cheers
So after some hard thinking, i figure it out.
For the first part, the problem was that, power bi does not let you upload the same graph with some modifications, i had to change the naming in the code so that it'll assume the different graph.
The second part was the tricky one, after moving around i found that the codes always broke, so i thought that calling the title again would do the trick, so it did! I hidden the other title and called again after the bar is drawn.
Revised code:
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;
}
}
}