43 Commits

Author SHA1 Message Date
Vadim Namniak 66da3411c3 updated to v0.3.1 2015-05-05 17:14:54 -04:00
Vadim Namniak a1ba88647e Merge pull request #6 from steoo/master
Fixed bug with numeric value of font-weight
2015-05-05 13:28:55 -04:00
Steoo 13abe2526c Fixed bug with numeric value of font-weight 2015-05-04 22:30:48 +02:00
Vadim Namniak ffcaf3425c Update README.md 2015-01-25 15:27:49 -05:00
Vadim Namniak 365bd4e24c Update README.md 2015-01-25 15:27:19 -05:00
Vadim Namniak 96001e64df Update README.md 2015-01-25 15:26:14 -05:00
Vadim Namniak 49fea5c2bb Update README.md 2015-01-25 15:23:53 -05:00
Vadim Namniak 020d1dee52 Update README.md 2015-01-25 15:22:28 -05:00
Vadim Namniak c75fae5ea0 Update README.md 2015-01-25 15:18:39 -05:00
Vadim Namniak 9b2c460a69 v0.3.0 justifyLines, lineHeight and allowNewLine 2015-01-25 14:53:51 -05:00
Vadim Namniak 055cdaeb13 version updates 2014-10-12 11:04:53 -04:00
Vadim Namniak cfdccc0c61 version update 2014-10-12 11:03:27 -04:00
Vadim Namniak bb707cd508 Update README.md 2014-10-12 10:49:45 -04:00
Vadim Namniak 8dda2cb645 Update README.md 2014-10-12 10:37:29 -04:00
Vadim Namniak 7e3d425769 Update README.md 2014-10-12 01:57:56 -04:00
Vadim Namniak 6e03f629ce Merge pull request #3 from gmjosack/master
Add the ability to stroke text.
2014-10-12 01:32:44 -04:00
Gary M. Josack ebb8908812 Add the ability to stroke text.
This is useful in scenarios where a background is many colors.
2014-10-11 21:33:06 -07:00
Vadim Namniak 30c326ed36 Update README.md 2014-10-08 23:03:57 -04:00
Vadim Namniak f464af8c5d context fixes + default font size added 2014-10-08 22:53:50 -04:00
Vadim Namniak 5b7a7f9cfe Merge pull request #2 from peeinears/master
Added sizeToFill option for resizing text to fill its padded container
2014-10-08 21:34:52 -04:00
Ian Pearce 45a2b83782 Do not break text when sizeToFill is on 2014-10-06 12:15:49 +08:00
Ian Pearce 43c8775359 Run grunt 2014-10-06 03:07:23 +08:00
Ian Pearce 4924f6f06a Slightly DRYer 2014-10-06 03:05:27 +08:00
Ian Pearce 60c009b432 Added sizeToFill option for resizing text to fill its container 2014-10-06 03:00:53 +08:00
Vadim Namniak e5ad6e9e22 Update README.md 2014-06-27 09:11:06 -04:00
Vadim Namniak b6eb83cbbc Update README.md 2014-06-27 09:10:44 -04:00
Vadim Namniak ba409c2f9a Update README.md 2014-06-27 09:10:31 -04:00
Vadim Namniak 9b14e6bc20 Update README.md 2014-06-27 09:09:55 -04:00
namniak ab5ee97446 gitignore update 2014-06-27 02:53:02 -04:00
namniak 68f08dccf0 gitignore update 2014-06-27 02:52:23 -04:00
namniak b86396f979 v0.1.1 2014-06-27 02:48:39 -04:00
Vadim Namniak 53f765b0e8 Update README.md 2014-06-27 02:35:40 -04:00
Vadim Namniak 4d7e9ed627 Delete package.json~ 2014-06-27 02:30:41 -04:00
Vadim Namniak 68a9da4826 Delete .npmignore~ 2014-06-27 02:30:28 -04:00
namniak 9534bbbdf7 added bower & npm repositories 2014-06-27 02:29:15 -04:00
Vadim Namniak d4566c71cf Update README.md 2014-06-27 02:16:45 -04:00
Vadim Namniak c5464dab42 Update README.md 2014-06-27 02:11:03 -04:00
Vadim Namniak c18627bd6a Delete bower.json~ 2014-06-27 01:44:38 -04:00
namniak a884a840db v0.1.0 2014-06-27 01:43:51 -04:00
Vadim Namniak c53c170d5c Delete bower.json 2014-06-27 01:07:49 -04:00
Vadim Namniak 19d9b83fea Delete package.json 2014-06-27 01:07:42 -04:00
Vadim Namniak 2361b45226 Delete CanvasTextWrapper.min.js 2014-06-27 01:07:30 -04:00
Vadim Namniak f2f142e81b Delete CanvasTextWrapper.js 2014-06-27 01:07:18 -04:00
14 changed files with 347 additions and 768 deletions
+2
View File
@@ -0,0 +1,2 @@
examples/
.idea/
+3
View File
@@ -0,0 +1,3 @@
node_modules
examples
bower.json
+255 -139
View File
@@ -1,172 +1,288 @@
/*! CanvasTextWrapper (https://github.com/namniak/CanvasTextWrapper)
* Version: 0.1.0
*
/*! CanvasTextWrapper
* https://github.com/namniak/CanvasTextWrapper
* Version: 0.3.0
* MIT License (http://www.opensource.org/licenses/mit-license.html)
* Copyright (c) 2014 Vadim Namniak
*/
(function() {
'use strict';
'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
};
var EL_WIDTH,EL_HEIGHT,MAX_TXT_WIDTH,MAX_TXT_HEIGHT;
window.CanvasTextWrapper = function(canvas, text, opts) {
var defaults = {
font: '18px Arial, sans-serif',
sizeToFill: false, // text is resized to fill the container (given font size is ignored)
lineHeight: 1, // default line height equivalent of '100%'
allowNewLine: true, // breaks text on every new line character '\n'
lineBreak: 'auto', // text fills the element's (canvas or parent) width going to a new line on a whole word
textAlign: 'left', // each line of text is aligned left
verticalAlign: 'top', // text lines block is aligned top
justifyLines: false, // lines are not justified
paddingX: 0, // 0px left & right text padding relatively to canvas or its container
paddingY: 0, // 0px top & bottom text padding relatively to canvas or its container
fitParent: false, // text is set to fit canvas width
strokeText: false // text is stroked according to context configuration
};
if (!(this instanceof CanvasTextWrapper)) {
throw new TypeError('CanvasTextWrapper constructor failed. Use "new" keyword when instantiating.');
}
var CanvasTextWrapper = function(canvas,text,options) {
if (!(this instanceof CanvasTextWrapper)) {
return new CanvasTextWrapper(canvas,text,options);
}
this.canvas = canvas;
this.text = text;
this.canvas = canvas;
this.text = text;
this.context = this.canvas.getContext('2d');
this.context.font = this.font;
this.context.textBaseline = 'bottom';
// set options to specified or default values
for (var property in defaultOptions) {
this[property] = (opts && opts[property]) ? opts[property] : defaultOptions[property];
}
for (var property in defaults) {
if (defaults.hasOwnProperty(property)) {
this[property] = (options && options[property]) ? options[property] : defaults[property];
}
}
// extract font size
this.lineHeight = parseInt(this.font.replace(/^\D+/g, ''), 10);
EL_WIDTH = (this.fitParent === false) ? this.canvas.width : this.canvas.parentNode.clientWidth;
EL_HEIGHT = (this.fitParent === false) ? this.canvas.height : this.canvas.parentNode.clientHeight;
MAX_TXT_WIDTH = EL_WIDTH - (this.paddingX * 2);
MAX_TXT_HEIGHT = EL_HEIGHT - (this.paddingY * 2);
// validate all set properties
this.validate();
this._init();
};
// basic context settings
this.context = this.canvas.getContext('2d');
this.context.font = this.font;
this.context.textBaseline = 'bottom';
CanvasTextWrapper.prototype = {
_init: function() {
/* Substituting this line that causing a bug with font-weight numeric values */
//this.fontSize = parseInt(this.font.replace(/^\D+/g,''),10) || 18;
this.drawText();
};
/* This line allow font values like : "italic 500 25px" to preserve both numeric a literal value of font-weight*/
this.fontSize = this.font.match(/\d+(px|em|\%)/g) ? +this.font.match(/\d+(px|em|\%)/g)[0].match(/\d+/g) : 18;
CanvasTextWrapper.prototype = {
this.textBlockHeight = 0;
this.lines = [];
this.newLineIndexes = [];
this.textPos = {x: 0,y: 0};
drawText: function() {
var canvas = this.canvas;
var context = canvas.getContext('2d');
this._setFont(this.fontSize);
this._setLineHeight();
this._validate();
this._render();
},
var elementWidth = (this.fitParent === false) ? canvas.width : canvas.parentNode.clientWidth;
var maxTextLength = elementWidth - (this.paddingX * 2);
_render: function() {
if (this.sizeToFill) {
var numWords = this.text.trim().split(/\s+/).length;
var fontSize = 0;
var words = this.text.split(/\s+/);
var lines = [];
var textPos = {
x: 0,
y: 0
};
do {
this._setFont(++fontSize);
this.lineHeight = this.fontSize;
this._wrap();
} while (this.textBlockHeight < MAX_TXT_HEIGHT && (this.lines.join(' ').split(/\s+/).length == numWords));
this.checkWordsLength(context, words, maxTextLength);
this.breakTextIntoLines(context, lines, words, maxTextLength);
this._setFont(--fontSize);
this.lineHeight = this.fontSize;
} else {
this._wrap();
}
// height of the broken down into lines text
var textBlockHeight = lines.length * this.lineHeight;
if (this.justifyLines && this.lineBreak === 'auto') {
this._justify();
}
// set vertical align for the whole text block
this.setTextVerticalAlign(textPos, textBlockHeight);
this._setAlignY();
this._drawText();
},
for (var i = 0; i < lines.length; i++) {
this.setTextHorizontalAlign(context, textPos, elementWidth, lines[i]);
_setFont: function(fontSize) {
var fontParts = (!this.sizeToFill) ? this.font.split(/\b\d+px\b/i) : this.context.font.split(/\b\d+px\b/i);
this.context.font = fontParts[0] + fontSize + 'px' + fontParts[1];
this.fontSize = fontSize;
},
textPos.y = parseInt(textPos.y) + parseInt(this.lineHeight);
context.fillText(lines[i], textPos.x, textPos.y);
}
},
_setLineHeight: function() {
if (!isNaN(this.lineHeight)) {
this.lineHeight = this.fontSize * this.lineHeight;
} else if (this.lineHeight.toString().indexOf('px') !== -1) {
this.lineHeight = parseInt(this.lineHeight);
} else if (this.lineHeight.toString().indexOf('%') !== -1) {
this.lineHeight = (parseInt(this.lineHeight) / 100) * this.fontSize;
}
},
checkWordsLength: function(context, words, maxTextLength) {
for (var i = 0; i < words.length; i++) {
var testString = '';
var tokenLen = context.measureText(words[i]).width;
_wrap: function() {
if (this.allowNewLine) {
var newLines = this.text.trim().split('\n');
for (var i = 0,idx = 0; i < newLines.length - 1; i++) {
idx += newLines[i].trim().split(/\s+/).length;
this.newLineIndexes.push(idx)
}
}
// 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];
}
var words = this.text.trim().split(/\s+/);
this._checkLength(words);
this._breakText(words);
// 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);
}
}
},
this.textBlockHeight = this.lines.length * this.lineHeight;
},
breakTextIntoLines: function(context, lines, words, maxTextLength) {
for (var i = 0, j = 0; i < words.length; j++) {
lines[j] = '';
_checkLength: function(words) {
var testString,tokenLen,sliced,leftover;
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++;
}
}
},
for (var i = 0; i < words.length; i++) {
testString = '';
tokenLen = this.context.measureText(words[i]).width;
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;
}
},
if (tokenLen > MAX_TXT_WIDTH) {
for (var k = 0; (this.context.measureText(testString + words[i][k]).width <= MAX_TXT_WIDTH) && (k < words[i].length); k++) {
testString += words[i][k];
}
setTextVerticalAlign: function(textPos, textBlockHeight) {
var elementHeight = (this.fitParent === false) ? this.canvas.height : this.canvas.parentNode.clientHeight;
sliced = words[i].slice(0,k);
leftover = words[i].slice(k);
words.splice(i,1,sliced,leftover);
}
}
},
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;
}
},
_breakText: function(words) {
for (var i = 0,j = 0; i < words.length; j++) {
this.lines[j] = '';
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".');
}
}
};
if (this.lineBreak === 'auto') {
while ((this.context.measureText(this.lines[j] + words[i]).width <= MAX_TXT_WIDTH) && (i < words.length)) {
this.lines[j] += words[i] + ' ';
i++;
if (this.allowNewLine) {
for (var k = 0; k < this.newLineIndexes.length; k++) {
if (this.newLineIndexes[k] === i) {
j++;
this.lines[j] = '';
break;
}
}
}
}
this.lines[j] = this.lines[j].trim();
} else {
this.lines[j] = words[i];
i++;
}
}
},
_justify: function() {
var maxLen,longestLineIndex,tokenLen;
for (var i = 0; i < this.lines.length; i++) {
tokenLen = this.context.measureText(this.lines[i]).width;
if (!maxLen || tokenLen > maxLen) {
maxLen = tokenLen;
longestLineIndex = i;
}
}
// fill lines with extra spaces
var numWords,spaceLength,numOfSpaces,num,filler;
var delimiter = '\u200A';
for (i = 0; i < this.lines.length; i++) {
if (i === longestLineIndex) continue;
numWords = this.lines[i].trim().split(/\s+/).length;
if (numWords <= 1) continue;
this.lines[i] = this.lines[i].trim().split(/\s+/).join(delimiter);
spaceLength = this.context.measureText(delimiter).width;
numOfSpaces = (maxLen - this.context.measureText(this.lines[i]).width) / spaceLength;
num = numOfSpaces / (numWords - 1);
filler = '';
for (var j = 0; j < num; j++) {
filler += delimiter;
}
this.lines[i] = this.lines[i].trim().split(delimiter).join(filler);
//console.log('numWords:', numWords, 'numOfSpaces:', numOfSpaces, 'num:', num);
}
},
_drawText: function() {
for (var i = 0; i < this.lines.length; i++) {
this._setAlignX(this.lines[i]);
this.textPos.y = parseInt(this.textPos.y) + this.lineHeight;
this.context.fillText(this.lines[i],this.textPos.x,this.textPos.y);
if (this.strokeText) {
this.context.strokeText(this.lines[i],this.textPos.x,this.textPos.y);
}
}
},
_setAlignX: function(line) {
if (this.textAlign == 'center') {
this.textPos.x = (EL_WIDTH - this.context.measureText(line).width) / 2;
} else if (this.textAlign == 'right') {
this.textPos.x = EL_WIDTH - this.context.measureText(line).width - this.paddingX;
} else {
this.textPos.x = this.paddingX;
}
},
_setAlignY: function() {
if (this.verticalAlign == 'middle') {
this.textPos.y = (EL_HEIGHT - this.textBlockHeight) / 2;
} else if (this.verticalAlign == 'bottom') {
this.textPos.y = EL_HEIGHT - this.textBlockHeight - this.paddingY;
} else {
this.textPos.y = this.paddingY;
}
},
_validate: function() {
if (!(this.canvas instanceof HTMLCanvasElement))
throw new TypeError('The first parameter must be an instance of HTMLCanvasElement.');
if (typeof this.text !== 'string')
throw new TypeError('The second parameter must be a string.');
if (isNaN(this.fontSize))
throw new TypeError('Cannot parse "font".');
if (isNaN(this.lineHeight))
throw new TypeError('Cannot parse "lineHeight".');
if (this.textAlign.toLocaleLowerCase() !== 'left' && this.textAlign.toLocaleLowerCase() !== 'center' && this.textAlign.toLocaleLowerCase() !== 'right')
throw new TypeError('Property "textAlign" must be set to either "left", "center", or "right".');
if (this.verticalAlign.toLocaleLowerCase() !== 'top' && this.verticalAlign.toLocaleLowerCase() !== 'middle' && this.verticalAlign.toLocaleLowerCase() !== 'bottom')
throw new TypeError('Property "verticalAlign" must be set to either "top", "middle", or "bottom".');
if (typeof this.justifyLines !== 'boolean')
throw new TypeError('Property "justifyLines" must be set to a Boolean.');
if (isNaN(this.paddingX))
throw new TypeError('Property "paddingX" must be set to a Number.');
if (isNaN(this.paddingY))
throw new TypeError('Property "paddingY" must be set to a Number.');
if (typeof this.fitParent !== 'boolean')
throw new TypeError('Property "fitParent" must be set to a Boolean.');
if (this.lineBreak.toLocaleLowerCase() !== 'auto' && this.lineBreak.toLocaleLowerCase() !== 'word')
throw new TypeError('Property "lineBreak" must be set to either "auto" or "word".');
if (typeof this.sizeToFill !== 'boolean')
throw new TypeError('Property "sizeToFill" must be set to a Boolean.');
if (typeof this.strokeText !== 'boolean')
throw new TypeError('Property "strokeText" must be set to a Boolean.');
}
};
window.CanvasTextWrapper = CanvasTextWrapper;
})();
+4 -4
View File
File diff suppressed because one or more lines are too long
+63
View File
@@ -1,2 +1,65 @@
CanvasTextWrapper
=================
##Syntax
```
new CanvasTextWrapper(HTMLCanvasElement, String [, options]);
```
```options``` - is an object with the following available properties and values:
- ```font:``` (String) - text style that includes font size in px, font weight, font family, etc. Similar to CSS font shorthand property
- ```lineHeight:``` (String or Number) - Number means n times font size where 1 is equivalent to '100%'. Also the property can be set in "%" or "px" using String
- ```textAlign: "left" | "center" | "right"``` - horizontal alignment of each line
- ```verticalAlign: "top" | "middle" | "bottom"``` - vertical alignment of the whole text block
- ```paddingX:``` (Number) - horizontal padding (in px) set equally on both, left and right sides
- ```paddingY:``` (Number) - vertical padding (in px) set equally on both, top and bottom sides
- ```fitParent:``` (Boolean) - if enabled, text will fit canvas container's width instead of canvas own width
- ```lineBreak: "auto" | "word"``` - text split rule. When using ```"auto"```, text goes to a next line on a whole word when there's no more room. If ```"word"``` is set as value, each next word will be placed on a new line.
- ```sizeToFill:``` (Boolean) - ignore given font size and line height and resize text to fill its padded container
- ```strokeText:``` (Boolean) - outline text based on context configuration
- ```justifyLines:``` (Boolean) - if enabled, all lines match the same width with flexed spaces between words (one-word lines are ignored).
- ```allowNewLine:``` (Boolean) if enabled, the text breaks on every new line character "\n" otherwise it'll be considered as a space
NOTE: if a single word is too long to fit the width with specified font size, it will break on any letter unless ```sizeToFill``` option is enabled.
##Defaults
```
{
font: "18px Arial, sans-serif",
lineHeight: 1,
textAlign: "left",
verticalAlign: "top",
paddingX: 0,
paddingY: 0,
fitParent: false,
lineBreak: "auto",
strokeText: false
sizeToFill: false,
allowNewLine: true,
justifyLines: false
}
```
##Usage
Configure context settings properties such as "fillStyle", "lineWidth" or "strokeStyle" before using CanvasTextWrapper like so:
```
var canvas = document.getElementById("#canvasText");
canvas.width = 200;
canvas.height = 200;
context = canvas.getContext("2d");
context.lineWidth = 2;
context.strokeStyle = "#ff0000";
CanvasTextWrapper(canvas,"Hello"); //default options will apply
```
##Examples
http://namniak.github.io/CanvasTextWrapper/
##Installation
```
bower install canvas-text-wrapper
npm install canvas-text-wrapper
```
+16 -12
View File
@@ -1,14 +1,18 @@
{
"name": "canvas-text-wrapper",
"version": "0.1.0",
"ignore": [
"**/.*",
"**/*.log",
"**/*.json",
"Gruntfile.js",
"examples",
"node_modules",
"README.md"
],
"homepage": "https://github.com/namniak/CanvasTextWrapper.git"
"name": "canvas-text-wrapper",
"version": "0.3.1",
"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/"
}
-48
View File
@@ -1,48 +0,0 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
-136
View File
@@ -1,136 +0,0 @@
body {
width: 960px;
margin: auto;
font-family: 'Open Sans', sans-serif;
color: #fff;
}
div, header, footer, article {
box-sizing: border-box;
}
header, footer, article {
width: 930px;
margin: auto;
background-color: #0D9F69;
padding: 20px;
}
header {
font-size: 60px;
font-weight: 700;
}
.description {
width: 800px;
margin-top: 20px;
font-size: 22px;
font-weight: normal;
}
footer {
margin-top: 40px;
}
a {
font-size: 20px;
font-weight: normal;
color: #fff;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
article {
border-top: 1px solid #fff;
}
.white-block {
display: table-cell;
height: 30px;
padding: 20px;
vertical-align: middle;
background-color: #fff;
font-weight: 100;
color: #0D9F69;
line-height: 120%;
}
p {
margin: 10px 0;
line-height: 120%;
}
h2 {
font-size: 30px;
}
h6 {
font-weight: 700;
text-decoration: underline;
display: inline;
}
.syntax {
padding: 10px 10px 0 20px;
}
.syntax > li {
list-style: none;
margin-bottom: 15px;
}
.values li {
text-indent: 20px;
list-style: inside circle;
line-height: 120%;
}
section {
margin-top: 40px;
}
section > div {
display: inline-block;
position: relative;
width: 450px;
margin: 15px;
border: 1px solid #0D9F69;
overflow: hidden;
}
section h2 {
color: #0D9F69;
text-indent: 30px;
margin-bottom: 20px;
}
section > div div {
width: 100%;
height: 200px;
background-color: #0D9F69;
margin-top: 250px;
padding: 20px;
}
canvas, img {
position: absolute;
top: 0;
left: 0;
}
img {
width: 100%;
z-index: -1;
}
span {
margin-left: 20px;
}
span, .emph {
font-weight: 600;
display: inline;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

-125
View File
@@ -1,125 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,700,600' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/styles.css">
<script src="js/CanvasTextWrapper.js"></script>
<script src="js/options.js"></script>
<script src="js/examples.js"></script>
<title>CanvasTextWrapper.js</title>
</head>
<body>
<header>
<p>CanvasTextWrapper.js</p>
<p class="description">
JavaScript canvas text wrapper that automatically splits a string into lines on specified rule with
optional alignments and padding.
</p>
</header>
<article>
<h2>Syntax:</h2><br/>
<p class="white-block">new CanvasTextWrapper(HTMLCanvasElement, String [, Options]);</p><br/>
<div>
<div class="emph">OPTIONS</div>
- is a JavaScript object with the following available properties and values:
</div>
<ul class="syntax">
<li>
<div class="emph">font</div>
(String) - text style that includes font size, family, etc. specified similarly to CSS
font shorthand property
</li>
<li>
<div class="emph">textAlign</div>
(String) - horizontal alignment that applies for each line
<ul class="values">
<li>"left"</li>
<li>"center"</li>
<li>"right"</li>
</ul>
</li>
<li>
<div class="emph">verticalAlign</div>
(String) - vertical alignment that applies on a whole block of text
<ul class="values">
<li>"top"</li>
<li>"middle"</li>
<li>"bottom"</li>
</ul>
</li>
<li>
<div class="emph">paddingX</div>
(Number) - horizontal padding in pixels set equally on both, left and right sides of
the element
</li>
<li>
<div class="emph">paddingY</div>
(Number) - vertical padding in pixels set equally on both, top and bottom sides of the element
</li>
<li>
<div class="emph">fitParent</div>
(Boolean) - parameter that controls which element to fit
<ul class="values">
<li>true - fit canvas parent's width instead of canvas own width</li>
<li>false - fit canvas width</li>
</ul>
</li>
<li>
<div class="emph">lineBreak</div>
(String) - text split rule
<ul class="values">
<li>"auto" - text fills the element's width going to a new line on a whole word when no more space</li>
<li>"word" - each next word will be placed on a new line</li>
</ul>
<p>
NOTE: if a single word is too long to fit the width with specified font size, it will be broken into as
many lines as required on any letter without specific word breaking rule.
</p>
</li>
</ul>
</article>
<article>
<h2>Defaults & Usage:</h2><br/>
<p>The default options object which values will be used if a property is not specified or no object is passed:</p>
<p class="white-block">
{&nbsp;font: "18px Arial, sans-serif",<br/>
&nbsp;&nbsp;&nbsp;textAlign: "left",<br/>
&nbsp;&nbsp;&nbsp;verticalAlign: "top",<br/>
&nbsp;&nbsp;&nbsp;paddingX: 0,<br/>
&nbsp;&nbsp;&nbsp;paddingY: 0,<br/>
&nbsp;&nbsp;&nbsp;fitParent: false,<br/>
&nbsp;&nbsp;&nbsp;lineBreak: "auto"&nbsp;}
</p>
<br/>
<p>
Use standard canvas text drawing methods such as "fillStyle" and "globalCompositeOperation" when needed before
using CanvasTextWrapper like so:
</p>
<p class="white-block">
var canvas = document.createElement('canvas');<br/>
canvas.width = 300;<br/>
canvas.height = 250;<br/>
context = canvas.getContext("2d");<br/>
context.fillStyle = "rgb(255, 255, 255)";<br/>
context.fillRect(0, 0, canvas.width, canvas.height);<br/><br/>
context.globalCompositeOperation = "destination-out";<br/>
var wrapper = new CanvasTextWrapper(canvas, 'Hello'); // default options will apply<br/>
</p>
</article>
<section>
<h2>Examples:</h2>
</section>
<footer>
&larr;&nbsp;<a href="https://github.com/namniak/CanvasTextWrapper">View on GitHub</a>
</footer>
</body>
</html>
-171
View File
@@ -1,171 +0,0 @@
/*! 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".');
}
}
};
})();
-76
View File
@@ -1,76 +0,0 @@
document.onreadystatechange = function() {
if (document.readyState === 'complete') {
(function() {
var container = document.getElementsByTagName('section')[0];
var w = 448;
var h = 250;
var aspectRatio = 0;
var text = 'Canvas text wrapping example';
var img = new Image();
img.src = 'img/bg.jpg';
img.onload = function() {
aspectRatio = img.naturalWidth / img.naturalHeight;
createExamples();
};
// use options.js file
var options = optionsArr;
function createExamples() {
var fragment = new DocumentFragment();
var context;
for (var i = 0; i < options.length; i++) {
var exampleItem = document.createElement('div');
fragment.appendChild(exampleItem);
// draw canvas image
var canvasImg = document.createElement('canvas');
canvasImg.width = w;
canvasImg.height = h;
context = canvasImg.getContext('2d');
context.drawImage(img, 0, 0, w, w * aspectRatio);
exampleItem.appendChild(canvasImg);
// create canvas mask layer
var canvasMask = document.createElement('canvas');
canvasMask.width = w;
canvasMask.height = h;
context = canvasMask.getContext('2d');
context.fillStyle = 'rgba(255,255,255, 1)';
context.fillRect(0, 0, w, h);
exampleItem.appendChild(canvasMask);
// create text to be cut out mask layer
context.fillStyle = '#212121';
context.globalCompositeOperation = 'destination-out';
// create wrapper
new CanvasTextWrapper(canvasMask, ('#' + (i + 1) + ' ' + text), options[i]);
// create hint code block
var hint = document.createElement('div');
exampleItem.appendChild(hint);
var optionsData = '';
// read used properties
for (var property in options[i]) {
var stringWrapper = (property == 'paddingX' || property == 'paddingY') ? '' : '"';
optionsData += ' <span>' + property + '</span>: ' +
stringWrapper + options[i][property] + stringWrapper + ',<br/>';
}
// print example code
hint.innerHTML = '<h6>CODE:</h6><p>' +
'new CanvasTextWrapper(canvasEl, textStr, {<br/>' + optionsData + '});' +
'</p>';
}
// inject document fragment into actual DOM
container.appendChild(fragment);
}
})();
}
};
-54
View File
@@ -1,54 +0,0 @@
(function() {
window.optionsArr = [
{
font: 'bold 55px Open Sans, sans-serif',
paddingX: 0,
paddingY: 0,
fitParent: false,
lineBreak: 'auto'
},
{
font: 'normal 40px Open Sans, sans-serif',
textAlign: 'center',
verticalAlign: 'top',
paddingY: 10,
lineBreak: 'word'
},
{
font: 'bold 55px Open Sans, sans-serif',
textAlign: 'right',
verticalAlign: 'bottom',
paddingX: 30
},
{
font: 'bold 35px Open Sans, sans-serif',
textAlign: 'center',
verticalAlign: 'middle'
},
{
font: 'bold 55px Open Sans, sans-serif',
textAlign: 'right',
verticalAlign: 'top',
paddingX: 15,
paddingY: 5
},
{
font: 'bold 45px Open Sans, sans-serif',
textAlign: 'center',
verticalAlign: 'middle',
lineBreak: 'word'
},
{
font: 'bold 25px Open Sans, sans-serif',
verticalAlign: 'bottom',
paddingX: 10,
paddingY: 60
},
{
font: '50px Open Sans, sans-serif',
textAlign: 'right',
verticalAlign: 'middle',
paddingX: 15
}
];
})();
+4 -3
View File
@@ -1,9 +1,10 @@
{
"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",
"description": "Pure JavaScript canvas text wrapper that automatically splits a string into lines on specified rule with alignment and padding.",
"version": "0.3.1",
"license": "MIT",
"main": "CanvasTextWrapper.min.js",
"homepage": "http://namniak.github.io/CanvasTextWrapper/",
"repository": {
"type": "git",
"url": "https://github.com/namniak/CanvasTextWrapper"
@@ -12,4 +13,4 @@
"bugs": {
"url": "https://github.com/namniak/CanvasTextWrapper/issues"
}
}
}