mirror of
https://github.com/konvajs/konva.git
synced 2025-09-18 18:27:58 +08:00
finished up new Scene and Hit Renderers. added new textShadow attrs for more flexibility. Added new fillStroke() method which encapsulates shadow application logic
This commit is contained in:
223
src/Shape.js
223
src/Shape.js
@@ -98,49 +98,6 @@ Kinetic.Shape = (function() {
|
||||
getCanvas: function() {
|
||||
return this.getLayer().getCanvas();
|
||||
},
|
||||
/**
|
||||
* helper method to stroke the shape
|
||||
* @name stroke
|
||||
* @methodOf Kinetic.Shape.prototype
|
||||
*/
|
||||
stroke: function(context, stroke, strokeWidth, shadow) {
|
||||
if(context.type === 'scene') {
|
||||
return this._strokeScene(context, stroke, strokeWidth, shadow);
|
||||
}
|
||||
else if(context.type === 'hit') {
|
||||
return this._strokeHit(context, strokeWidth);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
_strokeScene: function(context, stroke, strokeWidth, shadow) {
|
||||
if(stroke || strokeWidth) {
|
||||
context.save();
|
||||
var appliedShadow = this._applyShadow(context, shadow);
|
||||
context.lineWidth = strokeWidth || 2;
|
||||
context.strokeStyle = stroke || 'black';
|
||||
context.stroke(context);
|
||||
context.restore();
|
||||
|
||||
if(appliedShadow) {
|
||||
if(shadow.opacity) {
|
||||
this._strokeScene(context, stroke);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
_strokeHit: function(context, strokeWidth) {
|
||||
var stroke = this.colorKey;
|
||||
if(stroke || strokeWidth) {
|
||||
context.save();
|
||||
context.lineWidth = strokeWidth || 2;
|
||||
context.strokeStyle = stroke || 'black';
|
||||
context.stroke(context);
|
||||
context.restore();
|
||||
}
|
||||
return false;
|
||||
},
|
||||
_getFillType: function(fill) {
|
||||
var type = Kinetic.Type;
|
||||
if(!fill) {
|
||||
@@ -163,111 +120,36 @@ Kinetic.Shape = (function() {
|
||||
}
|
||||
},
|
||||
/**
|
||||
* helper method to fill and stroke shape based on fill and stroke properties,
|
||||
* and also automatically handle shadows, line joins, and line caps
|
||||
* @name render
|
||||
* @methodOf Kinetic.Shape.prototype
|
||||
*/
|
||||
render: function(context) {
|
||||
this.applyLineJoin(context, this.getLineJoin());
|
||||
this.applyLineCap(context, this.getLineCap());
|
||||
if(context.type === 'scene') {
|
||||
this.applyOpacity(context);
|
||||
}
|
||||
|
||||
var appliedShadow = this.fill(context, this.getFill(), this.getShadow());
|
||||
this.stroke(context, this.getStroke(), this.getStrokeWidth(), appliedShadow ? null : this.getShadow());
|
||||
},
|
||||
/**
|
||||
* helper method to fill the shape
|
||||
* fill current path
|
||||
* @name fill
|
||||
* @methodOf Kinetic.Shape.prototype
|
||||
*/
|
||||
fill: function(context, fill, shadow) {
|
||||
if(context.type === 'scene') {
|
||||
return this._fillScene(context, fill, shadow);
|
||||
}
|
||||
else if(context.type === 'hit') {
|
||||
return this._fillHit(context);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
_fillScene: function(context, fill, shadow) {
|
||||
var fillType = this._getFillType(fill);
|
||||
if(fill) {
|
||||
context.save();
|
||||
|
||||
var appliedShadow = this._applyShadow(context, shadow);
|
||||
var s = fill.start;
|
||||
var e = fill.end;
|
||||
|
||||
// color fill
|
||||
switch(fillType) {
|
||||
case 'COLOR':
|
||||
context.fillStyle = fill;
|
||||
context.fill(context);
|
||||
break;
|
||||
case 'PATTERN':
|
||||
var repeat = !fill.repeat ? 'repeat' : fill.repeat;
|
||||
if(fill.scale) {
|
||||
context.scale(fill.scale.x, fill.scale.y);
|
||||
}
|
||||
if(fill.offset) {
|
||||
context.translate(fill.offset.x, fill.offset.y);
|
||||
}
|
||||
|
||||
context.fillStyle = context.createPattern(fill.image, repeat);
|
||||
context.fill(context);
|
||||
break;
|
||||
case 'LINEAR_GRADIENT':
|
||||
var grd = context.createLinearGradient(s.x, s.y, e.x, e.y);
|
||||
var colorStops = fill.colorStops;
|
||||
|
||||
// build color stops
|
||||
for(var n = 0; n < colorStops.length; n += 2) {
|
||||
grd.addColorStop(colorStops[n], colorStops[n + 1]);
|
||||
}
|
||||
context.fillStyle = grd;
|
||||
context.fill(context);
|
||||
|
||||
break;
|
||||
case 'RADIAL_GRADIENT':
|
||||
var grd = context.createRadialGradient(s.x, s.y, s.radius, e.x, e.y, e.radius);
|
||||
var colorStops = fill.colorStops;
|
||||
|
||||
// build color stops
|
||||
for(var n = 0; n < colorStops.length; n += 2) {
|
||||
grd.addColorStop(colorStops[n], colorStops[n + 1]);
|
||||
}
|
||||
context.fillStyle = grd;
|
||||
context.fill(context);
|
||||
break;
|
||||
default:
|
||||
context.fillStyle = 'black';
|
||||
context.fill(context);
|
||||
break;
|
||||
}
|
||||
|
||||
context.restore();
|
||||
|
||||
if(appliedShadow) {
|
||||
if(shadow.opacity) {
|
||||
this._fillScene(context, fill);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
_fillHit: function(context) {
|
||||
context.save();
|
||||
context.fillStyle = this.colorKey;
|
||||
context.fill(context);
|
||||
context.restore();
|
||||
return false;
|
||||
fill: function(context) {
|
||||
context.renderer._fill(this);
|
||||
},
|
||||
/**
|
||||
* helper method to draw an image
|
||||
* stroke current path
|
||||
* @name stroke
|
||||
* @methodOf Kinetic.Shape.prototype
|
||||
*/
|
||||
stroke: function(context) {
|
||||
context.renderer._stroke(this);
|
||||
},
|
||||
/**
|
||||
* fill and stroke current path. Aside from being a convenience method
|
||||
* which fills and strokes the current path with a single method, its main purpose is
|
||||
* to ensure that the shadow object is not applied to both the fill and stroke. A shadow
|
||||
* will only be applied to either the fill or stroke. Fill
|
||||
* is given priority over stroke.
|
||||
* @name fillStroke
|
||||
* @methodOf Kinetic.Shape.prototype
|
||||
*/
|
||||
fillStroke: function(context) {
|
||||
context.renderer._fill(this);
|
||||
context.renderer._stroke(this, this.getShadow() && this.getFill());
|
||||
},
|
||||
/**
|
||||
* draw an image
|
||||
* @name drawImage
|
||||
* @methodOf Kinetic.Shape.prototype
|
||||
*/
|
||||
@@ -287,34 +169,20 @@ Kinetic.Shape = (function() {
|
||||
|
||||
context.restore();
|
||||
},
|
||||
applyOpacity: function(context) {
|
||||
_applyOpacity: function(context) {
|
||||
var absOpacity = this.getAbsoluteOpacity();
|
||||
if(absOpacity !== 1) {
|
||||
context.globalAlpha = absOpacity;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* helper method to set the line join of a shape
|
||||
* based on the applyLineJoin property
|
||||
* @name lineJoin
|
||||
* @methodOf Kinetic.Shape.prototype
|
||||
* @param {CanvasContext} context
|
||||
* @param {String} lineJoin
|
||||
*/
|
||||
applyLineJoin: function(context, lineJoin) {
|
||||
_applyLineJoin: function(context) {
|
||||
var lineJoin = this.getLineJoin();
|
||||
if(lineJoin) {
|
||||
context.lineJoin = lineJoin;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* helper method to set the line cap of a path
|
||||
* based on the lineCap property
|
||||
* @name applyLineCap
|
||||
* @methodOf Kinetic.Shape.prototype
|
||||
* @param {CanvasContext} context
|
||||
* @param {String} lineCap
|
||||
*/
|
||||
applyLineCap: function(context, lineCap) {
|
||||
_applyLineCap: function(context) {
|
||||
var lineCap = this.getLineCap();
|
||||
if(lineCap) {
|
||||
context.lineCap = lineCap;
|
||||
}
|
||||
@@ -391,29 +259,6 @@ Kinetic.Shape = (function() {
|
||||
_get: function(selector) {
|
||||
return this.nodeType === selector || this.shapeType === selector ? [this] : [];
|
||||
},
|
||||
_applyShadow: function(context, shadow) {
|
||||
if(shadow) {
|
||||
var aa = this.getAbsoluteOpacity();
|
||||
// defaults
|
||||
var color = shadow.color || 'black';
|
||||
var blur = shadow.blur || 5;
|
||||
var offset = shadow.offset || {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
|
||||
if(shadow.opacity) {
|
||||
context.globalAlpha = shadow.opacity * aa;
|
||||
}
|
||||
context.shadowColor = color;
|
||||
context.shadowBlur = blur;
|
||||
context.shadowOffsetX = offset.x;
|
||||
context.shadowOffsetY = offset.y;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
/**
|
||||
* determines if point is in the shape
|
||||
* @param {Object|Array} point point can be an object containing
|
||||
@@ -447,6 +292,9 @@ Kinetic.Shape = (function() {
|
||||
}
|
||||
|
||||
context.save();
|
||||
this._applyOpacity(context);
|
||||
this._applyLineJoin(context);
|
||||
this._applyLineCap(context);
|
||||
var len = family.length;
|
||||
for(var n = 0; n < len; n++) {
|
||||
var node = family[n], t = node.getTransform(), m = t.getMatrix();
|
||||
@@ -470,6 +318,9 @@ Kinetic.Shape = (function() {
|
||||
}
|
||||
|
||||
context.save();
|
||||
this._applyOpacity(context);
|
||||
this._applyLineJoin(context);
|
||||
this._applyLineCap(context);
|
||||
var len = family.length;
|
||||
for(var n = 0; n < len; n++) {
|
||||
var node = family[n], t = node.getTransform(), m = t.getMatrix();
|
||||
@@ -493,6 +344,8 @@ Kinetic.Shape = (function() {
|
||||
}
|
||||
|
||||
context.save();
|
||||
this._applyLineJoin(context);
|
||||
this._applyLineCap(context);
|
||||
var len = family.length;
|
||||
for(var n = 0; n < len; n++) {
|
||||
var node = family[n], t = node.getTransform(), m = t.getMatrix();
|
||||
|
@@ -27,7 +27,7 @@ Kinetic.Circle.prototype = {
|
||||
context.beginPath();
|
||||
context.arc(0, 0, this.getRadius(), 0, Math.PI * 2, true);
|
||||
context.closePath();
|
||||
this.render(context);
|
||||
this.fillStroke(context);
|
||||
},
|
||||
getWidth: function() {
|
||||
return this.getRadius() * 2;
|
||||
|
@@ -36,7 +36,7 @@ Kinetic.Ellipse.prototype = {
|
||||
context.arc(0, 0, r.x, 0, Math.PI * 2, true);
|
||||
context.restore();
|
||||
context.closePath();
|
||||
this.render(context);
|
||||
this.fillStroke(context);
|
||||
},
|
||||
/**
|
||||
* set radius
|
||||
|
@@ -36,7 +36,7 @@ Kinetic.Image.prototype = {
|
||||
context.beginPath();
|
||||
context.rect(0, 0, width, height);
|
||||
context.closePath();
|
||||
this.render(context);
|
||||
this.fillStroke(context);
|
||||
|
||||
if(this.attrs.image) {
|
||||
// if cropping
|
||||
@@ -59,7 +59,7 @@ Kinetic.Image.prototype = {
|
||||
context.beginPath();
|
||||
context.rect(0, 0, width, height);
|
||||
context.closePath();
|
||||
this.render(context);
|
||||
this.fillStroke(context);
|
||||
|
||||
if(imageBuffer) {
|
||||
this.drawImage(context, this.imageBuffer, 0, 0, width, height);
|
||||
|
@@ -47,7 +47,7 @@ Kinetic.Line.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
this.stroke(context, this.getStroke(), this.getStrokeWidth(), this.getShadow());
|
||||
this.stroke(context);
|
||||
},
|
||||
/**
|
||||
* set points array
|
||||
|
@@ -68,7 +68,7 @@ Kinetic.Path.prototype = {
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.render(context);
|
||||
this.fillStroke(context);
|
||||
}
|
||||
};
|
||||
Kinetic.Global.extend(Kinetic.Path, Kinetic.Shape);
|
||||
|
@@ -30,7 +30,7 @@ Kinetic.Polygon.prototype = {
|
||||
context.lineTo(this.attrs.points[n].x, this.attrs.points[n].y);
|
||||
}
|
||||
context.closePath();
|
||||
this.render(context);
|
||||
this.fillStroke(context);
|
||||
},
|
||||
/**
|
||||
* set points array
|
||||
|
@@ -42,7 +42,7 @@ Kinetic.Rect.prototype = {
|
||||
}
|
||||
context.closePath();
|
||||
|
||||
this.render(context);
|
||||
this.fillStroke(context);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -34,7 +34,7 @@ Kinetic.RegularPolygon.prototype = {
|
||||
context.lineTo(x, y);
|
||||
}
|
||||
context.closePath();
|
||||
this.render(context);
|
||||
this.fillStroke(context);
|
||||
}
|
||||
};
|
||||
Kinetic.Global.extend(Kinetic.RegularPolygon, Kinetic.Shape);
|
||||
|
@@ -35,11 +35,6 @@ Kinetic.Sprite.prototype = {
|
||||
var index = this.attrs.index;
|
||||
var f = this.attrs.animations[anim][index];
|
||||
|
||||
context.beginPath();
|
||||
context.rect(0, 0, f.width, f.height);
|
||||
context.closePath();
|
||||
this.render(context);
|
||||
|
||||
if(this.attrs.image) {
|
||||
|
||||
context.beginPath();
|
||||
@@ -57,8 +52,7 @@ Kinetic.Sprite.prototype = {
|
||||
context.beginPath();
|
||||
context.rect(0, 0, f.width, f.height);
|
||||
context.closePath();
|
||||
this.fill(context, this.getFill(), null);
|
||||
this.stroke(context, this.getStroke(), this.getStrokeWidth(), null);
|
||||
this.fillStroke(context);
|
||||
},
|
||||
/**
|
||||
* start sprite animation
|
||||
|
@@ -37,7 +37,7 @@ Kinetic.Star.prototype = {
|
||||
}
|
||||
context.closePath();
|
||||
|
||||
this.render(context);
|
||||
this.fillStroke(context);
|
||||
}
|
||||
};
|
||||
Kinetic.Global.extend(Kinetic.Star, Kinetic.Shape);
|
||||
|
@@ -68,7 +68,7 @@ Kinetic.Text.prototype = {
|
||||
}
|
||||
context.closePath();
|
||||
|
||||
this.render(context);
|
||||
this.fillStroke(context);
|
||||
/*
|
||||
* draw text
|
||||
*/
|
||||
@@ -96,10 +96,8 @@ Kinetic.Text.prototype = {
|
||||
context.translate((this.getWidth() - this._getTextSize(text).width - p * 2) / 2, 0);
|
||||
}
|
||||
|
||||
var appliedShadow = this.fillText(context, text, this.getTextFill(), this.getShadow());
|
||||
this.strokeText(context, text, this.getTextStroke(), this.getTextStrokeWidth(), appliedShadow ? null : this.getShadow());
|
||||
this.fillStrokeText(context, text);
|
||||
context.restore();
|
||||
|
||||
context.translate(0, lineHeightPx);
|
||||
}
|
||||
context.restore();
|
||||
@@ -128,7 +126,7 @@ Kinetic.Text.prototype = {
|
||||
}
|
||||
context.closePath();
|
||||
|
||||
this.render(context);
|
||||
this.fillStroke(context);
|
||||
},
|
||||
/**
|
||||
* set text
|
||||
@@ -185,92 +183,60 @@ Kinetic.Text.prototype = {
|
||||
height: parseInt(this.attrs.fontSize, 10)
|
||||
};
|
||||
},
|
||||
/**
|
||||
* helper method to fill text
|
||||
* @param {String} text
|
||||
* @name fillText
|
||||
* @methodOf Kinetic.Text.prototype
|
||||
*/
|
||||
fillText: function(context, text, textFill, shadow) {
|
||||
if(context.type === 'scene') {
|
||||
return this._fillTextScene(context, text, textFill, shadow);
|
||||
}
|
||||
else if(context.type === 'hit') {
|
||||
return this._fillTextHit(context, text);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
_fillTextScene: function(context, text, textFill, shadow) {
|
||||
fillText: function(context, text, skipShadow) {
|
||||
var textFill = this.getTextFill(), shadow = this.getShadow();
|
||||
if(textFill) {
|
||||
context.save();
|
||||
var appliedShadow = this._applyShadow(context, shadow);
|
||||
if(!skipShadow && shadow) {
|
||||
this._applyTextShadow(context);
|
||||
}
|
||||
context.fillStyle = textFill;
|
||||
context.fillText(text, 0, 0);
|
||||
context.restore();
|
||||
|
||||
if(appliedShadow) {
|
||||
if(shadow.opacity) {
|
||||
this._fillTextScene(context, text, textFill);
|
||||
return true;
|
||||
if(!skipShadow && shadow && shadow.opacity) {
|
||||
this.fillText(context, text, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
_fillTextHit: function(context, text) {
|
||||
context.save();
|
||||
context.fillStyle = this.colorKey;
|
||||
context.fillText(text, 0, 0);
|
||||
context.restore();
|
||||
return false;
|
||||
},
|
||||
/**
|
||||
* helper method to stroke text
|
||||
* if needed
|
||||
* @name strokeText
|
||||
* @methodOf Kinetic.Shape.prototype
|
||||
* @param {String} text
|
||||
*/
|
||||
strokeText: function(context, text, textStroke, textStrokeWidth, shadow) {
|
||||
if(context.type === 'scene') {
|
||||
this._strokeTextScene(context, text, textStroke, textStrokeWidth, shadow);
|
||||
}
|
||||
else if(context.type === 'hit') {
|
||||
this._strokeTextHit(context, text, textStrokeWidth);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
_strokeTextScene: function(context, text, textStroke, textStrokeWidth, shadow) {
|
||||
strokeText: function(context, text, skipShadow) {
|
||||
var textStroke = this.getTextStroke(), textStrokeWidth = this.getTextStrokeWidth(), shadow = this.getShadow();
|
||||
if(textStroke || textStrokeWidth) {
|
||||
context.save();
|
||||
var appliedShadow = this._applyShadow(context, shadow);
|
||||
// defaults
|
||||
textStroke = textStroke || 'black';
|
||||
textStrokeWidth = textStrokeWidth || 2;
|
||||
context.lineWidth = textStrokeWidth;
|
||||
context.strokeStyle = textStroke;
|
||||
if(!skipShadow && shadow) {
|
||||
this._applyTextShadow(context);
|
||||
}
|
||||
|
||||
context.lineWidth = textStrokeWidth || 2;
|
||||
context.strokeStyle = textStroke || 'black';
|
||||
context.strokeText(text, 0, 0);
|
||||
context.restore();
|
||||
|
||||
if(appliedShadow) {
|
||||
if(shadow.opacity) {
|
||||
this._strokeTextScene(context, text, textStroke, textStrokeWidth);
|
||||
return true;
|
||||
if(!skipShadow && shadow && shadow.opacity) {
|
||||
this.strokeText(context, text, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
_strokeTextHit: function(context, text, textStrokeWidth) {
|
||||
context.save();
|
||||
// defaults
|
||||
var textStroke = this.colorKey ? this.colorKey : 'black';
|
||||
var textStrokeWidth = textStrokeWidth || 2;
|
||||
context.lineWidth = textStrokeWidth;
|
||||
context.strokeStyle = textStroke;
|
||||
context.strokeText(text, 0, 0);
|
||||
context.restore();
|
||||
return false;
|
||||
fillStrokeText: function(context, text) {
|
||||
this.fillText(context, text);
|
||||
this.strokeText(context, text, this.getTextShadow() && this.getTextFill());
|
||||
},
|
||||
/**
|
||||
* 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
|
||||
@@ -337,13 +303,34 @@ Kinetic.Text.prototype = {
|
||||
row++;
|
||||
}
|
||||
this.textArr = arr;
|
||||
},
|
||||
_applyTextShadow: function(context) {
|
||||
var textShadow = this.getTextShadow();
|
||||
if(textShadow) {
|
||||
var aa = this.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;
|
||||
}
|
||||
}
|
||||
};
|
||||
Kinetic.Global.extend(Kinetic.Text, Kinetic.Shape);
|
||||
|
||||
// add getters setters
|
||||
Kinetic.Node.addGettersSetters(Kinetic.Text, ['fontFamily', 'fontSize', 'fontStyle', 'textFill', 'textStroke', 'textStrokeWidth', 'padding', 'align', 'lineHeight']);
|
||||
Kinetic.Node.addGetters(Kinetic.Text, ['text']);
|
||||
Kinetic.Node.addGetters(Kinetic.Text, ['text', 'textShadow']);
|
||||
/**
|
||||
* set font family
|
||||
* @name setFontFamily
|
||||
|
@@ -70,7 +70,7 @@ Kinetic.TextPath.prototype = {
|
||||
context.translate(p0.x, p0.y);
|
||||
context.rotate(glyphInfo[i].rotation);
|
||||
|
||||
this.render(context);
|
||||
this.fillStrokeText(context);
|
||||
|
||||
context.restore();
|
||||
|
||||
@@ -307,11 +307,9 @@ Kinetic.Node.addGetters(Kinetic.TextPath, ['text']);
|
||||
|
||||
// reference Text methods
|
||||
Kinetic.TextPath.prototype.fillText = Kinetic.Text.prototype.fillText;
|
||||
Kinetic.TextPath.prototype._fillTextScene = Kinetic.Text.prototype._fillTextScene;
|
||||
Kinetic.TextPath.prototype._fillTextHit = Kinetic.Text.prototype._fillTextHit;
|
||||
Kinetic.TextPath.prototype.strokeText = Kinetic.Text.prototype.strokeText;
|
||||
Kinetic.TextPath.prototype._strokeTextScene = Kinetic.Text.prototype._strokeTextScene;
|
||||
Kinetic.TextPath.prototype._strokeTextHit = Kinetic.Text.prototype._strokeTextHit;
|
||||
Kinetic.TextPath.prototype.fillStrokeText = Kinetic.Text.prototype.strokeText;
|
||||
|
||||
/**
|
||||
* set font family
|
||||
* @name setFontFamily
|
||||
|
@@ -12,8 +12,7 @@ Kinetic.Canvas = function(width, height, isHit) {
|
||||
this.element.width = width || 0;
|
||||
this.element.height = height || 0;
|
||||
|
||||
// set type
|
||||
this.context.type = isHit ? 'hit' : 'scene';
|
||||
this.context.renderer = isHit ? new Kinetic.HitRenderer(this.context) : new Kinetic.SceneRenderer(this.context);
|
||||
};
|
||||
|
||||
Kinetic.Canvas.prototype = {
|
||||
@@ -98,3 +97,137 @@ Kinetic.Canvas.prototype = {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Kinetic.SceneRenderer = function(context) {
|
||||
this.context = context;
|
||||
};
|
||||
|
||||
Kinetic.SceneRenderer.prototype = {
|
||||
_fill: function(shape, skipShadow) {
|
||||
var context = this.context, fill = shape.getFill(), fillType = shape._getFillType(fill), shadow = shape.getShadow();
|
||||
if(fill) {
|
||||
context.save();
|
||||
|
||||
if(!skipShadow && shadow) {
|
||||
this._applyShadow(shape);
|
||||
}
|
||||
var s = fill.start;
|
||||
var e = fill.end;
|
||||
|
||||
// color fill
|
||||
switch(fillType) {
|
||||
case 'COLOR':
|
||||
context.fillStyle = fill;
|
||||
context.fill(context);
|
||||
break;
|
||||
case 'PATTERN':
|
||||
var repeat = !fill.repeat ? 'repeat' : fill.repeat;
|
||||
if(fill.scale) {
|
||||
context.scale(fill.scale.x, fill.scale.y);
|
||||
}
|
||||
if(fill.offset) {
|
||||
context.translate(fill.offset.x, fill.offset.y);
|
||||
} file:///C:/Users/Eric/Documents/Eric/workspaces/KineticJS/dist/kinetic-current.js
|
||||
|
||||
context.fillStyle = context.createPattern(fill.image, repeat);
|
||||
context.fill(context);
|
||||
break;
|
||||
case 'LINEAR_GRADIENT':
|
||||
var grd = context.createLinearGradient(s.x, s.y, e.x, e.y);
|
||||
var colorStops = fill.colorStops;
|
||||
|
||||
// build color stops
|
||||
for(var n = 0; n < colorStops.length; n += 2) {
|
||||
grd.addColorStop(colorStops[n], colorStops[n + 1]);
|
||||
}
|
||||
context.fillStyle = grd;
|
||||
context.fill(context);
|
||||
|
||||
break;
|
||||
case 'RADIAL_GRADIENT':
|
||||
var grd = context.createRadialGradient(s.x, s.y, s.radius, e.x, e.y, e.radius);
|
||||
var colorStops = fill.colorStops;
|
||||
|
||||
// build color stops
|
||||
for(var n = 0; n < colorStops.length; n += 2) {
|
||||
grd.addColorStop(colorStops[n], colorStops[n + 1]);
|
||||
}
|
||||
context.fillStyle = grd;
|
||||
context.fill(context);
|
||||
break;
|
||||
default:
|
||||
context.fillStyle = 'black';
|
||||
context.fill(context);
|
||||
break;
|
||||
}
|
||||
|
||||
context.restore();
|
||||
|
||||
if(!skipShadow && shadow && shadow.opacity) {
|
||||
this._fill(shape, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
_stroke: function(shape, skipShadow) {
|
||||
var context = this.context, stroke = shape.getStroke(), strokeWidth = shape.getStrokeWidth(), shadow = shape.getShadow();
|
||||
if(stroke || strokeWidth) {
|
||||
context.save();
|
||||
if(!skipShadow && shadow) {
|
||||
this._applyShadow(shape);
|
||||
}
|
||||
context.lineWidth = strokeWidth || 2;
|
||||
context.strokeStyle = stroke || 'black';
|
||||
context.stroke(context);
|
||||
context.restore();
|
||||
|
||||
if(!skipShadow && shadow && shadow.opacity) {
|
||||
this._stroke(shape, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
_applyShadow: function(shape) {
|
||||
var context = this.context, shadow = shape.getShadow();
|
||||
if(shadow) {
|
||||
var aa = shape.getAbsoluteOpacity();
|
||||
// defaults
|
||||
var color = shadow.color || 'black';
|
||||
var blur = shadow.blur || 5;
|
||||
var offset = shadow.offset || {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
|
||||
if(shadow.opacity) {
|
||||
context.globalAlpha = shadow.opacity * aa;
|
||||
}
|
||||
context.shadowColor = color;
|
||||
context.shadowBlur = blur;
|
||||
context.shadowOffsetX = offset.x;
|
||||
context.shadowOffsetY = offset.y;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Kinetic.HitRenderer = function(context) {
|
||||
this.context = context;
|
||||
};
|
||||
|
||||
Kinetic.HitRenderer.prototype = {
|
||||
_fill: function(shape) {
|
||||
var context = this.context;
|
||||
context.save();
|
||||
context.fillStyle = shape.colorKey;
|
||||
context.fill(context);
|
||||
context.restore();
|
||||
},
|
||||
_stroke: function(shape) {
|
||||
var context = this.context, stroke = shape.colorKey, strokeWidth = shape.getStrokeWidth();
|
||||
if(stroke || strokeWidth) {
|
||||
context.save();
|
||||
context.lineWidth = strokeWidth || 2;
|
||||
context.strokeStyle = stroke || 'black';
|
||||
context.stroke(context);
|
||||
context.restore();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -141,7 +141,8 @@ Test.Modules.SHAPE = {
|
||||
context.lineTo(100, 0);
|
||||
context.lineTo(100, 100);
|
||||
context.closePath();
|
||||
this.render(context);
|
||||
this.fill(context);
|
||||
this.stroke(context);
|
||||
},
|
||||
x: 200,
|
||||
y: 100,
|
||||
@@ -156,7 +157,8 @@ Test.Modules.SHAPE = {
|
||||
context.lineTo(200, 0);
|
||||
context.lineTo(200, 100);
|
||||
context.closePath();
|
||||
this.render(context);
|
||||
this.fill(context);
|
||||
this.stroke(context);
|
||||
});
|
||||
var rect = new Kinetic.Rect({
|
||||
x: 10,
|
||||
@@ -175,7 +177,8 @@ Test.Modules.SHAPE = {
|
||||
context.lineTo(200, 0);
|
||||
context.lineTo(200, 100);
|
||||
context.closePath();
|
||||
this.render(context);
|
||||
this.fill(context);
|
||||
this.stroke(context);
|
||||
});
|
||||
|
||||
layer.add(shape);
|
||||
|
@@ -1,4 +1,53 @@
|
||||
Test.Modules.Text = {
|
||||
'add text with shadows': function(containerId) {
|
||||
var stage = new Kinetic.Stage({
|
||||
container: containerId,
|
||||
width: 578,
|
||||
height: 200
|
||||
});
|
||||
var layer = new Kinetic.Layer();
|
||||
|
||||
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',
|
||||
align: 'right',
|
||||
lineHeight: 1.2,
|
||||
width: 400,
|
||||
height: 100,
|
||||
padding: 10,
|
||||
|
||||
shadow: {
|
||||
color: 'black',
|
||||
blur: 1,
|
||||
offset: [10, 10],
|
||||
opacity: 0.2
|
||||
},
|
||||
textShadow: {
|
||||
color: 'red',
|
||||
blur: 1,
|
||||
offset: [10, 10],
|
||||
opacity: 0.2
|
||||
},
|
||||
|
||||
cornerRadius: 10,
|
||||
draggable: true
|
||||
});
|
||||
|
||||
// center text box
|
||||
text.setOffset(text.getWidth() / 2, text.getHeight() / 2);
|
||||
|
||||
layer.add(text);
|
||||
stage.add(layer);
|
||||
},
|
||||
'text getters and setters': function(containerId) {
|
||||
var stage = new Kinetic.Stage({
|
||||
container: containerId,
|
||||
|
Reference in New Issue
Block a user