mirror of
https://github.com/wassname/CanvasTextWrapper.git
synced 2026-06-27 18:21:38 +08:00
v0.1.0
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
/*! CanvasTextWrapper (https://github.com/namniak/CanvasTextWrapper)
|
||||
* Version: 0.1.0
|
||||
*
|
||||
* MIT License (http://www.opensource.org/licenses/mit-license.html)
|
||||
* Copyright (c) 2014 Vadim Namniak
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
var defaultOptions = {
|
||||
font: '18px Arial, sans-serif',
|
||||
textAlign: 'left', // each line of text is aligned left
|
||||
verticalAlign: 'top', // text lines block is aligned top
|
||||
paddingX: 0, // zero px left & right text padding relative to canvas or parent
|
||||
paddingY: 0, // zero px top & bottom text padding relative to canvas or parent
|
||||
fitParent: false, // text is tested to fit canvas width
|
||||
lineBreak: 'auto' // text fills the element's (canvas or parent) width going to a new line on a whole word
|
||||
};
|
||||
|
||||
window.CanvasTextWrapper = function(canvas, text, opts) {
|
||||
|
||||
if (!(this instanceof CanvasTextWrapper)) {
|
||||
throw new TypeError('CanvasTextWrapper constructor failed. Use "new" keyword when instantiating.');
|
||||
}
|
||||
|
||||
this.canvas = canvas;
|
||||
this.text = text;
|
||||
|
||||
// set options to specified or default values
|
||||
for (var property in defaultOptions) {
|
||||
this[property] = (opts && opts[property]) ? opts[property] : defaultOptions[property];
|
||||
}
|
||||
|
||||
// extract font size
|
||||
this.lineHeight = parseInt(this.font.replace(/^\D+/g, ''), 10);
|
||||
|
||||
// validate all set properties
|
||||
this.validate();
|
||||
|
||||
// basic context settings
|
||||
this.context = this.canvas.getContext('2d');
|
||||
this.context.font = this.font;
|
||||
this.context.textBaseline = 'bottom';
|
||||
|
||||
this.drawText();
|
||||
};
|
||||
|
||||
CanvasTextWrapper.prototype = {
|
||||
|
||||
drawText: function() {
|
||||
var canvas = this.canvas;
|
||||
var context = canvas.getContext('2d');
|
||||
|
||||
var elementWidth = (this.fitParent === false) ? canvas.width : canvas.parentNode.clientWidth;
|
||||
var maxTextLength = elementWidth - (this.paddingX * 2);
|
||||
|
||||
var words = this.text.split(/\s+/);
|
||||
var lines = [];
|
||||
var textPos = {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
|
||||
this.checkWordsLength(context, words, maxTextLength);
|
||||
this.breakTextIntoLines(context, lines, words, maxTextLength);
|
||||
|
||||
// height of the broken down into lines text
|
||||
var textBlockHeight = lines.length * this.lineHeight;
|
||||
|
||||
// set vertical align for the whole text block
|
||||
this.setTextVerticalAlign(textPos, textBlockHeight);
|
||||
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
this.setTextHorizontalAlign(context, textPos, elementWidth, lines[i]);
|
||||
|
||||
textPos.y = parseInt(textPos.y) + parseInt(this.lineHeight);
|
||||
context.fillText(lines[i], textPos.x, textPos.y);
|
||||
}
|
||||
},
|
||||
|
||||
checkWordsLength: function(context, words, maxTextLength) {
|
||||
for (var i = 0; i < words.length; i++) {
|
||||
var testString = '';
|
||||
var tokenLen = context.measureText(words[i]).width;
|
||||
|
||||
// check if a word exceeds the element's width
|
||||
if (tokenLen > maxTextLength) {
|
||||
for (var k = 0; (context.measureText(testString + words[i][k]).width <= maxTextLength) && (k < words[i].length); k++) {
|
||||
testString += words[i][k];
|
||||
}
|
||||
|
||||
// break the word because it's too long
|
||||
var sliced = words[i].slice(0, k);
|
||||
var leftover = words[i].slice(k);
|
||||
words.splice(i, 1, sliced, leftover);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
breakTextIntoLines: function(context, lines, words, maxTextLength) {
|
||||
for (var i = 0, j = 0; i < words.length; j++) {
|
||||
lines[j] = '';
|
||||
|
||||
if (this.lineBreak === 'auto') {
|
||||
// put as many full words in a line as can fit element
|
||||
while ((context.measureText(lines[j] + words[i]).width <= maxTextLength) && (i < words.length)) {
|
||||
lines[j] += words[i] + ' ';
|
||||
i++;
|
||||
}
|
||||
lines[j] = lines[j].trim();
|
||||
} else if (this.lineBreak === 'word') {
|
||||
// put each next word in a new line
|
||||
lines[j] = words[i];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setTextHorizontalAlign: function(context, textPos, elementWidth, line) {
|
||||
if (this.textAlign === 'center') {
|
||||
textPos.x = (elementWidth - context.measureText(line).width) / 2;
|
||||
} else if (this.textAlign === 'right') {
|
||||
textPos.x = elementWidth - context.measureText(line).width - this.paddingX;
|
||||
} else {
|
||||
textPos.x = this.paddingX;
|
||||
}
|
||||
},
|
||||
|
||||
setTextVerticalAlign: function(textPos, textBlockHeight) {
|
||||
var elementHeight = (this.fitParent === false) ? this.canvas.height : this.canvas.parentNode.clientHeight;
|
||||
|
||||
if (this.verticalAlign === 'middle') {
|
||||
textPos.y = (elementHeight - textBlockHeight) / 2;
|
||||
} else if (this.verticalAlign === 'bottom') {
|
||||
textPos.y = elementHeight - textBlockHeight - this.paddingY;
|
||||
} else {
|
||||
textPos.y = this.paddingY;
|
||||
}
|
||||
},
|
||||
|
||||
validate: function() {
|
||||
if (!(this.canvas instanceof HTMLCanvasElement)) {
|
||||
throw new TypeError('From CanvasTextWrapper(): Element passed as the first parameter is not an instance of HTMLCanvasElement.');
|
||||
}
|
||||
if (typeof this.text !== 'string') {
|
||||
throw new TypeError('From CanvasTextWrapper(): The second, dedicated for the text, parameter must be a string.');
|
||||
}
|
||||
if (isNaN(this.lineHeight)) {
|
||||
throw new TypeError('From CanvasTextWrapper(): Cannot parse font size as an Integer. Check "font" property\'s value.');
|
||||
}
|
||||
if (this.textAlign !== 'left' && this.textAlign !== 'center' && this.textAlign !== 'right') {
|
||||
throw new TypeError('From CanvasTextWrapper(): Unsupported horizontal align value is used. Property "textAlign" can only be set to "left", "center", or "right".');
|
||||
}
|
||||
if (this.verticalAlign !== 'top' && this.verticalAlign !== 'middle' && this.verticalAlign !== 'bottom') {
|
||||
throw new TypeError('From CanvasTextWrapper(): Unsupported vertical align value is used. Property "verticalAlign" can only be set to "top", "middle", or "bottom".');
|
||||
}
|
||||
if (isNaN(this.paddingX)) {
|
||||
throw new TypeError('From CanvasTextWrapper(): Unsupported horizontal padding value is used. Property "paddingX" must be set to a number');
|
||||
}
|
||||
if (isNaN(this.paddingY)) {
|
||||
throw new TypeError('From CanvasTextWrapper(): Unsupported vertical padding value is used. Property "paddingY" must be set to a number.');
|
||||
}
|
||||
if (typeof this.fitParent !== 'boolean') {
|
||||
throw new TypeError('From CanvasTextWrapper(): Property "fitParent" must be set to a Boolean.');
|
||||
}
|
||||
if (this.lineBreak !== 'auto' && this.lineBreak !== 'word') {
|
||||
throw new TypeError('From CanvasTextWrapper(): Unsupported line break value is used. Property "lineBreak" can only be set to "auto", or "word".');
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
/*! CanvasTextWrapper (https://github.com/namniak/CanvasTextWrapper)
|
||||
* Version: 0.1.0
|
||||
*
|
||||
* MIT License (http://www.opensource.org/licenses/mit-license.html)
|
||||
* Copyright (c) 2014 Vadim Namniak
|
||||
*/
|
||||
!function(){"use strict";var a={font:"18px Arial, sans-serif",textAlign:"left",verticalAlign:"top",paddingX:0,paddingY:0,fitParent:!1,lineBreak:"auto"};window.CanvasTextWrapper=function(b,c,d){if(!(this instanceof CanvasTextWrapper))throw new TypeError('CanvasTextWrapper constructor failed. Use "new" keyword when instantiating.');this.canvas=b,this.text=c;for(var e in a)this[e]=d&&d[e]?d[e]:a[e];this.lineHeight=parseInt(this.font.replace(/^\D+/g,""),10),this.validate(),this.context=this.canvas.getContext("2d"),this.context.font=this.font,this.context.textBaseline="bottom",this.drawText()},CanvasTextWrapper.prototype={drawText:function(){var a=this.canvas,b=a.getContext("2d"),c=this.fitParent===!1?a.width:a.parentNode.clientWidth,d=c-2*this.paddingX,e=this.text.split(/\s+/),f=[],g={x:0,y:0};this.checkWordsLength(b,e,d),this.breakTextIntoLines(b,f,e,d);var h=f.length*this.lineHeight;this.setTextVerticalAlign(g,h);for(var i=0;i<f.length;i++)this.setTextHorizontalAlign(b,g,c,f[i]),g.y=parseInt(g.y)+parseInt(this.lineHeight),b.fillText(f[i],g.x,g.y)},checkWordsLength:function(a,b,c){for(var d=0;d<b.length;d++){var e="",f=a.measureText(b[d]).width;if(f>c){for(var g=0;a.measureText(e+b[d][g]).width<=c&&g<b[d].length;g++)e+=b[d][g];var h=b[d].slice(0,g),i=b[d].slice(g);b.splice(d,1,h,i)}}},breakTextIntoLines:function(a,b,c,d){for(var e=0,f=0;e<c.length;f++)if(b[f]="","auto"===this.lineBreak){for(;a.measureText(b[f]+c[e]).width<=d&&e<c.length;)b[f]+=c[e]+" ",e++;b[f]=b[f].trim()}else"word"===this.lineBreak&&(b[f]=c[e],e++)},setTextHorizontalAlign:function(a,b,c,d){b.x="center"===this.textAlign?(c-a.measureText(d).width)/2:"right"===this.textAlign?c-a.measureText(d).width-this.paddingX:this.paddingX},setTextVerticalAlign:function(a,b){var c=this.fitParent===!1?this.canvas.height:this.canvas.parentNode.clientHeight;a.y="middle"===this.verticalAlign?(c-b)/2:"bottom"===this.verticalAlign?c-b-this.paddingY:this.paddingY},validate:function(){if(!(this.canvas instanceof HTMLCanvasElement))throw new TypeError("From CanvasTextWrapper(): Element passed as the first parameter is not an instance of HTMLCanvasElement.");if("string"!=typeof this.text)throw new TypeError("From CanvasTextWrapper(): The second, dedicated for the text, parameter must be a string.");if(isNaN(this.lineHeight))throw new TypeError('From CanvasTextWrapper(): Cannot parse font size as an Integer. Check "font" property\'s value.');if("left"!==this.textAlign&&"center"!==this.textAlign&&"right"!==this.textAlign)throw new TypeError('From CanvasTextWrapper(): Unsupported horizontal align value is used. Property "textAlign" can only be set to "left", "center", or "right".');if("top"!==this.verticalAlign&&"middle"!==this.verticalAlign&&"bottom"!==this.verticalAlign)throw new TypeError('From CanvasTextWrapper(): Unsupported vertical align value is used. Property "verticalAlign" can only be set to "top", "middle", or "bottom".');if(isNaN(this.paddingX))throw new TypeError('From CanvasTextWrapper(): Unsupported horizontal padding value is used. Property "paddingX" must be set to a number');if(isNaN(this.paddingY))throw new TypeError('From CanvasTextWrapper(): Unsupported vertical padding value is used. Property "paddingY" must be set to a number.');if("boolean"!=typeof this.fitParent)throw new TypeError('From CanvasTextWrapper(): Property "fitParent" must be set to a Boolean.');if("auto"!==this.lineBreak&&"word"!==this.lineBreak)throw new TypeError('From CanvasTextWrapper(): Unsupported line break value is used. Property "lineBreak" can only be set to "auto", or "word".')}}}();
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "canvas-text-wrapper",
|
||||
"version": "0.1.0",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"**/*.log",
|
||||
"**/*.json",
|
||||
"Gruntfile.js",
|
||||
"examples",
|
||||
"node_modules",
|
||||
"README.md"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/namniak/CanvasTextWrapper.git"
|
||||
},
|
||||
"homepage": "http://namniak.github.io/CanvasTextWrapper/"
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "canvas-text-wrapper",
|
||||
"version": "0.1.0",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"**/*.log",
|
||||
"**/*.json",
|
||||
"Gruntfile.js",
|
||||
"examples",
|
||||
"node_modules",
|
||||
"README.md"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/namniak/CanvasTextWrapper.git"
|
||||
},
|
||||
"homepage": "http://namniak.github.io/CanvasTextWrapper/"
|
||||
}
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "canvas-text-wrapper",
|
||||
"description": "Javascript canvas text wrapper that automatically breaks the text into lines on a rule of your choice with available horizontal and vertical align options.",
|
||||
"version": "0.1.0",
|
||||
"license": "MIT",
|
||||
"main": "CanvasTextWrapper.min.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/namniak/CanvasTextWrapper"
|
||||
},
|
||||
"author": "Vadim Namniak <vnamnyak@gmail.com> (https://github.com/namniak)",
|
||||
"bugs": {
|
||||
"url": "https://github.com/namniak/CanvasTextWrapper/issues"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user