huge changes to Text shape. Skinnied it up by removing rectangle rendering component. textFill is now fill, textStroke is now stroke, textShadow is now shadow, and textStrokeWidth is now strokeWidth

This commit is contained in:
Eric Rowell 2012-12-31 12:45:32 -08:00
parent 356661ecff
commit 7cb4c4269f
6 changed files with 144 additions and 250 deletions

View File

@ -17,7 +17,6 @@
* @param {Number} config.width default is auto
* @param {Number} config.height default is auto
* @param {Number} config.lineHeight default is 1.2
* @param {Number} config.cornerRadius
*/
Kinetic.Text = function(config) {
this._initText(config);
@ -35,8 +34,6 @@
padding: 0,
width: 'auto',
height: 'auto',
detectionType: 'path',
cornerRadius: 0,
lineHeight: 1.2
});
@ -57,15 +54,7 @@
that._setTextData();
},
drawFunc: function(canvas) {
var context = canvas.getContext();
// draw rect
Kinetic.Rect.prototype.drawFunc.call(this, canvas);
// draw text
var p = this.attrs.padding;
var lineHeightPx = this.attrs.lineHeight * this.getTextHeight();
var textArr = this.textArr;
var context = canvas.getContext(), p = this.attrs.padding, lineHeightPx = this.attrs.lineHeight * this.getTextHeight(), textArr = this.textArr;
context.font = this.attrs.fontStyle + ' ' + this.attrs.fontSize + 'pt ' + this.attrs.fontFamily;
context.textBaseline = 'middle';
@ -73,7 +62,7 @@
context.save();
context.translate(p, 0);
context.translate(0, p + this.getTextHeight() / 2);
// draw text lines
for(var n = 0; n < textArr.length; n++) {
var text = textArr[n];
@ -93,7 +82,14 @@
}
context.restore();
},
drawHitFunc: Kinetic.Rect.prototype.drawFunc,
drawHitFunc: function(canvas) {
var context = canvas.getContext(), width = this.getWidth(), height = this.getHeight();
context.beginPath();
context.rect(0, 0, width, height);
context.closePath();
canvas.fillStroke(this);
},
/**
* set text
* @name setText
@ -149,23 +145,6 @@
height: parseInt(this.attrs.fontSize, 10)
};
},
/**
* set text shadow object
* @name setTextShadow
* @methodOf Kinetic.Text.prototype
* @param {Object} config
* @param {String} config.color
* @param {Number} config.blur
* @param {Array|Object|Number} config.offset
* @param {Number} config.opacity
*/
setTextShadow: function(config) {
var type = Kinetic.Type;
if(config.offset !== undefined) {
config.offset = type._getXY(config.offset);
}
this.setAttr('textShadow', type._merge(config, this.getTextShadow()));
},
/**
* set text data. wrap logic and width and height setting occurs
* here
@ -239,27 +218,27 @@
* extend canvas renderers
*/
var fillText = function(shape, text, skipShadow) {
var textFill = shape.getTextFill(), textShadow = shape.getTextShadow(), context = this.context;
var textFill = shape.getFill(), context = this.context;
if(textFill) {
context.save();
if(!skipShadow && textShadow) {
this._applyTextShadow(shape);
if(!skipShadow && shape.hasShadow()) {
this._applyShadow(shape);
}
context.fillStyle = textFill;
context.fillText(text, 0, 0);
context.restore();
if(!skipShadow && textShadow && textShadow.opacity) {
if(!skipShadow && shape.hasShadow()) {
this.fillText(shape, text, true);
}
}
};
var strokeText = function(shape, text, skipShadow) {
var textStroke = shape.getTextStroke(), textStrokeWidth = shape.getTextStrokeWidth(), textShadow = shape.getTextShadow(), context = this.context;
var textStroke = shape.getStroke(), textStrokeWidth = shape.getStrokeWidth(), context = this.context;
if(textStroke || textStrokeWidth) {
context.save();
if(!skipShadow && textShadow) {
this._applyTextShadow(shape);
if(!skipShadow && shape.hasShadow()) {
this._applyShadow(shape);
}
context.lineWidth = textStrokeWidth || 2;
@ -267,51 +246,29 @@
context.strokeText(text, 0, 0);
context.restore();
if(!skipShadow && textShadow && textShadow.opacity) {
if(!skipShadow && shape.hasShadow()) {
this.strokeText(shape, text, true);
}
}
};
var fillStrokeText = function(shape, text) {
this.fillText(shape, text);
this.strokeText(shape, text, shape.getTextShadow() && shape.getTextFill());
this.strokeText(shape, text, shape.hasShadow() && shape.getFill());
};
var _applyTextShadow = function(shape) {
var textShadow = shape.getTextShadow(), context = this.context;
if(textShadow) {
var aa = shape.getAbsoluteOpacity();
// defaults
var color = textShadow.color || 'black';
var blur = textShadow.blur || 5;
var offset = textShadow.offset || {
x: 0,
y: 0
};
if(textShadow.opacity) {
context.globalAlpha = textShadow.opacity * aa;
}
context.shadowColor = color;
context.shadowBlur = blur;
context.shadowOffsetX = offset.x;
context.shadowOffsetY = offset.y;
}
};
// scene canvases
Kinetic.SceneCanvas.prototype.fillText = fillText;
Kinetic.SceneCanvas.prototype.strokeText = strokeText;
Kinetic.SceneCanvas.prototype.fillStrokeText = fillStrokeText;
Kinetic.SceneCanvas.prototype._applyTextShadow = _applyTextShadow;
// hit canvases
Kinetic.HitCanvas.prototype.fillText = fillText;
Kinetic.HitCanvas.prototype.strokeText = strokeText;
Kinetic.HitCanvas.prototype.fillStrokeText = fillStrokeText;
Kinetic.HitCanvas.prototype._applyTextShadow = _applyTextShadow;
// add getters setters
Kinetic.Node.addGettersSetters(Kinetic.Text, ['fontFamily', 'fontSize', 'fontStyle', 'textFill', 'textStroke', 'textStrokeWidth', 'padding', 'align', 'lineHeight', 'cornerRadius']);
Kinetic.Node.addGetters(Kinetic.Text, ['text', 'textShadow']);
Kinetic.Node.addGettersSetters(Kinetic.Text, ['fontFamily', 'fontSize', 'fontStyle', 'padding', 'align', 'lineHeight']);
Kinetic.Node.addGetters(Kinetic.Text, ['text']);
/**
* set font family
* @name setFontFamily
@ -333,27 +290,6 @@
* @param {String} fontStyle
*/
/**
* set text fill color
* @name setTextFill
* @methodOf Kinetic.Text.prototype
* @param {String} textFill
*/
/**
* set text stroke color
* @name setFontStroke
* @methodOf Kinetic.Text.prototype
* @param {String} textStroke
*/
/**
* set text stroke width
* @name setTextStrokeWidth
* @methodOf Kinetic.Text.prototype
* @param {int} textStrokeWidth
*/
/**
* set padding
* @name setPadding
@ -393,24 +329,6 @@
* @methodOf Kinetic.Text.prototype
*/
/**
* get text fill color
* @name getTextFill
* @methodOf Kinetic.Text.prototype
*/
/**
* get text stroke color
* @name getTextStroke
* @methodOf Kinetic.Text.prototype
*/
/**
* get text stroke width
* @name getTextStrokeWidth
* @methodOf Kinetic.Text.prototype
*/
/**
* get padding
* @name getPadding

View File

@ -104,7 +104,7 @@ Test.prototype = {
this.counter++;
console.log(this.counter + ') ' + key);
tests[key](key);
obj.testMessage.innerHTML = this.counter + ') ' + key + ': PASSED';
obj.testMessage.innerHTML = this.counter + ') ' + mod + ' - ' + key + ': PASSED';
obj.testMessage.setAttribute('class', 'gray');
}
}

View File

@ -792,13 +792,11 @@ Test.Modules.MANUAL = {
stroke: 'blue',
strokeWidth: 5,
lineJoin: "round",
shadow: {
color: '#aaa',
blur: 10,
offset: {
x: 5,
y: 5
}
shadowColor: '#aaa',
shadowBlur: 10,
shadowOffset: {
x: 5,
y: 5
},
draggable: true
});
@ -1025,12 +1023,10 @@ Test.Modules.MANUAL = {
var hbox = new Kinetic.Text({
x: 380,
y: 70,
fill: "#00D2FF",
strokeWidth: 4,
fontSize: 18,
fontFamily: "Calibri",
text: "shiftKey",
textFill: "black",
fill: "black",
padding: 15,
draggable: true,
dragBoundFunc: function(pos, evt) {
@ -1046,13 +1042,11 @@ Test.Modules.MANUAL = {
var vbox = new Kinetic.Text({
x: 70,
y: 70,
fill: "yellow",
strokeWidth: 4,
draggable: true,
fontSize: 18,
fontFamily: "Calibri",
text: "diagonal",
textFill: "black",
fill: "black",
padding: 15,
draggable: true,
dragBoundFunc: function(pos) {

View File

@ -289,9 +289,7 @@ Test.Modules.NODE = {
text: 'Some awesome text!',
fontSize: 14,
fontFamily: 'Calibri',
textFill: 'blue',
shadowColor: 'black',
shadowOffset: [20, 20],
fill: 'blue',
name: 'myText'
});
group.add(rect);
@ -326,9 +324,9 @@ Test.Modules.NODE = {
test(group.getChildren().length === 2, 'group should have two children');
test(clone.getChildren().length === 2, 'clone should have two children');
test(group.get('.myText')[0].getTextFill() === 'blue', 'group text should be blue');
test(clone.get('.myText')[0].getTextFill() === 'blue', 'clone text should be blue');
clone.get('.myText')[0].setTextFill('black');
test(group.get('.myText')[0].getFill() === 'blue', 'group text should be blue');
test(clone.get('.myText')[0].getFill() === 'blue', 'clone text should be blue');
clone.get('.myText')[0].setFill('black');
test(group.get('.myRect')[0].attrs.myAttr === 'group rect', 'group rect should have myAttr: group rect');
test(clone.get('.myRect')[0].attrs.myAttr === 'group rect', 'clone rect should have myAttr: group rect');
clone.get('.myRect')[0].setAttrs({
@ -338,8 +336,8 @@ Test.Modules.NODE = {
// Make sure that when we change a clone object attr that the rect object
// attr isn't updated by reference
test(group.get('.myText')[0].getTextFill() === 'blue', 'group text should be blue');
test(clone.get('.myText')[0].getTextFill() === 'black', 'clone text should be blue');
test(group.get('.myText')[0].getFill() === 'blue', 'group text should be blue');
test(clone.get('.myText')[0].getFill() === 'black', 'clone text should be blue');
test(group.get('.myRect')[0].attrs.myAttr === 'group rect', 'group rect should have myAttr: group rect');
test(clone.get('.myRect')[0].attrs.myAttr === 'clone rect', 'clone rect should have myAttr: clone rect');

View File

@ -260,5 +260,73 @@ Test.Modules.SHAPE = {
};
imageObj.src = '../assets/darth-vader.jpg';
},
'test size setters and getters': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 50,
fill: 'red'
});
var ellipse = new Kinetic.Ellipse({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: {
x: 100,
y: 50
},
fill: 'yellow'
});
layer.add(ellipse);
layer.add(circle);
stage.add(layer);
// circle tests
test(circle.attrs.width === undefined, 'circle.attrs.width should be undefined');
test(circle.attrs.height === undefined, 'circle.attrs.height should be undefined');
test(circle.getWidth() === 100, 'circle width should be 100');
test(circle.getHeight() === 100, 'circle height should be 100');
test(circle.getSize().width === 100, 'circle width should be 100');
test(circle.getSize().height === 100, 'circle height should be 100');
test(circle.getRadius() === 50, 'circle radius should be 50');
circle.setWidth(200);
test(circle.attrs.width === 200, 'circle.attrs.width should be 200');
test(circle.attrs.height === undefined, 'circle.attrs.height should be undefined');
test(circle.getWidth() === 200, 'circle width should be 200');
test(circle.getHeight() === 200, 'circle height should be 200');
test(circle.getSize().width === 200, 'circle width should be 200');
test(circle.getSize().height === 200, 'circle height should be 200');
test(circle.getRadius() === 100, 'circle radius should be 100');
// ellipse tests
test(ellipse.attrs.width === undefined, 'ellipse.attrs.width should be undefined');
test(ellipse.attrs.height === undefined, 'ellipse.attrs.height should be undefined');
test(ellipse.getWidth() === 200, 'ellipse width should be 200');
test(ellipse.getHeight() === 100, 'ellipse height should be 100');
test(ellipse.getSize().width === 200, 'ellipse width should be 200');
test(ellipse.getSize().height === 100, 'ellipse height should be 100');
test(ellipse.getRadius().x === 100, 'ellipse radius x should be 100');
ellipse.setWidth(400);
test(ellipse.attrs.width === 400, 'ellipse.attrs.width should be 400');
test(ellipse.attrs.height === undefined, 'ellipse.attrs.height should be undefined');
test(ellipse.getWidth() === 400, 'ellipse width should be 400');
test(ellipse.getHeight() === 100, 'ellipse height should be 100');
test(ellipse.getSize().width === 400, 'ellipse width should be 400');
test(ellipse.getSize().height === 100, 'ellipse height should be 100');
test(ellipse.getRadius().x === 200, 'ellipse radius x should be 200');
}
};

View File

@ -1,5 +1,5 @@
Test.Modules.Text = {
'add text with shadows': function(containerId) {
'add text with shadows': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
@ -7,44 +7,52 @@ Test.Modules.Text = {
});
var layer = new Kinetic.Layer();
var text = new Kinetic.Text({
var rect = new Kinetic.Rect({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
stroke: '#555',
strokeWidth: 5,
fill: '#ddd',
width: 400,
height: 100,
shadowColor: 'black',
shadowBlur: 1,
shadowOffset: [10, 10],
shadowOpacity: 0.2,
cornerRadius: 10
});
var text = new Kinetic.Text({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
text: 'Hello World!',
fontSize: 50,
fontFamily: 'Calibri',
fontStyle: 'normal',
textFill: '#888',
textStroke: '#333',
fill: '#888',
stroke: '#333',
align: 'right',
lineHeight: 1.2,
width: 400,
height: 100,
padding: 10,
shadowColor: 'black',
shadowColor: 'red',
shadowBlur: 1,
shadowOffset: [10, 10],
shadowOpacity: 0.2,
textShadow: {
color: 'red',
blur: 1,
offset: [10, 10],
opacity: 0.2
},
cornerRadius: 10,
shadowOpacity: 0.2
});
var group = new Kinetic.Group({
draggable: true
});
// center text box
rect.setOffset(text.getWidth() / 2, text.getHeight() / 2);
text.setOffset(text.getWidth() / 2, text.getHeight() / 2);
layer.add(text);
group.add(rect);
group.add(text);
layer.add(group);
stage.add(layer);
},
'text getters and setters': function(containerId) {
@ -58,15 +66,12 @@ Test.Modules.Text = {
var text = new Kinetic.Text({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
stroke: '#555',
strokeWidth: 5,
fill: '#ddd',
text: 'Hello World!',
fontSize: 50,
fontFamily: 'Calibri',
fontStyle: 'normal',
textFill: '#888',
textStroke: '#333',
fill: '#888',
stroke: '#333',
align: 'right',
lineHeight: 1.2,
width: 400,
@ -76,7 +81,6 @@ Test.Modules.Text = {
shadowBlur: 1,
shadowOffset: [10, 10],
shadowOpacity: 0.2,
cornerRadius: 10,
draggable: true
});
@ -92,22 +96,19 @@ Test.Modules.Text = {
test(text.getX() === stage.getWidth() / 2, 'text box x should be in center of stage');
test(text.getY() === stage.getHeight() / 2, 'text box y should be in center of stage');
test(text.getStroke() === '#555', 'text box stroke should be #555');
test(text.getStrokeWidth() === 5, 'text box stroke width should be 5');
test(text.getFill() === '#ddd', 'text box fill should be #ddd');
test(text.getText() === 'Hello World!', 'text should be Hello World!');
test(text.getFontSize() == 50, 'font size should 50');
test(text.getFontFamily() == 'Calibri', 'font family should be Calibri');
test(text.getFontStyle() == 'normal', 'font style should be normal');
test(text.getTextFill() == '#888', 'text fill should be #888');
test(text.getTextStroke() == '#333', 'text fill should be #333');
test(text.getFill() == '#888', 'text fill should be #888');
test(text.getStroke() == '#333', 'text fill should be #333');
test(text.getAlign() === 'right', 'text should be aligned right');
test(text.getLineHeight() === 1.2, 'line height should be 1.2');
test(text.getWidth() === 400, 'width should be 400');
test(text.getHeight() === 100, 'height should be 100');
test(text.getPadding() === 10, 'padding should be 10');
test(text.getShadowColor() === 'black', 'text box shadow color should be black');
test(text.getCornerRadius() === 10, 'text box corner radius should be 10');
test(text.getDraggable() === true, 'text should be draggable');
test(text.getWidth() === 400, 'box width should be 400');
@ -117,40 +118,32 @@ Test.Modules.Text = {
text.setX(1);
text.setY(2);
text.setStroke('orange');
text.setStrokeWidth(20);
text.setFill('red');
text.setText('bye world!');
text.setFontSize(10);
text.setFontFamily('Arial');
text.setFontStyle('bold');
text.setTextFill('green');
text.setTextStroke('yellow');
text.setFill('green');
text.setStroke('yellow');
text.setAlign('left');
text.setWidth(300);
text.setHeight(75);
text.setPadding(20);
text.setShadowColor('green');
text.setCornerRadius(20);
text.setDraggable(false);
test(text.getX() === 1, 'text box x should be 1');
test(text.getY() === 2, 'text box y should be 2');
test(text.getStroke() === 'orange', 'text box stroke should be orange');
test(text.getStrokeWidth() === 20, 'text box stroke width should be 20');
test(text.getFill() === 'red', 'text box fill should be red');
test(text.getText() === 'bye world!', 'text should be bye world!');
test(text.getFontSize() == 10, 'font size should 10');
test(text.getFontFamily() == 'Arial', 'font family should be Arial');
test(text.getFontStyle() == 'bold', 'font style should be bold');
test(text.getTextFill() == 'green', 'text fill should be green');
test(text.getTextStroke() == 'yellow', 'text fill should be yellow');
test(text.getFill() == 'green', 'text fill should be green');
test(text.getStroke() == 'yellow', 'text fill should be yellow');
test(text.getAlign() === 'left', 'text should be aligned left');
test(text.getWidth() === 300, 'width should be 300');
test(text.getHeight() === 75, 'height should be 75');
test(text.getPadding() === 20, 'padding should be 20');
test(text.getShadowColor() === 'green', 'text box shadow color should be green');
test(text.getCornerRadius() === 20, 'text box corner radius should be 20');
test(text.getDraggable() === false, 'text draggable should be false');
// test set text to integer
@ -161,74 +154,6 @@ Test.Modules.Text = {
//layer.setListening(false);
layer.drawHit();
},
'test size setters and getters': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 50,
fill: 'red'
});
var ellipse = new Kinetic.Ellipse({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: {
x: 100,
y: 50
},
fill: 'yellow'
});
layer.add(ellipse);
layer.add(circle);
stage.add(layer);
// circle tests
test(circle.attrs.width === undefined, 'circle.attrs.width should be undefined');
test(circle.attrs.height === undefined, 'circle.attrs.height should be undefined');
test(circle.getWidth() === 100, 'circle width should be 100');
test(circle.getHeight() === 100, 'circle height should be 100');
test(circle.getSize().width === 100, 'circle width should be 100');
test(circle.getSize().height === 100, 'circle height should be 100');
test(circle.getRadius() === 50, 'circle radius should be 50');
circle.setWidth(200);
test(circle.attrs.width === 200, 'circle.attrs.width should be 200');
test(circle.attrs.height === undefined, 'circle.attrs.height should be undefined');
test(circle.getWidth() === 200, 'circle width should be 200');
test(circle.getHeight() === 200, 'circle height should be 200');
test(circle.getSize().width === 200, 'circle width should be 200');
test(circle.getSize().height === 200, 'circle height should be 200');
test(circle.getRadius() === 100, 'circle radius should be 100');
// ellipse tests
test(ellipse.attrs.width === undefined, 'ellipse.attrs.width should be undefined');
test(ellipse.attrs.height === undefined, 'ellipse.attrs.height should be undefined');
test(ellipse.getWidth() === 200, 'ellipse width should be 200');
test(ellipse.getHeight() === 100, 'ellipse height should be 100');
test(ellipse.getSize().width === 200, 'ellipse width should be 200');
test(ellipse.getSize().height === 100, 'ellipse height should be 100');
test(ellipse.getRadius().x === 100, 'ellipse radius x should be 100');
ellipse.setWidth(400);
test(ellipse.attrs.width === 400, 'ellipse.attrs.width should be 400');
test(ellipse.attrs.height === undefined, 'ellipse.attrs.height should be undefined');
test(ellipse.getWidth() === 400, 'ellipse width should be 400');
test(ellipse.getHeight() === 100, 'ellipse height should be 100');
test(ellipse.getSize().width === 400, 'ellipse width should be 400');
test(ellipse.getSize().height === 100, 'ellipse height should be 100');
test(ellipse.getRadius().x === 200, 'ellipse radius x should be 200');
},
'text multi line': function(containerId) {
var stage = new Kinetic.Stage({
@ -241,15 +166,12 @@ Test.Modules.Text = {
var text = new Kinetic.Text({
x: 10,
y: 10,
stroke: '#555',
strokeWidth: 5,
fill: '#ddd',
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',
fontStyle: 'normal',
textFill: '#555',
fill: '#555',
//width: 20,
width: 380,
//width: 200,
@ -259,9 +181,7 @@ Test.Modules.Text = {
shadowBlur: 1,
shadowOffset: [10, 10],
shadowOpacity: 0.2,
cornerRadius: 10,
draggable: true,
detectionType: 'path'
draggable: true
});
// center text box
@ -295,7 +215,7 @@ Test.Modules.Text = {
fontSize: 16,
fontFamily: 'Calibri',
fontStyle: 'normal',
textFill: '#555',
fill: '#555',
//width: 20,
width: 380,
//width: 200,
@ -305,9 +225,7 @@ Test.Modules.Text = {
shadowBlur: 1,
shadowOffset: [10, 10],
shadowOpacity: 0.5,
cornerRadius: 10,
draggable: true,
detectionType: 'path'
draggable: true
});
layer.add(text);
@ -326,16 +244,14 @@ Test.Modules.Text = {
var text = new Kinetic.Text({
x: 10,
y: 10,
fill: '#ddd',
text: 'Some awesome text',
fontSize: 16,
fontFamily: 'Calibri',
fontStyle: 'normal',
textFill: '#555',
fill: '#555',
align: 'center',
padding: 5,
draggable: true,
detectionType: 'path'
draggable: true
});
var width = text.getWidth();