Last active
June 15, 2016 11:44
How the infogramVisual might look in one file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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