-
-
Save spatney/7c54e692347cc5991fb9a1d17a983d3f to your computer and use it in GitHub Desktop.
This file contains hidden or 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 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