Skip to content

Instantly share code, notes, and snippets.

@spatney
Last active May 10, 2016 06:34
Show Gist options
  • Save spatney/7c54e692347cc5991fb9a1d17a983d3f to your computer and use it in GitHub Desktop.
Save spatney/7c54e692347cc5991fb9a1d17a983d3f to your computer and use it in GitHub Desktop.
module powerbi.visuals {
export class Meme implements IVisual {
public static capabilities: VisualCapabilities = {
suppressDefaultTitle: true,
objects: {
text: {
displayName: 'Properties',
properties: {
topText: {
displayName: 'Top Text',
type: { text: true }
},
bottomText: {
displayName: 'Bottom Text',
type: { text: true }
},
url: {
displayName: 'URL',
type: { text: true }
},
fill: {
displayName: 'Fill',
type: { fill: { solid: { color: true } } }
}
},
},
}
};
private canvas;
private context;
private image;
private dataView: DataView;
private lastUrl = "";
public init(options: VisualInitOptions): void {
var canvas = this.canvas = document.createElement('canvas');
this.context = canvas.getContext('2d');
options.element.append($(canvas));
}
private getValue<T>(dataView: DataView, propName: string, defaultValue: T): T {
if (dataView && dataView.metadata.objects) {
var general = <DataViewObject>dataView.metadata.objects['text'];
if (general) {
var value = <T>general[propName];
if (value !== undefined) {
return value;
}
}
}
return defaultValue;
}
public update(options: VisualUpdateOptions) {
var dataView = null;
if (options.dataViews && options.dataViews.length > 0) {
dataView = this.dataView = options.dataViews[0];
}
this.canvas.width = options.viewport.width;
this.canvas.height = options.viewport.height;
var url = this.getValue<string>(dataView, 'url', 'http://img11.deviantart.net/f4a5/i/2015/108/f/c/philosoraptor_yoshi_by_triples_art-d7bifgp.jpg');
var top = this.getValue<string>(dataView, 'topText', 'Knock knock');
var bottom = this.getValue<string>(dataView, 'bottomText', '*Silence*');
if (this.lastUrl != url) {
this.lastUrl = url;
this.drawAsync(top, bottom, url);
} else {
this.drawMeme(top, bottom);
}
}
private drawAsync(top, bottom, url, fillStyle = 'white') {
var canvas = this.canvas;
var imageUrl = url;
var src = imageUrl;
var image = new Image();
image.src = src;
this.image = image;
image.onload = () => {
this.drawMeme(top, bottom, fillStyle);
}
}
private drawMeme(top, bottom, fillStyle = 'white') {
this.drawImage();
this.drawText(top, 0, fillStyle);
this.drawText(bottom, 1, fillStyle);
}
private drawImage() {
var image = this.image;
var canvas = this.canvas;
this.context.drawImage(image, 0, 0, canvas.width, canvas.height);
}
private drawText(text, topOrBottom: number, fillStyle, y?: number) {
var canvas = this.canvas;
var context = this.context;
context.fillStyle = fillStyle;
context.strokeStyle = 'black';
context.lineWidth = 2;
var fontSize = (canvas.height / 8);
context.font = fontSize + 'px Impact';
context.textAlign = 'center';
topOrBottom = topOrBottom || 0;
var fontSize = (canvas.height / 8);
var x = canvas.width / 2;
if (typeof y === 'undefined') {
y = fontSize;
if (topOrBottom === 1)
y = canvas.height - 10;
}
if (context.measureText(text).width > (canvas.width * 1.1)) {
var words = text.split(' ');
var wordsLength = words.length;
if (topOrBottom === 0) {
var i = wordsLength;
while (i--) {
var justThis = words.slice(0, i).join(' ');
if (context.measureText(justThis).width < (canvas.width * 1.0)) {
this.drawText(justThis, topOrBottom, fillStyle, y);
this.drawText(words.slice(i, wordsLength).join(' '), topOrBottom, fillStyle, y + fontSize);
return;
}
}
}
else if (topOrBottom === 1) {
for (var I = 0; i < wordsLength; i++) {
var justThis = words.slice(i, wordsLength).join(' ');
if (context.measureText(justThis).width < (canvas.width * 1.0)) {
this.drawText(justThis, topOrBottom, y);
this.drawText(words.slice(0, i).join(' '), topOrBottom, y - fontSize);
return;
}
}
}
}
context.fillText(text, x, y, canvas.width * .9);
context.strokeText(text, x, y, canvas.width * .9);
}
public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] {
var instances: VisualObjectInstance[] = [];
switch (options.objectName) {
case 'text':
var outerLine: VisualObjectInstance = {
objectName: 'text',
displayName: 'Properties',
selector: null,
properties: {
topText: this.getValue(this.dataView, 'topText', 'Knock knock'),
bottomText: this.getValue(this.dataView, 'bottomText', '*Silence*'),
url: this.getValue(this.dataView, 'url', 'http://img11.deviantart.net/f4a5/i/2015/108/f/c/philosoraptor_yoshi_by_triples_art-d7bifgp.jpg'),
}
};
instances.push(outerLine);
break;
}
return instances;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment