justify align for Text and TextPath

This commit is contained in:
Anton Lavrenov
2016-12-08 09:08:44 -05:00
parent c001901833
commit 9586d9316d
7 changed files with 116 additions and 20 deletions

View File

@@ -5,6 +5,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [Not released][Not released]
## Added
- new align value for `Konva.Text` and `Konva.TextPath`: `justify`
- new property for `Konva.Text` and `Konva.TextPath`: `textDecoration`. Right now it sports only '' (no decoration) and 'underline' values.
- new property for `Konva.Text`: `letterSpacing`
- new event `contentContextmenu` for `Konva.Stage`

View File

@@ -3,7 +3,7 @@
* Konva JavaScript Framework v1.2.2
* http://konvajs.github.io/
* Licensed under the MIT or GPL Version 2 licenses.
* Date: Wed Dec 07 2016
* Date: Thu Dec 08 2016
*
* Original work Copyright (C) 2011 - 2013 by Eric Rowell (KineticJS)
* Modified work Copyright (C) 2014 - 2015 by Anton Lavrenov (Konva)
@@ -12918,6 +12918,7 @@
var AUTO = 'auto',
//CANVAS = 'canvas',
CENTER = 'center',
JUSTIFY = 'justify',
CHANGE_KONVA = 'Change.konva',
CONTEXT_2D = '2d',
DASH = '-',
@@ -13083,6 +13084,7 @@
lineHeightPx = this.getLineHeight() * textHeight,
textArr = this.textArr,
textArrLen = textArr.length,
align = this.getAlign(),
totalWidth = this.getWidth(),
letterSpacing = this.getLetterSpacing(),
textDecoration = this.textDecoration(),
@@ -13112,10 +13114,10 @@
// horizontal alignment
context.save();
if(this.getAlign() === RIGHT) {
if(align === RIGHT) {
context.translate(totalWidth - width - p * 2, 0);
}
else if(this.getAlign() === CENTER) {
else if(align === CENTER) {
context.translate((totalWidth - width - p * 2) / 2, 0);
}
@@ -13131,9 +13133,15 @@
context.stroke();
context.restore();
}
if (letterSpacing !== 0) {
if ((letterSpacing !== 0) || align === JUSTIFY) {
// var words = text.split(' ');
var spacesNumber = text.split(' ').length - 1;
for(var li = 0; li < text.length; li++) {
var letter = text[li];
// skip justify for the last line
if ((letter === ' ') && (n !== textArrLen - 1)) {
context.translate(Math.ceil((totalWidth - width) / spacesNumber), 0);
}
this.partialText = letter;
context.fillStrokeShape(this);
context.translate(Math.round(this._getTextSize(letter).width) + letterSpacing, 0);
@@ -13445,7 +13453,7 @@
Konva.Factory.addGetterSetter(Konva.Text, 'align', LEFT);
/**
* get/set horizontal align of text. Can be 'left', 'center', or 'right'
* get/set horizontal align of text. Can be 'left', 'center', 'right' or 'justify'
* @name align
* @method
* @memberof Konva.Text.prototype
@@ -15241,6 +15249,7 @@
var that = this;
var size = this._getTextSize(this.attrs.text);
var letterSpacing = this.getLetterSpacing();
var align = this.align();
this.textWidth = size.width;
this.textHeight = size.height;
@@ -15258,14 +15267,15 @@
}
var offset = 0;
if (this.align() === 'center') {
if (align === 'center') {
offset = Math.max(0, fullPathWidth / 2 - textFullWidth / 2);
}
if (this.align() === 'right') {
if (align === 'right') {
offset = Math.max(0, fullPathWidth - textFullWidth);
}
var charArr = this.getText().split('');
var spacesNumber = this.getText().split(' ').length - 1;
var p0, p1, pathCmd;
@@ -15307,6 +15317,10 @@
var glyphWidth = that._getTextSize(c).width + letterSpacing;
if ((c === ' ') && (align === 'justify')) {
glyphWidth += (fullPathWidth - textFullWidth) / spacesNumber;
}
var currLen = 0;
var attempts = 0;
@@ -15545,7 +15559,7 @@
Konva.Factory.addGetterSetter(Konva.TextPath, 'align', 'left');
/**
* get/set horizontal align of text. Can be 'left', 'center', or 'right'
* get/set horizontal align of text. Can be 'left', 'center', 'right' or 'justify'
* @name align
* @method
* @memberof Konva.Text.prototype

10
konva.min.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -7,6 +7,7 @@
var AUTO = 'auto',
//CANVAS = 'canvas',
CENTER = 'center',
JUSTIFY = 'justify',
CHANGE_KONVA = 'Change.konva',
CONTEXT_2D = '2d',
DASH = '-',
@@ -103,6 +104,7 @@
lineHeightPx = this.getLineHeight() * textHeight,
textArr = this.textArr,
textArrLen = textArr.length,
align = this.getAlign(),
totalWidth = this.getWidth(),
letterSpacing = this.getLetterSpacing(),
textDecoration = this.textDecoration(),
@@ -132,10 +134,10 @@
// horizontal alignment
context.save();
if(this.getAlign() === RIGHT) {
if(align === RIGHT) {
context.translate(totalWidth - width - p * 2, 0);
}
else if(this.getAlign() === CENTER) {
else if(align === CENTER) {
context.translate((totalWidth - width - p * 2) / 2, 0);
}
@@ -151,9 +153,15 @@
context.stroke();
context.restore();
}
if (letterSpacing !== 0) {
if ((letterSpacing !== 0) || align === JUSTIFY) {
// var words = text.split(' ');
var spacesNumber = text.split(' ').length - 1;
for(var li = 0; li < text.length; li++) {
var letter = text[li];
// skip justify for the last line
if ((letter === ' ') && (n !== textArrLen - 1)) {
context.translate(Math.ceil((totalWidth - width) / spacesNumber), 0);
}
this.partialText = letter;
context.fillStrokeShape(this);
context.translate(Math.round(this._getTextSize(letter).width) + letterSpacing, 0);
@@ -465,7 +473,7 @@
Konva.Factory.addGetterSetter(Konva.Text, 'align', LEFT);
/**
* get/set horizontal align of text. Can be 'left', 'center', or 'right'
* get/set horizontal align of text. Can be 'left', 'center', 'right' or 'justify'
* @name align
* @method
* @memberof Konva.Text.prototype

View File

@@ -186,6 +186,7 @@
var that = this;
var size = this._getTextSize(this.attrs.text);
var letterSpacing = this.getLetterSpacing();
var align = this.align();
this.textWidth = size.width;
this.textHeight = size.height;
@@ -203,14 +204,15 @@
}
var offset = 0;
if (this.align() === 'center') {
if (align === 'center') {
offset = Math.max(0, fullPathWidth / 2 - textFullWidth / 2);
}
if (this.align() === 'right') {
if (align === 'right') {
offset = Math.max(0, fullPathWidth - textFullWidth);
}
var charArr = this.getText().split('');
var spacesNumber = this.getText().split(' ').length - 1;
var p0, p1, pathCmd;
@@ -252,6 +254,10 @@
var glyphWidth = that._getTextSize(c).width + letterSpacing;
if ((c === ' ') && (align === 'justify')) {
glyphWidth += (fullPathWidth - textFullWidth) / spacesNumber;
}
var currLen = 0;
var attempts = 0;
@@ -490,7 +496,7 @@
Konva.Factory.addGetterSetter(Konva.TextPath, 'align', 'left');
/**
* get/set horizontal align of text. Can be 'left', 'center', or 'right'
* get/set horizontal align of text. Can be 'left', 'center', 'right' or 'justify'
* @name align
* @method
* @memberof Konva.Text.prototype

View File

@@ -295,6 +295,43 @@ suite('Text', function(){
assert.equal(text.getLineHeight(), 20);
});
// ======================================================
test('text multi line with justify align', function() {
var stage = addStage();
var layer = new Konva.Layer();
var rect = new Konva.Rect({
x: 10,
y: 10,
width: 380,
height: 300,
fill: 'yellow'
});
var text = new Konva.Text({
x: 10,
y: 10,
text: 'HEADING\n\n All the world\'s a stage, merely players. They have their exits and their entrances; And one man in his time plays many parts.',
fontSize: 14,
fontFamily: 'Calibri',
fontStyle: 'normal',
fill: '#555',
width: 380,
align: 'justify',
letterSpacing: 5,
draggable: true
});
rect.height(text.getHeight());
layer.add(rect).add(text);
stage.add(layer);
var trace = 'fillStyle=#555;fillText( ,0,0);translate(9,0);fillStyle=#555;fillText(i,0,0);translate(9,0);fillStyle=#555;fillText(n,0,0);translate(12,0);translate(1,0);fillStyle=#555;fillText( ,0,0);translate(9,0);fillStyle=#555;fillText(h,0,0);translate(12,0);fillStyle=#555;fillText(i,0,0);translate(9,0);fillStyle=#555;fillText(s,0,0);translate(10,0);translate(1,0);fillStyle=#555;fillText( ,0,0);translate(9,0);restore();translate(0,14);save();fillStyle=#555;fillText(t,0,0);translate(9,0);fillStyle=#555;fillText(i,0,0);translate(9,0);fillStyle=#555;fillText(m,0,0);translate(16,0);fillStyle=#555;fillText(e,0,0);translate(11,0);fillStyle=#555;fillText( ,0,0);translate(9,0);fillStyle=#555;fillText(p,0,0);translate(12,0);fillStyle=#555;fillText(l,0,0);translate(9,0);fillStyle=#555;fillText(a,0,0);translate(11,0);fillStyle=#555;fillText(y,0,0);translate(12,0);fillStyle=#555;fillText(s,0,0);translate(10,0);fillStyle=#555;fillText( ,0,0);translate(9,0);fillStyle=#555;fillText(m,0,0);translate(16,0);fillStyle=#555;fillText(a,0,0);translate(11,0);fillStyle=#555;fillText(n,0,0);translate(12,0);fillStyle=#555;fillText(y,0,0);translate(12,0);fillStyle=#555;fillText( ,0,0);translate(9,0);fillStyle=#555;fillText(p,0,0);translate(12,0);fillStyle=#555;fillText(a,0,0);translate(11,0);fillStyle=#555;fillText(r,0,0);translate(10,0);fillStyle=#555;fillText(t,0,0);translate(9,0);fillStyle=#555;fillText(s,0,0);translate(10,0);fillStyle=#555;fillText(.,0,0);translate(9,0);restore();translate(0,14);restore();restore();';
assert.equal(layer.getContext().getTrace(), trace);
});
// ======================================================
test('text multi line with shadows', function() {
var stage = addStage();

View File

@@ -267,6 +267,36 @@ suite('TextPath', function() {
stage.add(layer);
});
test('Text path with justify align', function() {
var stage = addStage();
var layer = new Konva.Layer();
var c = "M10,10 C0,0 10,150 100,100 S300,150 400,50";
var textpath = new Konva.TextPath({
stroke: 'black',
strokeWidth: 1,
fill: 'orange',
fontSize: 10,
fontFamily: 'Arial',
letterSpacing: 5,
text: 'All the worlds a stage.',
align: 'justify',
data: c
});
// TODO: add test case
layer.add(textpath);
stage.add(layer);
// console.log(layer.getContext().getTrace(true));
var trace = 'rotate();fillStyle;fillText();lineWidth;strokeStyle;strokeText();restore();save();translate();rotate();fillStyle;fillText();lineWidth;strokeStyle;strokeText();restore();save();translate();rotate();fillStyle;fillText();lineWidth;strokeStyle;strokeText();restore();save();translate();rotate();fillStyle;fillText();lineWidth;strokeStyle;strokeText();restore();save();translate();rotate();fillStyle;fillText();lineWidth;strokeStyle;strokeText();restore();save();translate();rotate();fillStyle;fillText();lineWidth;strokeStyle;strokeText();restore();save();translate();rotate();fillStyle;fillText();lineWidth;strokeStyle;strokeText();restore();save();translate();rotate();fillStyle;fillText();lineWidth;strokeStyle;strokeText();restore();save();translate();rotate();fillStyle;fillText();lineWidth;strokeStyle;strokeText();restore();save();translate();rotate();fillStyle;fillText();lineWidth;strokeStyle;strokeText();restore();save();translate();rotate();fillStyle;fillText();lineWidth;strokeStyle;strokeText();restore();restore();restore();';
assert.equal(layer.getContext().getTrace(true), trace);
});
test('Text path with underline', function() {
var stage = addStage();
var layer = new Konva.Layer();