Skip to content

Instantly share code, notes, and snippets.

@AndyCross
Last active June 15, 2016 11:44
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AndyCross/999842907fa92d0aff69 to your computer and use it in GitHub Desktop.
Save AndyCross/999842907fa92d0aff69 to your computer and use it in GitHub Desktop.
How the infogramVisual might look in one file
module powerbi.visuals {
export interface ISvgComponent {
name;
attributes: [string[]];
children: ISvgComponent[];
}
export interface IInfoGraphData {
imageUris: string[];
categories: string[];
values: number[];
resolution: number[];
viewPort: number[];
shouldOverlayLabels: boolean;
title: string;
}
export interface ICoordinate {
x: number;
y: number;
}
export interface ImagesDataViewObjects extends DataViewObjects {
general: ImagesDataViewObject;
}
export interface ImagesDataViewObject extends DataViewObject {
imageUrls: string[];
}
export class InfoGraph implements IVisual {
public static capabilities: VisualCapabilities = {
dataRoles: [
{
name: 'Category',
kind: VisualDataRoleKind.Grouping,
},
{
name: 'Y',
kind: VisualDataRoleKind.Measure,
},
],
dataViewMappings: [{
categorical: {
categories: {
for: { in: 'Category' },
},
values: {
for: { in: 'Y' }
},
rowCount: { preferred: { max: 2 } }
},
}],
dataPoint: {
displayName: data.createDisplayNameGetter('Visual_DataPoint'),
properties: {
fill: {
displayName: data.createDisplayNameGetter('Visual_Fill'),
type: { fill: { solid: { color: true } } }
},
}
},
labels: {
displayName: data.createDisplayNameGetter('Visual_DataPointsLabels'),
properties: {
show: {
displayName: data.createDisplayNameGetter('Visual_Show'),
type: { bool: true }
},
color: {
displayName: data.createDisplayNameGetter('Visual_LabelsFill'),
type: { fill: { solid: { color: true } } }
},
labelDisplayUnits: {
displayName: data.createDisplayNameGetter('Visual_DisplayUnits'),
type: { formatting: { labelDisplayUnits: true } }
}
}
}
};
private imageUris: string[] = ["https://elastastorage.blob.core.windows.net/calendar.png",
"https://elastastorage.blob.core.windows.net/infogram.png"];
private resolution: InfographicResolution;
private svgContainer: D3.Selection;
private viewPort: IViewport;
public init = (options: VisualInitOptions) => {
this.viewPort = options.viewport;
this.svgContainer = d3.select(options.element.get(0))
.append("svg").attr("viewBox", "0 0 120 120")
.attr("preserveAspectRatio", "xMinYMid slice");
this.setContainerSizeOptions();
};
private setContainerSizeOptions() {
this.svgContainer
.attr("width", this.viewPort.width).attr("height", this.viewPort.height);
}
public update(options: VisualUpdateOptions) {
this.viewPort = options.viewport;
this.setContainerSizeOptions();
this.svgContainer.selectAll("*").remove();
var data = this.convert(options.dataViews[0]);
this.resolution = new InfographicResolution(100, 100,
data.resolution[0], data.resolution[1]);
this.draw(data);
}
private draw(data: IInfoGraphData) {
var resMap = this.resolution.getMap();
var cutOff = data.values[0] / (data.values[0] + data.values[1]);
var offset = this.resolution.getBoundary(cutOff);
var nth = 0;
resMap.forEach((row, rowIdx) => {
row.forEach((cell, idx) => {
var image = this.svgContainer.append("image")
.attr("x", cell.x).attr("y", cell.y)
.attr("width", this.resolution.getImageWidth()).attr("height", this.resolution.getImageHeight());
if (nth < offset)
image.attr("xlink:href", data.imageUris[0]);
else
image.attr("xlink:href", data.imageUris[1]);
nth++;
});
});
if (data.shouldOverlayLabels) {
this.svgContainer.append("text").attr("text-anchor", "start").attr("x", 20).attr("y", 20).attr("fill", "#999999")
.text(Math.round(data.values[0]));
this.svgContainer.append("text").attr("text-anchor", "end").attr("x", 80).attr("y", 80).attr("fill", "#999999")
.text(Math.round(data.values[1]));
};
}
private convert(data: DataView): IInfoGraphData {
if (data == null) return null;
var resolutionW = this.viewPort.width / 100;
var resolutionH = this.viewPort.height / 100;
if (data.categorical.categories == null) {
window.console.log('no categoricals');
return;
}
if (data.categorical.values == null) {
window.console.log('no values');
window.console.log(data);
return;
}
var dataModel: IInfoGraphData = {
imageUris: this.imageUris,
categories: data.categorical.categories[0].values.map((val) => { return <string>val; }),
values: data.categorical.values[0].values,
resolution: [resolutionW, resolutionH],
viewPort: [this.viewPort.width, this.viewPort.height],
shouldOverlayLabels: false,
title: "Comparing 1 Apple to 3 Oranges"
};
window.console.log(dataModel);
return dataModel;
}
};
export class InfographicResolution {
public width: number;
public height: number;
private viewPortWidth: number;
private viewPortHeight: number;
public constructor(viewPortWidth: number, viewPortHeight: number, width: number, height: number) {
this.width = width;
this.height = height;
this.viewPortWidth = viewPortWidth;
this.viewPortHeight = viewPortHeight;
}
public getImageWidth() {
return this.viewPortWidth / this.width;
}
public getImageHeight() {
return this.viewPortHeight / this.height;
}
public getBoundary(factor: number) {
var boundary = (this.width * this.height) * factor;
return boundary;
}
public getMap(): ICoordinate[][] {
var ret = [];
for (var i = 0; i < this.height; i++) {
var row = [];
for (var j = 0; j < this.width; j++) {
row.push(<ICoordinate> { x: j * this.getImageWidth(), y: i * this.getImageHeight() });
}
ret.push(row);
}
return ret;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment