mirror of
https://github.com/konvajs/konva.git
synced 2025-04-05 18:24:17 +08:00
transformer and text fixes. close #381
This commit is contained in:
parent
110d13b559
commit
7d5e0024be
@ -5,6 +5,12 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [new version][unreleased]
|
||||
|
||||
## Fixed
|
||||
|
||||
* Cursor fixes for `Konva.Transformer`
|
||||
* Fixed lineHeight behavior for `Konva.Text`
|
||||
* Some performance optimizations for `Konva.Text`
|
||||
|
||||
## [2.0.3][2018-04-21]
|
||||
|
||||
### Added
|
||||
|
60
konva.js
60
konva.js
@ -2,7 +2,7 @@
|
||||
* Konva JavaScript Framework v2.0.3
|
||||
* http://konvajs.github.io/
|
||||
* Licensed under the MIT
|
||||
* Date: Sat Apr 21 2018
|
||||
* Date: Tue Apr 24 2018
|
||||
*
|
||||
* Original work Copyright (C) 2011 - 2013 by Eric Rowell (KineticJS)
|
||||
* Modified work Copyright (C) 2014 - present by Anton Lavrenov (Konva)
|
||||
@ -14659,7 +14659,7 @@
|
||||
this.hitFunc(this._hitFunc);
|
||||
},
|
||||
_sceneFunc: function(context) {
|
||||
var p = this.getPadding(),
|
||||
var padding = this.getPadding(),
|
||||
textHeight = this.getTextHeight(),
|
||||
lineHeightPx = this.getLineHeight() * textHeight,
|
||||
textArr = this.textArr,
|
||||
@ -14676,12 +14676,11 @@
|
||||
|
||||
context.setAttr('textBaseline', MIDDLE);
|
||||
context.setAttr('textAlign', LEFT);
|
||||
context.save();
|
||||
if (p) {
|
||||
context.translate(p, 0);
|
||||
context.translate(0, p + textHeight / 2);
|
||||
if (padding) {
|
||||
context.translate(padding, 0);
|
||||
context.translate(0, padding + lineHeightPx / 2);
|
||||
} else {
|
||||
context.translate(0, textHeight / 2);
|
||||
context.translate(0, lineHeightPx / 2);
|
||||
}
|
||||
|
||||
// draw text lines
|
||||
@ -14693,9 +14692,9 @@
|
||||
// horizontal alignment
|
||||
context.save();
|
||||
if (align === RIGHT) {
|
||||
context.translate(totalWidth - width - p * 2, 0);
|
||||
context.translate(totalWidth - width - padding * 2, 0);
|
||||
} else if (align === CENTER) {
|
||||
context.translate((totalWidth - width - p * 2) / 2, 0);
|
||||
context.translate((totalWidth - width - padding * 2) / 2, 0);
|
||||
}
|
||||
|
||||
if (textDecoration.indexOf('underline') !== -1) {
|
||||
@ -14704,7 +14703,7 @@
|
||||
context.moveTo(0, Math.round(lineHeightPx / 2));
|
||||
context.lineTo(Math.round(width), Math.round(lineHeightPx / 2));
|
||||
// TODO: I have no idea what is real ratio
|
||||
// just /20 looks good enough
|
||||
// just /15 looks good enough
|
||||
context.lineWidth = fontSize / 15;
|
||||
context.strokeStyle = fill;
|
||||
context.stroke();
|
||||
@ -14745,9 +14744,10 @@
|
||||
context.fillStrokeShape(this);
|
||||
}
|
||||
context.restore();
|
||||
context.translate(0, lineHeightPx);
|
||||
if (textArrLen > 1) {
|
||||
context.translate(0, lineHeightPx);
|
||||
}
|
||||
}
|
||||
context.restore();
|
||||
},
|
||||
_hitFunc: function(context) {
|
||||
var width = this.getWidth(),
|
||||
@ -18617,11 +18617,23 @@
|
||||
'transformsEnabledChange.resizer'
|
||||
].join(' ');
|
||||
|
||||
var ANGLES = {
|
||||
'top-left': -45,
|
||||
'top-center': 0,
|
||||
'top-right': 45,
|
||||
'middle-right': -90,
|
||||
'middle-left': 90,
|
||||
'bottom-left': -135,
|
||||
'bottom-center': 180,
|
||||
'bottom-right': 135
|
||||
};
|
||||
|
||||
function getCursor(anchorName, rad) {
|
||||
if (anchorName === 'rotater') {
|
||||
return 'crosshair';
|
||||
}
|
||||
|
||||
rad += Konva.Util._degToRad(ANGLES[anchorName] || 0);
|
||||
var angle = (Konva.Util._radToDeg(rad) % 360 + 360) % 360;
|
||||
|
||||
if (
|
||||
@ -18888,23 +18900,23 @@
|
||||
// the basic idea is to find "angle" of handler
|
||||
var rad = Konva.getAngle(tr.rotation());
|
||||
|
||||
var cdx = tr.getWidth() / 2;
|
||||
var cdy = tr.getHeight() / 2;
|
||||
// var cdx = tr.getWidth() / 2;
|
||||
// var cdy = tr.getHeight() / 2;
|
||||
|
||||
var parentPos = tr.getAbsolutePosition(tr.getParent());
|
||||
var center = {
|
||||
x: parentPos.x + (cdx * Math.cos(rad) + cdy * Math.sin(-rad)),
|
||||
y: parentPos.y + (cdy * Math.cos(rad) + cdx * Math.sin(rad))
|
||||
};
|
||||
// var parentPos = tr.getAbsolutePosition(tr.getParent());
|
||||
// var center = {
|
||||
// x: parentPos.x + (cdx * Math.cos(rad) + cdy * Math.sin(-rad)),
|
||||
// y: parentPos.y + (cdy * Math.cos(rad) + cdx * Math.sin(rad))
|
||||
// };
|
||||
|
||||
var pos = this.getAbsolutePosition(tr.getParent());
|
||||
// var pos = this.getAbsolutePosition(tr.getParent());
|
||||
|
||||
var dx = -pos.x + center.x;
|
||||
var dy = -pos.y + center.y;
|
||||
// var dx = -pos.x + center.x;
|
||||
// var dy = -pos.y + center.y;
|
||||
|
||||
var angle = -Math.atan2(-dy, dx) - Math.PI / 2;
|
||||
// var angle = -Math.atan2(-dy, dx) - Math.PI / 2;
|
||||
|
||||
var cursor = getCursor(name, angle);
|
||||
var cursor = getCursor(name, rad);
|
||||
anchor.getStage().content.style.cursor = cursor;
|
||||
layer.batchDraw();
|
||||
});
|
||||
|
6
konva.min.js
vendored
6
konva.min.js
vendored
File diff suppressed because one or more lines are too long
@ -123,7 +123,7 @@
|
||||
this.hitFunc(this._hitFunc);
|
||||
},
|
||||
_sceneFunc: function(context) {
|
||||
var p = this.getPadding(),
|
||||
var padding = this.getPadding(),
|
||||
textHeight = this.getTextHeight(),
|
||||
lineHeightPx = this.getLineHeight() * textHeight,
|
||||
textArr = this.textArr,
|
||||
@ -140,12 +140,11 @@
|
||||
|
||||
context.setAttr('textBaseline', MIDDLE);
|
||||
context.setAttr('textAlign', LEFT);
|
||||
context.save();
|
||||
if (p) {
|
||||
context.translate(p, 0);
|
||||
context.translate(0, p + textHeight / 2);
|
||||
if (padding) {
|
||||
context.translate(padding, 0);
|
||||
context.translate(0, padding + lineHeightPx / 2);
|
||||
} else {
|
||||
context.translate(0, textHeight / 2);
|
||||
context.translate(0, lineHeightPx / 2);
|
||||
}
|
||||
|
||||
// draw text lines
|
||||
@ -157,9 +156,9 @@
|
||||
// horizontal alignment
|
||||
context.save();
|
||||
if (align === RIGHT) {
|
||||
context.translate(totalWidth - width - p * 2, 0);
|
||||
context.translate(totalWidth - width - padding * 2, 0);
|
||||
} else if (align === CENTER) {
|
||||
context.translate((totalWidth - width - p * 2) / 2, 0);
|
||||
context.translate((totalWidth - width - padding * 2) / 2, 0);
|
||||
}
|
||||
|
||||
if (textDecoration.indexOf('underline') !== -1) {
|
||||
@ -168,7 +167,7 @@
|
||||
context.moveTo(0, Math.round(lineHeightPx / 2));
|
||||
context.lineTo(Math.round(width), Math.round(lineHeightPx / 2));
|
||||
// TODO: I have no idea what is real ratio
|
||||
// just /20 looks good enough
|
||||
// just /15 looks good enough
|
||||
context.lineWidth = fontSize / 15;
|
||||
context.strokeStyle = fill;
|
||||
context.stroke();
|
||||
@ -209,9 +208,10 @@
|
||||
context.fillStrokeShape(this);
|
||||
}
|
||||
context.restore();
|
||||
context.translate(0, lineHeightPx);
|
||||
if (textArrLen > 1) {
|
||||
context.translate(0, lineHeightPx);
|
||||
}
|
||||
}
|
||||
context.restore();
|
||||
},
|
||||
_hitFunc: function(context) {
|
||||
var width = this.getWidth(),
|
||||
|
@ -23,11 +23,23 @@
|
||||
'transformsEnabledChange.resizer'
|
||||
].join(' ');
|
||||
|
||||
var ANGLES = {
|
||||
'top-left': -45,
|
||||
'top-center': 0,
|
||||
'top-right': 45,
|
||||
'middle-right': -90,
|
||||
'middle-left': 90,
|
||||
'bottom-left': -135,
|
||||
'bottom-center': 180,
|
||||
'bottom-right': 135
|
||||
};
|
||||
|
||||
function getCursor(anchorName, rad) {
|
||||
if (anchorName === 'rotater') {
|
||||
return 'crosshair';
|
||||
}
|
||||
|
||||
rad += Konva.Util._degToRad(ANGLES[anchorName] || 0);
|
||||
var angle = (Konva.Util._radToDeg(rad) % 360 + 360) % 360;
|
||||
|
||||
if (
|
||||
@ -269,23 +281,23 @@
|
||||
// the basic idea is to find "angle" of handler
|
||||
var rad = Konva.getAngle(tr.rotation());
|
||||
|
||||
var cdx = tr.getWidth() / 2;
|
||||
var cdy = tr.getHeight() / 2;
|
||||
// var cdx = tr.getWidth() / 2;
|
||||
// var cdy = tr.getHeight() / 2;
|
||||
|
||||
var parentPos = tr.getAbsolutePosition(tr.getParent());
|
||||
var center = {
|
||||
x: parentPos.x + (cdx * Math.cos(rad) + cdy * Math.sin(-rad)),
|
||||
y: parentPos.y + (cdy * Math.cos(rad) + cdx * Math.sin(rad))
|
||||
};
|
||||
// var parentPos = tr.getAbsolutePosition(tr.getParent());
|
||||
// var center = {
|
||||
// x: parentPos.x + (cdx * Math.cos(rad) + cdy * Math.sin(-rad)),
|
||||
// y: parentPos.y + (cdy * Math.cos(rad) + cdx * Math.sin(rad))
|
||||
// };
|
||||
|
||||
var pos = this.getAbsolutePosition(tr.getParent());
|
||||
// var pos = this.getAbsolutePosition(tr.getParent());
|
||||
|
||||
var dx = -pos.x + center.x;
|
||||
var dy = -pos.y + center.y;
|
||||
// var dx = -pos.x + center.x;
|
||||
// var dy = -pos.y + center.y;
|
||||
|
||||
var angle = -Math.atan2(-dy, dx) - Math.PI / 2;
|
||||
// var angle = -Math.atan2(-dy, dx) - Math.PI / 2;
|
||||
|
||||
var cursor = getCursor(name, angle);
|
||||
var cursor = getCursor(name, rad);
|
||||
anchor.getStage().content.style.cursor = cursor;
|
||||
layer.batchDraw();
|
||||
});
|
||||
|
@ -338,7 +338,8 @@ suite('Text', function() {
|
||||
var text = new Konva.Text({
|
||||
x: 10,
|
||||
y: 10,
|
||||
text: "HEADING\n\nAll the world's a stage, merely players. They have their exits and their entrances; And one man in his time plays many parts.",
|
||||
text:
|
||||
"HEADING\n\nAll the world's a stage, merely players. They have their exits and their entrances; And one man in his time plays many parts.",
|
||||
//text: 'HEADING\n\nThis is a really cool paragraph. \n And this is a footer.',
|
||||
fontSize: 14,
|
||||
fontFamily: 'Calibri',
|
||||
@ -364,42 +365,43 @@ suite('Text', function() {
|
||||
assert.equal(text.getLineHeight(), 20);
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
test('text single line with ellipsis', function() {
|
||||
var stage = addStage();
|
||||
var layer = new Konva.Layer();
|
||||
// ======================================================
|
||||
test('text single line with ellipsis', function() {
|
||||
var stage = addStage();
|
||||
var layer = new Konva.Layer();
|
||||
|
||||
var rect = new Konva.Rect({
|
||||
x: 10,
|
||||
y: 10,
|
||||
width: 380,
|
||||
height: 300,
|
||||
fill: 'red'
|
||||
});
|
||||
|
||||
var text = new Konva.Text({
|
||||
x: 10,
|
||||
y: 10,
|
||||
text: "HEADING\n\nAll 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: 100,
|
||||
padding: 0,
|
||||
lineHeight: 20,
|
||||
align: 'center',
|
||||
wrap: 'none',
|
||||
ellipsis: true
|
||||
});
|
||||
|
||||
layer.add(rect).add(text);
|
||||
stage.add(layer);
|
||||
|
||||
assert.equal(text.textArr.length, 3);
|
||||
assert.equal(text.textArr[2].text.slice(-1), '…');
|
||||
var rect = new Konva.Rect({
|
||||
x: 10,
|
||||
y: 10,
|
||||
width: 380,
|
||||
height: 300,
|
||||
fill: 'red'
|
||||
});
|
||||
|
||||
var text = new Konva.Text({
|
||||
x: 10,
|
||||
y: 10,
|
||||
text:
|
||||
"HEADING\n\nAll 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: 100,
|
||||
padding: 0,
|
||||
lineHeight: 20,
|
||||
align: 'center',
|
||||
wrap: 'none',
|
||||
ellipsis: true
|
||||
});
|
||||
|
||||
layer.add(rect).add(text);
|
||||
stage.add(layer);
|
||||
|
||||
assert.equal(text.textArr.length, 3);
|
||||
assert.equal(text.textArr[2].text.slice(-1), '…');
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
test('text multi line with justify align', function() {
|
||||
var stage = addStage();
|
||||
@ -416,7 +418,8 @@ suite('Text', function() {
|
||||
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.",
|
||||
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',
|
||||
@ -448,7 +451,7 @@ suite('Text', function() {
|
||||
stage.add(layer);
|
||||
|
||||
var trace =
|
||||
'fillStyle;fillText();translate();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();restore();translate();save();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();restore();translate();restore();restore();';
|
||||
'translate();fillStyle;fillText();translate();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();restore();translate();save();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();fillStyle;fillText();translate();restore();translate();restore();';
|
||||
|
||||
assert.equal(layer.getContext().getTrace(true), trace);
|
||||
});
|
||||
@ -463,7 +466,8 @@ suite('Text', function() {
|
||||
y: 10,
|
||||
//stroke: '#555',
|
||||
//strokeWidth: 5,
|
||||
text: "HEADING\n\nAll the world's a stage, and all the men and women merely players. They have their exits and their entrances; And one man in his time plays many parts.",
|
||||
text:
|
||||
"HEADING\n\nAll the world's a stage, and all the men and women merely players. They have their exits and their entrances; And one man in his time plays many parts.",
|
||||
//text: 'HEADING\n\nThis is a really cool paragraph. \n And this is a footer.',
|
||||
fontSize: 16,
|
||||
fontFamily: 'Calibri',
|
||||
@ -528,11 +532,11 @@ suite('Text', function() {
|
||||
|
||||
layer.add(text);
|
||||
stage.add(layer);
|
||||
// TODO
|
||||
|
||||
var trace =
|
||||
'clearRect();save();transform();font;textBaseline;textAlign;save();translate();save();save();beginPath();moveTo();lineTo();stroke();restore();fillStyle;fillText();restore();translate();save();save();beginPath();moveTo();lineTo();stroke();restore();fillStyle;fillText();restore();translate();restore();restore();';
|
||||
console.log(layer.getContext().getTrace(true));
|
||||
'clearRect();save();transform();font;textBaseline;textAlign;translate();save();save();beginPath();moveTo();lineTo();stroke();restore();fillStyle;fillText();restore();translate();save();save();beginPath();moveTo();lineTo();stroke();restore();fillStyle;fillText();restore();translate();restore();';
|
||||
// console.log(layer.getContext().getTrace(true));
|
||||
// console.log(trace);
|
||||
assert.equal(layer.getContext().getTrace(true), trace);
|
||||
});
|
||||
|
||||
@ -553,7 +557,7 @@ suite('Text', function() {
|
||||
stage.add(layer);
|
||||
|
||||
var trace =
|
||||
'clearRect();save();transform();font;textBaseline;textAlign;save();translate();save();save();beginPath();moveTo();lineTo();stroke();restore();save();beginPath();moveTo();lineTo();stroke();restore();fillStyle;fillText();restore();translate();save();save();beginPath();moveTo();lineTo();stroke();restore();save();beginPath();moveTo();lineTo();stroke();restore();fillStyle;fillText();restore();translate();restore();restore();';
|
||||
'clearRect();save();transform();font;textBaseline;textAlign;translate();save();save();beginPath();moveTo();lineTo();stroke();restore();save();beginPath();moveTo();lineTo();stroke();restore();fillStyle;fillText();restore();translate();save();save();beginPath();moveTo();lineTo();stroke();restore();save();beginPath();moveTo();lineTo();stroke();restore();fillStyle;fillText();restore();translate();restore();';
|
||||
assert.equal(layer.getContext().getTrace(true), trace);
|
||||
});
|
||||
|
||||
@ -721,4 +725,27 @@ suite('Text', function() {
|
||||
assert.equal(data[2], 0, 'no blue');
|
||||
assert.equal(data[3], 255, '255 alpha - fully visible');
|
||||
});
|
||||
|
||||
test('text should be centered in line height', function() {
|
||||
var stage = addStage();
|
||||
var layer = new Konva.Layer();
|
||||
|
||||
var text = new Konva.Text({
|
||||
fontSize: 40,
|
||||
text: 'Some good text',
|
||||
lineHeight: 3,
|
||||
draggable: true
|
||||
});
|
||||
layer.add(text);
|
||||
stage.add(layer);
|
||||
|
||||
// this text should look like it is positioned in y = 40
|
||||
|
||||
var trace =
|
||||
'clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);font=normal normal 40px Arial;textBaseline=middle;textAlign=left;translate(0,60);save();fillStyle=black;fillText(Some good text,0,0);restore();restore();';
|
||||
|
||||
console.log(layer.getContext().getTrace());
|
||||
console.log(trace);
|
||||
assert.equal(layer.getContext().getTrace(), trace);
|
||||
});
|
||||
});
|
||||
|
@ -989,7 +989,7 @@ suite('Transformer', function() {
|
||||
x: 50,
|
||||
y: 1
|
||||
});
|
||||
assert.equal(stage.content.style.cursor, 'nwse-resize');
|
||||
assert.equal(stage.content.style.cursor, 'nesw-resize');
|
||||
});
|
||||
|
||||
test('stopTransform method', function() {
|
||||
|
Loading…
Reference in New Issue
Block a user