├── test ├── res │ ├── file-for-ajax.txt │ └── external-svg.svg ├── system.js ├── test.html ├── mina.js ├── paper.js ├── primitives.js ├── set.js ├── matrix.js ├── filter.js ├── colors.js └── attrs.js ├── src ├── amd-footer.js ├── amd-banner.js ├── copy.js ├── equal.js ├── set.js ├── mina.js └── filter.js ├── .gitignore ├── demos ├── pattern │ ├── bg.png │ └── index.html ├── snap-mascot │ ├── style.css │ ├── index.html │ ├── snap-logo.html │ └── crocodile-1.html ├── tutorial │ ├── tutorial.html │ ├── mascot.svg │ └── index.html ├── animated-game │ └── js │ │ ├── tree-face.js │ │ ├── main.js │ │ ├── path-animal.js │ │ └── seedrandom.js ├── animated-map │ └── index.html └── illustrated-infographic-coffee │ └── index.html ├── doc ├── fonts │ ├── sourcesanspro-light-webfont.eot │ ├── sourcesanspro-light-webfont.ttf │ ├── sourcesanspro-light-webfont.woff │ ├── sourcecodepro-regular-webfont.eot │ ├── sourcecodepro-regular-webfont.ttf │ ├── sourcecodepro-regular-webfont.woff │ ├── sourcesanspro-regular-webfont.eot │ ├── sourcesanspro-regular-webfont.ttf │ ├── sourcesanspro-regular-webfont.woff │ ├── sourcesanspro-semibold-webfont.eot │ ├── sourcesanspro-semibold-webfont.ttf │ ├── sourcesanspro-semibold-webfont.woff │ └── stylesheet.css ├── img │ ├── search.svg │ └── search_dark.svg ├── css │ ├── dr.css │ └── prism.css └── js │ └── prism.js ├── CONTRIBUTING ├── .gitmodules ├── component.json ├── bower.json ├── package.json ├── dr.json ├── Gruntfile.js ├── README.md ├── NOTICE ├── template.dot └── LICENSE /test/res/file-for-ajax.txt: -------------------------------------------------------------------------------- 1 | success -------------------------------------------------------------------------------- /src/amd-footer.js: -------------------------------------------------------------------------------- 1 | return Snap; 2 | })); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | TAGS 2 | *~ 3 | _* 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /demos/pattern/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rthauby/Snap.svg/master/demos/pattern/bg.png -------------------------------------------------------------------------------- /doc/fonts/sourcesanspro-light-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rthauby/Snap.svg/master/doc/fonts/sourcesanspro-light-webfont.eot -------------------------------------------------------------------------------- /doc/fonts/sourcesanspro-light-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rthauby/Snap.svg/master/doc/fonts/sourcesanspro-light-webfont.ttf -------------------------------------------------------------------------------- /doc/fonts/sourcesanspro-light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rthauby/Snap.svg/master/doc/fonts/sourcesanspro-light-webfont.woff -------------------------------------------------------------------------------- /doc/fonts/sourcecodepro-regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rthauby/Snap.svg/master/doc/fonts/sourcecodepro-regular-webfont.eot -------------------------------------------------------------------------------- /doc/fonts/sourcecodepro-regular-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rthauby/Snap.svg/master/doc/fonts/sourcecodepro-regular-webfont.ttf -------------------------------------------------------------------------------- /doc/fonts/sourcecodepro-regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rthauby/Snap.svg/master/doc/fonts/sourcecodepro-regular-webfont.woff -------------------------------------------------------------------------------- /doc/fonts/sourcesanspro-regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rthauby/Snap.svg/master/doc/fonts/sourcesanspro-regular-webfont.eot -------------------------------------------------------------------------------- /doc/fonts/sourcesanspro-regular-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rthauby/Snap.svg/master/doc/fonts/sourcesanspro-regular-webfont.ttf -------------------------------------------------------------------------------- /doc/fonts/sourcesanspro-regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rthauby/Snap.svg/master/doc/fonts/sourcesanspro-regular-webfont.woff -------------------------------------------------------------------------------- /doc/fonts/sourcesanspro-semibold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rthauby/Snap.svg/master/doc/fonts/sourcesanspro-semibold-webfont.eot -------------------------------------------------------------------------------- /doc/fonts/sourcesanspro-semibold-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rthauby/Snap.svg/master/doc/fonts/sourcesanspro-semibold-webfont.ttf -------------------------------------------------------------------------------- /doc/fonts/sourcesanspro-semibold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rthauby/Snap.svg/master/doc/fonts/sourcesanspro-semibold-webfont.woff -------------------------------------------------------------------------------- /test/res/external-svg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | Contributions to this code are covered by the Adobe contributors 2 | license agreeent. Developers must sign and submit the Adobe CLA in 3 | order to contribute to this project. -------------------------------------------------------------------------------- /demos/snap-mascot/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | overflow: hidden; 3 | } 4 | 5 | body { 6 | background: #eee; 7 | text-align: center; 8 | } 9 | 10 | svg { 11 | display: inline-block; 12 | } 13 | 14 | iframe { 15 | display: inline-block; 16 | border: none; 17 | height: 300px; 18 | width: 400px; 19 | margin: 10px; 20 | } -------------------------------------------------------------------------------- /test/system.js: -------------------------------------------------------------------------------- 1 | describe("System check", function () { 2 | it("Snap exists", function () { 3 | expect(Snap).to.be.a("function"); 4 | }); 5 | it("eve exists", function () { 6 | expect(eve).to.be.a("function"); 7 | }); 8 | it("mina exists", function () { 9 | expect(mina).to.be.a("function"); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "third-party/mocha"] 2 | path = third-party/mocha 3 | url = https://github.com/visionmedia/mocha.git 4 | [submodule "third-party/eve"] 5 | path = third-party/eve 6 | url = https://github.com/adobe-webplatform/eve.git 7 | [submodule "third-party/expect"] 8 | path = third-party/expect 9 | url = https://github.com/LearnBoost/expect.js.git 10 | -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Snap.svg", 3 | "repo": "adobe-webplatform/Snap.svg", 4 | "description": "The JavaScript library for modern SVG graphics.", 5 | "version": "0.1.1", 6 | "keywords": ["svg", "snap", "js", "javascript"], 7 | "dependencies": {}, 8 | "development": {}, 9 | "main": "dist/snap.svg-min.js", 10 | "scripts": [ 11 | "dist/snap.svg-min.js" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /src/amd-banner.js: -------------------------------------------------------------------------------- 1 | (function (glob, factory) { 2 | // AMD support 3 | if (typeof define === "function" && define.amd) { 4 | // Define as an anonymous module 5 | define(["eve"], function( eve ) { 6 | return factory(glob, eve); 7 | }); 8 | } else { 9 | // Browser globals (glob is window) 10 | // Snap adds itself to window 11 | factory(glob, glob.eve); 12 | } 13 | }(this, function (window, eve) { -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Snap.svg", 3 | "version": "0.1.1", 4 | "homepage": "http://snapsvg.io", 5 | "authors": [ 6 | "Dmitry Baranovskiy " 7 | ], 8 | "description": "The JavaScript library for modern SVG graphics", 9 | "main": "dist/snap.svg-min.js", 10 | "keywords": [ 11 | "svg", 12 | "snap", 13 | "js", 14 | "javascript" 15 | ], 16 | "license": "Apache 2", 17 | "ignore": [ 18 | "**/.*", 19 | "node_modules", 20 | "bower_components", 21 | "test", 22 | "demos", 23 | "src" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "snapsvg", 3 | "version": "0.2.0", 4 | "description": "JavaScript Vector Library", 5 | "main": "Gruntfile.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git@github.com:adobe-webplatform/Snap.svg.git" 9 | }, 10 | "author": "Dmitry Baranovskiy", 11 | "license": "Apache License v2", 12 | "devDependencies": { 13 | "grunt": "~0.4.1", 14 | "grunt-contrib-uglify": "~0.2.0", 15 | "grunt-contrib-concat": "~0.3.0", 16 | "grunt-exec": "~0.4.2", 17 | "mocha": "*", 18 | "expect.js": "*", 19 | "eve": "*", 20 | "dr.js": "~0.1.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/copy.js: -------------------------------------------------------------------------------- 1 | // Snap.svg @VERSION 2 | // 3 | // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | // build: @DATE -------------------------------------------------------------------------------- /dr.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Snap.svg", 3 | "output": "doc/reference.html", 4 | "template": "template.dot", 5 | "files": [{ 6 | "url": "src/svg.js", 7 | "link": "https://github.com/adobe-webplatform/savage/blob/master/src/svg.js" 8 | }, { 9 | "url": "src/equal.js", 10 | "link": "https://github.com/adobe-webplatform/savage/blob/master/src/equal.js" 11 | }, { 12 | "url": "src/mina.js", 13 | "link": "https://github.com/adobe-webplatform/savage/blob/master/src/mina.js" 14 | }, { 15 | "url": "src/filter.js", 16 | "link": "https://github.com/adobe-webplatform/savage/blob/master/src/filter.js" 17 | }, { 18 | "url": "src/mouse.js", 19 | "link": "https://github.com/adobe-webplatform/savage/blob/master/src/mouse.js" 20 | }, { 21 | "url": "src/path.js", 22 | "link": "https://github.com/adobe-webplatform/savage/blob/master/src/path.js" 23 | }, { 24 | "url": "src/set.js", 25 | "link": "https://github.com/adobe-webplatform/savage/blob/master/src/set.js" 26 | }] 27 | } -------------------------------------------------------------------------------- /demos/snap-mascot/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | Snap 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /doc/img/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Slice 1 4 | Created with Sketch (http://www.bohemiancoding.com/sketch) 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /doc/img/search_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | ]> 9 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /demos/tutorial/tutorial.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Snap.svg 6 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 44 | 45 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | var pkg = grunt.file.readJSON("package.json"); 4 | 5 | // Project configuration. 6 | grunt.initConfig({ 7 | // Metadata. 8 | pkg: pkg, 9 | banner: grunt.file.read("./src/copy.js") 10 | .replace(/@VERSION/, pkg.version) 11 | .replace(/@DATE/, grunt.template.today("yyyy-mm-dd")) + "\n", 12 | // Task configuration. 13 | uglify: { 14 | options: { 15 | banner: "<%= banner %>", 16 | report: "min" 17 | }, 18 | dist: { 19 | src: "<%= concat.target.dest %>", 20 | dest: "dist/snap.svg-min.js" 21 | } 22 | }, 23 | concat: { 24 | options: { 25 | banner: "<%= banner %>" 26 | }, 27 | target: { 28 | dest: "dist/snap.svg.js", 29 | src: [ 30 | "./node_modules/eve/eve.js", 31 | "./src/amd-banner.js", 32 | "./src/mina.js", 33 | "./src/svg.js", 34 | "./src/path.js", 35 | "./src/set.js", 36 | "./src/equal.js", 37 | "./src/mouse.js", 38 | "./src/filter.js", 39 | "./src/amd-footer.js", 40 | ] 41 | } 42 | }, 43 | exec: { 44 | dr: { 45 | command: "node node_modules/dr.js/dr dr.json" 46 | } 47 | } 48 | }); 49 | 50 | grunt.loadNpmTasks("grunt-contrib-concat"); 51 | grunt.loadNpmTasks("grunt-contrib-uglify"); 52 | grunt.loadNpmTasks("grunt-exec"); 53 | 54 | grunt.registerTask("default", ["concat", "uglify", "exec"]); 55 | }; -------------------------------------------------------------------------------- /demos/animated-game/js/tree-face.js: -------------------------------------------------------------------------------- 1 | 2 | var TreeFace = Backbone.View.extend({ 3 | initialize: function () { 4 | this.s = this.options.s; 5 | this.el = this.options.tree; 6 | 7 | this.addFace(); 8 | 9 | /* 10 | setTimeout(function () { 11 | this.face.attr({ 12 | 'class': 'face animating' 13 | }); 14 | }.bind(this), Math.random() * 2000 ); 15 | */ 16 | 17 | this.hitarea = this.s.circle(0, 0, 40); 18 | this.hitarea.attr({ 19 | fill: 'transparent', 20 | 'class': 'hit-area' 21 | }); 22 | this.face.add(this.hitarea); 23 | this.hitarea.mouseover(this.handle_MOUSEOVER.bind(this)); 24 | this.hitarea.mouseout(this.handle_MOUSEOUT.bind(this)); 25 | }, 26 | 27 | handle_MOUSEOVER: function () { 28 | this.face.attr({ 29 | 'class': 'face animating' 30 | }); 31 | }, 32 | 33 | handle_MOUSEOUT: function () { 34 | this.face.attr({ 35 | 'class': 'face' 36 | }); 37 | }, 38 | 39 | addFace: function () { 40 | var mouth, 41 | eye, 42 | ey2, 43 | matrix; 44 | 45 | this.face = this.s.g(); 46 | this.face.attr({ 47 | 'class': 'face' 48 | }); 49 | /* 50 | mouth = this.s.circle(0, 5, 4); 51 | mouth.attr({fill: 'black', 'class': 'mouth'}); 52 | this.face.add(mouth); 53 | */ 54 | eye = this.s.path('M-2.75-6.75c0,0-2.537,2.5-5.667,2.5s-5.667-2.5-5.667-2.5s2.537-2.5,5.667-2.5S-2.75-6.75-2.75-6.75z'); 55 | eye.attr({fill: 'white', 'class': 'eye left'}); 56 | this.face.add(eye); 57 | 58 | eye2 = this.s.path('M14.583-6.75c0,0-2.537,2.5-5.667,2.5S3.25-6.75,3.25-6.75s2.537-2.5,5.667-2.5S14.583-6.75,14.583-6.75z'); 59 | eye2.attr({fill: 'white', 'class': 'eye right'}); 60 | this.face.add(eye2); 61 | 62 | matrix = new Snap.Matrix(); 63 | box = this.el.getBBox(); 64 | matrix.translate(box.cx, box.cy); 65 | matrix.scale(box.r2 / 40); 66 | 67 | this.face.transform(matrix.toTransformString()); 68 | this.el.add(this.face); 69 | }, 70 | }); 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [Snap.svg](http://snapsvg.io) 2 | ====== 3 | 4 | A JavaScript SVG library for the modern web. Learn more at [snapsvg.io](http://snapsvg.io). 5 | 6 | [Follow us on Twitter.](https://twitter.com/snapsvg) 7 | 8 | ### Learn 9 | 10 | * [About Snap.svg](http://snapsvg.io/about/) 11 | * [Getting Started](http://snapsvg.io/start/) 12 | * [API Reference](http://snapsvg.io/docs/) 13 | 14 | ### Use 15 | 16 | In your HTML file, load simply by: `` 17 | No other scripts are needed. Both the minified and uncompressed (for development) versions are in the `/dist` folder. 18 | 19 | ### Build 20 | 21 | Snap.svg uses [Grunt](http://gruntjs.com/) to build. 22 | 23 | * Open the terminal from the Snap.svg directory: 24 | 25 | cd Snap.svg 26 | 27 | * Install its command line interface (CLI) globally: 28 | 29 | npm install -g grunt-cli 30 | 31 | _*You might need to use `sudo npm`, depending on your configuration._ 32 | 33 | * Install dependencies with npm: 34 | 35 | npm install 36 | 37 | _*Snap.svg uses Grunt 0.4.0. You might want to [read](http://gruntjs.com/getting-started) more on their website if you haven’t upgraded since a lot has changed._ 38 | 39 | * Type `grunt` in the command line to build the files. 40 | * The results will be built into the release folder. 41 | * Alternatively type `grunt watch` to have the build run automatically when you make changes to source files. 42 | 43 | ### Contribute 44 | 45 | * [Fill out the CLA](http://snapsvg.io/contributions/). 46 | * [Fork](https://help.github.com/articles/fork-a-repo) the repo. 47 | * Create a branch: 48 | 49 | git checkout -b my_branch 50 | 51 | * Add your changes. 52 | * Commit your changes: 53 | 54 | git commit -am "Added some awesome stuff" 55 | 56 | * Push your branch: 57 | 58 | git push origin my_branch 59 | 60 | * Make a [pull request](https://help.github.com/articles/using-pull-requests) to `dev` branch. 61 | 62 | *Note:* Pull requests to other branches than `dev` or without filled CLA wouldn’t be accepted. 63 | -------------------------------------------------------------------------------- /doc/fonts/stylesheet.css: -------------------------------------------------------------------------------- 1 | 2 | @font-face { 3 | font-family: 'source-sans-pro'; 4 | src: url('sourcesanspro-light-webfont.eot'); 5 | src: url('sourcesanspro-light-webfont.eot?#iefix') format('embedded-opentype'), 6 | url('sourcesanspro-light-webfont.woff') format('woff'), 7 | url('sourcesanspro-light-webfont.ttf') format('truetype'), 8 | url('sourcesanspro-light-webfont.svg#source_sans_prolight') format('svg'); 9 | font-weight: 300; 10 | font-style: normal; 11 | 12 | } 13 | 14 | 15 | 16 | 17 | @font-face { 18 | font-family: 'source-sans-pro'; 19 | src: url('sourcesanspro-regular-webfont.eot'); 20 | src: url('sourcesanspro-regular-webfont.eot?#iefix') format('embedded-opentype'), 21 | url('sourcesanspro-regular-webfont.woff') format('woff'), 22 | url('sourcesanspro-regular-webfont.ttf') format('truetype'), 23 | url('sourcesanspro-regular-webfont.svg#source_sans_proregular') format('svg'); 24 | font-weight: 400; 25 | font-style: normal; 26 | 27 | } 28 | 29 | 30 | 31 | 32 | @font-face { 33 | font-family: 'source-sans-pro'; 34 | src: url('sourcesanspro-semibold-webfont.eot'); 35 | src: url('sourcesanspro-semibold-webfont.eot?#iefix') format('embedded-opentype'), 36 | url('sourcesanspro-semibold-webfont.woff') format('woff'), 37 | url('sourcesanspro-semibold-webfont.ttf') format('truetype'), 38 | url('sourcesanspro-semibold-webfont.svg#source_sans_prosemibold') format('svg'); 39 | font-weight: 600; 40 | font-style: normal; 41 | 42 | } 43 | 44 | 45 | 46 | 47 | @font-face { 48 | font-family: 'source-code-pro'; 49 | src: url('sourcecodepro-regular-webfont.eot'); 50 | src: url('sourcecodepro-regular-webfont.eot?#iefix') format('embedded-opentype'), 51 | url('sourcecodepro-regular-webfont.woff') format('woff'), 52 | url('sourcecodepro-regular-webfont.ttf') format('truetype'), 53 | url('sourcecodepro-regular-webfont.svg#source_code_proregular') format('svg'); 54 | font-weight: normal; 55 | font-style: normal; 56 | 57 | } -------------------------------------------------------------------------------- /test/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | Savage Tests 19 | 26 | 27 | 28 | 29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /demos/animated-game/js/main.js: -------------------------------------------------------------------------------- 1 | var WIDTH = 1024, 2 | HEIGHT = 720; 3 | console.log('oh'); 4 | 5 | var MainView = Backbone.View.extend({ 6 | initialize: function () { 7 | 8 | var i, 9 | dotGroup, 10 | animal; 11 | 12 | Math.seedrandom('fish'); 13 | 14 | this.state = 0; 15 | this.dots = []; 16 | this.animals = []; 17 | this.trees = []; 18 | this.treeFaces = []; 19 | this.s = Snap(document.getElementsByTagName('svg')[0]); 20 | 21 | //dot animals 22 | dotGroup = this.s.select('#dots'); 23 | this.dots = dotGroup.selectAll('*'); 24 | 25 | for (i = 0; i < this.dots.length; i += 1) { 26 | animal = new PathAnimal({s: this.s, dot: this.dots[i]}); 27 | this.animals.push(animal); 28 | } 29 | 30 | //sort depth 31 | for (i = 0; i < this.animals.length; i += 1) { 32 | if (i > 0) { 33 | var a = this.animals[i - 1].el, 34 | b = this.animals[i].el; 35 | 36 | if (a.matrix.split().dy > b.matrix.split().dy) { 37 | a.before(b); 38 | } 39 | } 40 | } 41 | 42 | //trees 43 | this.trees = this.s.selectAll('.tree'); 44 | for (i = 0; i < this.trees.length; i += 1) { 45 | var tree = new TreeFace({s: this.s, tree: this.trees[i]}); 46 | this.treeFaces.push(tree); 47 | } 48 | 49 | this.cube = document.getElementById('cube'); 50 | var $cubeHitArea = document.getElementById('cube-hitarea'); 51 | $cubeHitArea.addEventListener('click', this.handle_ROLL.bind(this)); 52 | 53 | setTimeout(this.animate.bind(this), 3000); 54 | }, 55 | 56 | handle_ROLL: function () { 57 | this.number = Math.ceil(Math.random() * 6); 58 | if (this.number == 6) { 59 | rx = 45; 60 | ry = 180; 61 | rz = -45; 62 | } else if (this.number == 5) { 63 | rx = 50; 64 | ry = 0; 65 | rz = 50; 66 | } else if (this.number == 4) { 67 | rx = -45; 68 | ry = 50; 69 | rz = 90; 70 | } else if (this.number == 3) { 71 | rx = -45; 72 | ry = 225; 73 | rz = -90; 74 | } else if (this.number == 2) { 75 | rx = -45; 76 | ry = 50; 77 | rz = 0; 78 | } else if (this.number == 1) { 79 | rx = 145; 80 | ry = -45; 81 | rz = 0; 82 | } else { 83 | rx = -90; 84 | ry = 0; 85 | rz = 0; 86 | } 87 | 88 | this.cube.style['webkitTransform'] = 'rotateX(' + rx + 'deg) rotateY(' + ry + 'deg) rotateZ(' + rz + 'deg)'; 89 | this.cube.style['MozTransform'] = 'rotateX(' + rx + 'deg) rotateY(' + ry + 'deg) rotateZ(' + rz + 'deg)'; 90 | }, 91 | 92 | trigger: function () { 93 | this.state += 1;//this.number; 94 | var animal = this.animals[this.state]; 95 | animal.handle_MOUSEOVER(); 96 | 97 | }, 98 | 99 | animate: function () { 100 | var tree = this.treeFaces[Math.floor(Math.random() * this.treeFaces.length)]; 101 | tree.handle_MOUSEOVER(); 102 | 103 | setTimeout(function () { 104 | tree.handle_MOUSEOUT(); 105 | }.bind(this), 3000); 106 | 107 | setTimeout(this.animate.bind(this), 3000); 108 | } 109 | }); 110 | 111 | var main = new MainView(); -------------------------------------------------------------------------------- /demos/animated-game/js/path-animal.js: -------------------------------------------------------------------------------- 1 | var PathAnimal = Backbone.View.extend({ 2 | initialize: function () { 3 | var _x, 4 | _y, 5 | PATHS = [ 6 | 'M0,0c0,0,0-28.008,0-46.707S0-89,0-89', 7 | 'M0,0c0,0-9.634-22.317,10-46.707S50-69,50-69', 8 | 'M0,0c0,0,17.52-24.431,0-56.707S-50-99-50-99' 9 | ]; 10 | 11 | this.s = this.options.s; 12 | this.dot = this.options.dot; 13 | _x = this.dot.attr('cx'); 14 | _y = this.dot.attr('cy'); 15 | 16 | this.el = this.s.g(); 17 | 18 | this.path = this.s.path(PATHS[Math.floor(Math.random() * PATHS.length)]); 19 | this.totalLength = this.dashOffset = this.path.getTotalLength(); 20 | 21 | this.path.attr({ 22 | fill: 'none', 23 | stroke: this.dot.attr('fill'), 24 | strokeWidth: 25, 25 | strokeMiterlimit: 10, 26 | strokeLinecap: 'round', 27 | opacity: 1, 28 | strokeDasharray: this.totalLength + " 200", 29 | strokeDashoffset: this.totalLength 30 | }); 31 | this.el.add(this.path); 32 | 33 | this.el.transform("t" + [_x, _y]); 34 | 35 | this.hitarea = this.s.circle(_x, _y, 30); 36 | this.hitarea.attr({ 37 | fill: 'transparent', 38 | 'class': 'hit-area' 39 | }); 40 | this.hitarea.mouseover(this.handle_MOUSEOVER.bind(this)); 41 | this.hitarea.mouseout(this.handle_MOUSEOUT.bind(this)); 42 | 43 | this.addFace(); 44 | }, 45 | 46 | addFace: function () { 47 | var mouth, 48 | eye, 49 | ey2; 50 | 51 | this.face = this.s.g(); 52 | this.face.attr({ 53 | 'class': 'face' 54 | }); 55 | 56 | mouth = this.s.circle(0, 5, 4); 57 | mouth.attr({fill: 'black', 'class': 'mouth'}); 58 | this.face.add(mouth); 59 | 60 | eye = this.s.path('M-2.75-6.75c0,0-2.537,2.5-5.667,2.5s-5.667-2.5-5.667-2.5s2.537-2.5,5.667-2.5S-2.75-6.75-2.75-6.75z'); 61 | eye.attr({fill: 'white', 'class': 'eye left'}); 62 | this.face.add(eye); 63 | 64 | eye2 = this.s.path('M14.583-6.75c0,0-2.537,2.5-5.667,2.5S3.25-6.75,3.25-6.75s2.537-2.5,5.667-2.5S14.583-6.75,14.583-6.75z'); 65 | eye2.attr({fill: 'white', 'class': 'eye right'}); 66 | this.face.add(eye2); 67 | 68 | this.face.transform("s.6"); 69 | this.el.add(this.face); 70 | }, 71 | 72 | handle_MOUSEOVER: function () { 73 | var instance = this; 74 | 75 | this.face.attr({ 76 | 'class': 'face animating' 77 | }); 78 | Snap.animate(this.dashOffset, 0, function (val) { 79 | instance.dashOffset = val; 80 | instance.render(); 81 | }, 500); 82 | }, 83 | 84 | handle_MOUSEOUT: function () { 85 | var instance = this; 86 | 87 | this.face.attr({ 88 | 'class': 'face' 89 | }); 90 | Snap.animate(this.dashOffset, this.totalLength, function (val) { 91 | instance.dashOffset = val; 92 | instance.render(); 93 | }, 500); 94 | }, 95 | 96 | render: function () { 97 | var point; 98 | 99 | this.path.attr({ 100 | 'stroke-dashoffset': this.dashOffset 101 | }); 102 | 103 | point = this.path.getPointAtLength(this.totalLength - this.dashOffset); 104 | this.face.transform("t" + [point.x, point.y] + "s.6"); 105 | } 106 | }); -------------------------------------------------------------------------------- /test/mina.js: -------------------------------------------------------------------------------- 1 | describe("Mina methods", function () { 2 | var s; 3 | beforeEach(function () { 4 | s = Snap(100, 100); 5 | }); 6 | afterEach(function () { 7 | s.remove(); 8 | }); 9 | 10 | var validateDescriptor = function(obj) { 11 | expect(obj).to.be.an('object'); 12 | expect(obj.id).to.be.a('string'); 13 | expect(obj.start).to.be.a('number'); 14 | expect(obj.end).to.be.a('number'); 15 | expect(obj.b).to.be.a('number'); 16 | expect(obj.s).to.be.a('number'); 17 | expect(obj.dur).to.be.a('number'); 18 | expect(obj.spd).to.be.a('number'); 19 | 20 | expect(obj.get).to.be.a('function'); 21 | expect(obj.set).to.be.a('function'); 22 | expect(obj.easing).to.be.a('function'); 23 | expect(obj.status).to.be.a('function'); 24 | expect(obj.speed).to.be.a('function'); 25 | expect(obj.duration).to.be.a('function'); 26 | expect(obj.stop).to.be.a('function'); 27 | }; 28 | 29 | it("mina", function() { 30 | var n; 31 | var animDescriptor = mina(10, 20, 0, 1000, function(newN) { 32 | n = newN; 33 | }, function() {}); 34 | 35 | validateDescriptor(animDescriptor); 36 | expect(animDescriptor.start).to.be(10); 37 | expect(animDescriptor.end).to.be(20); 38 | expect(animDescriptor.b).to.be(0); 39 | expect(animDescriptor.s).to.be(0); 40 | expect(animDescriptor.dur).to.be(1000); 41 | expect(animDescriptor.easing).to.be(mina.linear); 42 | }); 43 | it("mina.getById", function() { 44 | var anim1 = mina(10, 20, 0, 1000, function() {}, function() {}); 45 | var anim2 = mina(10, 20, 0, 1000, function() {}, function() {}); 46 | expect(mina.getById(anim1.id)).to.be(anim1); 47 | expect(mina.getById(anim2.id)).to.be(anim2); 48 | }); 49 | it("mina.time", function() { 50 | var now = (new Date).getTime(); 51 | expect(mina.time()).to.be(now); 52 | }); 53 | it("mina.backin", function() { 54 | expect(mina.backin(0)).to.be(0); 55 | expect(mina.backin(1)).to.be(1); 56 | }); 57 | it("mina.backout", function() { 58 | expect(mina.backout(0)).to.be(0); 59 | expect(mina.backout(1)).to.be(1); 60 | }); 61 | it("mina.bounce", function() { 62 | expect(mina.bounce(0)).to.be(0); 63 | expect(mina.bounce(1)).to.be(1); 64 | }); 65 | it("mina.easein", function() { 66 | expect(mina.easein(0)).to.be(0); 67 | expect(mina.easein(1)).to.be(1); 68 | }); 69 | it("mina.easeinout", function() { 70 | expect(mina.easeinout(0)).to.be(0); 71 | expect(mina.easeinout(1)).to.be(1); 72 | }); 73 | it("mina.easeout", function() { 74 | expect(mina.easeout(0)).to.be(0); 75 | expect(mina.easeout(1)).to.be(1); 76 | }); 77 | it("mina.elastic", function() { 78 | expect(mina.elastic(0)).to.be(0); 79 | expect(mina.elastic(1)).to.be(1); 80 | }); 81 | it("mina.linear", function() { 82 | expect(mina.linear(0)).to.be(0); 83 | expect(mina.linear(0.2)).to.be(0.2); 84 | expect(mina.linear(0.7)).to.be(0.7); 85 | expect(mina.linear(1)).to.be(1); 86 | }); 87 | }); -------------------------------------------------------------------------------- /doc/css/dr.css: -------------------------------------------------------------------------------- 1 | #content section.code { 2 | display: block; 3 | font-weight: 400; 4 | background: #181818; 5 | -moz-border-radius: 10px; 6 | -webkit-border-radius: 10px; 7 | border-radius: 10px; 8 | } 9 | #content section.code pre code { 10 | font-size: 14px; 11 | } 12 | code { 13 | font-family: source-code-pro, Menlo, "Arial Unicode MS", sans-serif; 14 | } 15 | a.dr-hash, 16 | a.dr-sourceline { 17 | -webkit-transition: opacity 0.2s linear; 18 | color: #333; 19 | font-family: Menlo, "Arial Unicode MS", sans-serif; 20 | margin: 0 0 0 .3em; 21 | opacity: 0; 22 | text-decoration: none; 23 | } 24 | h2:hover a.dr-hash, 25 | h3:hover a.dr-hash, 26 | h4:hover a.dr-hash, 27 | h5:hover a.dr-hash, 28 | h2:hover a.dr-sourceline, 29 | h3:hover a.dr-sourceline, 30 | h4:hover a.dr-sourceline, 31 | h5:hover a.dr-sourceline { 32 | opacity: 1; 33 | } 34 | .dr-param { 35 | float: left; 36 | min-width: 8em; 37 | } 38 | .dr-type { 39 | float: left; 40 | } 41 | .dr-type em, 42 | .dr-returns em, 43 | .dr-property em { 44 | -moz-border-radius: 5px; 45 | -webkit-border-radius: 5px; 46 | background: #ccc; 47 | border-radius: 5px; 48 | float: left; 49 | font-size: .75em; 50 | font-style: normal; 51 | font-weight: 700; 52 | margin: 0 8px 0 0; 53 | min-width: 80px; 54 | padding: 2px 5px; 55 | text-align: center; 56 | } 57 | .dr-type em.amp, 58 | .dr-returns em.amp, 59 | .dr-property em.amp { 60 | float: none; 61 | background: none; 62 | font-size: 1em; 63 | font-weight: 400; 64 | font-style: italic; 65 | margin: 0; 66 | padding: 0; 67 | min-width: 0; 68 | } 69 | .dr-property em.dr-type { 70 | margin: 4px 16px 0 0; 71 | } 72 | em.dr-type-string { 73 | background: #e1edb1; 74 | color: #3d4c00; 75 | } 76 | em.dr-type-object { 77 | background: #edb1b1; 78 | color: #4c0000; 79 | } 80 | em.dr-type-function { 81 | background: #cfb1ed; 82 | color: #26004c; 83 | } 84 | em.dr-type-number { 85 | background: #b1c9ed; 86 | color: #001e4c; 87 | } 88 | em.dr-type-boolean { 89 | background: #b1edc9; 90 | color: #004c1e; 91 | } 92 | em.dr-type-array { 93 | background: #edd5b1; 94 | color: #4c2d00; 95 | } 96 | .dr-optional { 97 | display: none; 98 | } 99 | ol.dr-json { 100 | background: #ddd; 101 | list-style: none; 102 | margin: 0 -30px; 103 | padding: 16px 30px; 104 | line-height: 1.5; 105 | } 106 | ol.dr-json .dr-json-key { 107 | float: left; 108 | min-width: 50px; 109 | margin-right: 16px; 110 | } 111 | ol.dr-json .dr-json-description { 112 | display: table; 113 | } 114 | ol.dr-json ol.dr-json { 115 | margin: 0; 116 | padding: 0 0 0 50px; 117 | } 118 | #pageNav li.dr-lvl1 a { 119 | padding-left: 1em; 120 | } 121 | #pageNav li.dr-lvl2 a { 122 | padding-left: 2em; 123 | } 124 | #pageNav li.dr-lvl3 a { 125 | padding-left: 3em; 126 | } 127 | #pageNav li.dr-lvl4 a { 128 | padding-left: 4em; 129 | } 130 | #pageNav li.dr-lvl5 a { 131 | padding-left: 5em; 132 | } 133 | #pageNav li.dr-lvl6 a { 134 | padding-left: 6em; 135 | } 136 | #pageNav ol { 137 | list-style: none; 138 | margin: 0; 139 | padding: 0; 140 | } -------------------------------------------------------------------------------- /demos/pattern/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | Snap 19 | 24 | 25 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /demos/animated-map/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | Long Flight 19 | 24 | 25 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /doc/css/prism.css: -------------------------------------------------------------------------------- 1 | /** 2 | * prism.js Twilight theme 3 | * Based (more or less) on the Twilight theme originally of Textmate fame. 4 | * @author Remy Bach 5 | */ 6 | code[class*="language-"], 7 | pre[class*="language-"] { 8 | color: white; 9 | direction: ltr; 10 | font-family: source-code-pro, Consolas, Monaco, 'Andale Mono', monospace; 11 | text-align: left; 12 | text-shadow: 0 -.1em .2em black; 13 | white-space: pre; 14 | word-spacing: normal; 15 | 16 | -moz-tab-size: 4; 17 | -o-tab-size: 4; 18 | tab-size: 4; 19 | 20 | -webkit-hyphens: none; 21 | -moz-hyphens: none; 22 | -ms-hyphens: none; 23 | hyphens: none; 24 | } 25 | 26 | pre[class*="language-"], 27 | :not(pre) > code[class*="language-"] { 28 | background:#181818; 29 | } 30 | 31 | /* Code blocks */ 32 | pre[class*="language-"] { 33 | margin: .5em 0; 34 | overflow: auto; 35 | } 36 | pre[class*="language-"]::selection { /* Safari */ 37 | background:hsl(200, 4%, 16%); /* #282A2B */ 38 | } 39 | pre[class*="language-"]::selection { /* Firefox */ 40 | background:hsl(200, 4%, 16%); /* #282A2B */ 41 | } 42 | 43 | /* Inline code */ 44 | :not(pre) > code[class*="language-"] { 45 | border-radius: .3em; 46 | border: .13em solid hsl(0,0%,33%); /* #545454 */ 47 | box-shadow: 1px 1px .3em -.1em black inset; 48 | padding: .15em .2em .05em; 49 | } 50 | 51 | .token.comment, 52 | .token.prolog, 53 | .token.doctype, 54 | .token.cdata { 55 | color: hsl(0, 0%, 47%); /* #777777 */ 56 | } 57 | 58 | .token.punctuation { 59 | opacity: .7; 60 | } 61 | 62 | .namespace { 63 | opacity: .7; 64 | } 65 | 66 | .token.tag, 67 | .token.boolean, 68 | .token.number { 69 | color: hsl(14, 58%, 55%); /* #CF6A4C */ 70 | } 71 | 72 | .token.keyword, 73 | .token.property, 74 | .token.selector { 75 | color:hsl(53, 89%, 79%); /* #F9EE98 */ 76 | } 77 | .token.attr-name, 78 | .token.attr-value, 79 | .token.string, 80 | .token.operator, 81 | .token.entity, 82 | .token.url, 83 | .language-css .token.string, 84 | .style .token.string { 85 | color:hsl(76, 21%, 52%); /* #8F9D6A */ 86 | } 87 | 88 | .token.atrule { 89 | color:hsl(218, 22%, 55%); /* #7587A6 */ 90 | } 91 | 92 | .token.regex, 93 | .token.important { 94 | color: hsl(42, 75%, 65%); /* #E9C062 */ 95 | } 96 | 97 | .token.important { 98 | font-weight: bold; 99 | } 100 | 101 | .token.entity { 102 | cursor: help; 103 | } 104 | pre[data-line] { 105 | padding: 1em 0 1em 3em; 106 | position: relative; 107 | } 108 | 109 | /* Markup */ 110 | .language-markup .token.tag, 111 | .language-markup .token.attr-name, 112 | .language-markup .token.punctuation { 113 | color: hsl(33, 33%, 52%); /* #AC885B */ 114 | } 115 | 116 | /* Text Selection colour */ 117 | ::selection { 118 | background: hsla(0,0%,93%,0.15); /* #EDEDED */ 119 | } 120 | ::-moz-selection { 121 | background: hsla(0,0%,93%,0.15); /* #EDEDED */ 122 | } 123 | 124 | /* Make the tokens sit above the line highlight so the colours don't look faded. */ 125 | .token { 126 | position:relative; 127 | z-index:1; 128 | } 129 | .line-highlight { 130 | background: -moz-linear-gradient(left, hsla(0, 0%, 33%,.1) 70%, hsla(0, 0%, 33%,0)); /* #545454 */ 131 | background: -o-linear-gradient(left, hsla(0, 0%, 33%,.1) 70%, hsla(0, 0%, 33%,0)); /* #545454 */ 132 | background: -webkit-linear-gradient(left, hsla(0, 0%, 33%,.1) 70%, hsla(0, 0%, 33%,0)); /* #545454 */ 133 | background: hsla(0, 0%, 33%, 0.25); /* #545454 */ 134 | background: linear-gradient(left, hsla(0, 0%, 33%,.1) 70%, hsla(0, 0%, 33%,0)); /* #545454 */ 135 | border-bottom:1px dashed hsl(0, 0%, 33%); /* #545454 */ 136 | border-top:1px dashed hsl(0, 0%, 33%); /* #545454 */ 137 | left: 0; 138 | line-height: inherit; 139 | margin-top: 0.75em; /* Same as .prism’s padding-top */ 140 | padding: inherit 0; 141 | pointer-events: none; 142 | position: absolute; 143 | right: 0; 144 | white-space: pre; 145 | z-index:0; 146 | } 147 | .line-highlight:before, 148 | .line-highlight[data-end]:after { 149 | background-color: hsl(215, 15%, 59%); /* #8794A6 */ 150 | border-radius: 999px; 151 | box-shadow: 0 1px white; 152 | color: hsl(24, 20%, 95%); /* #F5F2F0 */ 153 | content: attr(data-start); 154 | font: bold 65%/1.5 sans-serif; 155 | left: .6em; 156 | min-width: 1em; 157 | padding: 0 .5em; 158 | position: absolute; 159 | text-align: center; 160 | text-shadow: none; 161 | top: .4em; 162 | vertical-align: .3em; 163 | } 164 | .line-highlight[data-end]:after { 165 | bottom: .4em; 166 | content: attr(data-end); 167 | top: auto; 168 | } -------------------------------------------------------------------------------- /test/paper.js: -------------------------------------------------------------------------------- 1 | describe("Check for Paper Creation", function () { 2 | it("creates simple paper 20 × 10", function () { 3 | var s = Snap(20, 10); 4 | var S = s.node; 5 | expect(S).to.not.be(null); 6 | expect(S.getAttribute("width")).to.be("20"); 7 | expect(S.getAttribute("height")).to.be("10"); 8 | s.remove(); 9 | }); 10 | it("removal of paper", function () { 11 | var s = Snap(20, 10); 12 | var S = s.node; 13 | expect(S).to.not.be(null); 14 | s.remove(); 15 | S = document.querySelectorAll("svg").length; 16 | expect(S).to.be(1); 17 | }); 18 | it("creates simple paper 20% × 10em", function () { 19 | var s = Snap("20%", "10em"); 20 | var S = s.node; 21 | expect(S).to.not.be(null); 22 | expect(S.getAttribute("width")).to.be("20%"); 23 | expect(S.getAttribute("height")).to.be("10em"); 24 | s.remove(); 25 | }); 26 | it("converts existing SVG element to paper", function () { 27 | var S = document.getElementById("svgroot"); 28 | var s = Snap(S); 29 | expect(document.querySelector("#svgroot circle")).to.be(null); 30 | var c = s.circle(10, 20, 5); 31 | expect(document.querySelectorAll("#svgroot circle").length).to.be(1); 32 | c.remove(); 33 | }); 34 | it("converts existing SVG element to paper (as query)", function () { 35 | var S = document.getElementById("svgroot"); 36 | var s = Snap("#svgroot"); 37 | expect(document.querySelector("#svgroot circle")).to.be(null); 38 | var c = s.circle(10, 20, 5); 39 | expect(document.querySelectorAll("#svgroot circle").length).to.be(1); 40 | c.remove(); 41 | }); 42 | }); 43 | 44 | describe("Paper methods", function () { 45 | /* 46 | Paper.el 47 | Paper.filter 48 | Paper.gradient 49 | Paper.image 50 | Paper.toString 51 | */ 52 | var paper; 53 | beforeEach(function () { 54 | paper = Snap(100, 100); 55 | }); 56 | afterEach(function () { 57 | paper.remove(); 58 | }); 59 | 60 | it("Paper.el", function() { 61 | var c = paper.el("circle"); 62 | expect(c.node.nodeName).to.be("circle"); 63 | expect(c.node.parentNode).to.be(paper.node); 64 | }); 65 | it("Paper.filter", function() { 66 | var filter = paper.filter(''); 67 | expect(filter.node.nodeName).to.be('filter'); 68 | var child = filter.node.firstChild; 69 | expect(child).to.be.ok(); 70 | expect(child.nodeName).to.be('feGaussianBlur'); 71 | expect(child.getAttribute("stdDeviation")).to.be('2'); 72 | }); 73 | it("Paper.gradient - linear", function() { 74 | var gradient = paper.gradient("l(0, 0, 1, 1)#000-#f00-#fff"); 75 | expect(gradient.node.nodeName).to.be('linearGradient'); 76 | expect(gradient.node.getAttribute('x1')).to.be("0"); 77 | expect(gradient.node.getAttribute('y1')).to.be("0"); 78 | expect(gradient.node.getAttribute('x2')).to.be("1"); 79 | expect(gradient.node.getAttribute('y2')).to.be("1"); 80 | var stops = gradient.node.querySelectorAll("stop"); 81 | expect(stops.length).to.be(3); 82 | }); 83 | it("Paper.gradient - radial", function() { 84 | var gradient = paper.gradient("r(0.3, 0.4, 0.5)#000-#fff"); 85 | expect(gradient.node.nodeName).to.be('radialGradient'); 86 | expect(gradient.node.getAttribute('cx')).to.be("0.3"); 87 | expect(gradient.node.getAttribute('cy')).to.be("0.4"); 88 | expect(gradient.node.getAttribute('r')).to.be("0.5"); 89 | var stops = gradient.node.querySelectorAll("stop"); 90 | expect(stops.length).to.be(2); 91 | }); 92 | it("Paper.image", function() { 93 | var image = paper.image('#', 10, 20, 30, 40); 94 | var img = document.querySelector("image"); 95 | expect(img).to.not.be(null); 96 | expect(img.getAttribute("x")).to.be("10"); 97 | expect(img.getAttribute("y")).to.be("20"); 98 | expect(img.getAttribute("width")).to.be("30"); 99 | expect(img.getAttribute("height")).to.be("40"); 100 | }); 101 | it("Paper.toString", function() { 102 | paper.circle(10, 20, 30); 103 | var str = paper.toString(); 104 | expect(str).to.match(/.*?.*?/); 105 | }); 106 | it("Paper.getBBox", function() { 107 | paper.circle(50, 50, 30); 108 | var bb = paper.getBBox(); 109 | expect(bb.x).to.be(20); 110 | expect(bb.y).to.be(20); 111 | expect(bb.width).to.be(60); 112 | expect(bb.height).to.be(60); 113 | }); 114 | }); -------------------------------------------------------------------------------- /test/primitives.js: -------------------------------------------------------------------------------- 1 | describe("Primitives creation", function () { 2 | var s; 3 | beforeEach(function () { 4 | s = Snap(100, 100); 5 | }); 6 | afterEach(function () { 7 | s.remove(); 8 | }); 9 | it("creates a circle", function () { 10 | var c = s.circle(10, 20, 30); 11 | var C = document.querySelector("circle"); 12 | expect(C).to.not.be(null); 13 | expect(C.getAttribute("cx")).to.be("10"); 14 | expect(C.getAttribute("cy")).to.be("20"); 15 | expect(C.getAttribute("r")).to.be("30"); 16 | }); 17 | it("creates a rect", function () { 18 | var c = s.rect(10, 20, 30, 40, 5); 19 | var C = document.querySelector("rect"); 20 | expect(C).to.not.be(null); 21 | expect(C.getAttribute("x")).to.be("10"); 22 | expect(C.getAttribute("y")).to.be("20"); 23 | expect(C.getAttribute("width")).to.be("30"); 24 | expect(C.getAttribute("height")).to.be("40"); 25 | expect(C.getAttribute("rx")).to.be("5"); 26 | expect(C.getAttribute("ry")).to.be("5"); 27 | }); 28 | it("creates a rect with different rx & ry", function () { 29 | var c = s.rect(10, 20, 30, 40, 5, 6); 30 | var C = document.querySelector("rect"); 31 | expect(C).to.not.be(null); 32 | expect(C.getAttribute("x")).to.be("10"); 33 | expect(C.getAttribute("y")).to.be("20"); 34 | expect(C.getAttribute("width")).to.be("30"); 35 | expect(C.getAttribute("height")).to.be("40"); 36 | expect(C.getAttribute("rx")).to.be("5"); 37 | expect(C.getAttribute("ry")).to.be("6"); 38 | }); 39 | it("creates a ellipse", function () { 40 | var c = s.ellipse(10, 20, 30, 40); 41 | var C = document.querySelector("ellipse"); 42 | expect(C).to.not.be(null); 43 | expect(C.getAttribute("cx")).to.be("10"); 44 | expect(C.getAttribute("cy")).to.be("20"); 45 | expect(C.getAttribute("rx")).to.be("30"); 46 | expect(C.getAttribute("ry")).to.be("40"); 47 | }); 48 | it("creates a ellipse", function () { 49 | var c = s.ellipse(10, 20, 30, 40); 50 | var C = document.querySelector("ellipse"); 51 | expect(C).to.not.be(null); 52 | expect(C.getAttribute("cx")).to.be("10"); 53 | expect(C.getAttribute("cy")).to.be("20"); 54 | expect(C.getAttribute("rx")).to.be("30"); 55 | expect(C.getAttribute("ry")).to.be("40"); 56 | }); 57 | it("creates a path", function () { 58 | var c = s.path("M10,10,50,60"); 59 | var C = document.querySelector("path"); 60 | expect(C).to.not.be(null); 61 | expect(C.getAttribute("d")).to.be("M10,10,50,60"); 62 | expect(C.getBBox().width).to.be(40); 63 | }); 64 | it("creates a line", function () { 65 | var c = s.line(10, 10, 50, 60); 66 | var C = document.querySelector("line"); 67 | expect(C).to.not.be(null); 68 | expect(C.getAttribute("x1")).to.be("10"); 69 | expect(C.getBBox().width).to.be(40); 70 | }); 71 | it("creates a polyline", function () { 72 | var c = s.polyline(10, 10, 50, 60, 70, 80); 73 | var C = document.querySelector("polyline"); 74 | expect(C).to.not.be(null); 75 | expect(C.getAttribute("points")).to.be("10,10,50,60,70,80"); 76 | }); 77 | it("creates a polygon", function () { 78 | var c = s.polygon(10, 10, 50, 60, 70, 80); 79 | var C = document.querySelector("polygon"); 80 | expect(C).to.not.be(null); 81 | expect(C.getAttribute("points")).to.be("10,10,50,60,70,80"); 82 | }); 83 | it("creates a group", function () { 84 | var c = s.group(); 85 | var C = document.querySelector("g"); 86 | expect(C).to.not.be(null); 87 | }); 88 | it("creates and fills a group", function () { 89 | var c = s.group(), 90 | a = s.circle(10, 10, 10), 91 | b = s.circle(20, 20, 10), 92 | C = document.querySelector("g"); 93 | c.add(a, b); 94 | expect(C).to.not.be(null); 95 | expect(C.childNodes.length).to.be(2); 96 | }); 97 | it("creates and fills a group on creation", function () { 98 | var circle1 = s.circle(10, 10, 10); 99 | var circle2 = s.circle(20, 10, 10); 100 | var group = s.g(circle1, circle2); 101 | var groupEl = document.querySelector("g"); 102 | expect(groupEl).to.not.be(null); 103 | expect(groupEl.childNodes.length).to.be(2); 104 | }); 105 | it("creates a text", function () { 106 | var c = s.text(10, 10, "test"); 107 | var C = document.querySelector("text"); 108 | expect(C).to.not.be(null); 109 | expect(C.getAttribute("x")).to.be("10"); 110 | expect(C.textContent).to.be("test"); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /test/set.js: -------------------------------------------------------------------------------- 1 | describe("Set methods", function () { 2 | var s; 3 | beforeEach(function () { 4 | s = Snap(100, 100); 5 | }); 6 | afterEach(function () { 7 | s.remove(); 8 | }); 9 | it("Set.clear", function() { 10 | var rect1 = s.rect(10, 20, 30, 40); 11 | var rect2 = s.rect(10, 20, 30, 40); 12 | var set = Snap.set(rect1, rect2); 13 | expect(set.length).to.be(2); 14 | set.clear(); 15 | expect(set.length).to.be(0); 16 | }); 17 | it("Set.exclude", function() { 18 | var rect1 = s.rect(10, 20, 30, 40); 19 | var rect2 = s.rect(10, 20, 30, 40); 20 | var rect3 = s.rect(10, 20, 30, 40); 21 | var set = Snap.set(rect1, rect2, rect3); 22 | expect(set.length).to.be(3); 23 | var excluded = set.exclude(rect2); 24 | expect(set.length).to.be(2); 25 | expect(excluded).to.be(true); 26 | excluded = set.exclude(rect2); 27 | expect(set.length).to.be(2); 28 | expect(excluded).to.be(false); 29 | }); 30 | it("Set.remove", function() { 31 | var rect1 = s.rect(10, 20, 30, 40); 32 | var rect2 = s.rect(10, 20, 30, 40); 33 | var rect3 = s.rect(10, 20, 30, 40); 34 | var set = Snap.set(rect1, rect2, rect3); 35 | expect(set.length).to.be(3); 36 | set.remove(); 37 | expect(set.length).to.be(0); 38 | expect(rect1.removed).to.be(true); 39 | expect(rect2.removed).to.be(true); 40 | expect(rect3.removed).to.be(true); 41 | }); 42 | it("Set.forEach", function() { 43 | var rect1 = s.rect(10, 20, 30, 40); 44 | var rect2 = s.rect(10, 20, 30, 40); 45 | var rect3 = s.rect(10, 20, 30, 40); 46 | var set = Snap.set(rect1, rect2, rect3); 47 | var i = 0; 48 | var arr = [rect1, rect2, rect3]; 49 | var result = set.forEach(function(item) { 50 | expect(arr[i]).to.be(item); 51 | expect(this.isContext).to.be(true); 52 | i++; 53 | }, {isContext: true}); 54 | expect(result).to.be(set); 55 | expect(i).to.be(3); 56 | }); 57 | it("Set.pop", function() { 58 | var rect1 = s.rect(10, 20, 30, 40); 59 | var rect2 = s.rect(10, 20, 30, 40); 60 | var rect3 = s.rect(10, 20, 30, 40); 61 | var set = Snap.set(rect1, rect2, rect3); 62 | expect(set.length).to.be(3); 63 | var result = set.pop(); 64 | expect(set.length).to.be(2); 65 | expect(result).to.be(rect3); 66 | expect(set[0]).to.be(rect1); 67 | expect(set[1]).to.be(rect2); 68 | result = set.pop(); 69 | expect(set.length).to.be(1); 70 | expect(result).to.be(rect2); 71 | expect(set[0]).to.be(rect1); 72 | }); 73 | it("Set.push", function() { 74 | var rect1 = s.rect(10, 20, 30, 40); 75 | var rect2 = s.rect(10, 20, 30, 40); 76 | var rect3 = s.rect(10, 20, 30, 40); 77 | var set = Snap.set(rect1, rect2); 78 | expect(set.length).to.be(2); 79 | set.push(rect3); 80 | expect(set.length).to.be(3); 81 | expect(set[0]).to.be(rect1); 82 | expect(set[1]).to.be(rect2); 83 | expect(set[2]).to.be(rect3); 84 | }); 85 | it("Set.splice - remove only", function() { 86 | var rect1 = s.rect(10, 20, 30, 40); 87 | var rect2 = s.rect(10, 20, 30, 40); 88 | var rect3 = s.rect(10, 20, 30, 40); 89 | var rect4 = s.rect(10, 20, 30, 40); 90 | var set = Snap.set(rect1, rect2, rect3, rect4); 91 | var removedSet = set.splice(1, 2); 92 | expect(set.length).to.be(2); 93 | expect(set[0]).to.be(rect1); 94 | expect(set[1]).to.be(rect4); 95 | expect(removedSet.length).to.be(2); 96 | expect(removedSet[0]).to.be(rect2); 97 | expect(removedSet[1]).to.be(rect3); 98 | var emptySet = set.splice(0, 0); 99 | expect(set.length).to.be(2); 100 | expect(emptySet.length).to.be(0); 101 | }); 102 | it("Set.splice - remove & insert", function() { 103 | var rect1 = s.rect(10, 20, 30, 40); 104 | var rect2 = s.rect(10, 20, 30, 40); 105 | var rect3 = s.rect(10, 20, 30, 40); 106 | var rect4 = s.rect(10, 20, 30, 40); 107 | var set = Snap.set(rect1, rect2, rect3); 108 | var removedSet = set.splice(2, 1, rect4); 109 | expect(set.length).to.be(3); 110 | expect(set[0]).to.be(rect1); 111 | expect(set[1]).to.be(rect2); 112 | expect(set[2]).to.be(rect4); 113 | removedSet = set.splice(0, 3, rect4, rect3, rect2, rect1); 114 | expect(set[0]).to.be(rect4); 115 | expect(set[1]).to.be(rect3); 116 | expect(set[2]).to.be(rect2); 117 | expect(set[3]).to.be(rect1); 118 | expect(removedSet[0]).to.be(rect1); 119 | expect(removedSet[1]).to.be(rect2); 120 | expect(removedSet[2]).to.be(rect4); 121 | }); 122 | }); -------------------------------------------------------------------------------- /doc/js/prism.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Prism: Lightweight, robust, elegant syntax highlighting 3 | * MIT license http://www.opensource.org/licenses/mit-license.php/ 4 | * @author Lea Verou http://lea.verou.me 5 | */(function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{type:function(e){return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1]},clone:function(e){var n=t.util.type(e);switch(n){case"Object":var r={};for(var i in e)e.hasOwnProperty(i)&&(r[i]=t.util.clone(e[i]));return r;case"Array":return e.slice()}return e}},languages:{extend:function(e,n){var r=t.util.clone(t.languages[e]);for(var i in n)r[i]=n[i];return r},insertBefore:function(e,n,r,i){i=i||t.languages;var s=i[e],o={};for(var u in s)if(s.hasOwnProperty(u)){if(u==n)for(var a in r)r.hasOwnProperty(a)&&(o[a]=r[a]);o[u]=s[u]}return i[e]=o},DFS:function(e,n){for(var r in e){n.call(e,r,e[r]);t.util.type(e)==="Object"&&t.languages.DFS(e[r],n)}}},highlightAll:function(e,n){var r=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');for(var i=0,s;s=r[i++];)t.highlightElement(s,e===!0,n)},highlightElement:function(r,i,s){var o,u,a=r;while(a&&!e.test(a.className))a=a.parentNode;if(a){o=(a.className.match(e)||[,""])[1];u=t.languages[o]}if(!u)return;r.className=r.className.replace(e,"").replace(/\s+/g," ")+" language-"+o;a=r.parentNode;/pre/i.test(a.nodeName)&&(a.className=a.className.replace(e,"").replace(/\s+/g," ")+" language-"+o);var f=r.textContent;if(!f)return;f=f.replace(/&/g,"&").replace(/e.length)break e;if(p instanceof i)continue;a.lastIndex=0;var d=a.exec(p);if(d){l&&(c=d[1].length);var v=d.index-1+c,d=d[0].slice(c),m=d.length,g=v+m,y=p.slice(0,v+1),b=p.slice(g+1),w=[h,1];y&&w.push(y);var E=new i(u,f?t.tokenize(d,f):d);w.push(E);b&&w.push(b);Array.prototype.splice.apply(s,w)}}}return s},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[];r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(!r||!r.length)return;for(var i=0,s;s=r[i++];)s(n)}}},n=t.Token=function(e,t){this.type=e;this.content=t};n.stringify=function(e,r,i){if(typeof e=="string")return e;if(Object.prototype.toString.call(e)=="[object Array]")return e.map(function(t){return n.stringify(t,r,e)}).join("");var s={type:e.type,content:n.stringify(e.content,r,i),tag:"span",classes:["token",e.type],attributes:{},language:r,parent:i};s.type=="comment"&&(s.attributes.spellcheck="true");t.hooks.run("wrap",s);var o="";for(var u in s.attributes)o+=u+'="'+(s.attributes[u]||"")+'"';return"<"+s.tag+' class="'+s.classes.join(" ")+'" '+o+">"+s.content+""};if(!self.document){self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,i=n.code;self.postMessage(JSON.stringify(t.tokenize(i,t.languages[r])));self.close()},!1);return}var r=document.getElementsByTagName("script");r=r[r.length-1];if(r){t.filename=r.src;document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)}})();; 6 | Prism.languages.clike={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,lookbehind:!0},string:/("|')(\\?.)*?\1/g,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/ig,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g,"boolean":/\b(true|false)\b/g,"function":{pattern:/[a-z0-9_]+\(/ig,inside:{punctuation:/\(/}}, number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,operator:/[-+]{1,2}|!|<=?|>=?|={1,3}|(&){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g}; 7 | ; 8 | Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(var|let|if|else|while|do|for|return|in|instanceof|function|new|with|typeof|try|throw|catch|finally|null|break|continue)\b/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g});Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,lookbehind:!0}});Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/(<|<)script[\w\W]*?(>|>)[\w\W]*?(<|<)\/script(>|>)/ig,inside:{tag:{pattern:/(<|<)script[\w\W]*?(>|>)|(<|<)\/script(>|>)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}}); 9 | ; -------------------------------------------------------------------------------- /demos/snap-mascot/snap-logo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | Snap 19 | 20 | 21 | 82 | 83 | 84 | 85 | 86 | 87 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /test/matrix.js: -------------------------------------------------------------------------------- 1 | describe("Matrix methods", function () { 2 | it("Matrix.add - matrix", function() { 3 | var matrix1 = new Snap.Matrix(1, 0, 0, 1, 5, 5); 4 | var matrix2 = new Snap.Matrix(1, 0, 0, 1, 10, 10); 5 | var result = matrix1.add(matrix2); 6 | expect(result).to.eql({ 7 | a: 1, 8 | b: 0, 9 | c: 0, 10 | d: 1, 11 | e: 15, 12 | f: 15 13 | }); 14 | // add two 90 degree rotations 15 | var matrix3 = new Snap.Matrix(0, 1, -1, 0, 0, 0); 16 | var matrix4 = new Snap.Matrix(0, 1, -1, 0, 0, 0); 17 | result = matrix3.add(matrix4); 18 | expect(result).to.eql({ 19 | a: -1, 20 | b: 0, 21 | c: 0, 22 | d: -1, 23 | e: 0, 24 | f: 0 25 | }); 26 | }); 27 | it("Matrix.add - numbers", function() { 28 | var matrix1 = new Snap.Matrix(1, 0, 0, 1, 5, 5); 29 | var result = matrix1.add(1, 0, 0, 1, 10, 10); 30 | expect(result).to.eql({ 31 | a: 1, 32 | b: 0, 33 | c: 0, 34 | d: 1, 35 | e: 15, 36 | f: 15 37 | }); 38 | }); 39 | it("Matrix.clone", function() { 40 | var matrix1 = new Snap.Matrix(1, 2, 3, 4, 5, 6); 41 | var clone = matrix1.clone(); 42 | expect(clone).to.not.be(matrix1); 43 | expect(clone).to.eql({ 44 | a: 1, 45 | b: 2, 46 | c: 3, 47 | d: 4, 48 | e: 5, 49 | f: 6 50 | }); 51 | }); 52 | it("Matrix.invert", function() { 53 | var matrix1 = new Snap.Matrix(1, 2, 3, 4, 5, 6); 54 | var inverse = matrix1.invert(); 55 | expect(inverse).to.eql({ 56 | a: -2, 57 | b: 1, 58 | c: 1.5, 59 | d: -0.5, 60 | e: 1, 61 | f: -2 62 | }); 63 | }); 64 | it("Matrix.rotate", function() { 65 | var matrix = new Snap.Matrix(1, 0, 0, 1, 0, 0); 66 | matrix.rotate(45, 0, 0); 67 | expect(+matrix.a.toFixed(3)).to.be(0.707); 68 | expect(+matrix.b.toFixed(3)).to.be(0.707); 69 | expect(+matrix.c.toFixed(3)).to.be(-0.707); 70 | expect(+matrix.d.toFixed(3)).to.be(0.707); 71 | expect(+matrix.e.toFixed(3)).to.be(0); 72 | expect(+matrix.f.toFixed(3)).to.be(0); 73 | }); 74 | it("Matrix.scale - x", function() { 75 | var matrix = new Snap.Matrix(1, 0, 0, 1, 20, 30); 76 | matrix.scale(2); 77 | expect(matrix).to.eql({ 78 | a: 2, 79 | b: 0, 80 | c: 0, 81 | d: 2, 82 | e: 20, 83 | f: 30 84 | }); 85 | matrix.scale(0.5); 86 | expect(matrix).to.eql({ 87 | a: 1, 88 | b: 0, 89 | c: 0, 90 | d: 1, 91 | e: 20, 92 | f: 30 93 | }); 94 | }); 95 | it("Matrix.scale - x, y", function() { 96 | var matrix = new Snap.Matrix(1, 0, 0, 1, 20, 30); 97 | matrix.scale(2, 3); 98 | expect(matrix).to.eql({ 99 | a: 2, 100 | b: 0, 101 | c: 0, 102 | d: 3, 103 | e: 20, 104 | f: 30 105 | }); 106 | matrix.scale(0.5, 1); 107 | expect(matrix).to.eql({ 108 | a: 1, 109 | b: 0, 110 | c: 0, 111 | d: 3, 112 | e: 20, 113 | f: 30 114 | }); 115 | }); 116 | it("Matrix.scale - x, y, cx, cy", function() { 117 | var matrix = new Snap.Matrix(1, 0, 0, 1, 20, 30); 118 | matrix.scale(2, 3, 5, -5); 119 | expect(matrix).to.eql({ 120 | a: 2, 121 | b: 0, 122 | c: 0, 123 | d: 3, 124 | e: 15, 125 | f: 40 126 | }); 127 | }); 128 | it("Matrix.split", function() { 129 | var matrix = new Snap.Matrix(1, 0, 0, 1, 0, 0); 130 | var result = matrix.split(); 131 | expect(result.dx).to.be(0); 132 | expect(result.dy).to.be(0); 133 | expect(result.scalex).to.be(1); 134 | expect(result.scaley).to.be(1); 135 | expect(result.shear).to.be(0); 136 | expect(result.rotate).to.be(0); 137 | expect(result.isSimple).to.be(true); 138 | 139 | matrix = new Snap.Matrix(1.5, 0, 0, 0.5, 20, 25); 140 | result = matrix.split(); 141 | expect(result.dx).to.be(20); 142 | expect(result.dy).to.be(25); 143 | expect(result.scalex).to.be(1.5); 144 | expect(result.scaley).to.be(0.5); 145 | expect(result.shear).to.be(0); 146 | expect(result.rotate).to.be(0); 147 | expect(result.isSimple).to.be(true); 148 | }); 149 | it("Matrix.toTransformString", function() { 150 | var matrix = new Snap.Matrix(1.5, 0, 0, 0.5, 20, 25); 151 | var str = matrix.toTransformString(); 152 | var s = Snap(10, 10); 153 | var rect = s.rect(0, 0, 10, 20); 154 | rect.transform(str); 155 | var transform = rect.transform(); 156 | expect(transform.localMatrix).to.eql({ 157 | a: 1.5, 158 | b: 0, 159 | c: 0, 160 | d: 0.5, 161 | e: 20, 162 | f: 25 163 | }); 164 | }); 165 | it("Matrix.translate", function() { 166 | var matrix = new Snap.Matrix(1, 0, 0, 1, 20, 30); 167 | matrix.translate(10, -10); 168 | expect(matrix).to.eql({ 169 | a: 1, 170 | b: 0, 171 | c: 0, 172 | d: 1, 173 | e: 30, 174 | f: 20 175 | }); 176 | matrix.translate(-1, -2); 177 | expect(matrix).to.eql({ 178 | a: 1, 179 | b: 0, 180 | c: 0, 181 | d: 1, 182 | e: 29, 183 | f: 18 184 | }); 185 | }); 186 | it("Matrix.x", function() { 187 | var matrix = new Snap.Matrix(1, 0, 0, 1, 20, 30); 188 | var result = matrix.x(10, -10); 189 | expect(result).to.be(30); 190 | }); 191 | it("Matrix.y", function() { 192 | var matrix = new Snap.Matrix(1, 0, 0, 1, 20, 30); 193 | var result = matrix.y(10, -10); 194 | expect(result).to.be(20); 195 | }); 196 | 197 | }); -------------------------------------------------------------------------------- /src/equal.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | Snap.plugin(function (Snap, Element, Paper, glob) { 15 | var names = {}, 16 | reUnit = /[a-z]+$/i, 17 | Str = String; 18 | names.stroke = names.fill = "colour"; 19 | function getEmpty(item) { 20 | var l = item[0]; 21 | switch (l.toLowerCase()) { 22 | case "t": return [l, 0, 0]; 23 | case "m": return [l, 1, 0, 0, 1, 0, 0]; 24 | case "r": if (item.length == 4) { 25 | return [l, 0, item[2], item[3]]; 26 | } else { 27 | return [l, 0]; 28 | } 29 | case "s": if (item.length == 5) { 30 | return [l, 1, 1, item[3], item[4]]; 31 | } else if (item.length == 3) { 32 | return [l, 1, 1]; 33 | } else { 34 | return [l, 1]; 35 | } 36 | } 37 | } 38 | function equaliseTransform(t1, t2, getBBox) { 39 | t2 = Str(t2).replace(/\.{3}|\u2026/g, t1); 40 | t1 = Snap.parseTransformString(t1) || []; 41 | t2 = Snap.parseTransformString(t2) || []; 42 | var maxlength = Math.max(t1.length, t2.length), 43 | from = [], 44 | to = [], 45 | i = 0, j, jj, 46 | tt1, tt2; 47 | for (; i < maxlength; i++) { 48 | tt1 = t1[i] || getEmpty(t2[i]); 49 | tt2 = t2[i] || getEmpty(tt1); 50 | if ((tt1[0] != tt2[0]) || 51 | (tt1[0].toLowerCase() == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) || 52 | (tt1[0].toLowerCase() == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4])) 53 | ) { 54 | t1 = Snap._.transform2matrix(t1, getBBox()); 55 | t2 = Snap._.transform2matrix(t2, getBBox()); 56 | from = [["m", t1.a, t1.b, t1.c, t1.d, t1.e, t1.f]]; 57 | to = [["m", t2.a, t2.b, t2.c, t2.d, t2.e, t2.f]]; 58 | break; 59 | } 60 | from[i] = []; 61 | to[i] = []; 62 | for (j = 0, jj = Math.max(tt1.length, tt2.length); j < jj; j++) { 63 | j in tt1 && (from[i][j] = tt1[j]); 64 | j in tt2 && (to[i][j] = tt2[j]); 65 | } 66 | } 67 | return { 68 | from: path2array(from), 69 | to: path2array(to), 70 | f: getPath(from) 71 | }; 72 | } 73 | function getNumber(val) { 74 | return val; 75 | } 76 | function getUnit(unit) { 77 | return function (val) { 78 | return +val.toFixed(3) + unit; 79 | }; 80 | } 81 | function getColour(clr) { 82 | return Snap.rgb(clr[0], clr[1], clr[2]); 83 | } 84 | function getPath(path) { 85 | var k = 0, i, ii, j, jj, out, a, b = []; 86 | for (i = 0, ii = path.length; i < ii; i++) { 87 | out = "["; 88 | a = ['"' + path[i][0] + '"']; 89 | for (j = 1, jj = path[i].length; j < jj; j++) { 90 | a[j] = "val[" + (k++) + "]"; 91 | } 92 | out += a + "]"; 93 | b[i] = out; 94 | } 95 | return Function("val", "return Snap.path.toString.call([" + b + "])"); 96 | } 97 | function path2array(path) { 98 | var out = []; 99 | for (var i = 0, ii = path.length; i < ii; i++) { 100 | for (var j = 1, jj = path[i].length; j < jj; j++) { 101 | out.push(path[i][j]); 102 | } 103 | } 104 | return out; 105 | } 106 | Element.prototype.equal = function (name, b) { 107 | var A, B, a = Str(this.attr(name) || ""), 108 | el = this; 109 | if (a == +a && b == +b) { 110 | return { 111 | from: +a, 112 | to: +b, 113 | f: getNumber 114 | }; 115 | } 116 | if (names[name] == "colour") { 117 | A = Snap.color(a); 118 | B = Snap.color(b); 119 | return { 120 | from: [A.r, A.g, A.b, A.opacity], 121 | to: [B.r, B.g, B.b, B.opacity], 122 | f: getColour 123 | }; 124 | } 125 | if (name == "transform" || name == "gradientTransform" || name == "patternTransform") { 126 | if (b instanceof Snap.Matrix) { 127 | b = b.toTransformString(); 128 | } 129 | if (!Snap._.rgTransform.test(b)) { 130 | b = Snap._.svgTransform2string(b); 131 | } 132 | return equaliseTransform(a, b, function () { 133 | return el.getBBox(1); 134 | }); 135 | } 136 | if (name == "d" || name == "path") { 137 | A = Snap.path.toCubic(a, b); 138 | return { 139 | from: path2array(A[0]), 140 | to: path2array(A[1]), 141 | f: getPath(A[0]) 142 | }; 143 | } 144 | if (name == "points") { 145 | A = Str(a).split(","); 146 | B = Str(b).split(","); 147 | return { 148 | from: A, 149 | to: B, 150 | f: function (val) { return val; } 151 | }; 152 | } 153 | var aUnit = a.match(reUnit), 154 | bUnit = Str(b).match(reUnit); 155 | if (aUnit && aUnit == bUnit) { 156 | return { 157 | from: parseFloat(a), 158 | to: parseFloat(b), 159 | f: getUnit(aUnit) 160 | }; 161 | } else { 162 | return { 163 | from: this.asPX(name), 164 | to: this.asPX(name, b), 165 | f: getNumber 166 | }; 167 | } 168 | }; 169 | }); -------------------------------------------------------------------------------- /test/filter.js: -------------------------------------------------------------------------------- 1 | describe("Filter methods", function () { 2 | it("Snap.filter.blur", function() { 3 | var str = Snap.filter.blur(3); 4 | expect(str).to.be(''); 5 | str = Snap.filter.blur(0.123, 8); 6 | expect(str).to.be(''); 7 | }); 8 | it("Snap.filter.brightness", function() { 9 | var str = Snap.filter.brightness(0.3); 10 | expect(str).to.be(''); 11 | str = Snap.filter.brightness(1); 12 | expect(str).to.be(''); 13 | }); 14 | it("Snap.filter.contrast", function() { 15 | var str = Snap.filter.contrast(0.1); 16 | expect(str).to.be(''); 17 | str = Snap.filter.contrast(3); 18 | expect(str).to.be(''); 19 | }); 20 | it("Snap.filter.grayscale", function() { 21 | var str = Snap.filter.grayscale(0.5); 22 | expect(str).to.be(''); 23 | str = Snap.filter.grayscale(1); 24 | expect(str).to.be(''); 25 | }); 26 | it("Snap.filter.hueRotate", function() { 27 | var str = Snap.filter.hueRotate(180); 28 | expect(str).to.be(''); 29 | str = Snap.filter.hueRotate(90); 30 | expect(str).to.be(''); 31 | }); 32 | it("Snap.filter.hueRotate", function() { 33 | var str = Snap.filter.hueRotate(180); 34 | expect(str).to.be(''); 35 | str = Snap.filter.hueRotate(90); 36 | expect(str).to.be(''); 37 | }); 38 | it("Snap.filter.invert", function() { 39 | var str = Snap.filter.invert(0.6); 40 | expect(str).to.be(''); 41 | str = Snap.filter.invert(1); 42 | expect(str).to.be(''); 43 | }); 44 | it("Snap.filter.saturate", function() { 45 | var str = Snap.filter.saturate(0.3); 46 | expect(str).to.be(''); 47 | str = Snap.filter.saturate(1); 48 | expect(str).to.be(''); 49 | }); 50 | it("Snap.filter.sepia", function() { 51 | var str = Snap.filter.sepia(0.3); 52 | expect(str).to.be(''); 53 | str = Snap.filter.sepia(1); 54 | expect(str).to.be(''); 55 | }); 56 | it("Snap.filter.shadow - dx & dy", function() { 57 | var str = Snap.filter.shadow(5, 5); 58 | expect(str).to.be(''); 59 | str = Snap.filter.shadow(-1, 3); 60 | expect(str).to.be(''); 61 | }); 62 | it("Snap.filter.shadow - dx & dy, blur", function() { 63 | var str = Snap.filter.shadow(5, 5, 5); 64 | expect(str).to.be(''); 65 | str = Snap.filter.shadow(-1, 3, 10); 66 | expect(str).to.be(''); 67 | }); 68 | it("Snap.filter.shadow - dx & dy, color", function() { 69 | var str = Snap.filter.shadow(5, 5, '#F00'); 70 | expect(str).to.be(''); 71 | str = Snap.filter.shadow(-1, 3, 'hsla(128deg, 50%, 50%, 0.8)'); 72 | expect(str).to.be(''); 73 | }); 74 | 75 | it("Snap.filter.shadow - dx & dy, blur & color", function() { 76 | var str = Snap.filter.shadow(5, 5, 5, '#F00'); 77 | expect(str).to.be(''); 78 | str = Snap.filter.shadow(-1, 3, 10, 'hsla(128deg, 50%, 50%, 0.8)'); 79 | expect(str).to.be(''); 80 | }); 81 | 82 | 83 | }); -------------------------------------------------------------------------------- /demos/tutorial/mascot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 8 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 22 | 27 | 28 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 38 | 40 | 41 | 43 | 44 | 45 | 46 | 47 | 49 | 50 | 51 | 52 | 54 | 55 | 56 | 57 | 59 | 60 | 61 | 62 | 64 | 65 | 66 | 67 | 69 | 70 | 72 | 73 | 74 | 76 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /test/colors.js: -------------------------------------------------------------------------------- 1 | describe("Colours", function () { 2 | it("parses hex colour", function () { 3 | expect(Snap.color("#fC0").hex).to.be("#ffcc00"); 4 | }); 5 | it("parses RGB", function () { 6 | var c = Snap.color("rgb(255, 204, 0)"); 7 | expect(c.hex).to.be("#ffcc00"); 8 | expect(c.r).to.be(255); 9 | expect(c.g).to.be(204); 10 | expect(c.b).to.be(0); 11 | }); 12 | it("parses RGB - %", function () { 13 | var c = Snap.color("rgb(100%, 80%, 0%)"); 14 | expect(c.hex).to.be("#ffcc00"); 15 | expect(c.r).to.be(255); 16 | expect(c.g).to.be(204); 17 | expect(c.b).to.be(0); 18 | }); 19 | it("parses HSL", function () { 20 | var c = Snap.color("hsl(0.1333, 1, .5)"); 21 | expect(c.hex).to.be("#ffcc00"); 22 | expect(c.h.toFixed(3)).to.be("0.133"); 23 | expect(c.s).to.be(1); 24 | expect(c.l).to.be(.5); 25 | }); 26 | it("parses HSL - %", function () { 27 | var c = Snap.color("hsl(13.33%, 100%, 50%)"); 28 | expect(c.hex).to.be("#ffcc00"); 29 | expect(c.h.toFixed(3)).to.be("0.133"); 30 | expect(c.s).to.be(1); 31 | expect(c.l).to.be(.5); 32 | }); 33 | it("parses HSB", function () { 34 | var c = Snap.color("hsb(0.1333, 1, 1)"); 35 | expect(c.hex).to.be("#ffcc00"); 36 | expect(c.h.toFixed(3)).to.be("0.133"); 37 | expect(c.s).to.be(1); 38 | expect(c.v).to.be(1); 39 | }); 40 | it("parses HSB - %", function () { 41 | var c = Snap.color("hsb(13.33%, 100%, 100%)"); 42 | expect(c.hex).to.be("#ffcc00"); 43 | expect(c.h.toFixed(3)).to.be("0.133"); 44 | expect(c.s).to.be(1); 45 | expect(c.v).to.be(1); 46 | }); 47 | it("parses RGBA", function () { 48 | var c = Snap.color("rgba(255, 204, 0, .75)"); 49 | expect(c.hex).to.be("#ffcc00"); 50 | expect(c.r).to.be(255); 51 | expect(c.g).to.be(204); 52 | expect(c.b).to.be(0); 53 | expect(c.opacity).to.be(.75); 54 | }); 55 | it("parses HSLA", function () { 56 | var c = Snap.color("hsla(0.1333, 1, .5, .5)"); 57 | expect(c.hex).to.be("#ffcc00"); 58 | expect(c.r).to.be(255); 59 | expect(c.g).to.be(204); 60 | expect(c.b).to.be(0); 61 | expect(c.opacity).to.be(.5); 62 | }); 63 | it("parses HSBA", function () { 64 | var c = Snap.color("hsba(0.1333, 1, 1, .5)"); 65 | expect(c.hex).to.be("#ffcc00"); 66 | expect(c.r).to.be(255); 67 | expect(c.g).to.be(204); 68 | expect(c.b).to.be(0); 69 | expect(c.opacity).to.be(.5); 70 | }); 71 | it("parses names", function () { 72 | var c = Snap.color("DodgerBlue"); 73 | expect(c.hex).to.be("#1e90ff"); 74 | c = Snap.color("FireBrick"); 75 | expect(c.hex).to.be("#b22222"); 76 | c = Snap.color("MintCream"); 77 | expect(c.hex).to.be("#f5fffa"); 78 | }); 79 | it("parses to RGB", function() { 80 | var expectRGB = function(str) { 81 | var c = Snap.getRGB(str); 82 | expect(c.hex).to.be("#ffcc00"); 83 | expect(c.r).to.be(255); 84 | expect(c.g).to.be(204); 85 | expect(c.b).to.be(0); 86 | expect(c.error).to.not.be(true); 87 | }; 88 | 89 | expectRGB("#fc0"); 90 | expectRGB("#ffcc00"); 91 | expectRGB("rgb(255, 204, 0)"); 92 | expectRGB("rgb(100%, 80%, 0%)"); 93 | expectRGB("hsb(0.1333, 1, 1)"); 94 | expectRGB("hsb(13.33%, 100%, 100%)"); 95 | expectRGB("hsl(0.1333, 1, .5)"); 96 | expectRGB("hsl(13.33%, 100%, 50%)"); 97 | expectRGB("rgba(255, 204, 0, .75)"); 98 | expectRGB("hsla(0.1333, 1, .5, .5)"); 99 | expectRGB("hsba(0.1333, 1, 1, .5)"); 100 | var c = Snap.getRGB("DodgerBlue"); 101 | expect(c.hex).to.be("#1e90ff"); 102 | expect(c.r).to.be(30); 103 | expect(c.g).to.be(144); 104 | expect(c.b).to.be(255); 105 | expect(c.error).to.not.be(true); 106 | c = Snap.getRGB("foobar"); 107 | expect(!!c.error).to.be(true); 108 | c = Snap.getRGB("#zzz"); 109 | expect(!!c.error).to.be(true); 110 | c = Snap.getRGB("rgb(255)"); 111 | expect(!!c.error).to.be(true); 112 | c = Snap.getRGB("hsl(0, 0, 0"); 113 | expect(!!c.error).to.be(true); 114 | c = Snap.getRGB("rab(0, 0, 0)"); 115 | expect(!!c.error).to.be(true); 116 | }); 117 | it("creates hsb", function() { 118 | var str = Snap.hsb(0.13333, 1, 1); 119 | expect(str).to.be("#ffcc00"); 120 | str = Snap.hsb(0, 0.5, 0.5); 121 | expect(str).to.be("#804040"); 122 | }); 123 | it("creates rgb from hsb", function() { 124 | var rgb = Snap.hsb2rgb(0.13333, 1, 1); 125 | expect(rgb.r).to.be(255); 126 | expect(rgb.g).to.be(204); 127 | expect(rgb.b).to.be(0); 128 | expect(rgb.hex).to.be("#ffcc00"); 129 | rgb = Snap.hsb2rgb(0, 0.5, 0.5); 130 | expect(rgb.r).to.be(128); 131 | expect(rgb.g).to.be(64); 132 | expect(rgb.b).to.be(64); 133 | expect(rgb.hex).to.be("#804040"); 134 | }); 135 | it("creates hsl", function() { 136 | var str = Snap.hsl(0.13333, 1, 0.5); 137 | expect(str).to.be("#ffcc00"); 138 | str = Snap.hsl(0, 1, 0.75); 139 | expect(str).to.be("#ff8080"); 140 | }); 141 | it("creates rgb from hsl", function() { 142 | var rgb = Snap.hsl2rgb(0.13333, 1, 0.5); 143 | expect(rgb.r).to.be(255); 144 | expect(rgb.g).to.be(204); 145 | expect(rgb.b).to.be(0); 146 | expect(rgb.hex).to.be("#ffcc00"); 147 | rgb = Snap.hsl2rgb(0, 1, 0.75); 148 | expect(rgb.r).to.be(255); 149 | expect(rgb.g).to.be(128); 150 | expect(rgb.b).to.be(128); 151 | expect(rgb.hex).to.be("#ff8080"); 152 | }); 153 | it("creates rgb", function() { 154 | var str = Snap.rgb(255, 204, 0); 155 | expect(str).to.be("#ffcc00"); 156 | str = Snap.rgb(64, 128, 255); 157 | expect(str).to.be("#4080ff"); 158 | }); 159 | it("creates hsb from rgb", function() { 160 | var hsb = Snap.rgb2hsb(255, 204, 0); 161 | expect(hsb.h.toFixed(3)).to.be("0.133"); 162 | expect(hsb.s).to.be(1); 163 | expect(hsb.b).to.be(1); 164 | hsb = Snap.rgb2hsb(128, 64, 64); 165 | expect(hsb.h).to.be(0); 166 | expect(hsb.s.toFixed(1)).to.be("0.5"); 167 | expect(hsb.b.toFixed(1)).to.be("0.5"); 168 | }); 169 | it("creates hsl from rgb", function() { 170 | var hsl = Snap.rgb2hsl(255, 204, 0); 171 | expect(hsl.h.toFixed(3)).to.be("0.133"); 172 | expect(hsl.s).to.be(1); 173 | expect(hsl.l).to.be(0.5); 174 | hsl = Snap.rgb2hsl(255, 128, 128); 175 | expect(hsl.h).to.be(0); 176 | expect(hsl.s).to.be(1); 177 | expect(hsl.l.toFixed(2)).to.be("0.75"); 178 | }); 179 | }); 180 | -------------------------------------------------------------------------------- /src/set.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | Snap.plugin(function (Snap, Element, Paper, glob) { 15 | var mmax = Math.max, 16 | mmin = Math.min; 17 | 18 | // Set 19 | var Set = function (items) { 20 | this.items = []; 21 | this.length = 0; 22 | this.type = "set"; 23 | if (items) { 24 | for (var i = 0, ii = items.length; i < ii; i++) { 25 | if (items[i]) { 26 | this[this.items.length] = this.items[this.items.length] = items[i]; 27 | this.length++; 28 | } 29 | } 30 | } 31 | }, 32 | setproto = Set.prototype; 33 | /*\ 34 | * Set.push 35 | [ method ] 36 | ** 37 | * Adds each argument to the current set 38 | = (object) original element 39 | \*/ 40 | setproto.push = function () { 41 | var item, 42 | len; 43 | for (var i = 0, ii = arguments.length; i < ii; i++) { 44 | item = arguments[i]; 45 | if (item) { 46 | len = this.items.length; 47 | this[len] = this.items[len] = item; 48 | this.length++; 49 | } 50 | } 51 | return this; 52 | }; 53 | /*\ 54 | * Set.pop 55 | [ method ] 56 | ** 57 | * Removes last element and returns it 58 | = (object) element 59 | \*/ 60 | setproto.pop = function () { 61 | this.length && delete this[this.length--]; 62 | return this.items.pop(); 63 | }; 64 | /*\ 65 | * Set.forEach 66 | [ method ] 67 | ** 68 | * Executes given function for each element in the set 69 | * 70 | * If the function returns `false`, the loop stops running. 71 | ** 72 | - callback (function) function to run 73 | - thisArg (object) context object for the callback 74 | = (object) Set object 75 | \*/ 76 | setproto.forEach = function (callback, thisArg) { 77 | for (var i = 0, ii = this.items.length; i < ii; i++) { 78 | if (callback.call(thisArg, this.items[i], i) === false) { 79 | return this; 80 | } 81 | } 82 | return this; 83 | }; 84 | setproto.remove = function () { 85 | while (this.length) { 86 | this.pop().remove(); 87 | } 88 | return this; 89 | }; 90 | setproto.attr = function (value) { 91 | for (var i = 0, ii = this.items.length; i < ii; i++) { 92 | this.items[i].attr(value); 93 | } 94 | return this; 95 | }; 96 | /*\ 97 | * Set.clear 98 | [ method ] 99 | ** 100 | * Removes all elements from the set 101 | \*/ 102 | setproto.clear = function () { 103 | while (this.length) { 104 | this.pop(); 105 | } 106 | }; 107 | /*\ 108 | * Set.splice 109 | [ method ] 110 | ** 111 | * Removes range of elements from the set 112 | ** 113 | - index (number) position of the deletion 114 | - count (number) number of element to remove 115 | - insertion… (object) #optional elements to insert 116 | = (object) set elements that were deleted 117 | \*/ 118 | setproto.splice = function (index, count, insertion) { 119 | index = index < 0 ? mmax(this.length + index, 0) : index; 120 | count = mmax(0, mmin(this.length - index, count)); 121 | var tail = [], 122 | todel = [], 123 | args = [], 124 | i; 125 | for (i = 2; i < arguments.length; i++) { 126 | args.push(arguments[i]); 127 | } 128 | for (i = 0; i < count; i++) { 129 | todel.push(this[index + i]); 130 | } 131 | for (; i < this.length - index; i++) { 132 | tail.push(this[index + i]); 133 | } 134 | var arglen = args.length; 135 | for (i = 0; i < arglen + tail.length; i++) { 136 | this.items[index + i] = this[index + i] = i < arglen ? args[i] : tail[i - arglen]; 137 | } 138 | i = this.items.length = this.length -= count - arglen; 139 | while (this[i]) { 140 | delete this[i++]; 141 | } 142 | return new Set(todel); 143 | }; 144 | /*\ 145 | * Set.exclude 146 | [ method ] 147 | ** 148 | * Removes given element from the set 149 | ** 150 | - element (object) element to remove 151 | = (boolean) `true` if object was found and removed from the set 152 | \*/ 153 | setproto.exclude = function (el) { 154 | for (var i = 0, ii = this.length; i < ii; i++) if (this[i] == el) { 155 | this.splice(i, 1); 156 | return true; 157 | } 158 | return false; 159 | }; 160 | setproto.insertAfter = function (el) { 161 | var i = this.items.length; 162 | while (i--) { 163 | this.items[i].insertAfter(el); 164 | } 165 | return this; 166 | }; 167 | setproto.getBBox = function () { 168 | var x = [], 169 | y = [], 170 | x2 = [], 171 | y2 = []; 172 | for (var i = this.items.length; i--;) if (!this.items[i].removed) { 173 | var box = this.items[i].getBBox(); 174 | x.push(box.x); 175 | y.push(box.y); 176 | x2.push(box.x + box.width); 177 | y2.push(box.y + box.height); 178 | } 179 | x = mmin.apply(0, x); 180 | y = mmin.apply(0, y); 181 | x2 = mmax.apply(0, x2); 182 | y2 = mmax.apply(0, y2); 183 | return { 184 | x: x, 185 | y: y, 186 | x2: x2, 187 | y2: y2, 188 | width: x2 - x, 189 | height: y2 - y, 190 | cx: x + (x2 - x) / 2, 191 | cy: y + (y2 - y) / 2 192 | }; 193 | }; 194 | setproto.clone = function (s) { 195 | s = new Set; 196 | for (var i = 0, ii = this.items.length; i < ii; i++) { 197 | s.push(this.items[i].clone()); 198 | } 199 | return s; 200 | }; 201 | setproto.toString = function () { 202 | return "Snap\u2018s set"; 203 | }; 204 | setproto.type = "set"; 205 | // export 206 | Snap.set = function () { 207 | var set = new Set; 208 | if (arguments.length) { 209 | set.push.apply(set, Array.prototype.slice.call(arguments, 0)); 210 | } 211 | return set; 212 | }; 213 | }); -------------------------------------------------------------------------------- /test/attrs.js: -------------------------------------------------------------------------------- 1 | describe("Attributes", function () { 2 | var s, r; 3 | beforeEach(function () { 4 | s = Snap(100, 100); 5 | r = s.rect(10, 10, 50, 50); 6 | }); 7 | afterEach(function () { 8 | s.remove(); 9 | }); 10 | function colorTestProp(key) { 11 | var o = {}; 12 | return function () { 13 | o[key] = "#fc0"; 14 | r.attr(o); 15 | expect(r.node.getAttribute(key)).to.be("#ffcc00"); 16 | o[key] = "rgb(255, 204, 0)"; 17 | r.attr(o); 18 | expect(r.node.getAttribute(key)).to.be("#ffcc00"); 19 | o[key] = "hsl(0.1333, 1, .5)"; 20 | r.attr(o); 21 | expect(r.node.getAttribute(key)).to.be("#ffcc00"); 22 | o[key] = "hsb(0.1333, 1, 1)"; 23 | r.attr(o); 24 | expect(r.node.getAttribute(key)).to.be("#ffcc00"); 25 | o[key] = "rgba(255, 204, 0, .5)"; 26 | r.attr(o); 27 | expect(r.node.getAttribute(key)).to.be("rgba(255,204,0,0.5)"); 28 | o[key] = "hsla(0.1333, 1, .5, .5)"; 29 | r.attr(o); 30 | expect(r.node.getAttribute(key)).to.be("rgba(255,204,0,0.5)"); 31 | o[key] = "hsba(0.1333, 1, 1, .5)"; 32 | r.attr(o); 33 | expect(r.node.getAttribute(key)).to.be("rgba(255,204,0,0.5)"); 34 | }; 35 | } 36 | function colorTestStyle(key) { 37 | var o = {}; 38 | return function () { 39 | function val() { 40 | return Snap.color(r.node.getAttribute(key)).hex; 41 | } 42 | o[key] = "#fc0"; 43 | r.attr(o); 44 | expect(val()).to.be("#ffcc00"); 45 | o[key] = "rgb(255, 204, 0)"; 46 | r.attr(o); 47 | expect(val()).to.be("#ffcc00"); 48 | o[key] = "hsl(0.1333, 1, .5)"; 49 | r.attr(o); 50 | expect(val()).to.be("#ffcc00"); 51 | o[key] = "hsb(0.1333, 1, 1)"; 52 | r.attr(o); 53 | expect(val()).to.be("#ffcc00"); 54 | o[key] = "rgba(255, 204, 0, .5)"; 55 | r.attr(o); 56 | expect(val()).to.be("#ffcc00"); 57 | o[key] = "hsla(0.1333, 1, .5, .5)"; 58 | r.attr(o); 59 | expect(val()).to.be("#ffcc00"); 60 | o[key] = "hsba(0.1333, 1, 1, .5)"; 61 | r.attr(o); 62 | expect(val()).to.be("#ffcc00"); 63 | }; 64 | } 65 | it("sets fill", colorTestProp("fill")); 66 | it("sets stroke", colorTestStyle("stroke")); 67 | it("circle core attributes", function () { 68 | var c = s.circle(10, 20, 30); 69 | expect(c.node.getAttribute("cx")).to.be("10"); 70 | expect(c.node.getAttribute("cy")).to.be("20"); 71 | expect(c.node.getAttribute("r")).to.be("30"); 72 | c.attr({ 73 | cx: 40, 74 | cy: 50, 75 | r: "5%" 76 | }); 77 | expect(c.node.getAttribute("cx")).to.be("40"); 78 | expect(c.node.getAttribute("cy")).to.be("50"); 79 | expect(c.node.getAttribute("r")).to.be("5%"); 80 | }); 81 | it("rect core attributes", function () { 82 | var c = s.rect(10, 20, 30, 40); 83 | expect(c.node.getAttribute("x")).to.be("10"); 84 | expect(c.node.getAttribute("y")).to.be("20"); 85 | expect(c.node.getAttribute("width")).to.be("30"); 86 | expect(c.node.getAttribute("height")).to.be("40"); 87 | c.attr({ 88 | x: 40, 89 | y: 50, 90 | width: "5%", 91 | height: "6%", 92 | r: 10 93 | }); 94 | expect(c.node.getAttribute("x")).to.be("40"); 95 | expect(c.node.getAttribute("y")).to.be("50"); 96 | expect(c.node.getAttribute("width")).to.be("5%"); 97 | expect(c.node.getAttribute("height")).to.be("6%"); 98 | expect(c.node.getAttribute("rx")).to.be("10"); 99 | expect(c.node.getAttribute("ry")).to.be("10"); 100 | }); 101 | it("ellipse core attributes", function () { 102 | var c = s.ellipse(10, 20, 30, 40); 103 | expect(c.node.getAttribute("cx")).to.be("10"); 104 | expect(c.node.getAttribute("cy")).to.be("20"); 105 | expect(c.node.getAttribute("rx")).to.be("30"); 106 | expect(c.node.getAttribute("ry")).to.be("40"); 107 | c.attr({ 108 | cx: 40, 109 | cy: 50, 110 | rx: "5%", 111 | ry: "6%" 112 | }); 113 | expect(c.node.getAttribute("cx")).to.be("40"); 114 | expect(c.node.getAttribute("cy")).to.be("50"); 115 | expect(c.node.getAttribute("rx")).to.be("5%"); 116 | expect(c.node.getAttribute("ry")).to.be("6%"); 117 | }); 118 | it("path core attributes", function () { 119 | var c = s.path("M10,10 110,10"); 120 | expect(c.node.getAttribute("d")).to.be("M10,10 110,10"); 121 | c.attr({d: "M10,10 210,10"}); 122 | expect(c.node.getAttribute("d")).to.be("M10,10 210,10"); 123 | c.attr({path: "M10,10 310,10"}); 124 | expect(c.node.getAttribute("d")).to.be("M10,10 310,10"); 125 | }); 126 | it("text core attributes", function () { 127 | var c = s.text(10, 15, "testing"); 128 | expect(c.node.getAttribute("x")).to.be("10"); 129 | expect(c.node.getAttribute("y")).to.be("15"); 130 | expect(c.node.textContent).to.be("testing"); 131 | c.attr({ 132 | x: 20, 133 | y: 25, 134 | text: "texting" 135 | }); 136 | expect(c.node.getAttribute("x")).to.be("20"); 137 | expect(c.node.getAttribute("y")).to.be("25"); 138 | expect(c.node.textContent).to.be("texting"); 139 | }); 140 | it("line core attributes", function () { 141 | var c = s.line(10, 15, 110, 17); 142 | expect(c.node.getAttribute("x1")).to.be("10"); 143 | expect(c.node.getAttribute("y1")).to.be("15"); 144 | expect(c.node.getAttribute("x2")).to.be("110"); 145 | expect(c.node.getAttribute("y2")).to.be("17"); 146 | c.attr({ 147 | x1: 20, 148 | y1: 25, 149 | x2: 220, 150 | y2: 27 151 | }); 152 | expect(c.node.getAttribute("x1")).to.be("20"); 153 | expect(c.node.getAttribute("y1")).to.be("25"); 154 | expect(c.node.getAttribute("x2")).to.be("220"); 155 | expect(c.node.getAttribute("y2")).to.be("27"); 156 | }); 157 | it("polyline core attributes", function () { 158 | var c = s.polyline(10, 15, 20, 25, 30, 35); 159 | expect(c.node.getAttribute("points")).to.be("10,15,20,25,30,35"); 160 | c.attr({ 161 | points: [20, 25, 30, 35, 40, 45] 162 | }); 163 | expect(c.node.getAttribute("points")).to.be("20,25,30,35,40,45"); 164 | }); 165 | it("polygon core attributes", function () { 166 | var c = s.polygon(10, 15, 20, 25, 30, 35); 167 | expect(c.node.getAttribute("points")).to.be("10,15,20,25,30,35"); 168 | c.attr({ 169 | points: [20, 25, 30, 35, 40, 45] 170 | }); 171 | expect(c.node.getAttribute("points")).to.be("20,25,30,35,40,45"); 172 | }); 173 | }); 174 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Snap.svg is licensed under the Apache license version 2.0, January 2004 (see LICENSE file). 2 | 3 | Snap.svg uses the following third party libraries that may have licenses 4 | differing from that of Snap.svg itself. You can find the libraries and their 5 | respective licenses below. 6 | 7 | - eve ./node_modules/eve 8 | 9 | https://github.com/adobe-webplatform/eve/ 10 | 11 | Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. 12 | 13 | Licensed under the Apache License, Version 2.0 (the "License"); 14 | you may not use this file except in compliance with the License. 15 | You may obtain a copy of the License at 16 | 17 | http://www.apache.org/licenses/LICENSE-2.0 18 | 19 | Unless required by applicable law or agreed to in writing, software 20 | distributed under the License is distributed on an "AS IS" BASIS, 21 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | See the License for the specific language governing permissions and 23 | limitations under the License. 24 | 25 | - Mocha ./node_modules/mocha 26 | 27 | https://github.com/visionmedia/mocha/ 28 | 29 | (The MIT License) 30 | 31 | Copyright (c) 2011-2013 TJ Holowaychuk 32 | 33 | Permission is hereby granted, free of charge, to any person obtaining 34 | a copy of this software and associated documentation files (the 35 | 'Software'), to deal in the Software without restriction, including 36 | without limitation the rights to use, copy, modify, merge, publish, 37 | distribute, sublicense, and/or sell copies of the Software, and to 38 | permit persons to whom the Software is furnished to do so, subject to 39 | the following conditions: 40 | 41 | The above copyright notice and this permission notice shall be 42 | included in all copies or substantial portions of the Software. 43 | 44 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 45 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 46 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 47 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 48 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 49 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 50 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 51 | 52 | - Expect ./node_modules/expect.js 53 | 54 | https://github.com/LearnBoost/expect.js 55 | 56 | (The MIT License) 57 | 58 | Copyright (c) 2011 Guillermo Rauch 59 | 60 | Permission is hereby granted, free of charge, to any person obtaining 61 | a copy of this software and associated documentation files (the 62 | 'Software'), to deal in the Software without restriction, including 63 | without limitation the rights to use, copy, modify, merge, publish, 64 | distribute, sublicense, and/or sell copies of the Software, and to 65 | permit persons to whom the Software is furnished to do so, subject to 66 | the following conditions: 67 | 68 | The above copyright notice and this permission notice shall be 69 | included in all copies or substantial portions of the Software. 70 | 71 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 72 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 73 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 74 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 75 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 76 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 77 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 78 | 79 | - Grunt ./node_modules/grunt 80 | 81 | http://gruntjs.com 82 | 83 | Copyright (c) 2013 "Cowboy" Ben Alman 84 | 85 | Permission is hereby granted, free of charge, to any person 86 | obtaining a copy of this software and associated documentation 87 | files (the "Software"), to deal in the Software without 88 | restriction, including without limitation the rights to use, 89 | copy, modify, merge, publish, distribute, sublicense, and/or sell 90 | copies of the Software, and to permit persons to whom the 91 | Software is furnished to do so, subject to the following 92 | conditions: 93 | 94 | The above copyright notice and this permission notice shall be 95 | included in all copies or substantial portions of the Software. 96 | 97 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 98 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 99 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 100 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 101 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 102 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 103 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 104 | OTHER DEALINGS IN THE SOFTWARE. 105 | 106 | 107 | - Backbone ./demos/animated-game/js/backbone.js 108 | 109 | http://backbonejs.org/ 110 | 111 | (The MIT License) 112 | 113 | Copyright (c) 2010-2013 Jeremy Ashkenas, DocumentCloud 114 | 115 | Permission is hereby granted, free of charge, to any person obtaining 116 | a copy of this software and associated documentation files (the 117 | 'Software'), to deal in the Software without restriction, including 118 | without limitation the rights to use, copy, modify, merge, publish, 119 | distribute, sublicense, and/or sell copies of the Software, and to 120 | permit persons to whom the Software is furnished to do so, subject to 121 | the following conditions: 122 | 123 | The above copyright notice and this permission notice shall be 124 | included in all copies or substantial portions of the Software. 125 | 126 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 127 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 128 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 129 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 130 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 131 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 132 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 133 | 134 | 135 | - Underscore ./demos/animated-game/js/underscore.js 136 | 137 | http://underscorejs.org 138 | 139 | (The MIT License) 140 | 141 | Copyright (c) 2010-2013 Jeremy Ashkenas, DocumentCloud 142 | 143 | Permission is hereby granted, free of charge, to any person obtaining 144 | a copy of this software and associated documentation files (the 145 | 'Software'), to deal in the Software without restriction, including 146 | without limitation the rights to use, copy, modify, merge, publish, 147 | distribute, sublicense, and/or sell copies of the Software, and to 148 | permit persons to whom the Software is furnished to do so, subject to 149 | the following conditions: 150 | 151 | The above copyright notice and this permission notice shall be 152 | included in all copies or substantial portions of the Software. 153 | 154 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 155 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 156 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 157 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 158 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 159 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 160 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 161 | 162 | 163 | - jQuery ./demos/animated-game/js/jquery-1.9.0.min.js 164 | 165 | http://http://jquery.com/ 166 | 167 | (The MIT License) 168 | 169 | Copyright 2013 jQuery Foundation and other contributors 170 | http://jquery.com/ 171 | 172 | Permission is hereby granted, free of charge, to any person obtaining 173 | a copy of this software and associated documentation files (the 174 | 'Software'), to deal in the Software without restriction, including 175 | without limitation the rights to use, copy, modify, merge, publish, 176 | distribute, sublicense, and/or sell copies of the Software, and to 177 | permit persons to whom the Software is furnished to do so, subject to 178 | the following conditions: 179 | 180 | The above copyright notice and this permission notice shall be 181 | included in all copies or substantial portions of the Software. 182 | 183 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 184 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 185 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 186 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 187 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 188 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 189 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 190 | 191 | -------------------------------------------------------------------------------- /template.dot: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Snap.svg API Reference 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 37 | 38 | 39 | 40 | 57 | 58 | 60 | 61 |
62 |
63 |
64 |
65 | 66 |
67 | 76 |
77 |
78 |
79 |
80 | {{~it.out :item:index}} 81 |
82 |
83 |

{{=item[0].name}}

84 |
85 |
86 |
87 |
88 | {{~item :line:i}} 89 | {{ if (i > 0) { }} 90 | {{ if (line.text) { }}

{{=line.text.join("

")}}

{{ } }} 91 | {{ if (line.attr) { }}
92 |

Parameters

93 |
    94 | {{~line.attr :attr:j}}
  1. {{=attr.name}} 95 | {{~attr.type :type:k}}{{=type}} {{~}} 96 | {{=attr.desc}}
  2. 97 | {{~}} 98 |
99 |
{{ } }} 100 | {{ if (line.html) { }}{{=line.html}} 101 | {{ } }} 102 | {{ if (line.head) { }}

{{=line.head}}

103 | {{ } }} 104 | {{ if (line.code) { }}
{{=line.code.join("\n")}}
105 | {{ } }} 106 | {{ if (line.rtrn) { }}

107 | Returns: 108 | {{~line.rtrn.type :type:k}} 109 | {{=type}} 110 | {{~}} 111 | {{=line.rtrn.desc}} 112 |

113 | {{ } }} 114 | {{ if (line.json) { }}
    115 | {{~line.json :a:j}} 116 | {{ if (a.key) { }} 117 |
  1. 118 | {{=a.key}} 119 | {{~a.type :type:k}}{{=type}} {{~}} 120 | {{=a.desc}} 121 |
  2. 122 | {{ } else if (a.start) { }} 123 |
  3. {{=a.start}}
      124 | {{ } else if (a.end) { }} 125 |
  4. {{=a.end}}
  5. 126 | {{ } else { }} 127 |
  6. {{=a}}
  7. 128 | {{ } }} 129 | {{~}} 130 |
{{ } }} 131 | {{ } }} 132 | {{~}} 133 |
134 |
135 |
136 | {{~}} 137 |
138 |
139 |
140 |
141 | 142 | 143 | 157 | -------------------------------------------------------------------------------- /demos/snap-mascot/crocodile-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | Snap 19 | 20 | 21 | 78 | 79 | 80 | 81 | 82 | 83 | 85 | 86 | 88 | 90 | 91 | 93 | 94 | 95 | 96 | 97 | 102 | 107 | 108 | 110 | 111 | 112 | 113 | 114 | 115 | 117 | 118 | 120 | 121 | 123 | 124 | 125 | 126 | 127 | 129 | 130 | 131 | 132 | 134 | 135 | 136 | 137 | 139 | 140 | 141 | 142 | 144 | 145 | 146 | 147 | 149 | 150 | 152 | 153 | 154 | 156 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /demos/tutorial/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Tutorial 6 | 7 | 8 | 34 | 35 | 36 | 140 | 141 | 142 |
    143 |
  1. // First, let's create our drawing surface out of an existing SVG element 144 | // If you want to create a new surface just provide dimensions 145 | // like s = Snap(800, 600); 146 | var s = Snap("#svg");
  2. 147 |
  3. // Let's create a big circle in the middle: 148 | var bigCircle = s.circle(150, 150, 100); 149 | // By default it is black, let's change its attributes
  4. 150 |
  5. bigCircle.attr({ 151 | fill: "#bada55", 152 | stroke: "#000", 153 | strokeWidth: 5 154 | });
  6. 155 |
  7. // Now let's create another small circle: 156 | var smallCircle = s.circle(100, 150, 70);
  8. 157 |
  9. // Let's put this small circle and another one into a group: 158 | var discs = s.group(smallCircle, s.circle(200, 150, 70));
  10. 159 |
  11. // Now we can change attributes for the whole group 160 | discs.attr({ 161 | fill: "#fff" 162 | });
  12. 163 |
  13. // Now more interesting stuff 164 | // Let's assign this group as a mask for our big circle 165 | bigCircle.attr({ 166 | mask: discs 167 | });
  14. 168 |
  15. // Despite our small circle being part of a group 169 | // and part of a mask we can still access it: 170 | smallCircle.animate({r: 50}, 1000);
  16. 171 |
  17. // We don’t have a reference for second small circle, 172 | // but we can easily grab it with CSS selectors: 173 | discs.select("circle:nth-child(2)").animate({r: 50}, 1000);
  18. 174 |
  19. // Now let's create pattern 175 | var p = s.path("M10-5-10,15M15,0,0,15M0-5-20,15").attr({ 176 | fill: "none", 177 | stroke: "#bada55", 178 | strokeWidth: 5 179 | }); 180 | // To create a pattern, 181 | // just specify dimensions in the pattern method: 182 | p = p.pattern(0, 0, 10, 10); 183 | // Then use it as a fill on the big circle 184 | bigCircle.attr({ 185 | fill: p 186 | });
  20. 187 |
  21. // We can also grab a pattern from an SVG 188 | // already embedded into our page 189 | discs.attr({ 190 | fill: Snap("#pattern") 191 | });
  22. 192 |
  23. // Let's change the fill of the circles to gradient 193 | // This string means relative radial gradient 194 | // from white to black 195 | discs.attr({fill: "r()#fff-#000"}); 196 | // Note that we have two gradients, one for each circle
  24. 197 |
  25. // If we want them to share one gradient, 198 | // we need to use an absolute gradient with capital R 199 | discs.attr({fill: "R(150, 150, 100)#fff-#000"});
  26. 200 |
  27. // Of course we can animate color as well 201 | p.select("path").animate({stroke: "#f00"}, 1000);
  28. 202 |
  29. // Now let's load an external SVG file: 203 | Snap.load("mascot.svg", function (f) { 204 | // Note that we traverse and change attr before the SVG 205 | // is even added to the page 206 | f.select("polygon[fill='#09B39C']").attr({fill: "#bada55"}); 207 | g = f.select("g"); 208 | s.append(g); 209 | // Making croc draggable. Go ahead drag it around! 210 | g.drag(); 211 | // Obviously drag could take event handlers too 212 | // Looks like our croc is made from more than one polygon... 213 | });
  30. 214 |
  31. // Now let's load an external SVG file: 215 | Snap.load("mascot.svg", function (f) { 216 | // Note that we traverse and change attr before SVG 217 | // is even added to the page 218 | f.selectAll("polygon[fill='#09B39C']").attr({fill: "#bada55"}); 219 | g = f.select("g"); 220 | s.append(g); 221 | // Making croc draggable. Go ahead drag it around! 222 | g.drag(); 223 | // Obviously drag could take event handlers too 224 | // That’s better! selectAll for the rescue. 225 | });
  32. 226 |
  33. // Writing text is as simple as: 227 | s.text(200, 100, "Snap.svg");
  34. 228 |
  35. // Provide an array of strings (or arrays), to generate tspans 229 | var t = s.text(200, 120, ["Snap", ".", "svg"]); 230 | t.selectAll("tspan:nth-child(3)").attr({ 231 | fill: "#900", 232 | "font-size": "20px" 233 | });
  36. 234 |
235 | 236 |
237 | 238 | 239 | 240 | 241 | 242 | 243 | -------------------------------------------------------------------------------- /src/mina.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | var mina = (function (eve) { 15 | var animations = {}, 16 | requestAnimFrame = window.requestAnimationFrame || 17 | window.webkitRequestAnimationFrame || 18 | window.mozRequestAnimationFrame || 19 | window.oRequestAnimationFrame || 20 | window.msRequestAnimationFrame || 21 | function (callback) { 22 | setTimeout(callback, 16); 23 | }, 24 | isArray = Array.isArray || function (a) { 25 | return a instanceof Array || 26 | Object.prototype.toString.call(a) == "[object Array]"; 27 | }, 28 | idgen = 0, 29 | idprefix = "M" + (+new Date).toString(36), 30 | ID = function () { 31 | return idprefix + (idgen++).toString(36); 32 | }, 33 | diff = function (a, b, A, B) { 34 | if (isArray(a)) { 35 | res = []; 36 | for (var i = 0, ii = a.length; i < ii; i++) { 37 | res[i] = diff(a[i], b, A[i], B); 38 | } 39 | return res; 40 | } 41 | var dif = (A - a) / (B - b); 42 | return function (bb) { 43 | return a + dif * (bb - b); 44 | }; 45 | }, 46 | timer = Date.now || function () { 47 | return +new Date; 48 | }, 49 | sta = function (val) { 50 | var a = this; 51 | if (val == null) { 52 | return a.s; 53 | } 54 | var ds = a.s - val; 55 | a.b += a.dur * ds; 56 | a.B += a.dur * ds; 57 | a.s = val; 58 | }, 59 | speed = function (val) { 60 | var a = this; 61 | if (val == null) { 62 | return a.spd; 63 | } 64 | a.spd = val; 65 | }, 66 | duration = function (val) { 67 | var a = this; 68 | if (val == null) { 69 | return a.dur; 70 | } 71 | a.s = a.s * val / a.dur; 72 | a.dur = val; 73 | }, 74 | stopit = function () { 75 | var a = this; 76 | delete animations[a.id]; 77 | eve("mina.stop." + a.id, a); 78 | }, 79 | pause = function () { 80 | var a = this; 81 | if (a.pdif) { 82 | return; 83 | } 84 | delete animations[a.id]; 85 | a.pdif = a.get() - a.b; 86 | }, 87 | resume = function () { 88 | var a = this; 89 | if (!a.pdif) { 90 | return; 91 | } 92 | a.b = a.get() - a.pdif; 93 | delete a.pdif; 94 | animations[a.id] = a; 95 | }, 96 | frame = function () { 97 | var len = 0; 98 | for (var i in animations) if (animations.hasOwnProperty(i)) { 99 | var a = animations[i], 100 | b = a.get(), 101 | res; 102 | len++; 103 | a.s = (b - a.b) / (a.dur / a.spd); 104 | if (a.s >= 1) { 105 | delete animations[i]; 106 | a.s = 1; 107 | len--; 108 | (function (a) { 109 | setTimeout(function () { 110 | eve("mina.finish." + a.id, a); 111 | }); 112 | }(a)); 113 | } 114 | if (isArray(a.start)) { 115 | res = []; 116 | for (var j = 0, jj = a.start.length; j < jj; j++) { 117 | res[j] = +a.start[j] + 118 | (a.end[j] - a.start[j]) * a.easing(a.s); 119 | } 120 | } else { 121 | res = +a.start + (a.end - a.start) * a.easing(a.s); 122 | } 123 | a.set(res); 124 | } 125 | len && requestAnimFrame(frame); 126 | }, 127 | // SIERRA Unfamiliar with the word _slave_ in this context. Also, I don't know what _gereal_ means. Do you mean _general_? 128 | /*\ 129 | * mina 130 | [ method ] 131 | ** 132 | * Generic animation of numbers 133 | ** 134 | - a (number) start _slave_ number 135 | - A (number) end _slave_ number 136 | - b (number) start _master_ number (start time in general case) 137 | - B (number) end _master_ number (end time in gereal case) 138 | - get (function) getter of _master_ number (see @mina.time) 139 | - set (function) setter of _slave_ number 140 | - easing (function) #optional easing function, default is @mina.linear 141 | = (object) animation descriptor 142 | o { 143 | o id (string) animation id, 144 | o start (number) start _slave_ number, 145 | o end (number) end _slave_ number, 146 | o b (number) start _master_ number, 147 | o s (number) animation status (0..1), 148 | o dur (number) animation duration, 149 | o spd (number) animation speed, 150 | o get (function) getter of _master_ number (see @mina.time), 151 | o set (function) setter of _slave_ number, 152 | o easing (function) easing function, default is @mina.linear, 153 | o status (function) status getter/setter, 154 | o speed (function) speed getter/setter, 155 | o duration (function) duration getter/setter, 156 | o stop (function) animation stopper 157 | o } 158 | \*/ 159 | mina = function (a, A, b, B, get, set, easing) { 160 | var anim = { 161 | id: ID(), 162 | start: a, 163 | end: A, 164 | b: b, 165 | s: 0, 166 | dur: B - b, 167 | spd: 1, 168 | get: get, 169 | set: set, 170 | easing: easing || mina.linear, 171 | status: sta, 172 | speed: speed, 173 | duration: duration, 174 | stop: stopit, 175 | pause: pause, 176 | resume: resume 177 | }; 178 | animations[anim.id] = anim; 179 | var len = 0, i; 180 | for (i in animations) if (animations.hasOwnProperty(i)) { 181 | len++; 182 | if (len == 2) { 183 | break; 184 | } 185 | } 186 | len == 1 && requestAnimFrame(frame); 187 | return anim; 188 | }; 189 | /*\ 190 | * mina.time 191 | [ method ] 192 | ** 193 | * Returns the current time. Equivalent to: 194 | | function () { 195 | | return (new Date).getTime(); 196 | | } 197 | \*/ 198 | mina.time = timer; 199 | /*\ 200 | * mina.getById 201 | [ method ] 202 | ** 203 | * Returns an animation by its id 204 | - id (string) animation's id 205 | = (object) See @mina 206 | \*/ 207 | mina.getById = function (id) { 208 | return animations[id] || null; 209 | }; 210 | 211 | /*\ 212 | * mina.linear 213 | [ method ] 214 | ** 215 | * Default linear easing 216 | - n (number) input 0..1 217 | = (number) output 0..1 218 | \*/ 219 | mina.linear = function (n) { 220 | return n; 221 | }; 222 | /*\ 223 | * mina.easeout 224 | [ method ] 225 | ** 226 | * Easeout easing 227 | - n (number) input 0..1 228 | = (number) output 0..1 229 | \*/ 230 | mina.easeout = function (n) { 231 | return Math.pow(n, 1.7); 232 | }; 233 | /*\ 234 | * mina.easein 235 | [ method ] 236 | ** 237 | * Easein easing 238 | - n (number) input 0..1 239 | = (number) output 0..1 240 | \*/ 241 | mina.easein = function (n) { 242 | return Math.pow(n, .48); 243 | }; 244 | /*\ 245 | * mina.easeinout 246 | [ method ] 247 | ** 248 | * Easeinout easing 249 | - n (number) input 0..1 250 | = (number) output 0..1 251 | \*/ 252 | mina.easeinout = function (n) { 253 | if (n == 1) { 254 | return 1; 255 | } 256 | if (n == 0) { 257 | return 0; 258 | } 259 | var q = .48 - n / 1.04, 260 | Q = Math.sqrt(.1734 + q * q), 261 | x = Q - q, 262 | X = Math.pow(Math.abs(x), 1 / 3) * (x < 0 ? -1 : 1), 263 | y = -Q - q, 264 | Y = Math.pow(Math.abs(y), 1 / 3) * (y < 0 ? -1 : 1), 265 | t = X + Y + .5; 266 | return (1 - t) * 3 * t * t + t * t * t; 267 | }; 268 | /*\ 269 | * mina.backin 270 | [ method ] 271 | ** 272 | * Backin easing 273 | - n (number) input 0..1 274 | = (number) output 0..1 275 | \*/ 276 | mina.backin = function (n) { 277 | if (n == 1) { 278 | return 1; 279 | } 280 | var s = 1.70158; 281 | return n * n * ((s + 1) * n - s); 282 | }; 283 | /*\ 284 | * mina.backout 285 | [ method ] 286 | ** 287 | * Backout easing 288 | - n (number) input 0..1 289 | = (number) output 0..1 290 | \*/ 291 | mina.backout = function (n) { 292 | if (n == 0) { 293 | return 0; 294 | } 295 | n = n - 1; 296 | var s = 1.70158; 297 | return n * n * ((s + 1) * n + s) + 1; 298 | }; 299 | /*\ 300 | * mina.elastic 301 | [ method ] 302 | ** 303 | * Elastic easing 304 | - n (number) input 0..1 305 | = (number) output 0..1 306 | \*/ 307 | mina.elastic = function (n) { 308 | if (n == !!n) { 309 | return n; 310 | } 311 | return Math.pow(2, -10 * n) * Math.sin((n - .075) * 312 | (2 * Math.PI) / .3) + 1; 313 | }; 314 | /*\ 315 | * mina.bounce 316 | [ method ] 317 | ** 318 | * Bounce easing 319 | - n (number) input 0..1 320 | = (number) output 0..1 321 | \*/ 322 | mina.bounce = function (n) { 323 | var s = 7.5625, 324 | p = 2.75, 325 | l; 326 | if (n < (1 / p)) { 327 | l = s * n * n; 328 | } else { 329 | if (n < (2 / p)) { 330 | n -= (1.5 / p); 331 | l = s * n * n + .75; 332 | } else { 333 | if (n < (2.5 / p)) { 334 | n -= (2.25 / p); 335 | l = s * n * n + .9375; 336 | } else { 337 | n -= (2.625 / p); 338 | l = s * n * n + .984375; 339 | } 340 | } 341 | } 342 | return l; 343 | }; 344 | window.mina = mina; 345 | return mina; 346 | })(typeof eve == "undefined" ? function () {} : eve); -------------------------------------------------------------------------------- /src/filter.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | Snap.plugin(function (Snap, Element, Paper, glob) { 15 | var elproto = Element.prototype, 16 | pproto = Paper.prototype, 17 | rgurl = /^\s*url\((.+)\)/, 18 | Str = String, 19 | $ = Snap._.$; 20 | Snap.filter = {}; 21 | // SIERRA Paper.filter(): I don't understand the note. Does that mean an HTML should dedicate a separate SVG region for a filter definition? What's the advantage over a DEFS? 22 | /*\ 23 | * Paper.filter 24 | [ method ] 25 | ** 26 | * Creates a `` element 27 | ** 28 | - filstr (string) SVG fragment of filter provided as a string 29 | = (object) @Element 30 | * Note: It is recommended to use filters embedded into the page inside an empty SVG element. 31 | > Usage 32 | | var f = paper.filter(''), 33 | | c = paper.circle(10, 10, 10).attr({ 34 | | filter: f 35 | | }); 36 | \*/ 37 | pproto.filter = function (filstr) { 38 | var paper = this; 39 | if (paper.type != "svg") { 40 | paper = paper.paper; 41 | } 42 | var f = Snap.parse(Str(filstr)), 43 | id = Snap._.id(), 44 | width = paper.node.offsetWidth, 45 | height = paper.node.offsetHeight, 46 | filter = $("filter"); 47 | $(filter, { 48 | id: id, 49 | filterUnits: "userSpaceOnUse" 50 | }); 51 | filter.appendChild(f.node); 52 | paper.defs.appendChild(filter); 53 | return new Element(filter); 54 | }; 55 | 56 | eve.on("snap.util.getattr.filter", function () { 57 | eve.stop(); 58 | var p = $(this.node, "filter"); 59 | if (p) { 60 | var match = Str(p).match(rgurl); 61 | return match && Snap.select(match[1]); 62 | } 63 | }); 64 | eve.on("snap.util.attr.filter", function (value) { 65 | if (value instanceof Element && value.type == "filter") { 66 | eve.stop(); 67 | var id = value.node.id; 68 | if (!id) { 69 | $(value.node, {id: value.id}); 70 | id = value.id; 71 | } 72 | $(this.node, { 73 | filter: Snap.url(id) 74 | }); 75 | } 76 | if (!value || value == "none") { 77 | eve.stop(); 78 | this.node.removeAttribute("filter"); 79 | } 80 | }); 81 | /*\ 82 | * Snap.filter.blur 83 | [ method ] 84 | ** 85 | * Returns an SVG markup string for the blur filter 86 | ** 87 | - x (number) amount of horizontal blur, in pixels 88 | - y (number) #optional amount of vertical blur, in pixels 89 | = (string) filter representation 90 | > Usage 91 | | var f = paper.filter(Snap.filter.blur(5, 10)), 92 | | c = paper.circle(10, 10, 10).attr({ 93 | | filter: f 94 | | }); 95 | \*/ 96 | Snap.filter.blur = function (x, y) { 97 | if (x == null) { 98 | x = 2; 99 | } 100 | var def = y == null ? x : [x, y]; 101 | return Snap.format('\', { 102 | def: def 103 | }); 104 | }; 105 | Snap.filter.blur.toString = function () { 106 | return this(); 107 | }; 108 | /*\ 109 | * Snap.filter.shadow 110 | [ method ] 111 | ** 112 | * Returns an SVG markup string for the shadow filter 113 | ** 114 | - dx (number) horizontal shift of the shadow, in pixels 115 | - dy (number) vertical shift of the shadow, in pixels 116 | - blur (number) #optional amount of blur 117 | - color (string) #optional color of the shadow 118 | = (string) filter representation 119 | > Usage 120 | | var f = paper.filter(Snap.filter.shadow(0, 2, 3)), 121 | | c = paper.circle(10, 10, 10).attr({ 122 | | filter: f 123 | | }); 124 | \*/ 125 | Snap.filter.shadow = function (dx, dy, blur, color) { 126 | color = color || "#000"; 127 | if (blur == null) { 128 | blur = 4; 129 | } 130 | if (typeof blur == "string") { 131 | color = blur; 132 | blur = 4; 133 | } 134 | if (dx == null) { 135 | dx = 0; 136 | dy = 2; 137 | } 138 | if (dy == null) { 139 | dy = dx; 140 | } 141 | color = Snap.color(color); 142 | return Snap.format('', { 143 | color: color, 144 | dx: dx, 145 | dy: dy, 146 | blur: blur 147 | }); 148 | }; 149 | Snap.filter.shadow.toString = function () { 150 | return this(); 151 | }; 152 | /*\ 153 | * Snap.filter.grayscale 154 | [ method ] 155 | ** 156 | * Returns an SVG markup string for the grayscale filter 157 | ** 158 | - amount (number) amount of filter (`0..1`) 159 | = (string) filter representation 160 | \*/ 161 | Snap.filter.grayscale = function (amount) { 162 | if (amount == null) { 163 | amount = 1; 164 | } 165 | return Snap.format('', { 166 | a: 0.2126 + 0.7874 * (1 - amount), 167 | b: 0.7152 - 0.7152 * (1 - amount), 168 | c: 0.0722 - 0.0722 * (1 - amount), 169 | d: 0.2126 - 0.2126 * (1 - amount), 170 | e: 0.7152 + 0.2848 * (1 - amount), 171 | f: 0.0722 - 0.0722 * (1 - amount), 172 | g: 0.2126 - 0.2126 * (1 - amount), 173 | h: 0.0722 + 0.9278 * (1 - amount) 174 | }); 175 | }; 176 | Snap.filter.grayscale.toString = function () { 177 | return this(); 178 | }; 179 | /*\ 180 | * Snap.filter.sepia 181 | [ method ] 182 | ** 183 | * Returns an SVG markup string for the sepia filter 184 | ** 185 | - amount (number) amount of filter (`0..1`) 186 | = (string) filter representation 187 | \*/ 188 | Snap.filter.sepia = function (amount) { 189 | if (amount == null) { 190 | amount = 1; 191 | } 192 | return Snap.format('', { 193 | a: 0.393 + 0.607 * (1 - amount), 194 | b: 0.769 - 0.769 * (1 - amount), 195 | c: 0.189 - 0.189 * (1 - amount), 196 | d: 0.349 - 0.349 * (1 - amount), 197 | e: 0.686 + 0.314 * (1 - amount), 198 | f: 0.168 - 0.168 * (1 - amount), 199 | g: 0.272 - 0.272 * (1 - amount), 200 | h: 0.534 - 0.534 * (1 - amount), 201 | i: 0.131 + 0.869 * (1 - amount) 202 | }); 203 | }; 204 | Snap.filter.sepia.toString = function () { 205 | return this(); 206 | }; 207 | /*\ 208 | * Snap.filter.saturate 209 | [ method ] 210 | ** 211 | * Returns an SVG markup string for the saturate filter 212 | ** 213 | - amount (number) amount of filter (`0..1`) 214 | = (string) filter representation 215 | \*/ 216 | Snap.filter.saturate = function (amount) { 217 | if (amount == null) { 218 | amount = 1; 219 | } 220 | return Snap.format('', { 221 | amount: 1 - amount 222 | }); 223 | }; 224 | Snap.filter.saturate.toString = function () { 225 | return this(); 226 | }; 227 | /*\ 228 | * Snap.filter.hueRotate 229 | [ method ] 230 | ** 231 | * Returns an SVG markup string for the hue-rotate filter 232 | ** 233 | - angle (number) angle of rotation 234 | = (string) filter representation 235 | \*/ 236 | Snap.filter.hueRotate = function (angle) { 237 | angle = angle || 0; 238 | return Snap.format('', { 239 | angle: angle 240 | }); 241 | }; 242 | Snap.filter.hueRotate.toString = function () { 243 | return this(); 244 | }; 245 | /*\ 246 | * Snap.filter.invert 247 | [ method ] 248 | ** 249 | * Returns an SVG markup string for the invert filter 250 | ** 251 | - amount (number) amount of filter (`0..1`) 252 | = (string) filter representation 253 | \*/ 254 | Snap.filter.invert = function (amount) { 255 | if (amount == null) { 256 | amount = 1; 257 | } 258 | return Snap.format('', { 259 | amount: amount, 260 | amount2: 1 - amount 261 | }); 262 | }; 263 | Snap.filter.invert.toString = function () { 264 | return this(); 265 | }; 266 | /*\ 267 | * Snap.filter.brightness 268 | [ method ] 269 | ** 270 | * Returns an SVG markup string for the brightness filter 271 | ** 272 | - amount (number) amount of filter (`0..1`) 273 | = (string) filter representation 274 | \*/ 275 | Snap.filter.brightness = function (amount) { 276 | if (amount == null) { 277 | amount = 1; 278 | } 279 | return Snap.format('', { 280 | amount: amount 281 | }); 282 | }; 283 | Snap.filter.brightness.toString = function () { 284 | return this(); 285 | }; 286 | /*\ 287 | * Snap.filter.contrast 288 | [ method ] 289 | ** 290 | * Returns an SVG markup string for the contrast filter 291 | ** 292 | - amount (number) amount of filter (`0..1`) 293 | = (string) filter representation 294 | \*/ 295 | Snap.filter.contrast = function (amount) { 296 | if (amount == null) { 297 | amount = 1; 298 | } 299 | return Snap.format('', { 300 | amount: amount, 301 | amount2: .5 - amount / 2 302 | }); 303 | }; 304 | Snap.filter.contrast.toString = function () { 305 | return this(); 306 | }; 307 | }); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2013 Adobe Systems Incorporated 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /demos/animated-game/js/seedrandom.js: -------------------------------------------------------------------------------- 1 | // seedrandom.js version 2.2. 2 | // Author: David Bau 3 | // Date: 2013 Jun 15 4 | // 5 | // Defines a method Math.seedrandom() that, when called, substitutes 6 | // an explicitly seeded RC4-based algorithm for Math.random(). Also 7 | // supports automatic seeding from local or network sources of entropy. 8 | // 9 | // http://davidbau.com/encode/seedrandom.js 10 | // http://davidbau.com/encode/seedrandom-min.js 11 | // 12 | // Usage: 13 | // 14 | // 15 | // 16 | // Math.seedrandom('yay.'); Sets Math.random to a function that is 17 | // initialized using the given explicit seed. 18 | // 19 | // Math.seedrandom(); Sets Math.random to a function that is 20 | // seeded using the current time, dom state, 21 | // and other accumulated local entropy. 22 | // The generated seed string is returned. 23 | // 24 | // Math.seedrandom('yowza.', true); 25 | // Seeds using the given explicit seed mixed 26 | // together with accumulated entropy. 27 | // 28 | // Seeds using urandom bits from a server. 30 | // 31 | // More advanced examples: 32 | // 33 | // Math.seedrandom("hello."); // Use "hello." as the seed. 34 | // document.write(Math.random()); // Always 0.9282578795792454 35 | // document.write(Math.random()); // Always 0.3752569768646784 36 | // var rng1 = Math.random; // Remember the current prng. 37 | // 38 | // var autoseed = Math.seedrandom(); // New prng with an automatic seed. 39 | // document.write(Math.random()); // Pretty much unpredictable x. 40 | // 41 | // Math.random = rng1; // Continue "hello." prng sequence. 42 | // document.write(Math.random()); // Always 0.7316977468919549 43 | // 44 | // Math.seedrandom(autoseed); // Restart at the previous seed. 45 | // document.write(Math.random()); // Repeat the 'unpredictable' x. 46 | // 47 | // function reseed(event, count) { // Define a custom entropy collector. 48 | // var t = []; 49 | // function w(e) { 50 | // t.push([e.pageX, e.pageY, +new Date]); 51 | // if (t.length < count) { return; } 52 | // document.removeEventListener(event, w); 53 | // Math.seedrandom(t, true); // Mix in any previous entropy. 54 | // } 55 | // document.addEventListener(event, w); 56 | // } 57 | // reseed('mousemove', 100); // Reseed after 100 mouse moves. 58 | // 59 | // Version notes: 60 | // 61 | // The random number sequence is the same as version 1.0 for string seeds. 62 | // Version 2.0 changed the sequence for non-string seeds. 63 | // Version 2.1 speeds seeding and uses window.crypto to autoseed if present. 64 | // Version 2.2 alters non-crypto autoseeding to sweep up entropy from plugins. 65 | // 66 | // The standard ARC4 key scheduler cycles short keys, which means that 67 | // seedrandom('ab') is equivalent to seedrandom('abab') and 'ababab'. 68 | // Therefore it is a good idea to add a terminator to avoid trivial 69 | // equivalences on short string seeds, e.g., Math.seedrandom(str + '\0'). 70 | // Starting with version 2.0, a terminator is added automatically for 71 | // non-string seeds, so seeding with the number 111 is the same as seeding 72 | // with '111\0'. 73 | // 74 | // When seedrandom() is called with zero args, it uses a seed 75 | // drawn from the browser crypto object if present. If there is no 76 | // crypto support, seedrandom() uses the current time, the native rng, 77 | // and a walk of several DOM objects to collect a few bits of entropy. 78 | // 79 | // Each time the one- or two-argument forms of seedrandom are called, 80 | // entropy from the passed seed is accumulated in a pool to help generate 81 | // future seeds for the zero- and two-argument forms of seedrandom. 82 | // 83 | // On speed - This javascript implementation of Math.random() is about 84 | // 3-10x slower than the built-in Math.random() because it is not native 85 | // code, but that is typically fast enough. Some details (timings on 86 | // Chrome 25 on a 2010 vintage macbook): 87 | // 88 | // seeded Math.random() - avg less than 0.0002 milliseconds per call 89 | // seedrandom('explicit.') - avg less than 0.2 milliseconds per call 90 | // seedrandom('explicit.', true) - avg less than 0.2 milliseconds per call 91 | // seedrandom() with crypto - avg less than 0.2 milliseconds per call 92 | // 93 | // Autoseeding without crypto is somewhat slower, about 20-30 milliseconds on 94 | // a 2012 windows 7 1.5ghz i5 laptop, as seen on Firefox 19, IE 10, and Opera. 95 | // Seeded rng calls themselves are fast across these browsers, with slowest 96 | // numbers on Opera at about 0.0005 ms per seeded Math.random(). 97 | // 98 | // LICENSE (BSD): 99 | // 100 | // Copyright 2013 David Bau, all rights reserved. 101 | // 102 | // Redistribution and use in source and binary forms, with or without 103 | // modification, are permitted provided that the following conditions are met: 104 | // 105 | // 1. Redistributions of source code must retain the above copyright 106 | // notice, this list of conditions and the following disclaimer. 107 | // 108 | // 2. Redistributions in binary form must reproduce the above copyright 109 | // notice, this list of conditions and the following disclaimer in the 110 | // documentation and/or other materials provided with the distribution. 111 | // 112 | // 3. Neither the name of this module nor the names of its contributors may 113 | // be used to endorse or promote products derived from this software 114 | // without specific prior written permission. 115 | // 116 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 117 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 118 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 119 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 120 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 121 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 122 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 123 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 124 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 125 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 126 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 127 | // 128 | /** 129 | * All code is in an anonymous closure to keep the global namespace clean. 130 | */ 131 | (function ( 132 | global, pool, math, width, chunks, digits) { 133 | 134 | // 135 | // The following constants are related to IEEE 754 limits. 136 | // 137 | var startdenom = math.pow(width, chunks), 138 | significance = math.pow(2, digits), 139 | overflow = significance * 2, 140 | mask = width - 1; 141 | 142 | // 143 | // seedrandom() 144 | // This is the seedrandom function described above. 145 | // 146 | math['seedrandom'] = function(seed, use_entropy) { 147 | var key = []; 148 | 149 | // Flatten the seed string or build one from local entropy if needed. 150 | var shortseed = mixkey(flatten( 151 | use_entropy ? [seed, tostring(pool)] : 152 | 0 in arguments ? seed : autoseed(), 3), key); 153 | 154 | // Use the seed to initialize an ARC4 generator. 155 | var arc4 = new ARC4(key); 156 | 157 | // Mix the randomness into accumulated entropy. 158 | mixkey(tostring(arc4.S), pool); 159 | 160 | // Override Math.random 161 | 162 | // This function returns a random double in [0, 1) that contains 163 | // randomness in every bit of the mantissa of the IEEE 754 value. 164 | 165 | math['random'] = function() { // Closure to return a random double: 166 | var n = arc4.g(chunks), // Start with a numerator n < 2 ^ 48 167 | d = startdenom, // and denominator d = 2 ^ 48. 168 | x = 0; // and no 'extra last byte'. 169 | while (n < significance) { // Fill up all significant digits by 170 | n = (n + x) * width; // shifting numerator and 171 | d *= width; // denominator and generating a 172 | x = arc4.g(1); // new least-significant-byte. 173 | } 174 | while (n >= overflow) { // To avoid rounding up, before adding 175 | n /= 2; // last byte, shift everything 176 | d /= 2; // right using integer math until 177 | x >>>= 1; // we have exactly the desired bits. 178 | } 179 | return (n + x) / d; // Form the number within [0, 1). 180 | }; 181 | 182 | // Return the seed that was used 183 | return shortseed; 184 | }; 185 | 186 | // 187 | // ARC4 188 | // 189 | // An ARC4 implementation. The constructor takes a key in the form of 190 | // an array of at most (width) integers that should be 0 <= x < (width). 191 | // 192 | // The g(count) method returns a pseudorandom integer that concatenates 193 | // the next (count) outputs from ARC4. Its return value is a number x 194 | // that is in the range 0 <= x < (width ^ count). 195 | // 196 | /** @constructor */ 197 | function ARC4(key) { 198 | var t, keylen = key.length, 199 | me = this, i = 0, j = me.i = me.j = 0, s = me.S = []; 200 | 201 | // The empty key [] is treated as [0]. 202 | if (!keylen) { key = [keylen++]; } 203 | 204 | // Set up S using the standard key scheduling algorithm. 205 | while (i < width) { 206 | s[i] = i++; 207 | } 208 | for (i = 0; i < width; i++) { 209 | s[i] = s[j = mask & (j + key[i % keylen] + (t = s[i]))]; 210 | s[j] = t; 211 | } 212 | 213 | // The "g" method returns the next (count) outputs as one number. 214 | (me.g = function(count) { 215 | // Using instance members instead of closure state nearly doubles speed. 216 | var t, r = 0, 217 | i = me.i, j = me.j, s = me.S; 218 | while (count--) { 219 | t = s[i = mask & (i + 1)]; 220 | r = r * width + s[mask & ((s[i] = s[j = mask & (j + t)]) + (s[j] = t))]; 221 | } 222 | me.i = i; me.j = j; 223 | return r; 224 | // For robust unpredictability discard an initial batch of values. 225 | // See http://www.rsa.com/rsalabs/node.asp?id=2009 226 | })(width); 227 | } 228 | 229 | // 230 | // flatten() 231 | // Converts an object tree to nested arrays of strings. 232 | // 233 | function flatten(obj, depth) { 234 | var result = [], typ = (typeof obj)[0], prop; 235 | if (depth && typ == 'o') { 236 | for (prop in obj) { 237 | try { result.push(flatten(obj[prop], depth - 1)); } catch (e) {} 238 | } 239 | } 240 | return (result.length ? result : typ == 's' ? obj : obj + '\0'); 241 | } 242 | 243 | // 244 | // mixkey() 245 | // Mixes a string seed into a key that is an array of integers, and 246 | // returns a shortened string seed that is equivalent to the result key. 247 | // 248 | function mixkey(seed, key) { 249 | var stringseed = seed + '', smear, j = 0; 250 | while (j < stringseed.length) { 251 | key[mask & j] = 252 | mask & ((smear ^= key[mask & j] * 19) + stringseed.charCodeAt(j++)); 253 | } 254 | return tostring(key); 255 | } 256 | 257 | // 258 | // autoseed() 259 | // Returns an object for autoseeding, using window.crypto if available. 260 | // 261 | /** @param {Uint8Array=} seed */ 262 | function autoseed(seed) { 263 | try { 264 | global.crypto.getRandomValues(seed = new Uint8Array(width)); 265 | return tostring(seed); 266 | } catch (e) { 267 | return [+new Date, global, global.navigator.plugins, 268 | global.screen, tostring(pool)]; 269 | } 270 | } 271 | 272 | // 273 | // tostring() 274 | // Converts an array of charcodes to a string 275 | // 276 | function tostring(a) { 277 | return String.fromCharCode.apply(0, a); 278 | } 279 | 280 | // 281 | // When seedrandom.js is loaded, we immediately mix a few bits 282 | // from the built-in RNG into the entropy pool. Because we do 283 | // not want to intefere with determinstic PRNG state later, 284 | // seedrandom will not call math.random on its own again after 285 | // initialization. 286 | // 287 | mixkey(math.random(), pool); 288 | 289 | // End anonymous scope, and pass initial values. 290 | })( 291 | this, // global window object 292 | [], // pool: entropy pool starts empty 293 | Math, // math: package containing random, pow, and seedrandom 294 | 256, // width: each RC4 output is 0 <= x < 256 295 | 6, // chunks: at least six RC4 outputs for each double 296 | 52 // digits: there are 52 significant digits in a double 297 | ); -------------------------------------------------------------------------------- /demos/illustrated-infographic-coffee/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | Coffee Maker 19 | 20 | 58 | 59 | 391 | 392 | 393 | --------------------------------------------------------------------------------