mirror of
https://github.com/konvajs/konva.git
synced 2025-10-20 19:01:04 +08:00
new property for Konva.Text
and Konva.TextPath
: textDecoration
This commit is contained in:
@@ -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
|
||||||
|
@@ -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.
|
||||||
|
72
konva.js
72
konva.js
@@ -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
12
konva.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -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);
|
||||||
})();
|
})();
|
||||||
|
@@ -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);
|
||||||
})();
|
})();
|
||||||
|
@@ -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();
|
||||||
|
@@ -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();
|
||||||
|
Reference in New Issue
Block a user