now utilizing John Resig's mashup of Base.js and protototype.js inheritiance Class so that it's easy for developers to extend KineticJS objects with extend() or to simply tack on new methods and properties that's available to all children classes. Moved getter and setter logic to Node. Moved transition class to root directory and created Tween class

This commit is contained in:
Eric Rowell
2012-07-03 12:07:27 -07:00
parent e2e16d49c1
commit 3d4d2d20c0
24 changed files with 1600 additions and 1635 deletions

View File

@@ -1,7 +1,7 @@
#Building the KineticJS library #Building the KineticJS library
To build the library, you need to have Ruby and Rubygems installed. After that, install the dependencies by running `bundle install`. To build the library, you need to have Ruby and Rubygems installed. After that, install the dependencies by running `bundle install`.
To build a development version of the library, run `thor build:dev VERSION`, where VERSION is a string that can be anything you like. For example, using `thor build:dev core` will produce `kinetic-core.js`. To build a minified version of the library, run `thor build:prod VERSION`. If you want to add a release date other than the current day, use `-d="DATE"` (e.g. `-d="Mar 07 2012`). To build a development version of the library, run `thor build:dev VERSION`, where VERSION is a string that can be anything you like. For example, using `thor build:dev core` will produce `kinetic-core.js`. To build a minified version of the library, run `thor build:prod VERSION`. If you want to add a release date other than the current day, use `-d="DATE"` (e.g. `-d="Mar 07 2012"`).
If you add a file in the src directory, be sure to add the filename to the filename array in the Thorfile. If you add a file in the src directory, be sure to add the filename to the filename array in the Thorfile.

View File

@@ -3,10 +3,10 @@ require 'json/pure'
class Build < Thor 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. # 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 = [ FILES = [
"license.js", "src/GlobalObject.js", "src/Node.js", "src/Container.js", "src/Stage.js", "license.js", "src/GlobalObject.js", "src/util/Class.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/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/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/util/Transition.js" "src/shapes/Line.js", "src/shapes/Path.js", "src/util/Transform.js", "src/Transition.js", "src/util/Tween.js"
] ]
desc "dev", "Concatenate all the js files into /dist/kinetic-VERSION.js." desc "dev", "Concatenate all the js files into /dist/kinetic-VERSION.js."

1525
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

@@ -1,18 +1,15 @@
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// Container // Container
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
Kinetic.Container = Kinetic.Node.extend({
/** /**
* Container constructor.&nbsp; Containers are used to contain nodes or other containers * Container constructor.&nbsp; Containers are used to contain nodes or other containers
* @constructor * @constructor
*/ */
Kinetic.Container = function() { init: function(config) {
this.children = []; this.children = [];
}; this._super(config);
/* },
* Container methods
*/
Kinetic.Container.prototype = {
/** /**
* get children * get children
*/ */
@@ -224,4 +221,4 @@ Kinetic.Container.prototype = {
} }
} }
} }
}; });

View File

@@ -32,29 +32,6 @@ Kinetic.GlobalObject = {
}, },
lastDrawTime: 0 lastDrawTime: 0
}, },
extend: function(obj1, obj2) {
for(var key in obj2.prototype) {
if(obj2.prototype.hasOwnProperty(key) && obj1.prototype[key] === undefined) {
obj1.prototype[key] = obj2.prototype[key];
}
}
},
addSetters: function(constructor, arr) {
for(var n = 0; n < arr.length; n++) {
var attr = arr[n];
this._addSetter(constructor, attr);
}
},
addGetters: function(constructor, arr) {
for(var n = 0; n < arr.length; n++) {
var attr = arr[n];
this._addGetter(constructor, attr);
}
},
addSettersGetters: function(constructor, arr) {
this.addSetters(constructor, arr);
this.addGetters(constructor, arr);
},
_pullNodes: function(stage) { _pullNodes: function(stage) {
var tempNodes = this.tempNodes; var tempNodes = this.tempNodes;
for(var n = 0; n < tempNodes.length; n++) { for(var n = 0; n < tempNodes.length; n++) {
@@ -334,29 +311,6 @@ Kinetic.GlobalObject = {
return arr; return arr;
} }
},
_addSetter: function(constructor, attr) {
var that = this;
var method = 'set' + attr.charAt(0).toUpperCase() + attr.slice(1);
constructor.prototype[method] = function() {
var arg;
if(arguments.length == 1) {
arg = arguments[0];
}
else {
arg = Array.prototype.slice.call(arguments);
}
var obj = {};
obj[attr] = arg;
this.setAttrs(obj);
};
},
_addGetter: function(constructor, attr) {
var that = this;
var method = 'get' + attr.charAt(0).toUpperCase() + attr.slice(1);
constructor.prototype[method] = function(arg) {
return this.attrs[attr];
};
} }
}; };

View File

