new property for Konva.Text and Konva.TextPath: textDecoration

This commit is contained in:
Anton Lavrenov
2016-12-07 16:46:59 -05:00
parent 43fa56a381
commit 115002aaf6
8 changed files with 201 additions and 14 deletions

View File

@@ -5,7 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [Not released][Not released] ## [Not released][Not released]
## Added ## Added
- new properties for `Konva.Text`: `letterSpacing` - 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` - new event `contentContextmenu` for `Konva.Stage`
- `align` support for `Konva.TextPath` - `align` support for `Konva.TextPath`
- new method `toCanvas()` for converting a node into canvas element - new method `toCanvas()` for converting a node into canvas element

View File

@@ -3,5 +3,5 @@ Thank you for submitting an issue!
Please make sure to check current open and closed issues to see if your question has been asked or answered before. Please make sure to check current open and closed issues to see if your question has been asked or answered before.
If you have just a question (not a bug or a feature request) it is better to ask it in our [Gitter Chat](https://gitter.im/konvajs/konva) or in [Stackoverflow](http://stackoverflow.com/questions/tagged/konvajs). If you have just a question (not a bug or a feature request) it is better to ask it in our [Gitter Chat](https://gitter.im/konvajs/konva) or in [Stackoverflow](http://stackoverflow.com/questions/tagged/konvajs).
If you have a bug, please, try to create reproducable example with jsfiddle (or any simillar service). If you have a bug, please, try to create a reproducible example with jsfiddle (or any similar service).
You can use [this JSBIN](http://jsbin.com/xinabi/edit?html,js,output) as template. You can use [this JSBIN](http://jsbin.com/xinabi/edit?html,js,output) as a template.

View File

@@ -3,7 +3,7 @@
* Konva JavaScript Framework v1.2.2 * Konva JavaScript Framework v1.2.2
* http://konvajs.github.io/ * http://konvajs.github.io/
* Licensed under the MIT or GPL Version 2 licenses. * Licensed under the MIT or GPL Version 2 licenses.
* Date: Fri Nov 11 2016 * Date: Wed Dec 07 2016
* *
* Original work Copyright (C) 2011 - 2013 by Eric Rowell (KineticJS) * Original work Copyright (C) 2011 - 2013 by Eric Rowell (KineticJS)
* Modified work Copyright (C) 2014 - 2015 by Anton Lavrenov (Konva) * Modified work Copyright (C) 2014 - 2015 by Anton Lavrenov (Konva)
@@ -13085,6 +13085,8 @@
textArrLen = textArr.length, textArrLen = textArr.length,
totalWidth = this.getWidth(), totalWidth = this.getWidth(),
letterSpacing = this.getLetterSpacing(), letterSpacing = this.getLetterSpacing(),
textDecoration = this.textDecoration(),
fill = this.fill(),
n; n;
context.setAttr('font', this._getContextFont()); context.setAttr('font', this._getContextFont());
@@ -13100,6 +13102,7 @@
} }
// draw text lines // draw text lines
for(n = 0; n < textArrLen; n++) { for(n = 0; n < textArrLen; n++) {
var obj = textArr[n], var obj = textArr[n],
@@ -13115,12 +13118,21 @@
context.translate((totalWidth - width - p * 2) / 2, 0); context.translate((totalWidth - width - p * 2) / 2, 0);
} }
if (textDecoration === 'underline') {
context.save();
context.moveTo(0, Math.round(lineHeightPx / 2));
context.lineTo(Math.round(width), Math.round(lineHeightPx / 2));
// context
context.strokeStyle = fill;
context.stroke();
context.restore();
}
if (letterSpacing !== 0) { if (letterSpacing !== 0) {
for(var li = 0; li < text.length; li++) { for(var li = 0; li < text.length; li++) {
var letter = text[li]; var letter = text[li];
this.partialText = letter; this.partialText = letter;
context.fillStrokeShape(this); context.fillStrokeShape(this);
context.translate(this._getTextSize(letter).width + letterSpacing, 0); context.translate(Math.round(this._getTextSize(letter).width) + letterSpacing, 0);
} }
} else { } else {
this.partialText = text; this.partialText = text;
@@ -13508,6 +13520,23 @@
* text.text('Hello world!'); * text.text('Hello world!');
*/ */
Konva.Factory.addGetterSetter(Konva.Text, 'textDecoration', null);
/**
* get/set text decoration of a text. Can be '' or 'underline'
* @name textDecoration
* @method
* @memberof Konva.Text.prototype
* @param {String} textDecoration
* @returns {String}
* @example
* // get text decoration
* var textDecoration = text.textDecoration();
*
* // center text
* text.textDecoration('underline');
*/
Konva.Collection.mapMethods(Konva.Text); Konva.Collection.mapMethods(Konva.Text);
})(); })();
@@ -15099,6 +15128,10 @@
context.setAttr('textAlign', 'left'); context.setAttr('textAlign', 'left');
context.save(); context.save();
var textDecoration = this.textDecoration();
var fill = this.fill();
var fontSize = this.fontSize();
var glyphInfo = this.glyphInfo; var glyphInfo = this.glyphInfo;
for(var i = 0; i < glyphInfo.length; i++) { for(var i = 0; i < glyphInfo.length; i++) {
context.save(); context.save();
@@ -15110,10 +15143,21 @@
this.partialText = glyphInfo[i].text; this.partialText = glyphInfo[i].text;
context.fillStrokeShape(this); context.fillStrokeShape(this);
if (textDecoration === 'underline') {
// context.beginPath();
// context.strokeStyle = fill;
if (i === 0) {
context.moveTo(0, fontSize / 2);
}
context.lineTo(fontSize, fontSize / 2);
// context.stroke();
}
context.restore(); context.restore();
//// To assist with debugging visually, uncomment following //// To assist with debugging visually, uncomment following
// context.beginPath(); //
// if (i % 2) // if (i % 2)
// context.strokeStyle = 'cyan'; // context.strokeStyle = 'cyan';
// else // else
@@ -15123,6 +15167,11 @@
// context.lineTo(p1.x, p1.y); // context.lineTo(p1.x, p1.y);
// context.stroke(); // context.stroke();
} }
if (textDecoration === 'underline') {
context.strokeStyle = fill;
context.stroke();
}
context.restore(); context.restore();
}, },
_hitFunc: function(context) { _hitFunc: function(context) {
@@ -15564,6 +15613,23 @@
* @memberof Konva.TextPath.prototype * @memberof Konva.TextPath.prototype
*/ */
Konva.Factory.addGetterSetter(Konva.TextPath, 'textDecoration', null);
/**
* get/set text decoration of a text. Can be '' or 'underline'
* @name textDecoration
* @method
* @memberof Konva.Text.prototype
* @param {String} textDecoration
* @returns {String}
* @example
* // get text decoration
* var textDecoration = text.textDecoration();
*
* // center text
* text.textDecoration('underline');
*/
Konva.Collection.mapMethods(Konva.TextPath); Konva.Collection.mapMethods(Konva.TextPath);
})(); })();

12
konva.min.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -105,6 +105,8 @@
textArrLen = textArr.length, textArrLen = textArr.length,
totalWidth = this.getWidth(), totalWidth = this.getWidth(),
letterSpacing = this.getLetterSpacing(), letterSpacing = this.getLetterSpacing(),
textDecoration = this.textDecoration(),
fill = this.fill(),
n; n;
context.setAttr('font', this._getContextFont()); context.setAttr('font', this._getContextFont());
@@ -120,6 +122,7 @@
} }
// draw text lines // draw text lines
for(n = 0; n < textArrLen; n++) { for(n = 0; n < textArrLen; n++) {
var obj = textArr[n], var obj = textArr[n],
@@ -135,12 +138,21 @@
context.translate((totalWidth - width - p * 2) / 2, 0); context.translate((totalWidth - width - p * 2) / 2, 0);
} }
if (textDecoration === 'underline') {
context.save();
context.moveTo(0, Math.round(lineHeightPx / 2));
context.lineTo(Math.round(width), Math.round(lineHeightPx / 2));
// context
context.strokeStyle = fill;
context.stroke();
context.restore();
}
if (letterSpacing !== 0) { if (letterSpacing !== 0) {
for(var li = 0; li < text.length; li++) { for(var li = 0; li < text.length; li++) {
var letter = text[li]; var letter = text[li];
this.partialText = letter; this.partialText = letter;
context.fillStrokeShape(this); context.fillStrokeShape(this);
context.translate(this._getTextSize(letter).width + letterSpacing, 0); context.translate(Math.round(this._getTextSize(letter).width) + letterSpacing, 0);
} }
} else { } else {
this.partialText = text; this.partialText = text;
@@ -528,5 +540,22 @@
* text.text('Hello world!'); * text.text('Hello world!');
*/ */
Konva.Factory.addGetterSetter(Konva.Text, 'textDecoration', null);
/**
* get/set text decoration of a text. Can be '' or 'underline'
* @name textDecoration
* @method
* @memberof Konva.Text.prototype
* @param {String} textDecoration
* @returns {String}
* @example
* // get text decoration
* var textDecoration = text.textDecoration();
*
* // center text
* text.textDecoration('underline');
*/
Konva.Collection.mapMethods(Konva.Text); Konva.Collection.mapMethods(Konva.Text);
})(); })();

View File

@@ -77,6 +77,10 @@
context.setAttr('textAlign', 'left'); context.setAttr('textAlign', 'left');
context.save(); context.save();
var textDecoration = this.textDecoration();
var fill = this.fill();
var fontSize = this.fontSize();
var glyphInfo = this.glyphInfo; var glyphInfo = this.glyphInfo;
for(var i = 0; i < glyphInfo.length; i++) { for(var i = 0; i < glyphInfo.length; i++) {
context.save(); context.save();
@@ -88,10 +92,21 @@
this.partialText = glyphInfo[i].text; this.partialText = glyphInfo[i].text;
context.fillStrokeShape(this); context.fillStrokeShape(this);
if (textDecoration === 'underline') {
// context.beginPath();
// context.strokeStyle = fill;
if (i === 0) {
context.moveTo(0, fontSize / 2);
}
context.lineTo(fontSize, fontSize / 2);
// context.stroke();
}
context.restore(); context.restore();
//// To assist with debugging visually, uncomment following //// To assist with debugging visually, uncomment following
// context.beginPath(); //
// if (i % 2) // if (i % 2)
// context.strokeStyle = 'cyan'; // context.strokeStyle = 'cyan';
// else // else
@@ -101,6 +116,11 @@
// context.lineTo(p1.x, p1.y); // context.lineTo(p1.x, p1.y);
// context.stroke(); // context.stroke();
} }
if (textDecoration === 'underline') {
context.strokeStyle = fill;
context.stroke();
}
context.restore(); context.restore();
}, },
_hitFunc: function(context) { _hitFunc: function(context) {
@@ -542,5 +562,22 @@
* @memberof Konva.TextPath.prototype * @memberof Konva.TextPath.prototype
*/ */
Konva.Factory.addGetterSetter(Konva.TextPath, 'textDecoration', null);
/**
* get/set text decoration of a text. Can be '' or 'underline'
* @name textDecoration
* @method
* @memberof Konva.Text.prototype
* @param {String} textDecoration
* @returns {String}
* @example
* // get text decoration
* var textDecoration = text.textDecoration();
*
* // center text
* text.textDecoration('underline');
*/
Konva.Collection.mapMethods(Konva.TextPath); Konva.Collection.mapMethods(Konva.TextPath);
})(); })();

View File

@@ -330,6 +330,33 @@ suite('Text', function(){
}); });
// ======================================================
test('text multi line with textDecoration and spacing', function() {
var stage = addStage();
var layer = new Konva.Layer();
var text = new Konva.Text({
x: 10,
y: 10,
text: 'hello\nworld',
fontSize: 15,
fill: 'red',
letterSpacing: 5,
textDecoration: 'underline'
});
layer.add(text);
stage.add(layer);
var trace = 'clearRect(0,0,578,200);save();transform(1,0,0,1,10,10);font=normal normal 15px Arial;textBaseline=middle;textAlign=left;save();translate(0,7.5);save();save();moveTo(0,8);lineTo(52,8);stroke();restore();fillStyle=red;fillText(h,0,0);translate(13,0);fillStyle=red;fillText(e,0,0);translate(13,0);fillStyle=red;fillText(l,0,0);translate(8,0);fillStyle=red;fillText(l,0,0);translate(8,0);fillStyle=red;fillText(o,0,0);translate(13,0);restore();translate(0,15);save();save();moveTo(0,8);lineTo(56,8);stroke();restore();fillStyle=red;fillText(w,0,0);translate(16,0);fillStyle=red;fillText(o,0,0);translate(13,0);fillStyle=red;fillText(r,0,0);translate(10,0);fillStyle=red;fillText(l,0,0);translate(8,0);fillStyle=red;fillText(d,0,0);translate(13,0);restore();translate(0,15);restore();restore();';
assert.equal(layer.getContext().getTrace(), trace);
});
// ====================================================== // ======================================================
test('change font size should update text data', function() { test('change font size should update text data', function() {
var stage = addStage(); var stage = addStage();

View File

@@ -145,6 +145,8 @@ suite('TextPath', function() {
}); });
// ====================================================== // ======================================================
test('Render Text Along Elliptical Arc', function() { test('Render Text Along Elliptical Arc', function() {
var stage = addStage(); var stage = addStage();
@@ -265,6 +267,31 @@ suite('TextPath', function() {
stage.add(layer); stage.add(layer);
}); });
test('Text path with underline', 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({
fill: 'orange',
fontSize: 10,
fontFamily: 'Arial',
letterSpacing: 5,
text: 'All the worlds a stage.',
textDecoration: 'underline',
data: c
});
layer.add(textpath);
stage.add(layer);
var trace = 'rotate();fillStyle;fillText();lineTo();restore();save();translate();rotate();fillStyle;fillText();lineTo();restore();save();translate();rotate();fillStyle;fillText();lineTo();restore();save();translate();rotate();fillStyle;fillText();lineTo();restore();save();translate();rotate();fillStyle;fillText();lineTo();restore();save();translate();rotate();fillStyle;fillText();lineTo();restore();save();translate();rotate();fillStyle;fillText();lineTo();restore();save();translate();rotate();fillStyle;fillText();lineTo();restore();save();translate();rotate();fillStyle;fillText();lineTo();restore();save();translate();rotate();fillStyle;fillText();lineTo();restore();save();translate();rotate();fillStyle;fillText();lineTo();restore();save();translate();rotate();fillStyle;fillText();lineTo();restore();save();translate();rotate();fillStyle;fillText();lineTo();restore();save();translate();rotate();fillStyle;fillText();lineTo();restore();stroke();restore();restore();';
assert.equal(layer.getContext().getTrace(true), trace);
});
test('Text with baseline', function() { test('Text with baseline', function() {
var stage = addStage(); var stage = addStage();