added sizeToFill option + ui updates

This commit is contained in:
Vadim Namniak
2014-10-08 22:48:48 -04:00
parent d2d3578322
commit cb7cb65b9e
5 changed files with 90 additions and 60 deletions
+9
View File
@@ -3,6 +3,7 @@ body {
margin: auto;
font-family: 'Open Sans', sans-serif;
color: #fff;
line-height: 140%;
}
div, header, footer, article {
@@ -128,9 +129,17 @@ img {
span {
margin-left: 20px;
margin-right: 5px;
}
span, .emph {
font-weight: 600;
display: inline;
}
strong {
background: #fff;
color: #0D9F69;
font-weight: bold;
padding: 0 5px;
}
+26 -15
View File
@@ -76,27 +76,38 @@
<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>
<li>
<div class="emph">sizeToFill</div>
(Boolean) - auto font size to fill text container
<ul class="values">
<li>"true" - ignore given font size and resize text to fill its padded container</li>
<li>"true" - use specified or default font size</li>
</ul>
</li>
<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 unless <strong>sizeToFill</strong> option is used.
</p>
</ul><br/>
<h2>Defaults</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/>
<pre class="white-block">
{
font: "18px Arial, sans-serif",
textAlign: "left",
verticalAlign: "top",
paddingX: 0,
paddingY: 0,
fitParent: false,
lineBreak: "auto",
sizeToFill: false
}
</pre>
<br/><br/>
<h2>Usage</h2><br/>
<p>
+44 -16
View File
@@ -1,5 +1,5 @@
/*! CanvasTextWrapper (https://github.com/namniak/CanvasTextWrapper)
* Version: 0.1.0
* Version: 0.2.0
*
* MIT License (http://www.opensource.org/licenses/mit-license.html)
* Copyright (c) 2014 Vadim Namniak
@@ -15,10 +15,12 @@
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
lineBreak: 'auto', // text fills the element's (canvas or parent) width going to a new line on a whole word
sizeToFill: false // text is resized to fill the container (given font size is ignored)
};
window.CanvasTextWrapper = function(canvas, text, opts) {
if (!(this instanceof CanvasTextWrapper)) {
throw new TypeError('CanvasTextWrapper constructor failed. Use "new" keyword when instantiating.');
}
@@ -32,7 +34,7 @@
}
// extract font size
this.lineHeight = parseInt(this.font.replace(/^\D+/g, ''), 10);
this.lineHeight = parseInt(this.font.replace(/^\D+/g, ''), 10) || 18;
// validate all set properties
this.validate();
@@ -48,36 +50,59 @@
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 elementWidth = (this.fitParent === false) ? this.canvas.width : this.canvas.parentNode.clientWidth;
var textPos = {
x: 0,
y: 0
};
this.checkWordsLength(context, words, maxTextLength);
this.breakTextIntoLines(context, lines, words, maxTextLength);
if (this.sizeToFill) {
// starting at 1px increase font size by 1px until text block exceeds the height of its padded container or until words break
var elementHeight = ((this.fitParent === false) ? this.canvas.height : this.canvas.parentNode.clientHeight) - (this.paddingX * 2);
var numWords = this.text.trim().split(/\s+/).length;
var fontSize = 0;
do {
this.setFontSize(++fontSize);
var lines = this.getWrappedText(elementWidth);
var textBlockHeight = lines.length * this.lineHeight;
} while (textBlockHeight < elementHeight && lines.join(' ').split(/\s+/).length == numWords);
// height of the broken down into lines text
// use previous font size, not the one that broke the while condition
this.setFontSize(--fontSize);
}
var lines = this.getWrappedText(elementWidth);
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]);
this.setTextHorizontalAlign(this.context, textPos, elementWidth, lines[i]);
textPos.y = parseInt(textPos.y) + parseInt(this.lineHeight);
context.fillText(lines[i], textPos.x, textPos.y);
this.context.fillText(lines[i], textPos.x, textPos.y);
}
},
setFontSize: function(size) {
var fontParts = this.context.font.split(/\b\d+px\b/i);
this.context.font = fontParts[0] + size + 'px' + fontParts[1];
this.lineHeight = size;
},
getWrappedText: function(elementWidth) {
var maxTextLength = elementWidth - (this.paddingX * 2);
var words = this.text.trim().split(/\s+/);
var lines = [];
this.checkWordsLength(this.context, words, maxTextLength);
this.breakTextIntoLines(this.context, lines, words, maxTextLength);
return lines;
},
checkWordsLength: function(context, words, maxTextLength) {
for (var i = 0; i < words.length; i++) {
var testString = '';
@@ -166,6 +191,9 @@
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 (typeof this.sizeToFill !== 'boolean') {
throw new TypeError('From CanvasTextWrapper(): Property "sizeToFill" must be set to a Boolean.');
}
}
};
})();
+2 -2
View File
@@ -57,8 +57,8 @@ document.onreadystatechange = function() {
// read used properties
for (var property in options[i]) {
var stringWrapper = (property == 'paddingX' || property == 'paddingY') ? '' : '"';
optionsData += ' <span>' + property + '</span>: ' +
var stringWrapper = (property == 'paddingX' || property == 'paddingY' || property == 'sizeToFill') ? '' : '"';
optionsData += ' <span>' + property + ':</span> ' +
stringWrapper + options[i][property] + stringWrapper + ',<br/>';
}
+9 -27
View File
@@ -1,16 +1,11 @@
(function() {
window.optionsArr = [
{
font: 'bold 55px Open Sans, sans-serif',
paddingX: 0,
paddingY: 0,
fitParent: false,
lineBreak: 'auto'
font: 'bold 55px Open Sans, sans-serif'
},
{
font: 'normal 40px Open Sans, sans-serif',
font: 'normal 40px Impact, Charcoal, sans-serif',
textAlign: 'center',
verticalAlign: 'top',
paddingY: 10,
lineBreak: 'word'
},
@@ -21,34 +16,21 @@
paddingX: 30
},
{
font: 'bold 35px Open Sans, sans-serif',
font: 'bold 35px Verdana, Geneva, sans-serif',
textAlign: 'center',
verticalAlign: 'middle'
},
{
font: 'bold 55px Open Sans, sans-serif',
font: 'bold 50px Tahoma, Geneva, sans-serif',
textAlign: 'right',
verticalAlign: 'top',
paddingX: 15,
paddingY: 5
paddingX: 25,
paddingY: 25
},
{
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
//lineBreak: 'word',
sizeToFill: true
}
];
})();
})();