new Canvas class to decouple layer and canvas, providing more flexibility. drawing operations now require a canvas object rather than an optional layer which contained a canvas. fixed some transformation issues introduced with a pull request that I pulled in last week

This commit is contained in:
Eric Rowell 2012-07-18 23:28:45 -07:00
parent 20adf7e036
commit d8bbbf6353
24 changed files with 548 additions and 555 deletions

View File

@ -3,7 +3,7 @@ require 'json/pure'
class Build < Thor
# This is the list of files to concatenate. The first file will appear at the top of the final file. All files are relative to the lib directory.
FILES = [
"license.js", "src/Global.js", "src/util/Type.js", "src/util/Class.js", "src/Animation.js", "src/Node.js", "src/Container.js", "src/Stage.js",
"license.js", "src/Global.js", "src/util/Type.js", "src/util/Canvas.js", "src/util/Class.js", "src/Animation.js", "src/Node.js", "src/Container.js", "src/Stage.js",
"src/Layer.js", "src/Group.js", "src/Shape.js", "src/shapes/Rect.js", "src/shapes/Ellipse.js", "src/shapes/Image.js",
"src/shapes/Sprite.js", "src/shapes/Polygon.js", "src/shapes/RegularPolygon.js", "src/shapes/Star.js", "src/shapes/Text.js",
"src/shapes/Line.js", "src/shapes/Path.js", "src/util/Transform.js", "src/Transition.js", "src/util/Tween.js", "src/filters/Grayscale.js"

523
dist/kinetic-core.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -211,18 +211,18 @@ Kinetic.Container = Kinetic.Node.extend({
/**
* draw children
*/
_drawChildren: function(layer) {
_drawChildren: function(canvas) {
var stage = this.getStage();
var children = this.children;
for(var n = 0; n < children.length; n++) {
var child = children[n];
if(child.nodeType === 'Shape') {
if(child.isVisible() && stage.isVisible()) {
child._draw( layer ? layer : child.getLayer());
child._draw(canvas);
}
}
else {
child.draw(layer);
child.draw(canvas);
}
}
},
@ -230,27 +230,8 @@ Kinetic.Container = Kinetic.Node.extend({
* set children indices
*/
_setChildrenIndices: function() {
/*
* if reordering Layers, remove all canvas elements
* from the container except the buffer and backstage canvases
* and then readd all the layers
*/
if(this.nodeType === 'Stage') {
var canvases = this.content.children;
var bufferCanvas = canvases[0];
var backstageCanvas = canvases[1];
this.content.innerHTML = '';
this.content.appendChild(bufferCanvas);
this.content.appendChild(backstageCanvas);
}
for(var n = 0; n < this.children.length; n++) {
this.children[n].index = n;
if(this.nodeType === 'Stage') {
this.content.appendChild(this.children[n].canvas);
}
}
}
});

View File

@ -14,12 +14,12 @@ Kinetic.Group = Kinetic.Container.extend({
// call super constructor
this._super(config);
},
draw: function(layer) {
this._draw(layer);
draw: function(canvas) {
this._draw(canvas);
},
_draw: function(layer) {
_draw: function(canvas) {
if(this.attrs.visible) {
this._drawChildren(layer);
this._drawChildren(canvas);
}
}
});

View File

@ -20,9 +20,8 @@ Kinetic.Layer = Kinetic.Container.extend({
this.beforeDrawFunc = undefined;
this.afterDrawFunc = undefined;
this.canvas = document.createElement('canvas');
this.context = this.canvas.getContext('2d');
this.canvas.style.position = 'absolute';
this.canvas = new Kinetic.Canvas();
this.canvas.getElement().style.position = 'absolute';
// call super constructor
this._super(config);
@ -33,7 +32,7 @@ Kinetic.Layer = Kinetic.Container.extend({
* @name draw
* @methodOf Kinetic.Layer.prototype
*/
draw: function(layer) {
draw: function(canvas) {
var throttle = this.attrs.throttle;
var date = new Date();
var time = date.getTime();
@ -41,7 +40,7 @@ Kinetic.Layer = Kinetic.Container.extend({
var tt = 1000 / throttle;
if(timeDiff >= tt || throttle > 200) {
this._draw(layer);
this._draw(canvas);
if(this.drawTimeout !== undefined) {
clearTimeout(this.drawTimeout);
@ -58,7 +57,7 @@ Kinetic.Layer = Kinetic.Container.extend({
* wait 17ms before trying again (60fps)
*/
this.drawTimeout = setTimeout(function() {
that.draw(layer);
that.draw(canvas);
}, 17);
}
},
@ -78,19 +77,6 @@ Kinetic.Layer = Kinetic.Container.extend({
afterDraw: function(func) {
this.afterDrawFunc = func;
},
/**
* clears the canvas context tied to the layer. Clearing
* a layer does not remove its children. The nodes within
* the layer will be redrawn whenever the .draw() method
* is used again.
* @name clear
* @methodOf Kinetic.Layer.prototype
*/
clear: function() {
var context = this.getContext();
var canvas = this.getCanvas();
context.clearRect(0, 0, canvas.width, canvas.height);
},
/**
* get layer canvas
* @name getCanvas
@ -100,12 +86,12 @@ Kinetic.Layer = Kinetic.Container.extend({
return this.canvas;
},
/**
* get layer context
* get layer canvas context
* @name getContext
* @methodOf Kinetic.Layer.prototype
*/
getContext: function() {
return this.context;
return this.canvas.context;
},
/**
* Creates a composite data URL. If MIME type is not
@ -115,7 +101,7 @@ Kinetic.Layer = Kinetic.Container.extend({
* based on what's draw on the layer, rather than drawing
* the current state of each child node
* @name toDataURL
* @methodOf Kinetic.Stage.prototype
* @methodOf Kinetic.Layer.prototype
* @param {String} [mimeType]
* @param {Number} [quality]
*/
@ -123,16 +109,24 @@ Kinetic.Layer = Kinetic.Container.extend({
try {
// If this call fails (due to browser bug, like in Firefox 3.6),
// then revert to previous no-parameter image/png behavior
return this.getCanvas().toDataURL(mimeType, quality);
return this.getCanvas().element.toDataURL(mimeType, quality);
}
catch(e) {
return this.getCanvas().toDataURL();
return this.getCanvas().element.toDataURL();
}
},
/**
* private draw children
*/
_draw: function(layer) {
_draw: function(canvas) {
/*
* if canvas is not defined, then use the canvas
* tied to the layer
*/
if(!canvas) {
canvas = this.getCanvas();
}
var date = new Date();
var time = date.getTime();
this.lastDrawTime = time;
@ -143,8 +137,7 @@ Kinetic.Layer = Kinetic.Container.extend({
}
if(this.attrs.clearBeforeDraw) {
var clearLayer = layer ? layer : this;
clearLayer.clear();
canvas.clear();
}
if(this.isVisible()) {
@ -154,7 +147,7 @@ Kinetic.Layer = Kinetic.Container.extend({
}
// draw children
this._drawChildren(layer);
this._drawChildren(canvas);
}
// after draw handler

View File

@ -386,7 +386,10 @@ Kinetic.Node = Kinetic.Class.extend({
* @methodOf Kinetic.Node.prototype
*/
getAbsolutePosition: function() {
return this.getAbsoluteTransform().getTranslation();
var trans = this.getAbsoluteTransform();
var o = this.getOffset();
trans.translate(o.x, o.y);
return trans.getTranslation();
},
/**
* set absolute position relative to stage
@ -416,9 +419,16 @@ Kinetic.Node = Kinetic.Class.extend({
x: 1,
y: 1
};
this.attrs.offset = {
x: 0,
y: 0
};
var o = this.getOffset();
// unravel transform
var it = this.getAbsoluteTransform();
it.invert();
it.translate(pos.x, pos.y);
pos = {
@ -434,6 +444,10 @@ Kinetic.Node = Kinetic.Class.extend({
x: scale.x,
y: scale.y
};
this.attrs.offset = {
x: offset.x,
y: offset.y
};
},
/**
* move node by an amount
@ -727,7 +741,6 @@ Kinetic.Node = Kinetic.Class.extend({
for(var n = 0; n < family.length; n++) {
var node = family[n];
var m = node.getTransform();
am.multiply(m);
}
@ -803,14 +816,14 @@ Kinetic.Node = Kinetic.Class.extend({
saveImageData: function() {
try {
var stage = this.getStage();
var bufferLayer = stage.bufferLayer;
var bufferLayerContext = bufferLayer.getContext();
var bufferCanvas = stage.bufferCanvas;
var bufferContext = bufferCanvas.getContext();
var width = stage.getWidth();
var height = stage.getHeight();
bufferLayer.clear();
this._draw(bufferLayer);
var imageData = bufferLayerContext.getImageData(0, 0, width, height);
bufferCanvas.clear();
this._draw(bufferCanvas);
var imageData = bufferContext.getImageData(0, 0, width, height);
this.imageData = imageData;
}
catch(e) {
@ -838,24 +851,23 @@ Kinetic.Node = Kinetic.Class.extend({
* specified, then "image/png" will result. For "image/jpeg", specify a quality
* level as quality (range 0.0 - 1.0)
* @name toDataURL
* @methodOf Kinetic.Stage.prototype
* @methodOf Kinetic.Node.prototype
* @param {String} [mimeType]
* @param {Number} [quality]
*/
toDataURL: function(mimeType, quality) {
var bufferLayer = this.getStage().bufferLayer;
var bufferCanvas = bufferLayer.getCanvas();
var bufferContext = bufferLayer.getContext();
bufferLayer.clear();
this._draw(bufferLayer);
var bufferCanvas = this.getStage().bufferCanvas;
var bufferContext = bufferCanvas.getContext();
bufferCanvas.clear();
this._draw(bufferCanvas);
try {
// If this call fails (due to browser bug, like in Firefox 3.6),
// then revert to previous no-parameter image/png behavior
return bufferLayer.getCanvas().toDataURL(mimeType, quality);
return bufferCanvas.element.toDataURL(mimeType, quality);
}
catch(e) {
return bufferLayer.getCanvas().toDataURL();
return bufferCanvas.element.toDataURL();
}
},
/**
@ -910,9 +922,10 @@ Kinetic.Node = Kinetic.Class.extend({
if(pos) {
var m = this.getTransform().getTranslation();
var am = this.getAbsoluteTransform().getTranslation();
var ap = this.getAbsolutePosition();
go.drag.node = this;
go.drag.offset.x = pos.x - this.getAbsoluteTransform().getTranslation().x;
go.drag.offset.y = pos.y - this.getAbsoluteTransform().getTranslation().y;
go.drag.offset.x = pos.x - ap.x;
go.drag.offset.y = pos.y - ap.y;
}
},
_onDraggableChange: function() {

View File

@ -30,24 +30,20 @@ Kinetic.Shape = Kinetic.Node.extend({
this._super(config);
},
/**
* get layer context where the shape is being drawn. When
* the shape is being rendered, .getContext() returns the context of the
* user created layer that contains the shape. When the event detection
* engine is determining whether or not an event has occured on that shape,
* .getContext() returns the context of the invisible path layer.
* get canvas context tied to the layer
* @name getContext
* @methodOf Kinetic.Shape.prototype
*/
getContext: function() {
return this.tempLayer.getContext();
return this.getLayer().getContext();
},
/**
* get shape temp layer canvas
* get canvas tied to the layer
* @name getCanvas
* @methodOf Kinetic.Shape.prototype
*/
getCanvas: function() {
return this.tempLayer.getCanvas();
return this.getLayer().getCanvas();
},
/**
* helper method to stroke the shape and apply
@ -55,15 +51,14 @@ Kinetic.Shape = Kinetic.Node.extend({
* @name stroke
* @methodOf Kinetic.Shape.prototype
*/
stroke: function() {
stroke: function(context) {
var go = Kinetic.Global;
var appliedShadow = false;
var context = this.getContext();
if(this.attrs.stroke || this.attrs.strokeWidth) {
context.save();
if(this.attrs.shadow && !this.appliedShadow) {
appliedShadow = this._applyShadow();
appliedShadow = this._applyShadow(context);
}
var stroke = this.attrs.stroke ? this.attrs.stroke : 'black';
@ -71,12 +66,12 @@ Kinetic.Shape = Kinetic.Node.extend({
context.lineWidth = strokeWidth;
context.strokeStyle = stroke;
context.stroke();
context.stroke(context);
context.restore();
}
if(appliedShadow) {
this.stroke();
this.stroke(context);
}
},
/**
@ -85,16 +80,15 @@ Kinetic.Shape = Kinetic.Node.extend({
* @name fill
* @methodOf Kinetic.Shape.prototype
* */
fill: function() {
fill: function(context) {
var appliedShadow = false;
var context = this.getContext();
context.save();
var fill = this.attrs.fill;
if(fill) {
if(this.attrs.shadow && !this.appliedShadow) {
appliedShadow = this._applyShadow();
appliedShadow = this._applyShadow(context);
}
var s = fill.start;
@ -105,7 +99,7 @@ Kinetic.Shape = Kinetic.Node.extend({
if( typeof fill == 'string') {
f = this.attrs.fill;
context.fillStyle = f;
context.fill();
context.fill(context);
}
// pattern
else if(fill.image) {
@ -122,12 +116,11 @@ Kinetic.Shape = Kinetic.Node.extend({
}
context.fillStyle = f;
context.fill();
context.fill(context);
context.restore();
}
// linear gradient
else if(!s.radius && !e.radius) {
var context = this.getContext();
var grd = context.createLinearGradient(s.x, s.y, e.x, e.y);
var colorStops = fill.colorStops;
@ -137,11 +130,10 @@ Kinetic.Shape = Kinetic.Node.extend({
}
f = grd;
context.fillStyle = f;
context.fill();
context.fill(context);
}
// radial gradient
else if((s.radius || s.radius === 0) && (e.radius || e.radius === 0)) {
var context = this.getContext();
var grd = context.createRadialGradient(s.x, s.y, s.radius, e.x, e.y, e.radius);
var colorStops = fill.colorStops;
@ -151,18 +143,18 @@ Kinetic.Shape = Kinetic.Node.extend({
}
f = grd;
context.fillStyle = f;
context.fill();
context.fill(context);
}
else {
f = 'black';
context.fillStyle = f;
context.fill();
context.fill(context);
}
}
context.restore();
if(appliedShadow) {
this.fill();
this.fill(context);
}
},
/**
@ -171,13 +163,12 @@ Kinetic.Shape = Kinetic.Node.extend({
* @name fillText
* @methodOf Kinetic.Shape.prototype
*/
fillText: function(text) {
fillText: function(context, text) {
var appliedShadow = false;
var context = this.getContext();
context.save();
if(this.attrs.textFill) {
if(this.attrs.shadow && !this.appliedShadow) {
appliedShadow = this._applyShadow();
appliedShadow = this._applyShadow(context);
}
context.fillStyle = this.attrs.textFill;
context.fillText(text, 0, 0);
@ -185,7 +176,7 @@ Kinetic.Shape = Kinetic.Node.extend({
context.restore();
if(appliedShadow) {
this.fillText(text, 0, 0);
this.fillText(context, text, 0, 0);
}
},
/**
@ -195,13 +186,12 @@ Kinetic.Shape = Kinetic.Node.extend({
* @methodOf Kinetic.Shape.prototype
* @param {String} text
*/
strokeText: function(text) {
strokeText: function(context, text) {
var appliedShadow = false;
var context = this.getContext();
context.save();
if(this.attrs.textStroke || this.attrs.textStrokeWidth) {
if(this.attrs.shadow && !this.appliedShadow) {
appliedShadow = this._applyShadow();
appliedShadow = this._applyShadow(context);
}
// defaults
@ -213,12 +203,12 @@ Kinetic.Shape = Kinetic.Node.extend({
}
context.lineWidth = this.attrs.textStrokeWidth;
context.strokeStyle = this.attrs.textStroke;
context.strokeText(text, 0, 0);
context.strokeText(context, text, 0, 0);
}
context.restore();
if(appliedShadow) {
this.strokeText(text, 0, 0);
this.strokeText(context, text, 0, 0);
}
},
/**
@ -229,21 +219,20 @@ Kinetic.Shape = Kinetic.Node.extend({
*/
drawImage: function() {
var appliedShadow = false;
var context = this.getContext();
var context = arguments[0];
context.save();
var a = Array.prototype.slice.call(arguments);
if(a.length === 5 || a.length === 9) {
if(a.length === 6 || a.length === 10) {
if(this.attrs.shadow && !this.appliedShadow) {
appliedShadow = this._applyShadow();
appliedShadow = this._applyShadow(context);
}
switch(a.length) {
case 5:
context.drawImage(a[0], a[1], a[2], a[3], a[4]);
break;
case 9:
context.drawImage(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]);
break;
if(a.length === 6) {
context.drawImage(a[1], a[2], a[3], a[4], a[5]);
}
else {
context.drawImage(a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);
}
}
@ -259,8 +248,7 @@ Kinetic.Shape = Kinetic.Node.extend({
* @name applyLineJoin
* @methodOf Kinetic.Shape.prototype
*/
applyLineJoin: function() {
var context = this.getContext();
applyLineJoin: function(context) {
if(this.attrs.lineJoin) {
context.lineJoin = this.attrs.lineJoin;
}
@ -269,8 +257,7 @@ Kinetic.Shape = Kinetic.Node.extend({
* apply shadow. return true if shadow was applied
* and false if it was not
*/
_applyShadow: function() {
var context = this.getContext();
_applyShadow: function(context) {
var s = this.attrs.shadow;
if(s) {
var aa = this.getAbsoluteAlpha();
@ -308,12 +295,12 @@ Kinetic.Shape = Kinetic.Node.extend({
// path detection
if(this.attrs.detectionType === 'path') {
var pathLayer = stage.pathLayer;
var pathLayerContext = pathLayer.getContext();
var pathCanvas = stage.pathCanvas;
var pathCanvasContext = pathCanvas.getContext();
this._draw(pathLayer);
this._draw(pathCanvas);
return pathLayerContext.isPointInPath(pos.x, pos.y);
return pathCanvasContext.isPointInPath(pos.x, pos.y);
}
// pixel detection
@ -326,10 +313,10 @@ Kinetic.Shape = Kinetic.Node.extend({
// default
return false;
},
_draw: function(layer) {
if(layer && this.attrs.drawFunc) {
var stage = layer.getStage();
var context = layer.getContext();
_draw: function(canvas) {
if(this.attrs.drawFunc) {
var stage = this.getStage();
var context = canvas.getContext();
var family = [];
var parent = this.parent;
@ -348,8 +335,6 @@ Kinetic.Shape = Kinetic.Node.extend({
context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
}
this.tempLayer = layer;
/*
* pre styles include alpha, linejoin
*/
@ -357,11 +342,11 @@ Kinetic.Shape = Kinetic.Node.extend({
if(absAlpha !== 1) {
context.globalAlpha = absAlpha;
}
this.applyLineJoin();
this.applyLineJoin(context);
// draw the shape
this.appliedShadow = false;
this.attrs.drawFunc.call(this);
this.attrs.drawFunc.call(this, canvas.getContext());
context.restore();
}
}

View File

@ -85,8 +85,8 @@ Kinetic.Stage = Kinetic.Container.extend({
* @name draw
* @methodOf Kinetic.Stage.prototype
*/
draw: function(layer) {
this._draw(layer);
draw: function(canvas) {
this._draw(canvas);
},
/**
* set stage size
@ -288,37 +288,25 @@ Kinetic.Stage = Kinetic.Container.extend({
* @param {Number} [quality]
*/
toDataURL: function(callback, mimeType, quality) {
/*
* we need to create a temp layer rather than using
* the bufferLayer because the stage toDataURL method
* is asynchronous, which means that other parts of the
* code base could be updating or clearing the bufferLayer
* while the stage toDataURL method is processing
*/
var tempLayer = new Kinetic.Layer();
tempLayer.getCanvas().width = this.attrs.width;
tempLayer.getCanvas().height = this.attrs.height;
tempLayer.parent = this;
var tempCanvas = tempLayer.getCanvas();
var tempContext = tempLayer.getContext();
var canvas = new Kinetic.Canvas(this.attrs.width, this.attrs.height);
var context = canvas.getContext();
var layers = this.children;
function drawLayer(n) {
var layer = layers[n];
var layerUrl;
var canvasUrl;
try {
// If this call fails (due to browser bug, like in Firefox 3.6),
// then revert to previous no-parameter image/png behavior
layerUrl = layer.getCanvas().toDataURL(mimeType, quality);
canvasUrl = canvas.getElement().toDataURL(mimeType, quality);
}
catch(e) {
layerUrl = layer.getCanvas().toDataURL();
canvasUrl = canvas.getElement().toDataURL();
}
var imageObj = new Image();
imageObj.onload = function() {
tempContext.drawImage(imageObj, 0, 0);
context.drawImage(imageObj, 0, 0);
if(n < layers.length - 1) {
drawLayer(n + 1);
@ -327,14 +315,14 @@ Kinetic.Stage = Kinetic.Container.extend({
try {
// If this call fails (due to browser bug, like in Firefox 3.6),
// then revert to previous no-parameter image/png behavior
callback(tempLayer.getCanvas().toDataURL(mimeType, quality));
callback(canvas.getElement().toDataURL(mimeType, quality));
}
catch(e) {
callback(tempLayer.getCanvas().toDataURL());
callback(canvas.getElement().toDataURL());
}
}
};
imageObj.src = layerUrl;
imageObj.src = canvasUrl;
}
drawLayer(0);
},
@ -360,18 +348,15 @@ Kinetic.Stage = Kinetic.Container.extend({
this.content.style.width = width + 'px';
this.content.style.height = height + 'px';
// set buffer layer and path layer sizes
this.bufferLayer.getCanvas().width = width;
this.bufferLayer.getCanvas().height = height;
this.pathLayer.getCanvas().width = width;
this.pathLayer.getCanvas().height = height;
// set buffer canvas and path canvas sizes
this.bufferCanvas.setSize(width, height);
this.pathCanvas.setSize(width, height);
// set user defined layer dimensions
var layers = this.children;
for(var n = 0; n < layers.length; n++) {
var layer = layers[n];
layer.getCanvas().width = width;
layer.getCanvas().height = height;
layer.getCanvas().setSize(width, height);
layer.draw();
}
},
@ -395,12 +380,11 @@ Kinetic.Stage = Kinetic.Container.extend({
* @param {Layer} layer
*/
_add: function(layer) {
layer.canvas.width = this.attrs.width;
layer.canvas.height = this.attrs.height;
layer.canvas.setSize(this.attrs.width, this.attrs.height);
// draw layer and append canvas to container
layer.draw();
this.content.appendChild(layer.canvas);
this.content.appendChild(layer.canvas.element);
/*
* set layer last draw time to zero
@ -603,7 +587,7 @@ Kinetic.Stage = Kinetic.Container.extend({
this._setMousePosition(evt);
this._setTouchPosition(evt);
this.pathLayer.clear();
this.pathCanvas.clear();
/*
* loop through layers. If at any point an event
@ -794,28 +778,6 @@ Kinetic.Stage = Kinetic.Container.extend({
left: left
};
},
/**
* modify path context
* @param {CanvasContext} context
*/
_modifyPathContext: function(context) {
context.stroke = function() {
};
context.fill = function() {
};
context.fillRect = function(x, y, width, height) {
context.rect(x, y, width, height);
};
context.strokeRect = function(x, y, width, height) {
context.rect(x, y, width, height);
};
context.drawImage = function() {
};
context.fillText = function() {
};
context.strokeText = function() {
};
},
/**
* end drag and drop
*/
@ -910,34 +872,15 @@ Kinetic.Stage = Kinetic.Container.extend({
this.content.className = 'kineticjs-content';
this.attrs.container.appendChild(this.content);
// default layers
this.bufferLayer = new Kinetic.Layer({
name: 'bufferLayer'
this.bufferCanvas = new Kinetic.Canvas({
width: this.attrs.width,
height: this.attrs.height
});
this.pathLayer = new Kinetic.Layer({
name: 'pathLayer'
this.pathCanvas = new Kinetic.Canvas({
width: this.attrs.width,
height: this.attrs.height
});
// set parents
this.bufferLayer.parent = this;
this.pathLayer.parent = this;
// customize back stage context
this._modifyPathContext(this.pathLayer.context);
// hide canvases
this.bufferLayer.getCanvas().style.display = 'none';
this.pathLayer.getCanvas().style.display = 'none';
// add buffer layer
this.bufferLayer.canvas.className = 'kineticjs-buffer-layer';
this.content.appendChild(this.bufferLayer.canvas);
// add path layer
this.pathLayer.canvas.className = 'kineticjs-path-layer';
this.content.appendChild(this.pathLayer.canvas);
this.setSize(this.attrs.width, this.attrs.height);
this.pathCanvas.strip();
this._resizeDOM();
},
_addId: function(node) {
@ -1018,8 +961,8 @@ Kinetic.Stage = Kinetic.Container.extend({
this.anim = undefined;
this.animRunning = false;
},
_draw: function(layer) {
this._drawChildren(layer);
_draw: function(canvas) {
this._drawChildren(canvas);
}
});

View File

@ -18,9 +18,7 @@ Kinetic.Ellipse = Kinetic.Shape.extend({
this.shapeType = "Ellipse";
config.drawFunc = function() {
var canvas = this.getCanvas();
var context = this.getContext();
config.drawFunc = function(context) {
var r = this.getRadius();
context.beginPath();
context.save();
@ -30,8 +28,8 @@ Kinetic.Ellipse = Kinetic.Shape.extend({
context.arc(0, 0, r.x, 0, Math.PI * 2, true);
context.restore();
context.closePath();
this.fill();
this.stroke();
this.fill(context);
this.stroke(context);
};
// call super constructor
this._super(config);

View File

@ -14,18 +14,16 @@
Kinetic.Image = Kinetic.Shape.extend({
init: function(config) {
this.shapeType = "Image";
config.drawFunc = function() {
config.drawFunc = function(context) {
if(!!this.attrs.image) {
var width = this.getWidth();
var height = this.getHeight();
var canvas = this.getCanvas();
var context = this.getContext();
context.beginPath();
context.rect(0, 0, width, height);
context.closePath();
this.fill();
this.stroke();
this.fill(context);
this.stroke(context);
// if cropping
if(this.attrs.crop && this.attrs.crop.width && this.attrs.crop.height) {
@ -33,11 +31,11 @@ Kinetic.Image = Kinetic.Shape.extend({
var cropY = this.attrs.crop.y ? this.attrs.crop.y : 0;
var cropWidth = this.attrs.crop.width;
var cropHeight = this.attrs.crop.height;
this.drawImage(this.attrs.image, cropX, cropY, cropWidth, cropHeight, 0, 0, width, height);
this.drawImage(context, this.attrs.image, cropX, cropY, cropWidth, cropHeight, 0, 0, width, height);
}
// no cropping
else {
this.drawImage(this.attrs.image, 0, 0, width, height);
this.drawImage(context, this.attrs.image, 0, 0, width, height);
}
}
};

View File

@ -17,8 +17,7 @@ Kinetic.Line = Kinetic.Shape.extend({
});
this.shapeType = "Line";
config.drawFunc = function() {
var context = this.getContext();
config.drawFunc = function(context) {
var lastPos = {};
context.beginPath();
@ -31,7 +30,7 @@ Kinetic.Line = Kinetic.Shape.extend({
// draw dashed line
var lastX = this.attrs.points[n - 1].x;
var lastY = this.attrs.points[n - 1].y;
this._dashedLine(lastX, lastY, x, y, this.attrs.dashArray);
this._dashedLine(context, lastX, lastY, x, y, this.attrs.dashArray);
}
else {
// draw normal line
@ -43,7 +42,7 @@ Kinetic.Line = Kinetic.Shape.extend({
context.lineCap = this.attrs.lineCap;
}
this.stroke();
this.stroke(context);
};
// call super constructor
this._super(config);
@ -51,8 +50,7 @@ Kinetic.Line = Kinetic.Shape.extend({
/**
* draw dashed line. Written by Phrogz
*/
_dashedLine: function(x, y, x2, y2, dashArray) {
var context = this.getContext();
_dashedLine: function(context, x, y, x2, y2, dashArray) {
var dashCount = dashArray.length;
var dx = (x2 - x), dy = (y2 - y);

View File

@ -14,8 +14,7 @@ Kinetic.Path = Kinetic.Shape.extend({
this.dataArray = [];
var that = this;
config.drawFunc = function() {
var context = this.getContext();
config.drawFunc = function(context) {
var ca = this.dataArray;
// context position
context.beginPath();
@ -56,8 +55,8 @@ Kinetic.Path = Kinetic.Shape.extend({
break;
}
}
this.fill();
this.stroke();
this.fill(context);
this.stroke(context);
};
// call super constructor
this._super(config);

View File

@ -14,16 +14,15 @@ Kinetic.Polygon = Kinetic.Shape.extend({
});
this.shapeType = "Polygon";
config.drawFunc = function() {
var context = this.getContext();
config.drawFunc = function(context) {
context.beginPath();
context.moveTo(this.attrs.points[0].x, this.attrs.points[0].y);
for(var n = 1; n < this.attrs.points.length; n++) {
context.lineTo(this.attrs.points[n].x, this.attrs.points[n].y);
}
context.closePath();
this.fill();
this.stroke();
this.fill(context);
this.stroke(context);
};
// call super constructor
this._super(config);

View File

@ -17,8 +17,7 @@ Kinetic.Rect = Kinetic.Shape.extend({
this.shapeType = "Rect";
config.drawFunc = function() {
var context = this.getContext();
config.drawFunc = function(context) {
context.beginPath();
if(this.attrs.cornerRadius === 0) {
// simple rect - don't bother doing all that complicated maths stuff.
@ -38,8 +37,8 @@ Kinetic.Rect = Kinetic.Shape.extend({
}
context.closePath();
this.fill();
this.stroke();
this.fill(context);
this.stroke(context);
};
// call super constructor
this._super(config);

View File

@ -15,8 +15,7 @@ Kinetic.RegularPolygon = Kinetic.Shape.extend({
});
this.shapeType = "RegularPolygon";
config.drawFunc = function() {
var context = this.getContext();
config.drawFunc = function(context) {
context.beginPath();
context.moveTo(0, 0 - this.attrs.radius);
@ -26,8 +25,8 @@ Kinetic.RegularPolygon = Kinetic.Shape.extend({
context.lineTo(x, y);
}
context.closePath();
this.fill();
this.stroke();
this.fill(context);
this.stroke(context);
};
// call super constructor
this._super(config);

View File

@ -14,9 +14,8 @@ Kinetic.Sprite = Kinetic.Shape.extend({
frameRate: 17
});
config.drawFunc = function() {
config.drawFunc = function(context) {
if(!!this.attrs.image) {
var context = this.getContext();
var anim = this.attrs.animation;
var index = this.attrs.index;
var f = this.attrs.animations[anim][index];
@ -25,7 +24,7 @@ Kinetic.Sprite = Kinetic.Shape.extend({
context.rect(0, 0, f.width, f.height);
context.closePath();
this.drawImage(this.attrs.image, f.x, f.y, f.width, f.height, 0, 0, f.width, f.height);
this.drawImage(context, this.attrs.image, f.x, f.y, f.width, f.height, 0, 0, f.width, f.height);
}
};
// call super constructor

View File

@ -16,8 +16,7 @@ Kinetic.Star = Kinetic.Shape.extend({
});
this.shapeType = "Star";
config.drawFunc = function() {
var context = this.getContext();
config.drawFunc = function(context) {
context.beginPath();
context.moveTo(0, 0 - this.attrs.outerRadius);
@ -29,8 +28,8 @@ Kinetic.Star = Kinetic.Shape.extend({
}
context.closePath();
this.fill();
this.stroke();
this.fill(context);
this.stroke(context);
};
// call super constructor
this._super(config);

View File

@ -27,8 +27,7 @@ Kinetic.Text = Kinetic.Shape.extend({
this.dummyCanvas = document.createElement('canvas');
this.shapeType = "Text";
config.drawFunc = function() {
var context = this.getContext();
config.drawFunc = function(context) {
/*
* draw rect
*/
@ -54,8 +53,8 @@ Kinetic.Text = Kinetic.Shape.extend({
}
context.closePath();
this.fill();
this.stroke();
this.fill(context);
this.stroke(context);
/*
* draw text
*/
@ -83,8 +82,8 @@ Kinetic.Text = Kinetic.Shape.extend({
context.translate((this.getBoxWidth() - this._getTextSize(text).width - p * 2) / 2, 0);
}
this.fillText(text);
this.strokeText(text);
this.fillText(context, text);
this.strokeText(context, text);
context.restore();
context.translate(0, lineHeightPx);

96
src/util/Canvas.js Normal file
View File

@ -0,0 +1,96 @@
///////////////////////////////////////////////////////////////////////
// Canvas
///////////////////////////////////////////////////////////////////////
/**
* Canvas wrapper constructor
* @constructor
* @param {Number} width
* @param {Number} height
*/
Kinetic.Canvas = function(width, height) {
this.element = document.createElement('canvas');
this.context = this.element.getContext('2d');
// set dimensions
this.element.width = width;
this.element.height = height;
};
Kinetic.Canvas.prototype = {
/**
* clear canvas
* @name clear
* @methodOf Kinetic.Canvas.prototype
*/
clear: function() {
var context = this.getContext();
var el = this.getElement();
context.clearRect(0, 0, el.width, el.height);
},
/**
* get element
* @name getElement
* @methodOf Kinetic.Canvas.prototype
*/
getElement: function() {
return this.element;
},
/**
* get context
* @name getContext
* @methodOf Kinetic.Canvas.prototype
*/
getContext: function() {
return this.context;
},
/**
* set width
* @name setWidth
* @methodOf Kinetic.Canvas.prototype
*/
setWidth: function(width) {
this.element.width = width;
},
/**
* set height
* @name setHeight
* @methodOf Kinetic.Canvas.prototype
*/
setHeight: function(height) {
this.element.height = height;
},
/**
* set size
* @name setSize
* @methodOf Kinetic.Canvas.prototype
*/
setSize: function(width, height) {
this.setWidth(width);
this.setHeight(height);
},
/**
* strip away all functions that draw pixels onto the bitmap
* @name strip
* @methodOf Kinetic.Canvas.prototype
* @param {CanvasContext} context
*/
strip: function() {
var context = this.context;
context.stroke = function() {
};
context.fill = function() {
};
context.fillRect = function(x, y, width, height) {
context.rect(x, y, width, height);
};
context.strokeRect = function(x, y, width, height) {
context.rect(x, y, width, height);
};
context.drawImage = function() {
};
context.fillText = function() {
};
context.strokeText = function() {
};
}
};

View File

@ -152,7 +152,7 @@ Test.prototype.tests = {
context.quadraticCurveTo(300, 100, 260, 170);
context.closePath();
context.fillStyle = 'blue';
context.fill();
context.fill(context);
},
draggable: true
});

View File

@ -1349,8 +1349,7 @@ Test.prototype.tests = {
rect.rotate(0.01);
layer.draw();
});
//stage.start();
stage.start();
},
'STAGE - hide stage': function(containerId) {
var stage = new Kinetic.Stage({

View File

@ -25,7 +25,7 @@ Test.prototype.tests = {
var imageData = context.getImageData(7, 7, 106, 106);
endTimer('create image data');
layer.clear();
layer.canvas.clear();
startTimer();
for(var n = 0; n < 10000; n++) {
@ -62,7 +62,7 @@ Test.prototype.tests = {
var imageObj = new Image();
imageObj.onload = function() {
layer.clear();
layer.canvas.clear();
startTimer();
for(var n = 0; n < 10000; n++) {

View File

@ -68,8 +68,8 @@ Test.prototype.tests = {
test(stage.getSize().height === 155, 'stage height should be 155');
test(stage.getDOM().style.width === '333px', 'content width should be 333');
test(stage.getDOM().style.height === '155px', 'content height should be 155px');
test(layer.getCanvas().width === 333, 'layer canvas width should be 333');
test(layer.getCanvas().height === 155, 'layer canvas width should be 155');
test(layer.getCanvas().element.width === 333, 'layer canvas element width should be 333');
test(layer.getCanvas().element.height === 155, 'layer canvas element width should be 155');
},
'STAGE - add shape then stage then layer': function(containerId) {
var stage = new Kinetic.Stage({
@ -340,15 +340,14 @@ Test.prototype.tests = {
var layer = new Kinetic.Layer();
var group = new Kinetic.Group();
var drawTriangle = function() {
var context = this.getContext();
var drawTriangle = function(context) {
context.beginPath();
context.moveTo(200, 50);
context.lineTo(420, 80);
context.quadraticCurveTo(300, 100, 260, 170);
context.closePath();
this.fill();
this.stroke();
this.fill(context);
this.stroke(context);
};
var triangle = new Kinetic.Shape({
drawFunc: drawTriangle,
@ -388,15 +387,14 @@ Test.prototype.tests = {
height: 200
});
var drawTriangle = function() {
var context = this.getContext();
var drawTriangle = function(context) {
context.beginPath();
context.moveTo(200, 50);
context.lineTo(420, 80);
context.quadraticCurveTo(300, 100, 260, 170);
context.closePath();
this.fill();
this.stroke();
this.fill(context);
this.stroke(context);
};
var json = '{"attrs":{"width":578,"height":200,"visible":true,"listen":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"offset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Stage","children":[{"attrs":{"throttle":80,"clearBeforeDraw":true,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"offset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false,"listen":true},"nodeType":"Layer","children":[{"attrs":{"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"offset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false,"listen":true},"nodeType":"Group","children":[{"attrs":{"detectionType":"path","visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"offset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false,"fill":"#00D2FF","stroke":"black","strokeWidth":4,"shadow":{"blur":10,"alpha":1,"offset":{"x":0,"y":0}},"listen":true,"id":"myTriangle"},"nodeType":"Shape"}]}]}]}';
stage.load(json);
@ -2167,7 +2165,7 @@ Test.prototype.tests = {
setTimeout(function() {
sprite.setAnimation('kicking');
sprite.afterFrame(0, function() {
sprite.afterFrame(5, function() {
sprite.setAnimation('standing');
});
}, 2000);
@ -2720,15 +2718,14 @@ Test.prototype.tests = {
});
var layer = new Kinetic.Layer();
var shape = new Kinetic.Shape({
drawFunc: function() {
var context = this.getContext();
drawFunc: function(context) {
context.beginPath();
context.moveTo(0, 0);
context.lineTo(100, 0);
context.lineTo(100, 100);
context.closePath();
this.fill();
this.stroke();
this.fill(context);
this.stroke(context);
},
x: 200,
y: 100,
@ -2748,15 +2745,14 @@ Test.prototype.tests = {
});
var layer = new Kinetic.Layer();
var shape = new Kinetic.Shape({
drawFunc: function() {
var context = this.getContext();
drawFunc: function(context) {
context.beginPath();
context.moveTo(0, 0);
context.lineTo(100, 0);
context.lineTo(100, 100);
context.closePath();
this.fill();
this.stroke();
this.fill(context);
this.stroke(context);
},
x: 200,
y: 100,
@ -2765,15 +2761,14 @@ Test.prototype.tests = {
strokeWidth: 5
});
shape.setDrawFunc(function() {
var context = this.getContext();
shape.setDrawFunc(function(context) {
context.beginPath();
context.moveTo(0, 0);
context.lineTo(200, 0);
context.lineTo(200, 100);
context.closePath();
this.fill();
this.stroke();
this.fill(context);
this.stroke(context);
});
layer.add(shape);
@ -4024,6 +4019,8 @@ Test.prototype.tests = {
test(stage.get('.layerName')[0].attrs.id === 'layerId', 'problem with layer name selector');
test(stage.get('#layerId')[0].attrs.id === 'layerId', 'problem with layer id selector');
layer.draw();
},
'NODE - test drag and drop properties and methods': function(containerId) {
var stage = new Kinetic.Stage({