├── test ├── assets │ ├── lion.png │ ├── bamoon.jpg │ ├── bunny.png │ ├── darth-vader.jpg │ ├── cropped-darth.jpg │ ├── cropped-darth.png │ └── scorpion-sprite.png ├── performance │ ├── random-squares-dev.html │ ├── random-squares-v5.0.1.html │ ├── rotate-star.html │ ├── rotate-cached-star.html │ └── common │ │ └── random-squares.js ├── unit │ ├── Util-test.js │ ├── shapes │ │ ├── Polygon-test.js │ │ ├── Ellipse-test.js │ │ ├── Wedge-test.js │ │ ├── Arc-test.js │ │ ├── Ring-test.js │ │ ├── Blob-test.js │ │ ├── Spline-test.js │ │ ├── Line-test.js │ │ └── Rect-test.js │ ├── filters │ │ ├── Solarize-test.js │ │ ├── Mask-test.js │ │ ├── Noise-test.js │ │ ├── Pixelate-test.js │ │ ├── Threshold-test.js │ │ ├── Posterize-test.js │ │ ├── Enhance-test.js │ │ ├── Invert-test.js │ │ ├── Sepia-test.js │ │ ├── Grayscale-test.js │ │ ├── Emboss-test.js │ │ ├── RGB-test.js │ │ ├── HSL-test.js │ │ ├── Ripple-test.js │ │ ├── Kaleidoscope-test.js │ │ ├── Brighten-test.js │ │ └── HSV-test.js │ ├── Group-test.js │ ├── Canvas-test.js │ ├── plugins │ │ ├── Arrow-test.js │ │ ├── Star-test.js │ │ ├── RegularPolygon-test.js │ │ └── Label-test.js │ ├── FastLayer-test.js │ ├── BaseLayer-test.js │ ├── Collection-test.js │ ├── Global-test.js │ ├── Animation-test.js │ ├── DragAndDrop-test.js │ └── Tween-test.js ├── setStats.js ├── memory │ ├── build-destroy-text.html │ └── build-destroy-star.html ├── memLeakTest.html ├── lib │ └── stats.js ├── runner.js ├── node-runner.js └── runner.html ├── .npmignore ├── doc-includes ├── ContainerParams.txt ├── NodeParams.txt └── ShapeParams.txt ├── .travis.yml ├── .jshintrc ├── src ├── Group.js ├── filters │ ├── Invert.js │ ├── Grayscale.js │ ├── Brighten.js │ ├── Threshold.js │ ├── Noise.js │ ├── Posterize.js │ ├── Solarize.js │ ├── Sepia.js │ ├── RGB.js │ ├── Pixelate.js │ ├── HSV.js │ ├── HSL.js │ └── Enhance.js ├── plugins │ ├── RegularPolygon.js │ ├── Star.js │ └── Arrow.js ├── shapes │ ├── Rect.js │ ├── Circle.js │ ├── Wedge.js │ ├── Arc.js │ ├── Ring.js │ └── Ellipse.js ├── FastLayer.js └── Factory.js ├── .gitignore ├── bower.json ├── bower-template.json ├── package.json ├── nodejs-demo.js ├── README.md └── presentation-schedule.md /test/assets/lion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericdrowell/KineticJS/HEAD/test/assets/lion.png -------------------------------------------------------------------------------- /test/assets/bamoon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericdrowell/KineticJS/HEAD/test/assets/bamoon.jpg -------------------------------------------------------------------------------- /test/assets/bunny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericdrowell/KineticJS/HEAD/test/assets/bunny.png -------------------------------------------------------------------------------- /test/assets/darth-vader.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericdrowell/KineticJS/HEAD/test/assets/darth-vader.jpg -------------------------------------------------------------------------------- /test/assets/cropped-darth.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericdrowell/KineticJS/HEAD/test/assets/cropped-darth.jpg -------------------------------------------------------------------------------- /test/assets/cropped-darth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericdrowell/KineticJS/HEAD/test/assets/cropped-darth.png -------------------------------------------------------------------------------- /test/assets/scorpion-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericdrowell/KineticJS/HEAD/test/assets/scorpion-sprite.png -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | dist 2 | doc-includes 3 | jsdoc-master 4 | src 5 | docs 6 | test 7 | .travis.yml 8 | Gruntfile.js 9 | bower-template.json 10 | bower.json 11 | presentation-schedule.md 12 | *.sublime-project 13 | *.sublime-workspace -------------------------------------------------------------------------------- /doc-includes/ContainerParams.txt: -------------------------------------------------------------------------------- 1 | * @param {Object} [config.clip] set clip 2 | * @param {Number} [config.clipX] set clip x 3 | * @param {Number} [config.clipY] set clip y 4 | * @param {Number} [config.clipWidth] set clip width 5 | * @param {Number} [config.clipHeight] set clip height 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.11' 4 | branches: 5 | only: 6 | - master 7 | before_script: 8 | - npm install 9 | script: 10 | - grunt test 11 | deploy: 12 | provider: npm 13 | email: lavrton@gmail.com 14 | api_key: 15 | secure: rYqyBhn3K8tnt/XK6RFodBiIsIqwmUuPBEAOQxRt/elK4F7BVC+ba7/xgsvdFLP+Bqn4sS8b/YjfxUqm0lfxoph3qvvyKZ+qjuGCXBtvbY8EgGqX3FJKq/LJp8Vu4encCUOpI3PWXQEB+0OrC8ntKnBn1L1WP6lzDbRHj49e9ew= 16 | on: 17 | tags: true 18 | repo: ericdrowell/KineticJS 19 | -------------------------------------------------------------------------------- /test/performance/random-squares-dev.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/unit/Util-test.js: -------------------------------------------------------------------------------- 1 | suite('Util', function(){ 2 | var util; 3 | 4 | test('get()', function(){ 5 | assert.equal(Kinetic.Util.get(1, 2), 1); 6 | assert.equal(Kinetic.Util.get(undefined, 2), 2); 7 | assert.equal(Kinetic.Util.get(undefined, {foo:'bar'}).foo, 'bar'); 8 | }); 9 | 10 | test('test _getRGBString()', function(){ 11 | 12 | assert.equal(Kinetic.Util._getRGBAString({}), 'rgba(0,0,0,1)'); 13 | 14 | assert.equal(Kinetic.Util._getRGBAString({ 15 | red: 100, 16 | green: 150, 17 | blue: 200, 18 | alpha: 0.5 19 | }), 'rgba(100,150,200,0.5)'); 20 | 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "curly": true, 3 | "immed": true, 4 | "latedef": true, 5 | "newcap": true, 6 | "noarg": true, 7 | "sub": true, 8 | "undef": true, 9 | "boss": true, 10 | "eqnull": true, 11 | "node": true, 12 | "latedef": true, 13 | "quotmark": "single", 14 | "unused": true, 15 | "trailing" : true, 16 | "laxbreak" : true, 17 | "globals": { 18 | "Kinetic": false, 19 | "document": false, 20 | "window" : false, 21 | "navigator" : false, 22 | "define" : false, 23 | "Image" : false, 24 | "assert" : false, 25 | "test": false, 26 | "addStage" : false 27 | } 28 | } -------------------------------------------------------------------------------- /test/unit/shapes/Polygon-test.js: -------------------------------------------------------------------------------- 1 | suite('Polygon', function() { 2 | test('add polygon', function() { 3 | var stage = addStage(); 4 | 5 | var layer = new Kinetic.Layer(); 6 | var points = [73,192,73,160,340,23,500,109,499,139,342,93]; 7 | 8 | var poly = new Kinetic.Line({ 9 | points: points, 10 | fill: 'green', 11 | stroke: 'blue', 12 | strokeWidth: 5, 13 | closed: true 14 | }); 15 | 16 | layer.add(poly); 17 | stage.add(layer); 18 | 19 | assert.equal(poly.getClassName(), 'Line'); 20 | }); 21 | }); -------------------------------------------------------------------------------- /test/performance/random-squares-v5.0.1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/Group.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | Kinetic.Util.addMethods(Kinetic.Group, { 3 | ___init: function(config) { 4 | this.nodeType = 'Group'; 5 | // call super constructor 6 | Kinetic.Container.call(this, config); 7 | }, 8 | _validateAdd: function(child) { 9 | var type = child.getType(); 10 | if (type !== 'Group' && type !== 'Shape') { 11 | Kinetic.Util.error('You may only add groups and shapes to groups.'); 12 | } 13 | } 14 | }); 15 | Kinetic.Util.extend(Kinetic.Group, Kinetic.Container); 16 | 17 | Kinetic.Collection.mapMethods(Kinetic.Group); 18 | })(); 19 | -------------------------------------------------------------------------------- /src/filters/Invert.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | /** 3 | * Invert Filter 4 | * @function 5 | * @memberof Kinetic.Filters 6 | * @param {Object} imageData 7 | * @example 8 | * node.cache(); 9 | * node.filters([Kinetic.Filters.Invert]); 10 | */ 11 | Kinetic.Filters.Invert = function(imageData) { 12 | var data = imageData.data, 13 | len = data.length, 14 | i; 15 | 16 | for(i = 0; i < len; i += 4) { 17 | // red 18 | data[i] = 255 - data[i]; 19 | // green 20 | data[i + 1] = 255 - data[i + 1]; 21 | // blue 22 | data[i + 2] = 255 - data[i + 2]; 23 | } 24 | }; 25 | })(); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | documentation 3 | analysis 4 | node_modules 5 | bower_components 6 | phantomjs.exe 7 | docs 8 | jsdoc-template 9 | test/sandbox.html 10 | 11 | # Numerous always-ignore extensions 12 | *.diff 13 | *.err 14 | *.orig 15 | *.log 16 | *.rej 17 | *.swo 18 | *.swp 19 | *.vi 20 | *~ 21 | *.sass-cache 22 | 23 | # OS or Editor folders 24 | .DS_Store 25 | Thumbs.db 26 | .cache 27 | .project 28 | .settings 29 | .tmproj 30 | *.esproj 31 | nbproject 32 | *.sublime-project 33 | *.sublime-workspace 34 | *.md.html 35 | 36 | # Dreamweaver added files 37 | _notes 38 | dwsync.xml 39 | 40 | # Komodo 41 | *.komodoproject 42 | .komodotools 43 | 44 | # Folders to ignore 45 | .hg 46 | .svn 47 | .CVS 48 | intermediate 49 | publish 50 | .idea 51 | 52 | -------------------------------------------------------------------------------- /src/filters/Grayscale.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | /** 3 | * Grayscale Filter 4 | * @function 5 | * @memberof Kinetic.Filters 6 | * @param {Object} imageData 7 | * @example 8 | * node.cache(); 9 | * node.filters([Kinetic.Filters.Grayscale]); 10 | */ 11 | Kinetic.Filters.Grayscale = function(imageData) { 12 | var data = imageData.data, 13 | len = data.length, 14 | i, brightness; 15 | 16 | for(i = 0; i < len; i += 4) { 17 | brightness = 0.34 * data[i] + 0.5 * data[i + 1] + 0.16 * data[i + 2]; 18 | // red 19 | data[i] = brightness; 20 | // green 21 | data[i + 1] = brightness; 22 | // blue 23 | data[i + 2] = brightness; 24 | } 25 | }; 26 | })(); 27 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "KineticJS", 3 | "version": "5.1.1", 4 | "homepage": "http://kineticjs.com/", 5 | "authors": [ 6 | "Eric Rowell" 7 | ], 8 | "description": "KineticJS is an HTML5 Canvas JavaScript framework that enables high performance animations, transitions, node nesting, layering, filtering, caching, event handling for desktop and mobile applications, and much more.", 9 | "keywords": [ 10 | "canvas", 11 | "animations", 12 | "graphic", 13 | "html5" 14 | ], 15 | "license": "MIT", 16 | "ignore": [ 17 | "**/.*", 18 | "test", 19 | "tests", 20 | "doc-includes", 21 | "src", 22 | "*.yml", 23 | ".jshitrc", 24 | ".npmignore", 25 | ".gitignore", 26 | "Gruntfile.js", 27 | "bower-template.json", 28 | "server.js", 29 | "presentation-schedule.md" 30 | ], 31 | "main": "kinetic.js" 32 | } 33 | -------------------------------------------------------------------------------- /bower-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "KineticJS", 3 | "version": "@@version", 4 | "homepage": "http://kineticjs.com/", 5 | "authors": [ 6 | "Eric Rowell" 7 | ], 8 | "description": "KineticJS is an HTML5 Canvas JavaScript framework that enables high performance animations, transitions, node nesting, layering, filtering, caching, event handling for desktop and mobile applications, and much more.", 9 | "keywords": [ 10 | "canvas", 11 | "animations", 12 | "graphic", 13 | "html5" 14 | ], 15 | "license": "MIT", 16 | "ignore": [ 17 | "**/.*", 18 | "test", 19 | "tests", 20 | "doc-includes", 21 | "src", 22 | "*.yml", 23 | ".jshitrc", 24 | ".npmignore", 25 | ".gitignore", 26 | "Gruntfile.js", 27 | "bower-template.json", 28 | "server.js", 29 | "presentation-schedule.md" 30 | ], 31 | "main": "kinetic.js" 32 | } 33 | -------------------------------------------------------------------------------- /test/setStats.js: -------------------------------------------------------------------------------- 1 | window.requestAnimFrame = (function(callback){ 2 | return window.requestAnimationFrame || 3 | window.webkitRequestAnimationFrame || 4 | window.mozRequestAnimationFrame || 5 | window.oRequestAnimationFrame || 6 | window.msRequestAnimationFrame || 7 | function(callback){ 8 | window.setTimeout(callback, 1000 / 30); 9 | }; 10 | })(); 11 | 12 | stats = new Stats(); 13 | stats.setMode(0); 14 | stats.domElement.style.position = 'fixed'; 15 | stats.domElement.style.left = '0px'; 16 | stats.domElement.style.top = '0px'; 17 | document.body.appendChild(stats.domElement); 18 | 19 | function setStats() { 20 | stats.begin(); 21 | requestAnimFrame(function(){ 22 | stats.end(); 23 | setStats(); 24 | }); 25 | } 26 | 27 | setStats(); -------------------------------------------------------------------------------- /test/unit/filters/Solarize-test.js: -------------------------------------------------------------------------------- 1 | suite('Solarize', function() { 2 | 3 | // ====================================================== 4 | test('solarize', function(done) { 5 | var stage = addStage(); 6 | 7 | var imageObj = new Image(); 8 | imageObj.onload = function() { 9 | var layer = new Kinetic.Layer(); 10 | darth = new Kinetic.Image({ 11 | x: 10, 12 | y: 10, 13 | image: imageObj, 14 | draggable: true 15 | }); 16 | 17 | layer.add(darth); 18 | stage.add(layer); 19 | darth.cache(); 20 | darth.filters([Kinetic.Filters.Solarize]); 21 | 22 | 23 | layer.draw(); 24 | 25 | 26 | done(); 27 | 28 | }; 29 | imageObj.src = 'assets/darth-vader.jpg'; 30 | //imageObj.src = 'assets/lion.png'; 31 | 32 | }); 33 | 34 | }); -------------------------------------------------------------------------------- /test/unit/shapes/Ellipse-test.js: -------------------------------------------------------------------------------- 1 | suite('Ellipse', function(){ 2 | 3 | // ====================================================== 4 | test('add ellipse', function(){ 5 | var stage = addStage(); 6 | var layer = new Kinetic.Layer(); 7 | var ellipse = new Kinetic.Ellipse({ 8 | x: stage.getWidth() / 2, 9 | y: stage.getHeight() / 2, 10 | radius: {x:70, y:35}, 11 | fill: 'green', 12 | stroke: 'black', 13 | strokeWidth: 8 14 | }); 15 | layer.add(ellipse); 16 | stage.add(layer); 17 | assert.equal(ellipse.getClassName(), 'Ellipse'); 18 | 19 | var trace = layer.getContext().getTrace(); 20 | assert.equal(trace, 'clearRect(0,0,578,200);save();transform(1,0,0,1,289,100);beginPath();save();scale(1,0.5);arc(0,0,70,0,6.283,false);restore();closePath();fillStyle=green;fill();lineWidth=8;strokeStyle=black;stroke();restore();'); 21 | }); 22 | }); -------------------------------------------------------------------------------- /test/unit/shapes/Wedge-test.js: -------------------------------------------------------------------------------- 1 | suite('Wedge', function() { 2 | // ====================================================== 3 | test('add wedge', function() { 4 | var stage = addStage(); 5 | var layer = new Kinetic.Layer(); 6 | var wedge = new Kinetic.Wedge({ 7 | x: 100, 8 | y: 100, 9 | radius: 70, 10 | angle: 180 * 0.4, 11 | fill: 'green', 12 | stroke: 'black', 13 | strokeWidth: 4, 14 | name: 'myCircle', 15 | draggable: true 16 | }); 17 | 18 | layer.add(wedge); 19 | stage.add(layer); 20 | 21 | assert.equal(wedge.getClassName(), 'Wedge'); 22 | 23 | var trace = layer.getContext().getTrace(); 24 | //console.log(trace); 25 | assert.equal(trace, 'clearRect(0,0,578,200);save();transform(1,0,0,1,100,100);beginPath();arc(0,0,70,0,1.257,false);lineTo(0,0);closePath();fillStyle=green;fill();lineWidth=4;strokeStyle=black;stroke();restore();'); 26 | }); 27 | 28 | }); -------------------------------------------------------------------------------- /test/unit/shapes/Arc-test.js: -------------------------------------------------------------------------------- 1 | suite('Arc', function() { 2 | // ====================================================== 3 | test('add arc', function() { 4 | var stage = addStage(); 5 | var layer = new Kinetic.Layer(); 6 | var arc = new Kinetic.Arc({ 7 | x: 100, 8 | y: 100, 9 | innerRadius: 50, 10 | outerRadius: 80, 11 | angle: 90, 12 | fill: 'green', 13 | stroke: 'black', 14 | strokeWidth: 4, 15 | name: 'myArc', 16 | draggable: true 17 | }); 18 | 19 | layer.add(arc); 20 | stage.add(layer); 21 | 22 | assert.equal(arc.getClassName(), 'Arc'); 23 | 24 | var trace = layer.getContext().getTrace(); 25 | //console.log(trace); 26 | assert.equal(trace, 'clearRect(0,0,578,200);save();transform(1,0,0,1,100,100);beginPath();arc(0,0,80,0,1.571,false);arc(0,0,50,1.571,0,true);closePath();fillStyle=green;fill();lineWidth=4;strokeStyle=black;stroke();restore();'); 27 | }); 28 | 29 | }); -------------------------------------------------------------------------------- /test/unit/Group-test.js: -------------------------------------------------------------------------------- 1 | suite('Group', function() { 2 | 3 | // ====================================================== 4 | test('cache group with text', function() { 5 | var stage = addStage(); 6 | 7 | var layer = new Kinetic.Layer(); 8 | var group = new Kinetic.Group({ 9 | draggable : true, 10 | x: 100, 11 | y: 40 12 | }); 13 | var text = new Kinetic.Text({ 14 | text : "some text", 15 | fontSize: 20, 16 | fill: "black", 17 | y : 50 18 | }); 19 | 20 | var rect = new Kinetic.Rect({ 21 | height : 100, 22 | width : 100, 23 | stroke : "#00B80C", 24 | strokeWidth: 10, 25 | cornerRadius: 1 26 | }); 27 | group.add(text); 28 | group.add(rect); 29 | layer.add(group); 30 | 31 | stage.add(layer); 32 | 33 | group.cache({ 34 | x: -5, 35 | y: -5, 36 | width : 110, 37 | height : 110, 38 | drawBorder: true 39 | }).offsetX(5).offsetY(5); 40 | 41 | stage.draw(); 42 | }); 43 | }); 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /test/unit/Canvas-test.js: -------------------------------------------------------------------------------- 1 | suite('Canvas', function() { 2 | // ====================================================== 3 | test('pixel ratio', function() { 4 | var stage = addStage(); 5 | 6 | var layer = new Kinetic.Layer(); 7 | 8 | var circle = new Kinetic.Circle({ 9 | x: 578/2, 10 | y: 100, 11 | radius: 70, 12 | fill: 'green', 13 | stroke: 'blue', 14 | strokeWidth: 4 15 | }); 16 | 17 | layer.add(circle); 18 | stage.add(layer); 19 | 20 | 21 | stage.setWidth(578/2); 22 | stage.setHeight(100); 23 | 24 | stage.draw(); 25 | 26 | layer.getCanvas().setPixelRatio(1); 27 | assert.equal(layer.getCanvas().getPixelRatio(), 1); 28 | assert.equal(layer.getCanvas().width, 289); 29 | assert.equal(layer.getCanvas().height, 100); 30 | 31 | layer.getCanvas().setPixelRatio(2); 32 | assert.equal(layer.getCanvas().getPixelRatio(), 2); 33 | assert.equal(layer.getCanvas().width, 578); 34 | assert.equal(layer.getCanvas().height, 200); 35 | 36 | layer.draw(); 37 | 38 | }); 39 | }); -------------------------------------------------------------------------------- /test/unit/plugins/Arrow-test.js: -------------------------------------------------------------------------------- 1 | suite('Arrow', function() { 2 | // ====================================================== 3 | test('add arrow', function() { 4 | var stage = addStage(); 5 | var layer = new Kinetic.Layer(); 6 | 7 | var arrow = new Kinetic.Arrow({ 8 | points: [73,160, 340, 23], 9 | stroke: 'blue', 10 | fill : 'blue', 11 | strokeWidth: 1, 12 | draggable: true, 13 | tension: 0 14 | }); 15 | 16 | layer.add(arrow); 17 | stage.add(layer); 18 | 19 | arrow.setPoints([1, 2, 3, 4]); 20 | assert.equal(arrow.points()[0], 1); 21 | 22 | arrow.setPoints([5,6,7,8]); 23 | assert.equal(arrow.getPoints()[0], 5); 24 | arrow.setPoints([73, 160, 340, 23, 50,100, 80, 50]); 25 | arrow.tension(0); 26 | 27 | arrow.pointerLength(15); 28 | assert.equal(arrow.pointerLength(), 15); 29 | 30 | arrow.pointerWidth(15); 31 | assert.equal(arrow.pointerWidth(), 15); 32 | 33 | assert.equal(arrow.getClassName(), 'Arrow'); 34 | 35 | layer.draw(); 36 | showHit(layer); 37 | }); 38 | }); -------------------------------------------------------------------------------- /test/unit/filters/Mask-test.js: -------------------------------------------------------------------------------- 1 | suite('Mask', function() { 2 | 3 | // ====================================================== 4 | test('basic', function(done) { 5 | var stage = addStage(); 6 | 7 | var imageObj = new Image(); 8 | imageObj.onload = function() { 9 | 10 | var layer = new Kinetic.Layer({ 11 | throttle: 999 12 | }); 13 | var bamoon = new Kinetic.Image({ 14 | x: 0, 15 | y: 0, 16 | image: imageObj, 17 | draggable: true 18 | }), 19 | filtered = new Kinetic.Image({ 20 | x: 300, 21 | y: 0, 22 | image: imageObj, 23 | draggable: true 24 | }); 25 | 26 | layer.add(bamoon); 27 | layer.add(filtered); 28 | stage.add(layer); 29 | 30 | filtered.cache(); 31 | filtered.filters([Kinetic.Filters.Mask]); 32 | filtered.threshold(10); 33 | 34 | layer.draw(); 35 | 36 | done(); 37 | 38 | }; 39 | imageObj.src = 'assets/bamoon.jpg'; 40 | 41 | }); 42 | 43 | }); -------------------------------------------------------------------------------- /doc-includes/NodeParams.txt: -------------------------------------------------------------------------------- 1 | @param {Number} [config.x] 2 | * @param {Number} [config.y] 3 | * @param {Number} [config.width] 4 | * @param {Number} [config.height] 5 | * @param {Boolean} [config.visible] 6 | * @param {Boolean} [config.listening] whether or not the node is listening for events 7 | * @param {String} [config.id] unique id 8 | * @param {String} [config.name] non-unique name 9 | * @param {Number} [config.opacity] determines node opacity. Can be any number between 0 and 1 10 | * @param {Object} [config.scale] set scale 11 | * @param {Number} [config.scaleX] set scale x 12 | * @param {Number} [config.scaleY] set scale y 13 | * @param {Number} [config.rotation] rotation in degrees 14 | * @param {Object} [config.offset] offset from center point and rotation point 15 | * @param {Number} [config.offsetX] set offset x 16 | * @param {Number} [config.offsetY] set offset y 17 | * @param {Boolean} [config.draggable] makes the node draggable. When stages are draggable, you can drag and drop 18 | * the entire stage by dragging any portion of the stage 19 | * @param {Number} [config.dragDistance] 20 | * @param {Function} [config.dragBoundFunc] -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kinetic", 3 | "version": "5.1.1", 4 | "devDependencies": { 5 | "grunt-contrib-jshint": "0.10.0", 6 | "grunt-contrib-nodeunit": "0.4.1", 7 | "grunt-contrib-uglify": "0.6.0", 8 | "grunt-contrib-concat": "0.5.0", 9 | "grunt-replace": "0.7.9", 10 | "grunt-contrib-clean": "0.6.0", 11 | "mocha": "1.21.4", 12 | "chai": "1.9.2", 13 | "phantomjs": "1.9.10", 14 | "mocha-phantomjs": "3.5.0", 15 | "grunt-cli": "0.1.13", 16 | "grunt": "0.4.5", 17 | "connect": "3.2.0", 18 | "grunt-contrib-copy": "~0.6.0", 19 | "jsdoc": "~3.3.0-alpha9", 20 | "grunt-mocha-phantomjs": "~0.6.0", 21 | "grunt-contrib-watch": "~0.6.1", 22 | "grunt-shell": "~1.1.1" 23 | }, 24 | "keywords": [ 25 | "canvas", 26 | "animations", 27 | "graphic", 28 | "html5" 29 | ], 30 | "browser": { 31 | "canvas": false, 32 | "jsdom": false 33 | }, 34 | "bugs": { 35 | "url": "https://github.com/ericdrowell/KineticJS/issues" 36 | }, 37 | "readmeFilename": "README.md", 38 | "main": "kinetic.js", 39 | "repository": { 40 | "type": "git", 41 | "url": "git://github.com/ericdrowell/KineticJS.git" 42 | }, 43 | "author": "Eric Rowell", 44 | "license": "MIT" 45 | } 46 | -------------------------------------------------------------------------------- /test/unit/FastLayer-test.js: -------------------------------------------------------------------------------- 1 | suite('FastLayer', function() { 2 | 3 | // ====================================================== 4 | test('basic render', function() { 5 | var stage = addStage(); 6 | 7 | var layer = new Kinetic.FastLayer(); 8 | 9 | var circle = new Kinetic.Circle({ 10 | x: 100, 11 | y: stage.getHeight() / 2, 12 | radius: 70, 13 | fill: 'green', 14 | stroke: 'black', 15 | strokeWidth: 4 16 | }); 17 | 18 | layer.add(circle); 19 | stage.add(layer); 20 | 21 | 22 | }); 23 | 24 | test('cache shape on fast layer', function(){ 25 | var stage = addStage(); 26 | var layer = new Kinetic.FastLayer(); 27 | 28 | var circle = new Kinetic.Circle({ 29 | x: 74, 30 | y: 74, 31 | radius: 70, 32 | fill: 'green', 33 | stroke: 'black', 34 | strokeWidth: 4, 35 | name: 'myCircle' 36 | }); 37 | 38 | layer.add(circle); 39 | stage.add(layer); 40 | 41 | 42 | circle.cache({ 43 | x: -74, 44 | y: -74, 45 | width: 148, 46 | height: 148 47 | }).offset({ 48 | x: 74, 49 | y: 74 50 | }); 51 | 52 | layer.draw(); 53 | 54 | 55 | }); 56 | 57 | 58 | }); -------------------------------------------------------------------------------- /test/unit/BaseLayer-test.js: -------------------------------------------------------------------------------- 1 | suite('BaseLayer', function() { 2 | 3 | // ====================================================== 4 | test('width and height', function() { 5 | var stage = addStage(); 6 | 7 | var layer = new Kinetic.FastLayer(); 8 | assert.equal(layer.width(), undefined, 'while layer is not on stage width is undefined'); 9 | assert.equal(layer.height(), undefined, 'while layer is not on stage height is undefined'); 10 | 11 | layer.width(10); 12 | assert.equal(layer.width(), undefined, 'while layer is not on stage changing width doing nothing'); 13 | layer.height(10); 14 | assert.equal(layer.height(), undefined, 'while layer is not on stage changing height doing nothing'); 15 | stage.add(layer); 16 | 17 | assert.equal(layer.width(), stage.width(), 'while layer is on stage width is stage`s width'); 18 | assert.equal(layer.height(), stage.height(), 'while layer is on stage height is stage`s height'); 19 | 20 | layer.width(10); 21 | assert.equal(layer.width(), stage.width(), 'while layer is on stage changing width doing nothing'); 22 | layer.height(10); 23 | assert.equal(layer.height(), stage.height(), 'while layer is on stage changing height doing nothing'); 24 | }); 25 | }); -------------------------------------------------------------------------------- /src/filters/Brighten.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | /** 3 | * Brighten Filter. 4 | * @function 5 | * @memberof Kinetic.Filters 6 | * @param {Object} imageData 7 | * @example 8 | * node.cache(); 9 | * node.filters([Kinetic.Filters.Brighten]); 10 | * node.brightness(0.8); 11 | */ 12 | Kinetic.Filters.Brighten = function(imageData) { 13 | var brightness = this.brightness() * 255, 14 | data = imageData.data, 15 | len = data.length, 16 | i; 17 | 18 | for(i = 0; i < len; i += 4) { 19 | // red 20 | data[i] += brightness; 21 | // green 22 | data[i + 1] += brightness; 23 | // blue 24 | data[i + 2] += brightness; 25 | } 26 | }; 27 | 28 | Kinetic.Factory.addGetterSetter(Kinetic.Node, 'brightness', 0, null, Kinetic.Factory.afterSetFilter); 29 | /** 30 | * get/set filter brightness. The brightness is a number between -1 and 1. Positive values 31 | * brighten the pixels and negative values darken them. Use with {@link Kinetic.Filters.Brighten} filter. 32 | * @name brightness 33 | * @method 34 | * @memberof Kinetic.Node.prototype 35 | * @param {Number} brightness value between -1 and 1 36 | * @returns {Number} 37 | */ 38 | 39 | })(); 40 | -------------------------------------------------------------------------------- /test/performance/rotate-star.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 56 | 57 | -------------------------------------------------------------------------------- /src/filters/Threshold.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | /** 4 | * Threshold Filter. Pushes any value above the mid point to 5 | * the max and any value below the mid point to the min. 6 | * This affects the alpha channel. 7 | * @function 8 | * @name Threshold 9 | * @memberof Kinetic.Filters 10 | * @param {Object} imageData 11 | * @author ippo615 12 | * @example 13 | * node.cache(); 14 | * node.filters([Kinetic.Filters.Threshold]); 15 | * node.threshold(0.1); 16 | */ 17 | 18 | Kinetic.Filters.Threshold = function (imageData) { 19 | var level = this.threshold() * 255, 20 | data = imageData.data, 21 | len = data.length, 22 | i; 23 | 24 | for (i = 0; i < len; i += 1) { 25 | data[i] = data[i] < level ? 0 : 255; 26 | } 27 | }; 28 | 29 | Kinetic.Factory.addGetterSetter(Kinetic.Node, 'threshold', 0.5, null, Kinetic.Factory.afterSetFilter); 30 | 31 | /** 32 | * get/set threshold. Must be a value between 0 and 1. Use with {@link Kinetic.Filters.Threshold} or {@link Kinetic.Filters.Mask} filter. 33 | * @name threshold 34 | * @method 35 | * @memberof Kinetic.Node.prototype 36 | * @param {Number} threshold 37 | * @returns {Number} 38 | */ 39 | })(); -------------------------------------------------------------------------------- /src/filters/Noise.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | /** 4 | * Noise Filter. Randomly adds or substracts to the color channels 5 | * @function 6 | * @name Noise 7 | * @memberof Kinetic.Filters 8 | * @param {Object} imageData 9 | * @author ippo615 10 | * @example 11 | * node.cache(); 12 | * node.filters([Kinetic.Filters.Noise]); 13 | * node.noise(0.8); 14 | */ 15 | Kinetic.Filters.Noise = function (imageData) { 16 | var amount = this.noise() * 255, 17 | data = imageData.data, 18 | nPixels = data.length, 19 | half = amount / 2, 20 | i; 21 | 22 | for (i = 0; i < nPixels; i += 4) { 23 | data[i + 0] += half - 2 * half * Math.random(); 24 | data[i + 1] += half - 2 * half * Math.random(); 25 | data[i + 2] += half - 2 * half * Math.random(); 26 | } 27 | }; 28 | 29 | Kinetic.Factory.addGetterSetter(Kinetic.Node, 'noise', 0.2, null, Kinetic.Factory.afterSetFilter); 30 | 31 | /** 32 | * get/set noise amount. Must be a value between 0 and 1. Use with {@link Kinetic.Filters.Noise} filter. 33 | * @name noise 34 | * @method 35 | * @memberof Kinetic.Node.prototype 36 | * @param {Number} noise 37 | * @returns {Number} 38 | */ 39 | })(); 40 | -------------------------------------------------------------------------------- /test/unit/filters/Noise-test.js: -------------------------------------------------------------------------------- 1 | suite('Noise', function () { 2 | 3 | // ====================================================== 4 | test('noise tween', function(done) { 5 | var stage = addStage(); 6 | 7 | var imageObj = new Image(); 8 | imageObj.onload = function() { 9 | 10 | var layer = new Kinetic.Layer(); 11 | darth = new Kinetic.Image({ 12 | x: 10, 13 | y: 10, 14 | image: imageObj, 15 | draggable: true 16 | }); 17 | 18 | layer.add(darth); 19 | stage.add(layer); 20 | 21 | darth.cache(); 22 | darth.filters([Kinetic.Filters.Noise]); 23 | darth.noise(1); 24 | layer.draw(); 25 | 26 | var tween = new Kinetic.Tween({ 27 | node: darth, 28 | duration: 5.0, 29 | noise: 0, 30 | easing: Kinetic.Easings.EaseInOut 31 | }); 32 | 33 | darth.on('mouseover', function() { 34 | tween.play(); 35 | }); 36 | 37 | darth.on('mouseout', function() { 38 | tween.reverse(); 39 | }); 40 | 41 | done(); 42 | }; 43 | imageObj.src = 'assets/lion.png'; 44 | 45 | }); 46 | 47 | }); 48 | -------------------------------------------------------------------------------- /test/unit/filters/Pixelate-test.js: -------------------------------------------------------------------------------- 1 | suite('Pixelate', function () { 2 | 3 | // ====================================================== 4 | test('tween pixelate', function(done) { 5 | var stage = addStage(); 6 | 7 | var imageObj = new Image(); 8 | imageObj.onload = function() { 9 | 10 | var layer = new Kinetic.Layer(); 11 | lion = new Kinetic.Image({ 12 | x: 10, 13 | y: 10, 14 | image: imageObj, 15 | draggable: true 16 | }); 17 | 18 | layer.add(lion); 19 | stage.add(layer); 20 | 21 | lion.cache(); 22 | lion.filters([Kinetic.Filters.Pixelate]); 23 | lion.pixelSize(16); 24 | layer.draw(); 25 | 26 | var tween = new Kinetic.Tween({ 27 | node: lion, 28 | duration: 3.0, 29 | pixelSize: 1, 30 | easing: Kinetic.Easings.EaseInOut 31 | }); 32 | 33 | lion.on('mouseover', function() { 34 | tween.play(); 35 | }); 36 | 37 | lion.on('mouseout', function() { 38 | tween.reverse(); 39 | }); 40 | 41 | done(); 42 | 43 | }; 44 | imageObj.src = 'assets/lion.png'; 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /test/memory/build-destroy-text.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 59 | 60 | -------------------------------------------------------------------------------- /test/unit/filters/Threshold-test.js: -------------------------------------------------------------------------------- 1 | suite('Threshold', function () { 2 | // ====================================================== 3 | test('image tween', function(done) { 4 | var stage = addStage(); 5 | 6 | var imageObj = new Image(); 7 | imageObj.onload = function() { 8 | 9 | var layer = new Kinetic.Layer(); 10 | darth = new Kinetic.Image({ 11 | x: 10, 12 | y: 10, 13 | image: imageObj, 14 | draggable: true 15 | }); 16 | 17 | layer.add(darth); 18 | stage.add(layer); 19 | 20 | darth.cache(); 21 | darth.filters([Kinetic.Filters.Threshold]); 22 | darth.threshold(1); 23 | layer.draw(); 24 | 25 | var tween = new Kinetic.Tween({ 26 | node: darth, 27 | duration: 5.0, 28 | threshold: 0, 29 | easing: Kinetic.Easings.EaseInOut 30 | }); 31 | 32 | darth.on('mouseover', function() { 33 | tween.play(); 34 | }); 35 | 36 | darth.on('mouseout', function() { 37 | tween.reverse(); 38 | }); 39 | 40 | done(); 41 | }; 42 | imageObj.src = 'assets/darth-vader.jpg'; 43 | 44 | }); 45 | 46 | }); 47 | -------------------------------------------------------------------------------- /test/unit/filters/Posterize-test.js: -------------------------------------------------------------------------------- 1 | suite('Posterize', function () { 2 | 3 | // ====================================================== 4 | test('on image tween', function(done) { 5 | var stage = addStage(); 6 | 7 | var imageObj = new Image(); 8 | imageObj.onload = function() { 9 | 10 | var layer = new Kinetic.Layer(); 11 | darth = new Kinetic.Image({ 12 | x: 10, 13 | y: 10, 14 | image: imageObj, 15 | draggable: true 16 | }); 17 | 18 | layer.add(darth); 19 | stage.add(layer); 20 | 21 | darth.cache(); 22 | darth.filters([Kinetic.Filters.Posterize]); 23 | darth.levels(0.2); 24 | layer.draw(); 25 | 26 | var tween = new Kinetic.Tween({ 27 | node: darth, 28 | duration: 1.0, 29 | levels: 0, 30 | easing: Kinetic.Easings.Linear 31 | }); 32 | 33 | darth.on('mouseover', function() { 34 | tween.play(); 35 | }); 36 | 37 | darth.on('mouseout', function() { 38 | tween.reverse(); 39 | }); 40 | 41 | done(); 42 | }; 43 | imageObj.src = 'assets/darth-vader.jpg'; 44 | 45 | }); 46 | 47 | }); 48 | -------------------------------------------------------------------------------- /src/filters/Posterize.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | /** 4 | * Posterize Filter. Adjusts the channels so that there are no more 5 | * than n different values for that channel. This is also applied 6 | * to the alpha channel. 7 | * @function 8 | * @name Posterize 9 | * @author ippo615 10 | * @memberof Kinetic.Filters 11 | * @param {Object} imageData 12 | * @example 13 | * node.cache(); 14 | * node.filters([Kinetic.Filters.Posterize]); 15 | * node.levels(0.8); 16 | */ 17 | 18 | Kinetic.Filters.Posterize = function (imageData) { 19 | // level must be between 1 and 255 20 | var levels = Math.round(this.levels() * 254) + 1, 21 | data = imageData.data, 22 | len = data.length, 23 | scale = (255 / levels), 24 | i; 25 | 26 | for (i = 0; i < len; i += 1) { 27 | data[i] = Math.floor(data[i] / scale) * scale; 28 | } 29 | }; 30 | 31 | Kinetic.Factory.addGetterSetter(Kinetic.Node, 'levels', 0.5, null, Kinetic.Factory.afterSetFilter); 32 | 33 | /** 34 | * get/set levels. Must be a number between 0 and 1. Use with {@link Kinetic.Filters.Posterize} filter. 35 | * @name levels 36 | * @method 37 | * @memberof Kinetic.Node.prototype 38 | * @param {Number} level between 0 and 1 39 | * @returns {Number} 40 | */ 41 | })(); -------------------------------------------------------------------------------- /test/memory/build-destroy-star.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 63 | 64 | -------------------------------------------------------------------------------- /test/performance/rotate-cached-star.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 63 | 64 | -------------------------------------------------------------------------------- /src/filters/Solarize.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | /** 3 | * Solarize Filter 4 | * Pixastic Lib - Solarize filter - v0.1.0 5 | * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/ 6 | * License: [http://www.pixastic.com/lib/license.txt] 7 | * @function 8 | * @name Solarize 9 | * @memberof Kinetic.Filters 10 | * @param {Object} imageData 11 | * @example 12 | * node.cache(); 13 | * node.filters([Kinetic.Filters.Solarize]); 14 | */ 15 | Kinetic.Filters.Solarize = function (imageData) { 16 | var data = imageData.data, 17 | w = imageData.width, 18 | h = imageData.height, 19 | w4 = w*4, 20 | y = h; 21 | 22 | do { 23 | var offsetY = (y-1)*w4; 24 | var x = w; 25 | do { 26 | var offset = offsetY + (x-1)*4; 27 | var r = data[offset]; 28 | var g = data[offset+1]; 29 | var b = data[offset+2]; 30 | 31 | if (r > 127) { 32 | r = 255 - r; 33 | } 34 | if (g > 127) { 35 | g = 255 - g; 36 | } 37 | if (b > 127) { 38 | b = 255 - b; 39 | } 40 | 41 | data[offset] = r; 42 | data[offset+1] = g; 43 | data[offset+2] = b; 44 | } while (--x); 45 | } while (--y); 46 | }; 47 | })(); 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/filters/Sepia.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | /** 3 | * Sepia Filter 4 | * Based on: Pixastic Lib - Sepia filter - v0.1.0 5 | * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/ 6 | * @function 7 | * @name Sepia 8 | * @memberof Kinetic.Filters 9 | * @param {Object} imageData 10 | * @author Jacob Seidelin