@@ -1,32 +1,23 @@
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// Group // Group
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
Kinetic.Group = Kinetic.Container.extend({
/**
* Group constructor. Groups are used to contain shapes or other groups.
* @constructor
* @augments Kinetic.Container
* @augments Kinetic.Node
* @param {Object} config
*/
init: function(config) {
this.nodeType = 'Group';
/** // call super constructor
* Group constructor. Groups are used to contain shapes or other groups. this._super(config);
* @constructor },
* @augments Kinetic.Container
* @augments Kinetic.Node
* @param {Object} config
*/
Kinetic.Group = function(config) {
this.nodeType = 'Group';;
// call super constructors
Kinetic.Container.apply(this, []);
Kinetic.Node.apply(this, [config]);
};
/*
* Group methods
*/
Kinetic.Group.prototype = {
draw: function() { draw: function() {
if(this.attrs.visible) { if(this.attrs.visible) {
this._drawChildren(); this._drawChildren();
} }
} }
}; });
// Extend Container and Node
Kinetic.GlobalObject.extend(Kinetic.Group, Kinetic.Container);
Kinetic.GlobalObject.extend(Kinetic.Group, Kinetic.Node);

View File

@@ -1,37 +1,33 @@
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// Layer // Layer
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
/** Kinetic.Layer = Kinetic.Container.extend({
* Layer constructor. Layers are tied to their own canvas element and are used /**
* to contain groups or shapes * Layer constructor. Layers are tied to their own canvas element and are used
* @constructor * to contain groups or shapes
* @augments Kinetic.Container * @constructor
* @augments Kinetic.Node * @augments Kinetic.Container
* @param {Object} config * @augments Kinetic.Node
*/ * @param {Object} config
Kinetic.Layer = function(config) { */
this.setDefaultAttrs({ init: function(config) {
throttle: 80, this.setDefaultAttrs({
clearBeforeDraw: true throttle: 80,
}); clearBeforeDraw: true
});
this.nodeType = 'Layer'; this.nodeType = 'Layer';
this.lastDrawTime = 0; this.lastDrawTime = 0;
this.beforeDrawFunc = undefined; this.beforeDrawFunc = undefined;
this.afterDrawFunc = undefined; this.afterDrawFunc = undefined;
this.canvas = document.createElement('canvas'); this.canvas = document.createElement('canvas');
this.context = this.canvas.getContext('2d'); this.context = this.canvas.getContext('2d');
this.canvas.style.position = 'absolute'; this.canvas.style.position = 'absolute';
// call super constructors // call super constructor
Kinetic.Container.apply(this, []); this._super(config);
Kinetic.Node.apply(this, [config]); },
};
/*
* Layer methods
*/
Kinetic.Layer.prototype = {
/** /**
* draw children nodes. this includes any groups * draw children nodes. this includes any groups
* or shapes * or shapes
@@ -145,13 +141,10 @@ Kinetic.Layer.prototype = {
this.afterDrawFunc.call(this); this.afterDrawFunc.call(this);
} }
} }
}; });
// Extend Container and Node
Kinetic.GlobalObject.extend(Kinetic.Layer, Kinetic.Container);
Kinetic.GlobalObject.extend(Kinetic.Layer, Kinetic.Node);
// add setters and getters // add getters and setters
Kinetic.GlobalObject.addSettersGetters(Kinetic.Layer, ['clearBeforeDraw']); Kinetic.Node.addGettersSetters(Kinetic.Layer, ['clearBeforeDraw']);
/** /**
* set flag which determines if the layer is cleared or not * set flag which determines if the layer is cleared or not
@@ -166,4 +159,4 @@ Kinetic.GlobalObject.addSettersGetters(Kinetic.Layer, ['clearBeforeDraw']);
* before drawing * before drawing
* @name getClearBeforeDraw * @name getClearBeforeDraw
* @methodOf Kinetic.Layer.prototype * @methodOf Kinetic.Layer.prototype
*/ */

View File

@@ -1,72 +1,69 @@
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// Node // Node
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
/** Kinetic.Node = Kinetic.Class.extend({
* Node constructor.&nbsp; Nodes are entities that can be transformed, layered, /**
* and have events bound to them. They are the building blocks of a KineticJS * Node constructor.&nbsp; Nodes are entities that can be transformed, layered,
* application * and have events bound to them. They are the building blocks of a KineticJS
* @constructor * application
* @param {Object} config * @constructor
*/ * @param {Object} config
Kinetic.Node = function(config) {
this.defaultNodeAttrs = {
visible: true,
listening: true,
name: undefined,
alpha: 1,
x: 0,
y: 0,
scale: {
x: 1,
y: 1
},
rotation: 0,
offset: {
x: 0,
y: 0
},
dragConstraint: 'none',
dragBounds: {},
draggable: false
};
this.setDefaultAttrs(this.defaultNodeAttrs);
this.eventListeners = {};
this.setAttrs(config);
// bind events
this.on('draggableChange.kinetic', function() {
if(this.attrs.draggable) {
this._listenDrag();
}
else {
// remove event listeners
this._dragCleanup();
/*
* force drag and drop to end
* if this node is currently in
* drag and drop mode
*/
var stage = this.getStage();
var go = Kinetic.GlobalObject;
if(stage && go.drag.node && go.drag.node._id === this._id) {
stage._endDrag();
}
}
});
/*
* simulate draggable change event
* to init drag and drop logic from the
* above event binder
*/ */
this.simulate('draggableChange'); init: function(config) {
}; this.defaultNodeAttrs = {
/* visible: true,
* Node methods listening: true,
*/ name: undefined,
Kinetic.Node.prototype = { alpha: 1,
x: 0,
y: 0,
scale: {
x: 1,
y: 1
},
rotation: 0,
offset: {
x: 0,
y: 0
},
dragConstraint: 'none',
dragBounds: {},
draggable: false
};
this.setDefaultAttrs(this.defaultNodeAttrs);
this.eventListeners = {};
this.setAttrs(config);
// bind events
this.on('draggableChange.kinetic', function() {
if(this.attrs.draggable) {
this._listenDrag();
}
else {
// remove event listeners
this._dragCleanup();
/*
* force drag and drop to end
* if this node is currently in
* drag and drop mode
*/
var stage = this.getStage();
var go = Kinetic.GlobalObject;
if(stage && go.drag.node && go.drag.node._id === this._id) {
stage._endDrag();
}
}
});
/*
* simulate draggable change event
* to init drag and drop logic from the
* above event binder
*/
this.simulate('draggableChange');
},
/** /**
* bind events to the node. KineticJS supports mouseover, mousemove, * bind events to the node. KineticJS supports mouseover, mousemove,
* mouseout, mousedown, mouseup, click, dblclick, touchstart, touchmove, * mouseout, mousedown, mouseup, click, dblclick, touchstart, touchmove,
@@ -766,11 +763,51 @@ Kinetic.Node.prototype = {
this._handleEvent.call(this.parent, eventType, evt); this._handleEvent.call(this.parent, eventType, evt);
} }
} }
}; });
// add setters and getters // add getter and setter methods
Kinetic.GlobalObject.addSettersGetters(Kinetic.Node, ['x', 'y', 'scale', 'detectionType', 'rotation', 'alpha', 'name', 'id', 'offset', 'draggable', 'dragConstraint', 'dragBounds', 'listening']); Kinetic.Node.addSetters = function(constructor, arr) {
Kinetic.GlobalObject.addSetters(Kinetic.Node, ['rotationDeg']); for(var n = 0; n < arr.length; n++) {
var attr = arr[n];
this._addSetter(constructor, attr);
}
};
Kinetic.Node.addGetters = function(constructor, arr) {
for(var n = 0; n < arr.length; n++) {
var attr = arr[n];
this._addGetter(constructor, attr);
}
};
Kinetic.Node.addGettersSetters = function(constructor, arr) {
this.addSetters(constructor, arr);
this.addGetters(constructor, arr);
};
Kinetic.Node._addSetter = function(constructor, attr) {
var that = this;
var method = 'set' + attr.charAt(0).toUpperCase() + attr.slice(1);
constructor.prototype[method] = function() {
var arg;
if(arguments.length == 1) {
arg = arguments[0];
}
else {
arg = Array.prototype.slice.call(arguments);
}
var obj = {};
obj[attr] = arg;
this.setAttrs(obj);
};
};
Kinetic.Node._addGetter = function(constructor, attr) {
var that = this;
var method = 'get' + attr.charAt(0).toUpperCase() + attr.slice(1);
constructor.prototype[method] = function(arg) {
return this.attrs[attr];
};
};
// add getters setters
Kinetic.Node.addGettersSetters(Kinetic.Node, ['x', 'y', 'scale', 'detectionType', 'rotation', 'alpha', 'name', 'id', 'offset', 'draggable', 'dragConstraint', 'dragBounds', 'listening']);
Kinetic.Node.addSetters(Kinetic.Node, ['rotationDeg']);
/** /**
* set node x position * set node x position

View File

@@ -1,38 +1,35 @@
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// Shape // Shape
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
/** Kinetic.Shape = Kinetic.Node.extend({
* Shape constructor. Shapes are used to objectify drawing bits of a KineticJS /**
* application * Shape constructor. Shapes are used to objectify drawing bits of a KineticJS
* @constructor * application
* @augments Kinetic.Node * @constructor
* @param {Object} config * @augments Kinetic.Node
* @config {String|Object} [fill] can be a string color, a linear gradient object, a radial * @param {Object} config
* gradient object, or a pattern object. * @config {String|Object} [fill] can be a string color, a linear gradient object, a radial
* @config {String} [stroke] stroke color * gradient object, or a pattern object.
* @config {Number} [strokeWidth] stroke width * @config {String} [stroke] stroke color
* @config {String} [lineJoin] line join can be "miter", "round", or "bevel". The default * @config {Number} [strokeWidth] stroke width
* is "miter" * @config {String} [lineJoin] line join can be "miter", "round", or "bevel". The default
* @config {Object} [shadow] shadow object * is "miter"
* @config {String} [detectionType] shape detection type. Can be "path" or "pixel". * @config {Object} [shadow] shadow object
* The default is "path" because it performs better * @config {String} [detectionType] shape detection type. Can be "path" or "pixel".
*/ * The default is "path" because it performs better
Kinetic.Shape = function(config) { */
this.setDefaultAttrs({ init: function(config) {
detectionType: 'path' this.setDefaultAttrs({
}); detectionType: 'path'
});
this.data = []; this.data = [];
this.nodeType = 'Shape'; this.nodeType = 'Shape';
this.appliedShadow = false; this.appliedShadow = false;
// call super constructor // call super constructor
Kinetic.Node.apply(this, [config]); this._super(config);
}; },
/*
* Shape methods
*/
Kinetic.Shape.prototype = {
/** /**
* get layer context where the shape is being drawn. When * get layer context where the shape is being drawn. When
* the shape is being rendered, .getContext() returns the context of the * the shape is being rendered, .getContext() returns the context of the
@@ -377,12 +374,10 @@ Kinetic.Shape.prototype = {
context.restore(); context.restore();
} }
} }
}; });
// extend Node
Kinetic.GlobalObject.extend(Kinetic.Shape, Kinetic.Node);
// add setters and getters // add getters and setters
Kinetic.GlobalObject.addSettersGetters(Kinetic.Shape, ['fill', 'stroke', 'lineJoin', 'strokeWidth', 'shadow', 'drawFunc']); Kinetic.Node.addGettersSetters(Kinetic.Shape, ['fill', 'stroke', 'lineJoin', 'strokeWidth', 'shadow', 'drawFunc']);
/** /**
* set fill which can be a color, linear gradient object, * set fill which can be a color, linear gradient object,

View File

@@ -1,58 +1,53 @@
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// Stage // Stage
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
/** Kinetic.Stage = Kinetic.Container.extend({
* Stage constructor. A stage is used to contain multiple layers and handle /**
* animations * Stage constructor. A stage is used to contain multiple layers and handle
* @constructor * animations
* @augments Kinetic.Container * @constructor
* @augments Kinetic.Node * @augments Kinetic.Container
* @param {String|DomElement} cont Container id or DOM element * @augments Kinetic.Node
* @param {int} width * @param {String|DomElement} cont Container id or DOM element
* @param {int} height * @param {int} width
*/ * @param {int} height
Kinetic.Stage = function(config) {
this.setDefaultAttrs({
width: 400,
height: 200,
throttle: 80
});
/*
* if container is a string, assume it's an id for
* a DOM element
*/ */
if( typeof config.container === 'string') { init: function(config) {
config.container = document.getElementById(config.container); this.setDefaultAttrs({
} width: 400,
height: 200,
throttle: 80
});
// call super constructors /*
Kinetic.Container.apply(this, []); * if container is a string, assume it's an id for
Kinetic.Node.apply(this, [config]); * a DOM element
*/
if( typeof config.container === 'string') {
config.container = document.getElementById(config.container);
}
this._setStageDefaultProperties(); // call super constructor
this._id = Kinetic.GlobalObject.idCounter++; this._super(config);
this._buildDOM();
this._bindContentEvents();
//change events this._setStageDefaultProperties();
this.on('widthChange.kinetic', function() { this._id = Kinetic.GlobalObject.idCounter++;
this._resizeDOM(); this._buildDOM();
}); this._bindContentEvents();
this.on('heightChange.kinetic', function() { //change events
this._resizeDOM(); this.on('widthChange.kinetic', function() {
}); this._resizeDOM();
var go = Kinetic.GlobalObject; });
go.stages.push(this);
this._addId(this);
this._addName(this);
}; this.on('heightChange.kinetic', function() {
/* this._resizeDOM();
* Stage methods });
*/ var go = Kinetic.GlobalObject;
Kinetic.Stage.prototype = { go.stages.push(this);
this._addId(this);
this._addName(this);
},
/** /**
* sets onFrameFunc for animation * sets onFrameFunc for animation
* @param {function} func * @param {function} func
@@ -979,13 +974,10 @@ Kinetic.Stage.prototype = {
this.anim = undefined; this.anim = undefined;
this.animRunning = false; this.animRunning = false;
} }
}; });
// Extend Container and Node
Kinetic.GlobalObject.extend(Kinetic.Stage, Kinetic.Container);
Kinetic.GlobalObject.extend(Kinetic.Stage, Kinetic.Node);
// add setters and getters // add getters and setters
Kinetic.GlobalObject.addSettersGetters(Kinetic.Stage, ['width', 'height', 'throttle']); Kinetic.Node.addGettersSetters(Kinetic.Stage, ['width', 'height', 'throttle']);
/** /**
* get width * get width

93
src/Transition.js Normal file
View File

@@ -0,0 +1,93 @@
/**
* Transition constructor. The transitionTo() Node method
* returns a reference to the transition object which you can use
* to stop, resume, or restart the transition
* @constructor
*/
Kinetic.Transition = function(node, config) {
this.node = node;
this.config = config;
this.tweens = [];
var that = this;
// add tween for each property
function addTween(c, attrs, obj, rootObj) {
for(var key in c) {
if(key !== 'duration' && key !== 'easing' && key !== 'callback') {
// if val is an object then traverse
if(Kinetic.GlobalObject._isObject(c[key])) {
obj[key] = {};
addTween(c[key], attrs[key], obj[key], rootObj);
}
else {
that._add(that._getTween(attrs, key, c[key], obj, rootObj));
}
}
}
}
var obj = {};
addTween(config, node.attrs, obj, obj);
var finishedTweens = 0;
for(var n = 0; n < this.tweens.length; n++) {
var tween = this.tweens[n];
tween.onFinished = function() {
finishedTweens++;
if(finishedTweens >= that.tweens.length) {
that.onFinished();
}
};
}
};
/*
* Transition methods
*/
Kinetic.Transition.prototype = {
/**
* start transition
*/
start: function() {
for(var n = 0; n < this.tweens.length; n++) {
this.tweens[n].start();
}
},
/**
* stop transition
*/
stop: function() {
for(var n = 0; n < this.tweens.length; n++) {
this.tweens[n].stop();
}
},
/**
* resume transition
*/
resume: function() {
for(var n = 0; n < this.tweens.length; n++) {
this.tweens[n].resume();
}
},
_onEnterFrame: function() {
for(var n = 0; n < this.tweens.length; n++) {
this.tweens[n].onEnterFrame();
}
},
_add: function(tween) {
this.tweens.push(tween);
},
_getTween: function(attrs, prop, val, obj, rootObj) {
var config = this.config;
var node = this.node;
var easing = config.easing;
if(easing === undefined) {
easing = 'linear';
}
var tween = new Kinetic.Tween(node, function(i) {
obj[prop] = i;
node.setAttrs(rootObj);
}, Kinetic.Tweens[easing], attrs[prop], val, config.duration);
return tween;
}
};

View File

@@ -1,51 +1,48 @@
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// Ellipse // Ellipse
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
/** Kinetic.Ellipse = Kinetic.Shape.extend({
* Ellipse constructor /**
* @constructor * Ellipse constructor
* @augments Kinetic.Shape * @constructor
* @param {Object} config * @augments Kinetic.Shape
*/ * @param {Object} config
Kinetic.Ellipse = function(config) { */
this.setDefaultAttrs({ init: function(config) {
radius: { this.setDefaultAttrs({
x: 0, radius: {
y: 0 x: 0,
} y: 0
}); }
});
this.shapeType = "Ellipse"; this.shapeType = "Ellipse";
config.drawFunc = function() { config.drawFunc = function() {
var canvas = this.getCanvas(); var canvas = this.getCanvas();
var context = this.getContext(); var context = this.getContext();
var r = this.getRadius(); var r = this.getRadius();
context.beginPath(); context.beginPath();
context.save(); context.save();
if(r.x !== r.y) { if(r.x !== r.y) {
context.scale(1, r.y / r.x); context.scale(1, r.y / r.x);
} }
context.arc(0, 0, r.x, 0, Math.PI * 2, true); context.arc(0, 0, r.x, 0, Math.PI * 2, true);
context.restore(); context.restore();
context.closePath(); context.closePath();
this.fill(); this.fill();
this.stroke(); this.stroke();
}; };
// call super constructor // call super constructor
Kinetic.Shape.apply(this, [config]); this._super(config);
this._convertRadius(); this._convertRadius();
var that = this; var that = this;
this.on('radiusChange', function() { this.on('radiusChange', function() {
that._convertRadius(); that._convertRadius();
}); });
}; },
// Circle backwards compatibility
Kinetic.Circle = Kinetic.Ellipse;
Kinetic.Ellipse.prototype = {
/** /**
* converts numeric radius into an object * converts numeric radius into an object
*/ */
@@ -63,12 +60,13 @@ Kinetic.Ellipse.prototype = {
*/ */
this.attrs.radius = go._getXY(radius); this.attrs.radius = go._getXY(radius);
} }
}; });
// extend Shape
Kinetic.GlobalObject.extend(Kinetic.Ellipse, Kinetic.Shape);
// add setters and getters // Circle backwards compatibility
Kinetic.GlobalObject.addSettersGetters(Kinetic.Ellipse, ['radius']); Kinetic.Circle = Kinetic.Ellipse;
// add getters setters
Kinetic.Node.addGettersSetters(Kinetic.Ellipse, ['radius']);
/** /**
* set radius * set radius

View File

@@ -1,48 +1,45 @@
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// Image // Image
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
/** Kinetic.Image = Kinetic.Shape.extend({
* Image constructor /**
* @constructor * Image constructor
* @augments Kinetic.Shape * @constructor
* @param {Object} config * @augments Kinetic.Shape
*/ * @param {Object} config
Kinetic.Image = function(config) { */
this.shapeType = "Image"; init: function(config) {
config.drawFunc = function() { this.shapeType = "Image";
if(!!this.attrs.image) { config.drawFunc = function() {
var width = !!this.attrs.width ? this.attrs.width : this.attrs.image.width; if(!!this.attrs.image) {
var height = !!this.attrs.height ? this.attrs.height : this.attrs.image.height; var width = !!this.attrs.width ? this.attrs.width : this.attrs.image.width;
var canvas = this.getCanvas(); var height = !!this.attrs.height ? this.attrs.height : this.attrs.image.height;
var context = this.getContext(); var canvas = this.getCanvas();
var context = this.getContext();
context.beginPath(); context.beginPath();
context.rect(0, 0, width, height); context.rect(0, 0, width, height);
context.closePath(); context.closePath();
this.fill(); this.fill();
this.stroke(); this.stroke();
// if cropping // if cropping
if(this.attrs.crop && this.attrs.crop.width && this.attrs.crop.height) { if(this.attrs.crop && this.attrs.crop.width && this.attrs.crop.height) {
var cropX = this.attrs.crop.x ? this.attrs.crop.x : 0; var cropX = this.attrs.crop.x ? this.attrs.crop.x : 0;
var cropY = this.attrs.crop.y ? this.attrs.crop.y : 0; var cropY = this.attrs.crop.y ? this.attrs.crop.y : 0;
var cropWidth = this.attrs.crop.width; var cropWidth = this.attrs.crop.width;
var cropHeight = this.attrs.crop.height; var cropHeight = this.attrs.crop.height;
this.drawImage(this.attrs.image, cropX, cropY, cropWidth, cropHeight, 0, 0, width, height); this.drawImage(this.attrs.image, cropX, cropY, cropWidth, cropHeight, 0, 0, width, height);
}
// no cropping
else {
this.drawImage(this.attrs.image, 0, 0, width, height);
}
} }
// no cropping };
else { // call super constructor
this.drawImage(this.attrs.image, 0, 0, width, height); this._super(config);
} },
}
};
// call super constructor
Kinetic.Shape.apply(this, [config]);
};
/*
* Image methods
*/
Kinetic.Image.prototype = {
/** /**
* set width and height * set width and height
*/ */
@@ -59,11 +56,10 @@ Kinetic.Image.prototype = {
height: this.attrs.height height: this.attrs.height
}; };
} }
}; });
// extend Shape
Kinetic.GlobalObject.extend(Kinetic.Image, Kinetic.Shape); // add getters setters
// add setters and getters Kinetic.Node.addGettersSetters(Kinetic.Image, ['height', 'width', 'image', 'crop']);
Kinetic.GlobalObject.addSettersGetters(Kinetic.Image, ['height', 'width', 'image', 'crop']);
/** /**
* set width * set width

View File

@@ -1,56 +1,53 @@
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// Line // Line
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
/** Kinetic.Line = Kinetic.Shape.extend({
* Line constructor.&nbsp; Lines are defined by an array of points /**
* @constructor * Line constructor.&nbsp; Lines are defined by an array of points
* @augments Kinetic.Shape * @constructor
* @param {Object} config * @augments Kinetic.Shape
*/ * @param {Object} config
Kinetic.Line = function(config) { */
this.setDefaultAttrs({ init: function(config) {
points: [], this.setDefaultAttrs({
lineCap: 'butt', points: [],
dashArray: [], lineCap: 'butt',
detectionType: 'pixel' dashArray: [],
}); detectionType: 'pixel'
});
this.shapeType = "Line"; this.shapeType = "Line";
config.drawFunc = function() { config.drawFunc = function() {
var context = this.getContext(); var context = this.getContext();
var lastPos = {}; var lastPos = {};
context.beginPath(); context.beginPath();
context.moveTo(this.attrs.points[0].x, this.attrs.points[0].y); context.moveTo(this.attrs.points[0].x, this.attrs.points[0].y);
for(var n = 1; n < this.attrs.points.length; n++) { for(var n = 1; n < this.attrs.points.length; n++) {
var x = this.attrs.points[n].x; var x = this.attrs.points[n].x;
var y = this.attrs.points[n].y; var y = this.attrs.points[n].y;
if(this.attrs.dashArray.length > 0) { if(this.attrs.dashArray.length > 0) {
// draw dashed line // draw dashed line
var lastX = this.attrs.points[n - 1].x; var lastX = this.attrs.points[n - 1].x;
var lastY = this.attrs.points[n - 1].y; var lastY = this.attrs.points[n - 1].y;
this._dashedLine(lastX, lastY, x, y, this.attrs.dashArray); this._dashedLine(lastX, lastY, x, y, this.attrs.dashArray);
}
else {
// draw normal line
context.lineTo(x, y);
}
} }
else {
// draw normal line if(!!this.attrs.lineCap) {
context.lineTo(x, y); context.lineCap = this.attrs.lineCap;
} }
}
if(!!this.attrs.lineCap) { this.stroke();
context.lineCap = this.attrs.lineCap; };
} // call super constructor
this._super(config);
this.stroke(); },
};
// call super constructor
Kinetic.Shape.apply(this, [config]);
};
/*
* Line methods
*/
Kinetic.Line.prototype = {
/** /**
* draw dashed line. Written by Phrogz * draw dashed line. Written by Phrogz
*/ */
@@ -98,12 +95,10 @@ Kinetic.Line.prototype = {
context.moveTo(x2, y2); context.moveTo(x2, y2);
} }
}; });
// extend Shape // add getters setters
Kinetic.GlobalObject.extend(Kinetic.Line, Kinetic.Shape); Kinetic.Node.addGettersSetters(Kinetic.Line, ['dashArray', 'lineCap', 'points']);
// add setters and getters
Kinetic.GlobalObject.addSettersGetters(Kinetic.Line, ['dashArray', 'lineCap', 'points']);
/** /**
* set dash array. * set dash array.

View File

@@ -1,78 +1,75 @@
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// SVG Path // SVG Path
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
/** Kinetic.Path = Kinetic.Shape.extend({
* Path constructor. /**
* @author Jason Follas * Path constructor.
* @constructor * @author Jason Follas
* @augments Kinetic.Shape * @constructor
* @param {Object} config * @augments Kinetic.Shape
*/ * @param {Object} config
Kinetic.Path = function(config) { */
this.shapeType = "Path"; init: function(config) {
this.dataArray = []; this.shapeType = "Path";
var that = this; this.dataArray = [];
var that = this;
config.drawFunc = function() { config.drawFunc = function() {
var context = this.getContext(); var context = this.getContext();
var ca = this.dataArray; var ca = this.dataArray;
// context position // context position
context.beginPath(); context.beginPath();
for(var n = 0; n < ca.length; n++) { for(var n = 0; n < ca.length; n++) {
var c = ca[n].command; var c = ca[n].command;
var p = ca[n].points; var p = ca[n].points;
switch(c) { switch(c) {
case 'L': case 'L':
context.lineTo(p[0], p[1]); context.lineTo(p[0], p[1]);
break; break;
case 'M': case 'M':
context.moveTo(p[0], p[1]); context.moveTo(p[0], p[1]);
break; break;
case 'C': case 'C':
context.bezierCurveTo(p[0], p[1], p[2], p[3], p[4], p[5]); context.bezierCurveTo(p[0], p[1], p[2], p[3], p[4], p[5]);
break; break;
case 'Q': case 'Q':
context.quadraticCurveTo(p[0], p[1], p[2], p[3]); context.quadraticCurveTo(p[0], p[1], p[2], p[3]);
break; break;
case 'A': case 'A':
var cx = p[0], cy = p[1], rx = p[2], ry = p[3], theta = p[4], dTheta = p[5], psi = p[6], fs = p[7]; var cx = p[0], cy = p[1], rx = p[2], ry = p[3], theta = p[4], dTheta = p[5], psi = p[6], fs = p[7];
var r = (rx > ry) ? rx : ry; var r = (rx > ry) ? rx : ry;
var scaleX = (rx > ry) ? 1 : rx / ry; var scaleX = (rx > ry) ? 1 : rx / ry;
var scaleY = (rx > ry) ? ry / rx : 1; var scaleY = (rx > ry) ? ry / rx : 1;
context.translate(cx, cy); context.translate(cx, cy);
context.rotate(psi); context.rotate(psi);
context.scale(scaleX, scaleY); context.scale(scaleX, scaleY);
context.arc(0, 0, r, theta, theta + dTheta, 1 - fs); context.arc(0, 0, r, theta, theta + dTheta, 1 - fs);
context.scale(1 / scaleX, 1 / scaleY); context.scale(1 / scaleX, 1 / scaleY);
context.rotate(-psi); context.rotate(-psi);
context.translate(-cx, -cy); context.translate(-cx, -cy);
break; break;
case 'z': case 'z':
context.closePath(); context.closePath();
break; break;
}
} }
} this.fill();
this.fill(); //console.profile();
//console.profile(); this.stroke();
this.stroke(); //console.profileEnd();
//console.profileEnd(); };
}; // call super constructor
// call super constructor this._super(config);
Kinetic.Shape.apply(this, [config]);
this.dataArray = this.getDataArray(); this.dataArray = this.getDataArray();
this.on('dataChange', function() { this.on('dataChange', function() {
that.dataArray = that.getDataArray(); that.dataArray = that.getDataArray();
}); });
}; },
/*
* Path methods
*/
Kinetic.Path.prototype = {
/** /**
* get parsed data array from the data * get parsed data array from the data
* string. V, v, H, h, and l data are converted to * string. V, v, H, h, and l data are converted to
@@ -366,13 +363,10 @@ Kinetic.Path.prototype = {
return [cx, cy, rx, ry, theta, dTheta, psi, fs]; return [cx, cy, rx, ry, theta, dTheta, psi, fs];
} }
}; });
// extend Shape // add getters setters
Kinetic.GlobalObject.extend(Kinetic.Path, Kinetic.Shape); Kinetic.Node.addGettersSetters(Kinetic.Path, ['data']);
// add setters and getters
Kinetic.GlobalObject.addSettersGetters(Kinetic.Path, ['data']);
/** /**
* set SVG path data string. This method * set SVG path data string. This method

View File

@@ -1,37 +1,37 @@
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// Polygon // Polygon
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
/** Kinetic.Polygon = Kinetic.Shape.extend({
* Polygon constructor.&nbsp; Polygons are defined by an array of points /**
* @constructor * Polygon constructor.&nbsp; Polygons are defined by an array of points
* @augments Kinetic.Shape * @constructor
* @param {Object} config * @augments Kinetic.Shape
*/ * @param {Object} config
Kinetic.Polygon = function(config) { */
this.setDefaultAttrs({ init: function(config) {
points: [] this.setDefaultAttrs({
}); points: []
});
this.shapeType = "Polygon"; this.shapeType = "Polygon";
config.drawFunc = function() { config.drawFunc = function() {
var context = this.getContext(); var context = this.getContext();
context.beginPath(); context.beginPath();
context.moveTo(this.attrs.points[0].x, this.attrs.points[0].y); context.moveTo(this.attrs.points[0].x, this.attrs.points[0].y);
for(var n = 1; n < this.attrs.points.length; n++) { for(var n = 1; n < this.attrs.points.length; n++) {
context.lineTo(this.attrs.points[n].x, this.attrs.points[n].y); context.lineTo(this.attrs.points[n].x, this.attrs.points[n].y);
} }
context.closePath(); context.closePath();
this.fill(); this.fill();
this.stroke(); this.stroke();
}; };
// call super constructor // call super constructor
Kinetic.Shape.apply(this, [config]); this._super(config);
}; }
// extend Shape });
Kinetic.GlobalObject.extend(Kinetic.Polygon, Kinetic.Shape);
// add setters and getters // add getters setters
Kinetic.GlobalObject.addSettersGetters(Kinetic.Polygon, ['points']); Kinetic.Node.addGettersSetters(Kinetic.Polygon, ['points']);
/** /**
* set points array * set points array

View File

@@ -1,52 +1,49 @@
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// Rect // Rect
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
/** Kinetic.Rect = Kinetic.Shape.extend({
* Rect constructor /**
* @constructor * Rect constructor
* @augments Kinetic.Shape * @constructor
* @param {Object} config * @augments Kinetic.Shape
*/ * @param {Object} config
Kinetic.Rect = function(config) { */
this.setDefaultAttrs({ init: function(config) {
width: 0, this.setDefaultAttrs({
height: 0, width: 0,
cornerRadius: 0 height: 0,
}); cornerRadius: 0
});
this.shapeType = "Rect"; this.shapeType = "Rect";
config.drawFunc = function() { config.drawFunc = function() {
var context = this.getContext(); var context = this.getContext();
context.beginPath(); context.beginPath();
if(this.attrs.cornerRadius === 0) { if(this.attrs.cornerRadius === 0) {
// simple rect - don't bother doing all that complicated maths stuff. // simple rect - don't bother doing all that complicated maths stuff.
context.rect(0, 0, this.attrs.width, this.attrs.height); context.rect(0, 0, this.attrs.width, this.attrs.height);
} }
else { else {
// arcTo would be nicer, but browser support is patchy (Opera) // arcTo would be nicer, but browser support is patchy (Opera)
context.moveTo(this.attrs.cornerRadius, 0); context.moveTo(this.attrs.cornerRadius, 0);
context.lineTo(this.attrs.width - this.attrs.cornerRadius, 0); context.lineTo(this.attrs.width - this.attrs.cornerRadius, 0);
context.arc(this.attrs.width - this.attrs.cornerRadius, this.attrs.cornerRadius, this.attrs.cornerRadius, Math.PI * 3 / 2, 0, false); context.arc(this.attrs.width - this.attrs.cornerRadius, this.attrs.cornerRadius, this.attrs.cornerRadius, Math.PI * 3 / 2, 0, false);
context.lineTo(this.attrs.width, this.attrs.height - this.attrs.cornerRadius); context.lineTo(this.attrs.width, this.attrs.height - this.attrs.cornerRadius);
context.arc(this.attrs.width - this.attrs.cornerRadius, this.attrs.height - this.attrs.cornerRadius, this.attrs.cornerRadius, 0, Math.PI / 2, false); context.arc(this.attrs.width - this.attrs.cornerRadius, this.attrs.height - this.attrs.cornerRadius, this.attrs.cornerRadius, 0, Math.PI / 2, false);
context.lineTo(this.attrs.cornerRadius, this.attrs.height); context.lineTo(this.attrs.cornerRadius, this.attrs.height);
context.arc(this.attrs.cornerRadius, this.attrs.height - this.attrs.cornerRadius, this.attrs.cornerRadius, Math.PI / 2, Math.PI, false); context.arc(this.attrs.cornerRadius, this.attrs.height - this.attrs.cornerRadius, this.attrs.cornerRadius, Math.PI / 2, Math.PI, false);
context.lineTo(0, this.attrs.cornerRadius); context.lineTo(0, this.attrs.cornerRadius);
context.arc(this.attrs.cornerRadius, this.attrs.cornerRadius, this.attrs.cornerRadius, Math.PI, Math.PI * 3 / 2, false); context.arc(this.attrs.cornerRadius, this.attrs.cornerRadius, this.attrs.cornerRadius, Math.PI, Math.PI * 3 / 2, false);
} }
context.closePath(); context.closePath();
this.fill(); this.fill();
this.stroke(); this.stroke();
}; };
// call super constructor // call super constructor
Kinetic.Shape.apply(this, [config]); this._super(config);
}; },
/*
* Rect methods
*/
Kinetic.Rect.prototype = {
/** /**
* set width and height * set width and height
*/ */
@@ -63,13 +60,10 @@ Kinetic.Rect.prototype = {
height: this.attrs.height height: this.attrs.height
}; };
} }
}; });
// extend Shape // add getters setters
Kinetic.GlobalObject.extend(Kinetic.Rect, Kinetic.Shape); Kinetic.Node.addGettersSetters(Kinetic.Rect, ['width', 'height', 'cornerRadius']);
// add setters and getters
Kinetic.GlobalObject.addSettersGetters(Kinetic.Rect, ['width', 'height', 'cornerRadius']);
/** /**
* set width * set width

View File

@@ -1,41 +1,41 @@
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// RegularPolygon // RegularPolygon
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
/** Kinetic.RegularPolygon = Kinetic.Shape.extend({
* RegularPolygon constructor.&nbsp; Examples include triangles, squares, pentagons, hexagons, etc. /**
* @constructor * RegularPolygon constructor.&nbsp; Examples include triangles, squares, pentagons, hexagons, etc.
* @augments Kinetic.Shape * @constructor
* @param {Object} config * @augments Kinetic.Shape
*/ * @param {Object} config
Kinetic.RegularPolygon = function(config) { */
this.setDefaultAttrs({ init: function(config) {
radius: 0, this.setDefaultAttrs({
sides: 0 radius: 0,
}); sides: 0
});
this.shapeType = "RegularPolygon"; this.shapeType = "RegularPolygon";
config.drawFunc = function() { config.drawFunc = function() {
var context = this.getContext(); var context = this.getContext();
context.beginPath(); context.beginPath();
context.moveTo(0, 0 - this.attrs.radius); context.moveTo(0, 0 - this.attrs.radius);
for(var n = 1; n < this.attrs.sides; n++) { for(var n = 1; n < this.attrs.sides; n++) {
var x = this.attrs.radius * Math.sin(n * 2 * Math.PI / this.attrs.sides); var x = this.attrs.radius * Math.sin(n * 2 * Math.PI / this.attrs.sides);
var y = -1 * this.attrs.radius * Math.cos(n * 2 * Math.PI / this.attrs.sides); var y = -1 * this.attrs.radius * Math.cos(n * 2 * Math.PI / this.attrs.sides);
context.lineTo(x, y); context.lineTo(x, y);
} }
context.closePath(); context.closePath();
this.fill(); this.fill();
this.stroke(); this.stroke();
}; };
// call super constructor // call super constructor
Kinetic.Shape.apply(this, [config]); this._super(config);
}; }
// extend Shape });
Kinetic.GlobalObject.extend(Kinetic.RegularPolygon, Kinetic.Shape);
// add setters and getters // add getters setters
Kinetic.GlobalObject.addSettersGetters(Kinetic.Rect, ['radius', 'sides']); Kinetic.Node.addGettersSetters(Kinetic.Rect, ['radius', 'sides']);
/** /**
* set radius * set radius

View File

@@ -1,45 +1,42 @@
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// Sprite // Sprite
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
/** Kinetic.Sprite = Kinetic.Shape.extend({
* Sprite constructor /**
* @constructor * Sprite constructor
* @augments Kinetic.Shape * @constructor
* @param {Object} config * @augments Kinetic.Shape
*/ * @param {Object} config
Kinetic.Sprite = function(config) { */
this.setDefaultAttrs({ init: function(config) {
index: 0, this.setDefaultAttrs({
frameRate: 17 index: 0,
}); frameRate: 17
});
config.drawFunc = function() { config.drawFunc = function() {
if(!!this.attrs.image) { if(!!this.attrs.image) {
var context = this.getContext(); var context = this.getContext();
var anim = this.attrs.animation; var anim = this.attrs.animation;
var index = this.attrs.index; var index = this.attrs.index;
var f = this.attrs.animations[anim][index]; var f = this.attrs.animations[anim][index];
context.beginPath(); context.beginPath();
context.rect(0, 0, f.width, f.height); context.rect(0, 0, f.width, f.height);
context.closePath(); context.closePath();
this.drawImage(this.attrs.image, f.x, f.y, f.width, f.height, 0, 0, f.width, f.height); this.drawImage(this.attrs.image, f.x, f.y, f.width, f.height, 0, 0, f.width, f.height);
} }
}; };
// call super constructor // call super constructor
Kinetic.Shape.apply(this, [config]); this._super(config);
var that = this; var that = this;
this.on('animationChange', function() { this.on('animationChange', function() {
// reset index when animation changes // reset index when animation changes
that.setIndex(0); that.setIndex(0);
}); });
}; },
/*
* Sprite methods
*/
Kinetic.Sprite.prototype = {
/** /**
* start sprite animation * start sprite animation
*/ */
@@ -79,12 +76,10 @@ Kinetic.Sprite.prototype = {
this.attrs.index = 0; this.attrs.index = 0;
} }
} }
}; });
// extend Shape
Kinetic.GlobalObject.extend(Kinetic.Sprite, Kinetic.Shape);
// add setters and getters // add getters setters
Kinetic.GlobalObject.addSettersGetters(Kinetic.Sprite, ['animation', 'animations', 'index']); Kinetic.Node.addGettersSetters(Kinetic.Sprite, ['animation', 'animations', 'index']);
/** /**
* set animation key * set animation key

View File

@@ -1,44 +1,44 @@
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// Star // Star
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
/** Kinetic.Star = Kinetic.Shape.extend({
* Star constructor /**
* @constructor * Star constructor
* @augments Kinetic.Shape * @constructor
* @param {Object} config * @augments Kinetic.Shape
*/ * @param {Object} config
Kinetic.Star = function(config) { */
this.setDefaultAttrs({ init: function(config) {
numPoints: 0, this.setDefaultAttrs({
innerRadius: 0, numPoints: 0,
outerRadius: 0 innerRadius: 0,
}); outerRadius: 0
});
this.shapeType = "Star"; this.shapeType = "Star";
config.drawFunc = function() { config.drawFunc = function() {
var context = this.getContext(); var context = this.getContext();
context.beginPath(); context.beginPath();
context.moveTo(0, 0 - this.attrs.outerRadius); context.moveTo(0, 0 - this.attrs.outerRadius);
for(var n = 1; n < this.attrs.numPoints * 2; n++) { for(var n = 1; n < this.attrs.numPoints * 2; n++) {
var radius = n % 2 === 0 ? this.attrs.outerRadius : this.attrs.innerRadius; var radius = n % 2 === 0 ? this.attrs.outerRadius : this.attrs.innerRadius;
var x = radius * Math.sin(n * Math.PI / this.attrs.numPoints); var x = radius * Math.sin(n * Math.PI / this.attrs.numPoints);
var y = -1 * radius * Math.cos(n * Math.PI / this.attrs.numPoints); var y = -1 * radius * Math.cos(n * Math.PI / this.attrs.numPoints);
context.lineTo(x, y); context.lineTo(x, y);
} }
context.closePath(); context.closePath();
this.fill(); this.fill();
this.stroke(); this.stroke();
}; };
// call super constructor // call super constructor
Kinetic.Shape.apply(this, [config]); this._super(config);
}; }
// extend Shape });
Kinetic.GlobalObject.extend(Kinetic.Star, Kinetic.Shape);
// add setters and getters // add getters setters
Kinetic.GlobalObject.addSettersGetters(Kinetic.Star, ['numPoints', 'innerRadius', 'outerRadius']); Kinetic.Node.addGettersSetters(Kinetic.Star, ['numPoints', 'innerRadius', 'outerRadius']);
/** /**
* set number of points * set number of points

View File

@@ -7,106 +7,103 @@
* @augments Kinetic.Shape * @augments Kinetic.Shape
* @param {Object} config * @param {Object} config
*/ */
Kinetic.Text = function(config) { Kinetic.Text = Kinetic.Shape.extend({
this.setDefaultAttrs({ init: function(config) {
fontFamily: 'Calibri', this.setDefaultAttrs({
text: '', fontFamily: 'Calibri',
fontSize: 12, text: '',
align: 'left', fontSize: 12,
verticalAlign: 'top', align: 'left',
fontStyle: 'normal', verticalAlign: 'top',
padding: 0, fontStyle: 'normal',
width: 'auto', padding: 0,
height: 'auto', width: 'auto',
detectionType: 'path', height: 'auto',
cornerRadius: 0, detectionType: 'path',
lineHeight: 1.2 cornerRadius: 0,
}); lineHeight: 1.2
});
this.dummyCanvas = document.createElement('canvas'); this.dummyCanvas = document.createElement('canvas');
this.shapeType = "Text"; this.shapeType = "Text";
config.drawFunc = function() { config.drawFunc = function() {
var context = this.getContext(); var context = this.getContext();
/* /*
* draw rect * draw rect
*/ */
context.beginPath(); context.beginPath();
var boxWidth = this.getBoxWidth(); var boxWidth = this.getBoxWidth();
var boxHeight = this.getBoxHeight(); var boxHeight = this.getBoxHeight();
if(this.attrs.cornerRadius === 0) { if(this.attrs.cornerRadius === 0) {
// simple rect - don't bother doing all that complicated maths stuff. // simple rect - don't bother doing all that complicated maths stuff.
context.rect(0, 0, boxWidth, boxHeight); context.rect(0, 0, boxWidth, boxHeight);
} }
else { else {
// arcTo would be nicer, but browser support is patchy (Opera) // arcTo would be nicer, but browser support is patchy (Opera)
context.moveTo(this.attrs.cornerRadius, 0); context.moveTo(this.attrs.cornerRadius, 0);
context.lineTo(boxWidth - this.attrs.cornerRadius, 0); context.lineTo(boxWidth - this.attrs.cornerRadius, 0);
context.arc(boxWidth - this.attrs.cornerRadius, this.attrs.cornerRadius, this.attrs.cornerRadius, Math.PI * 3 / 2, 0, false); context.arc(boxWidth - this.attrs.cornerRadius, this.attrs.cornerRadius, this.attrs.cornerRadius, Math.PI * 3 / 2, 0, false);
context.lineTo(boxWidth, boxHeight - this.attrs.cornerRadius); context.lineTo(boxWidth, boxHeight - this.attrs.cornerRadius);
context.arc(boxWidth - this.attrs.cornerRadius, boxHeight - this.attrs.cornerRadius, this.attrs.cornerRadius, 0, Math.PI / 2, false); context.arc(boxWidth - this.attrs.cornerRadius, boxHeight - this.attrs.cornerRadius, this.attrs.cornerRadius, 0, Math.PI / 2, false);
context.lineTo(this.attrs.cornerRadius, boxHeight); context.lineTo(this.attrs.cornerRadius, boxHeight);
context.arc(this.attrs.cornerRadius, boxHeight - this.attrs.cornerRadius, this.attrs.cornerRadius, Math.PI / 2, Math.PI, false); context.arc(this.attrs.cornerRadius, boxHeight - this.attrs.cornerRadius, this.attrs.cornerRadius, Math.PI / 2, Math.PI, false);
context.lineTo(0, this.attrs.cornerRadius); context.lineTo(0, this.attrs.cornerRadius);
context.arc(this.attrs.cornerRadius, this.attrs.cornerRadius, this.attrs.cornerRadius, Math.PI, Math.PI * 3 / 2, false); context.arc(this.attrs.cornerRadius, this.attrs.cornerRadius, this.attrs.cornerRadius, Math.PI, Math.PI * 3 / 2, false);
} }
context.closePath(); context.closePath();
this.fill(); this.fill();
this.stroke(); this.stroke();
/* /*
* draw text * draw text
*/ */
var p = this.attrs.padding; var p = this.attrs.padding;
var lineHeightPx = this.attrs.lineHeight * this.getTextHeight(); var lineHeightPx = this.attrs.lineHeight * this.getTextHeight();
var textArr = this.textArr; var textArr = this.textArr;
context.font = this.attrs.fontStyle + ' ' + this.attrs.fontSize + 'pt ' + this.attrs.fontFamily; context.font = this.attrs.fontStyle + ' ' + this.attrs.fontSize + 'pt ' + this.attrs.fontFamily;
context.textBaseline = 'middle'; context.textBaseline = 'middle';
context.textAlign = 'left'; context.textAlign = 'left';
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];
// horizontal alignment
context.save(); context.save();
if(this.attrs.align === 'right') { context.translate(p, 0);
context.translate(this.getBoxWidth() - this._getTextSize(text).width - p * 2, 0); context.translate(0, p + this.getTextHeight() / 2);
}
else if(this.attrs.align === 'center') {
context.translate((this.getBoxWidth() - this._getTextSize(text).width - p * 2) / 2, 0);
}
this.fillText(text); // draw text lines
this.strokeText(text); for(var n = 0; n < textArr.length; n++) {
var text = textArr[n];
// horizontal alignment
context.save();
if(this.attrs.align === 'right') {
context.translate(this.getBoxWidth() - this._getTextSize(text).width - p * 2, 0);
}
else if(this.attrs.align === 'center') {
context.translate((this.getBoxWidth() - this._getTextSize(text).width - p * 2) / 2, 0);
}
this.fillText(text);
this.strokeText(text);
context.restore();
context.translate(0, lineHeightPx);
}
context.restore(); context.restore();
};
// call super constructor
this._super(config);
context.translate(0, lineHeightPx); // update text data for certain attr changes
var attrs = ['width', 'height', 'padding', 'text', 'textStroke', 'textStrokeWidth'];
var that = this;
for(var n = 0; n < attrs.length; n++) {
var attr = attrs[n];
this.on(attr + 'Change', that._setTextData);
} }
context.restore();
};
// call super constructor
Kinetic.Shape.apply(this, [config]);
// update text data for certain attr changes that._setTextData();
var attrs = ['width', 'height', 'padding', 'text', 'textStroke', 'textStrokeWidth']; },
var that = this;
for(var n = 0; n < attrs.length; n++) {
var attr = attrs[n];
this.on(attr + 'Change', that._setTextData);
}
that._setTextData();
};
/*
* Text methods
*/
Kinetic.Text.prototype = {
/** /**
* get text width in pixels * get text width in pixels
*/ */
@@ -183,12 +180,9 @@ Kinetic.Text.prototype = {
this.textArr = arr; this.textArr = arr;
} }
}; });
// extend Shape // add getters setters
Kinetic.GlobalObject.extend(Kinetic.Text, Kinetic.Shape); Kinetic.Node.addGettersSetters(Kinetic.Text, ['fontFamily', 'fontSize', 'fontStyle', 'textFill', 'textStroke', 'textStrokeWidth', 'padding', 'align', 'lineHeight', 'text', 'width', 'height', 'cornerRadius', 'fill', 'stroke', 'strokeWidth', 'shadow']);
// add setters and getters
Kinetic.GlobalObject.addSettersGetters(Kinetic.Text, ['fontFamily', 'fontSize', 'fontStyle', 'textFill', 'textStroke', 'textStrokeWidth', 'padding', 'align', 'lineHeight', 'text', 'width', 'height', 'cornerRadius', 'fill', 'stroke', 'strokeWidth', 'shadow']);
/** /**
* set font family * set font family

60
src/util/Class.js Normal file
View File

@@ -0,0 +1,60 @@
/* Simple JavaScript Inheritance
* By John Resig http://ejohn.org/
* MIT Licensed.
*/
// Inspired by base2 and Prototype
(function() {
var initializing = false, fnTest = /xyz/.test(function() { xyz;
}) ? /\b_super\b/ : /.*/;
// The base Class implementation (does nothing)
Kinetic.Class = function() {
};
// Create a new Class that inherits from this class
Kinetic.Class.extend = function(prop) {
var _super = this.prototype;
// Instantiate a base class (but only create the instance,
// don't run the init constructor)
initializing = true;
var prototype = new this();
initializing = false;
// Copy the properties over onto the new prototype
for(var name in prop) {
// Check if we're overwriting an existing function
prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function(name, fn) {
return function() {
var tmp = this._super;
// Add a new ._super() method that is the same method
// but on the super-class
this._super = _super[name];
// The method only need to be bound temporarily, so we
// remove it when we're done executing
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, prop[name]) : prop[name];
}
// The dummy class constructor
function Class() {
// All construction is actually done in the init method
if(!initializing && this.init)
this.init.apply(this, arguments);
}
// Populate our constructed prototype object
Class.prototype = prototype;
// Enforce the constructor to be what we expect
Class.prototype.constructor = Class;
// And make this class extendable
Class.extend = arguments.callee;
return Class;
};
})();

View File

@@ -4,101 +4,6 @@
* an animation of a single Node property. A Transition is a set of * an animation of a single Node property. A Transition is a set of
* multiple tweens * multiple tweens
*/ */
/**
* Transition constructor used by KineticJS. The transitionTo() Node method
* returns a reference to the transition object which you can use
* to stop, resume, or restart the transition
* @constructor
*/
Kinetic.Transition = function(node, config) {
this.node = node;
this.config = config;
this.tweens = [];
var that = this;
// add tween for each property
function addTween(c, attrs, obj, rootObj) {
for(var key in c) {
if(key !== 'duration' && key !== 'easing' && key !== 'callback') {
// if val is an object then traverse
if(Kinetic.GlobalObject._isObject(c[key])) {
obj[key] = {};
addTween(c[key], attrs[key], obj[key], rootObj);
}
else {
that._add(that._getTween(attrs, key, c[key], obj, rootObj));
}
}
}
}
var obj = {};
addTween(config, node.attrs, obj, obj);
var finishedTweens = 0;
for(var n = 0; n < this.tweens.length; n++) {
var tween = this.tweens[n];
tween.onFinished = function() {
finishedTweens++;
if(finishedTweens >= that.tweens.length) {
that.onFinished();
}
};
}
};
/*
* Transition methods
*/
Kinetic.Transition.prototype = {
/**
* start transition
*/
start: function() {
for(var n = 0; n < this.tweens.length; n++) {
this.tweens[n].start();
}
},
/**
* stop transition
*/
stop: function() {
for(var n = 0; n < this.tweens.length; n++) {
this.tweens[n].stop();
}
},
/**
* resume transition
*/
resume: function() {
for(var n = 0; n < this.tweens.length; n++) {
this.tweens[n].resume();
}
},
_onEnterFrame: function() {
for(var n = 0; n < this.tweens.length; n++) {
this.tweens[n].onEnterFrame();
}
},
_add: function(tween) {
this.tweens.push(tween);
},
_getTween: function(attrs, prop, val, obj, rootObj) {
var config = this.config;
var node = this.node;
var easing = config.easing;
if(easing === undefined) {
easing = 'linear';
}
var tween = new Kinetic.Tween(node, function(i) {
obj[prop] = i;
node.setAttrs(rootObj);
}, Kinetic.Tweens[easing], attrs[prop], val, config.duration);
return tween;
}
};
/** /**
* Tween constructor * Tween constructor
*/ */