Simply add a 32x32 SVG as a DAX Measure
Set properties to Image URL
Add data fields and custom colors
import powerbi from "powerbi-visuals-api";
import IVisual = powerbi.extensibility.visual. IVisual;
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions; import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import DataView = powerbi.DataView;
import EnumerateVisualObjectInstancesOptions = powerbi.EnumerateVisualObjectInstancesOptions; import VisualObjectInstance = powerbi.VisualObjectInstance;
import {valueFormatter} from "powerbi-visuals-utils-formattingutils";
import {svg} from "d3";
export class Visual implements IVisual {
private target: HTMLElement;
private svgContBackgroundColor: string;
private svgColor: string;
private textColor: string;
private labelColor: string;
constructor(options: VisualConstructorOptions) { this.target = options.element;
}
public update(options: VisualUpdateOptions) {
const dataView: DataView = options.dataViews[0];
const measure = dataView.categorical.values[0].values[0] as number;
const svgMeasure = dataView.categorical.values[1]?.values[0] as string;
// Ensure we get the correct label for the measure
const measureColumn = dataView.metadata.columns.find(col => col.roles["measure"]); const label = measureColumn? measureColumn.displayName: "Measure"; const measureFormat = measureColumn? measureColumn.format: undefined;
const objects = dataView.metadata.objects;
// Set defaults
this.svgContBackgroundColor = objects && objects.svgSettings && objects.svgSettings.svgContBackgroundColor? (objects.svgSettings.svgContBackgroundColor as powerbi.Fill).solid.color: "#000000";
this.svgColor= objects && objects.svgSettings && objects.svgSettings.svgColor? (objects.svgSettings.svgColor as powerbi.Fill).solid.color: "#fff";
this.textColor = objects && objects.svgSettings && objects.svgSettings.textColor? (objects.svgSettings.textColor as powerbi.Fill).solid.color: "#000000";
this.labelColor = objects && objects.svgSettings && objects.svgSettings.labelColor? (objects.svgSettings.labelColor as powerbi.Fill).solid.color: "#808080";
//Create canvas
this.target.innerHTML = '';
this.target.style.display = 'flex';
this.target.style.flexWrap = 'nowrap';
this.target.style.alignItems = 'center';
this.target.style.justifyContent = 'center';
this.target.style.height='100%';
const card = document.createElement('div');
card.style.display = 'flex';
card.style.flexDirection = 'row';
card.style.alignItems = 'center'; card.style.padding="20px";
card.style.height="100%";
card.style.width = "100%";
card.style.gap = "25px";
//Label Container
const labelCont = document.createElement('div'); // labelCont.style.backgroundColor = "red";
labelCont.style.display = "flex";
labelCont.style.height="100px";
labelCont.style.flexDirection = "column";
labelCont.style.justifyContent="center"; labelCont.style.gap = "2.5px"; labelCont.style.fontSize = "16px";
//svg Container
const svgCont = document.createElement('div'); //svgCont.style.backgroundColor = "orange"; svgCont.style.height = "50px";
svgCont.style.width = "50px";
svgCont.style.display = "flex";
svgCont.style.justifyContent="center";
svgCont.style.alignItems = "center";
svgCont.style.borderRadius = "10px";
svgCont.style.backgroundColor = this.svgContBackgroundColor;
// Label
const labelElement = document.createElement('div'); labelElement.textContent = label.toUpperCase();
labelElement.style.letterSpacing="2px"; labelElement.style.fontSize="10.5px";
labelElement.style.color = this.labelColor;
// Measure
const measureElement = document.createElement('div');
measureElement.textContent = this.formatMeasure(measure, measureFormat); measureElement.style.color = this.textColor; measureElement.style.fontWeight = "bold";
// SVG
const svgElement = document.createElement('div'); svgElement.innerHTML = svgMeasure;
svgElement.style.display = "flex";
svgElement.style.justifyContent = "center"; svgElement.style.alignItems = "center";
// Apply the color to all SVG elements
const svgInner = svgElement.querySelector('svg'); if (svgInner) {
const elements = svgInner.querySelectorAll('*'); elements.forEach(element => {
const currentFill = element.getAttribute('fill');
const currentStroke = element.getAttribute('stroke');
if (currentFill && currentFill !== 'none' && currentFill !== 'transparent') {
element.setAttribute('fill', this.svgColor);
}
if (currentStroke && currentStroke !== 'none' && currentStroke !== 'transparent') {
element.setAttribute('stroke', this.svgColor);
}
});
}
labelCont.appendChild(labelElement);
labelCont.appendChild(measureElement);
svgCont.appendChild(svgElement);
card.appendChild(svgCont);
card.appendChild(labelCont);
this.target.appendChild(card);
}
private formatMeasure(measure: number, format: string): string{
const formatter = valueFormatter.create({ format });
return formatter.format(measure);
}
public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] { const instances: VisualObjectInstance[] = [];
switch (options.objectName) {
case 'svgSettings':
instances.push({
objectName: 'svgSettings',
properties: {
svgColor: this.svgColor,
textColor: this.textColor,
labelColor: this.labelColor,
svgContBackgroundColor: this.svgContBackgroundColor,
},
selector: null
});
break;
}
return instances;
}
}
{
"dataRoles":[
{
"name": "measure",
"kind": "Measure",
"displayName": "Measure"
},
{
"name": "svgMeasure",
"kind": "Measure",
"displayName": "SVG Measure"
}
],
"dataViewMappings": [
{
"conditions": [
{
"measure": { "max":1},
"svgMeasure": { "max":1}
}
],
"categorical": {
"values": {
"select":[
{"bind": { "to": "measure"}},
{"bind": { "to": "svgMeasure"}}
]
}
}
}
],
"objects": {
"general": {
"displayName": "General",
"properties":{
"label":{
"displayName": "Label",
"type":{"text": true }
}
}
},
"svgSettings": {
"displayName": "SVG Settings",
"properties":{
"svgContBackgroundColor": {
"displayName": "SVG Background Color",
"type":{"fill": { "solid": { "color": true }}}
},
"svgColor": {
"displayName": "SVG Color",
"type":{"fill": { "solid": { "color": true }}}
},
"textColor": {
"displayName":"Text Color",
"type":{"fill": { "solid": { "color": true }}}
},
"labelColor": {
"displayName": "Label Color",
"type": { "fill": { "solid": { "color": true }}}
}
}
}
},
"privileges": []
}