material-avatar.js
;(function(win, doc) {
/**
* Main function to create material avatars
* @param element - The element(s) to apply the material avatar look to
*/
function MaterialAvatar(elements, options) {
if (!elements) {
throw(new Error('No elements selected/found'));
}
var _this = this;
this.options = {
colorPalette: [
'#1abc9c', '#2ecc71', '#3498db',
'#9b59b6', '#34495e', '#16a085',
'#27ae60', '#2980b9', '#8e44ad',
'#2c3e50', '#f1c40f', '#e67e22',
'#e74c3c', '#95a5a6', '#f39c12',
'#d35400', '#c0392b', '#bdc3c7',
'#7f8c8d'
],
fontFamily: 'Arial'
};
this.name = 'MaterialAvatar';
extend(_this.options, options);
this.elements = elements;
if (this.elements[0]) {
//Turn our HTMLCollection into an array so we can iterate through it.
this.elements = [].slice.call(this.elements);
this.elements.forEach(function(element){
element.avatar = new Avatar(element, _this.options);
});
} else {
this.elements.avatar = new Avatar(elements, _this.options);
}
}
MaterialAvatar.prototype.updateOptions = function(options) {
var _this = this;
if (options) {
this.options = options;
}
this.elements.forEach(function(element){
element.avatar.options = _this.options;
});
};
function Avatar(element, options) {
if (!element) {
throw(new Error('No element selected/found'));
}
var _this = this;
this.element = element;
this.options = options;
this.canvas = doc.createElement('canvas');
//Push our reflows to a new animation frame.
requestAnimationFrame(function() {
return _this.init();
});
}
Avatar.prototype.init = function(){
this.width = parseInt(this.element.offsetWidth, 10);
this.height = parseInt(this.element.offsetHeight, 10);
this.canvas.setAttribute('width', this.width);
this.canvas.setAttribute('height', this.width);
this.initials = this.getInitials();
this.fontSize = this.getFontSize();
this.render();
};
Avatar.prototype.render = function() {
this.backgroundColor = this.generateColor(this.initials.charCodeAt(0) - 65);
this.context = this.canvas.getContext('2d');
//Create our font styles
this.context.font = this.fontSize + 'px/0px ' + this.options.fontFamily;
this.context.textAlign = 'center';
//Decide what type of shape we should draw for the background
if (this.options) {
if(this.options.shape === 'circle') {
this._drawCircle();
} else {
this._drawSquare();
}
} else {
this._drawSquare();
}
//Create the color and add our initials
this.context.fillStyle = this.getTextColor();
this.context.fillText(
this.initials,
this.width/2,
(this.height / 2) + ((this.fontSize*0.68)/2)
);
//Remove the inner text and swap in the canvas elemnt
this.element.innerHTML = '';
this.element.appendChild(this.canvas);
};
//Creates circle background area
Avatar.prototype._drawCircle = function() {
var centerX = this.width / 2;
var centerY = this.height / 2;
var radius = this.width / 2;
this.context.beginPath();
this.context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
this.context.fillStyle = this.backgroundColor;
this.context.fill();
};
//Creates square background area
Avatar.prototype._drawSquare = function() {
this.context.fillStyle = this.backgroundColor;
this.context.fillRect(0, 0, this.width, this.height);
};
Avatar.prototype.getInitials = function () {
if (this.options.initials) {
return this.options.initials;
}
this.name = this.options.name || this.element.getAttribute('data-name') || this.element.innerHTML.trim();
var _nameSplit = this.name.split(' ');
var _initials;
this.element.setAttribute('data-name', this.name);
//Get initials from name
if (_nameSplit.length > 1) {
_initials = _nameSplit[0].charAt(0).toUpperCase() + _nameSplit[1].charAt(0).toUpperCase();
} else {
_initials = _nameSplit[0].charAt(0).toUpperCase();
}
return _initials;
};
Avatar.prototype.getFontSize = function () {
if (this.options.fontSize) {
if(typeof this.options.fontSize === 'function') {
return this.options.fontSize(this.height, this.initials.length);
}
return this.options.fontSize;
}
var _fontSize = this.height/((this.initials.length*0.5) + 1);
return _fontSize;
};
Avatar.prototype.getTextColor = function () {
//Override generated text color with a custom one
if (this.options.textColor) {
return this.options.textColor;
}
var _hexColor = this._hexToRgb(this.backgroundColor);
//Optional fallback incase our function returns null
if (!_hexColor) return '#222';
var _colorValue = (_hexColor.r * 299) + (_hexColor.g * 587) + (_hexColor.b * 114);
return (Math.round(_colorValue/1000) > 125) ? '#222' : '#fff';
};
Avatar.prototype._hexToRgb = function (hex) {
var _result;
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
hex = hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, function(m, r, g, b) {
return r + r + g + g + b + b;
});
_result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
if (_result) {
return {
r: parseInt(_result[1], 16),
g: parseInt(_result[2], 16),
b: parseInt(_result[3], 16)
};
}
return null;
};
Avatar.prototype.generateColor = function (index) {
if (this.options.backgroundColor) {
return this.options.backgroundColor;
}
//Uses the randomColor generator - https://github.com/davidmerfield/randomColor
if (typeof randomColor !== undefined) {
if (this.options && this.options.randomColor) {
return randomColor(this.options.randomColor);
} else if (!this.options) {
return randomColor();
}
}
return this.options.colorPalette[Math.abs(index) % this.options.colorPalette.length];
};
// export
win.MaterialAvatar = MaterialAvatar;
if (typeof jQuery !== 'undefined' && typeof jQuery.fn !== 'undefined') {
jQuery.fn.materialAvatar = function(options) {
return this.each(function() {
if (!jQuery.data(this, 'plugin_materialAvatar')) {
jQuery.data(this, 'plugin_materialAvatar', new MaterialAvatar(this, options));
}
});
};
}
function extend(_this, obj) {
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
_this[i] = obj[i];
}
}
}
})(window, document);