Repository: kenjiSpecial/100day-canvas-bootcamp-training Branch: master Commit: ad10e045958d Files: 108 Total size: 725.3 KB Directory structure: gitextract_de7fdsmn/ ├── .bowerrc ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jshintrc ├── Gruntfile.js ├── README.md ├── app/ │ ├── .htaccess │ ├── 404.html │ ├── gl-html/ │ │ ├── gl00.html │ │ ├── gl01.html │ │ ├── gl57.html │ │ ├── three58.html │ │ └── three64.html │ ├── gl-index.html │ ├── index.html │ ├── json/ │ │ └── awwwrd.js │ ├── robots.txt │ ├── scripts/ │ │ ├── 0-components/ │ │ │ ├── boilerplate.js │ │ │ ├── data.js │ │ │ ├── output.js │ │ │ └── path.js │ │ ├── 1-illusion-of-life/ │ │ │ ├── 1-squash.js │ │ │ ├── 10-animation.js │ │ │ ├── 11-animation-2.js │ │ │ ├── 12-secondary-action.js │ │ │ ├── 13-secondary-action.js │ │ │ ├── 14-undefined.js │ │ │ ├── 15-undefined.js │ │ │ ├── 16-undefined.js │ │ │ ├── 17-undefined.js │ │ │ ├── 18-undefined.js │ │ │ ├── 19-undefined.js │ │ │ ├── 2-squash.js │ │ │ ├── 20-undefined.js │ │ │ ├── 21-undefined.js │ │ │ ├── 22-sine-cos.js │ │ │ ├── 22-undefined.js │ │ │ ├── 23-undefined.js │ │ │ ├── 3-stage.js │ │ │ ├── 4-anticipation.js │ │ │ ├── 5-pose-to-pos.js │ │ │ ├── 6-pose-to-pose.js │ │ │ ├── 7-pose-to-pose.js │ │ │ ├── 8-arcs.js │ │ │ └── 9-arcs.js │ │ ├── 2-numbers/ │ │ │ ├── 24-number0.js │ │ │ └── 25-number0.js │ │ ├── 3-algorithm/ │ │ │ ├── -1-43-undefined-botsu.js │ │ │ ├── 33-bubble-sort.js │ │ │ ├── 34-search.js │ │ │ ├── 35-undefined.js │ │ │ ├── 36-undefined.js │ │ │ ├── 37-undefined.js │ │ │ ├── 38-undefined.js │ │ │ ├── 39-undefined.js │ │ │ ├── 40-undefined.js │ │ │ ├── 41-undefined.js │ │ │ └── 42-undefined.js │ │ ├── 4-webgl/ │ │ │ ├── 0-test-three-js-example.js │ │ │ ├── 1-test-three-js-example.js │ │ │ ├── 2-test-three-js-example.js │ │ │ ├── 48-three-js-shader.js │ │ │ ├── 49-three-js.js │ │ │ ├── 50-three-js-with-shader.js │ │ │ ├── 55-gl.js │ │ │ ├── 56-gl.js │ │ │ ├── 57-gl.js │ │ │ ├── 58-three-js.js │ │ │ ├── 64-three-js.js │ │ │ ├── 99-00-gl-learning.js │ │ │ └── vendors/ │ │ │ └── minMatrix.js │ │ ├── 5-loop/ │ │ │ ├── 43-loop.js │ │ │ ├── 44-loop.js │ │ │ ├── 45-loop.js │ │ │ ├── 46-loop.js │ │ │ ├── 47-loop.js │ │ │ └── 51-loop.js │ │ ├── 6-letters/ │ │ │ ├── 52-letters.js │ │ │ ├── 53-letters.js │ │ │ └── 54-letter.js │ │ ├── 99-hobby/ │ │ │ ├── 26-undefined.js │ │ │ ├── 27-simple-boid.js │ │ │ ├── 28-02-combination.js │ │ │ ├── 28-combination.js │ │ │ ├── 30-mouse-boid.js │ │ │ ├── 32-boid-collection.js │ │ │ ├── 99-01-canvas-letter.js │ │ │ ├── 99-02-shader-example.js │ │ │ ├── 99-03-circle-drawing.js │ │ │ ├── 99-04-flag-animation.js │ │ │ └── 99-05-color-draw.js │ │ ├── helpers/ │ │ │ ├── boilterplate.js │ │ │ ├── colorConverter.js │ │ │ ├── keyEvents.js │ │ │ └── svg-parse.js │ │ ├── main.js │ │ └── ref/ │ │ └── camera.js │ ├── styles/ │ │ └── main.scss │ └── three-js-shader-sample.html ├── bower.json ├── package.json └── test/ ├── index.html ├── lib/ │ ├── chai.js │ ├── expect.js │ └── mocha/ │ ├── mocha.css │ └── mocha.js └── spec/ └── test.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .bowerrc ================================================ { "directory": "app/bower_components" } ================================================ FILE: .editorconfig ================================================ # EditorConfig helps developers define and maintain consistent # coding styles between different editors and IDEs # editorconfig.org root = true [*] # Change these settings to your own preference indent_style = space indent_size = 4 # We recommend you to keep these unchanged end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true [*.md] trim_trailing_whitespace = false ================================================ FILE: .gitattributes ================================================ * text=auto ================================================ FILE: .gitignore ================================================ node_modules dist .tmp .sass-cache app/bower_components test/bower_components ================================================ FILE: .jshintrc ================================================ { "node": true, "browser": true, "esnext": true, "bitwise": true, "camelcase": true, "curly": true, "eqeqeq": true, "immed": true, "indent": 4, "latedef": true, "newcap": true, "noarg": true, "quotmark": "single", "undef": true, "unused": true, "strict": true, "trailing": true, "smarttabs": true, "jquery": true } ================================================ FILE: Gruntfile.js ================================================ // Generated on 2014-05-01 using generator-webapp 0.4.8 'use strict'; // # Globbing // for performance reasons we're only matching one level down: // 'test/spec/{,*/}*.js' // use this if you want to recursively match all subfolders: // 'test/spec/**/*.js' module.exports = function (grunt) { // Load grunt tasks automatically require('load-grunt-tasks')(grunt); // Time how long tasks take. Can help when optimizing build times require('time-grunt')(grunt); // Define the configuration for all the tasks grunt.initConfig({ // Project settings config: { // Configurable paths app: 'app', dist: 'dist' }, // Watches files for changes and runs tasks based on the changed files watch: { bower: { files: ['bower.json'], tasks: ['bowerInstall'] }, gruntfile: { files: ['Gruntfile.js'] }, compass: { files: ['<%= config.app %>/styles/{,*/}*.{scss,sass}'], tasks: ['compass:server', 'autoprefixer'] }, styles: { files: ['<%= config.app %>/styles/{,*/}*.css'], tasks: ['newer:copy:styles', 'autoprefixer'] }, livereload: { options: { livereload: '<%= connect.options.livereload %>' }, files: [ ] } }, // The actual grunt server settings connect: { options: { port: 9000, livereload: 35729, // Change this to '0.0.0.0' to access the server from outside hostname: '0.0.0.0' }, livereload: { options: { open: true, base: [ '.tmp', '<%= config.app %>' ] } }, test: { options: { port: 9001, base: [ '.tmp', 'test', '<%= config.app %>' ] } }, dist: { options: { open: true, base: '<%= config.dist %>', livereload: false } } }, // Empties folders to start fresh clean: { dist: { files: [{ dot: true, src: [ '.tmp', '<%= config.dist %>/*', '!<%= config.dist %>/.git*' ] }] }, server: '.tmp' }, // Make sure code styles are up to par and there are no obvious mistakes jshint: { options: { jshintrc: '.jshintrc', reporter: require('jshint-stylish') }, all: [ 'Gruntfile.js', '<%= config.app %>/scripts/{,*/}*.js', '!<%= config.app %>/scripts/vendor/*', 'test/spec/{,*/}*.js' ] }, // Mocha testing framework configuration options mocha: { all: { options: { run: true, urls: ['http://<%= connect.test.options.hostname %>:<%= connect.test.options.port %>/index.html'] } } }, // Compiles Sass to CSS and generates necessary files if requested compass: { options: { sassDir: '<%= config.app %>/styles', cssDir: '.tmp/styles', generatedImagesDir: '.tmp/images/generated', imagesDir: '<%= config.app %>/images', javascriptsDir: '<%= config.app %>/scripts', fontsDir: '<%= config.app %>/styles/fonts', importPath: '<%= config.app %>/bower_components', httpImagesPath: '/images', httpGeneratedImagesPath: '/images/generated', httpFontsPath: '/styles/fonts', relativeAssets: false, assetCacheBuster: false }, dist: { options: { generatedImagesDir: '<%= config.dist %>/images/generated' } }, server: { options: { debugInfo: true } } }, // Add vendor prefixed styles autoprefixer: { options: { browsers: ['last 1 version'] }, dist: { files: [{ expand: true, cwd: '.tmp/styles/', src: '{,*/}*.css', dest: '.tmp/styles/' }] } }, // Automatically inject Bower components into the HTML file bowerInstall: { app: { src: ['<%= config.app %>/index.html'], ignorePath: '<%= config.app %>/', exclude: ['<%= config.app %>/bower_components/bootstrap-sass/vendor/assets/javascripts/bootstrap.js'] }, sass: { src: ['<%= config.app %>/styles/{,*/}*.{scss,sass}'], ignorePath: '<%= config.app %>/bower_components/' } }, // Renames files for browser caching purposes rev: { dist: { files: { src: [ '<%= config.dist %>/scripts/{,*/}*.js', '<%= config.dist %>/styles/{,*/}*.css', '<%= config.dist %>/images/{,*/}*.*', '<%= config.dist %>/styles/fonts/{,*/}*.*', '<%= config.dist %>/*.{ico,png}' ] } } }, // Reads HTML for usemin blocks to enable smart builds that automatically // concat, minify and revision files. Creates configurations in memory so // additional tasks can operate on them useminPrepare: { options: { dest: '<%= config.dist %>' }, html: '<%= config.app %>/index.html' }, // Performs rewrites based on rev and the useminPrepare configuration usemin: { options: { assetsDirs: ['<%= config.dist %>', '<%= config.dist %>/images'] }, html: ['<%= config.dist %>/{,*/}*.html'], css: ['<%= config.dist %>/styles/{,*/}*.css'] }, // The following *-min tasks produce minified files in the dist folder imagemin: { dist: { files: [{ expand: true, cwd: '<%= config.app %>/images', src: '{,*/}*.{gif,jpeg,jpg,png}', dest: '<%= config.dist %>/images' }] } }, svgmin: { dist: { files: [{ expand: true, cwd: '<%= config.app %>/images', src: '{,*/}*.svg', dest: '<%= config.dist %>/images' }] } }, htmlmin: { dist: { options: { collapseBooleanAttributes: true, collapseWhitespace: true, removeAttributeQuotes: true, removeCommentsFromCDATA: true, removeEmptyAttributes: true, removeOptionalTags: true, removeRedundantAttributes: true, useShortDoctype: true }, files: [{ expand: true, cwd: '<%= config.dist %>', src: '{,*/}*.html', dest: '<%= config.dist %>' }] } }, // By default, your `index.html`'s will take care of // minification. These next options are pre-configured if you do not wish // to use the Usemin blocks. // cssmin: { // dist: { // files: { // '<%= config.dist %>/styles/main.css': [ // '.tmp/styles/{,*/}*.css', // '<%= config.app %>/styles/{,*/}*.css' // ] // } // } // }, // uglify: { // dist: { // files: { // '<%= config.dist %>/scripts/scripts.js': [ // '<%= config.dist %>/scripts/scripts.js' // ] // } // } // }, // concat: { // dist: {} // }, // Copies remaining files to places other tasks can use copy: { dist: { files: [{ expand: true, dot: true, cwd: '<%= config.app %>', dest: '<%= config.dist %>', src: [ '*.{ico,png,txt}', '.htaccess', 'images/{,*/}*.webp', '{,*/}*.html', 'styles/fonts/{,*/}*.*' ] }] }, styles: { expand: true, dot: true, cwd: '<%= config.app %>/styles', dest: '.tmp/styles/', src: '{,*/}*.css' } }, // Generates a custom Modernizr build that includes only the tests you // reference in your app modernizr: { devFile: '<%= config.app %>/bower_components/modernizr/modernizr.js', outputFile: '<%= config.dist %>/scripts/vendor/modernizr.js', files: [ '<%= config.dist %>/scripts/{,*/}*.js', '<%= config.dist %>/styles/{,*/}*.css', '!<%= config.dist %>/scripts/vendor/*' ], uglify: true }, // Run some tasks in parallel to speed up build process concurrent: { server: [ 'compass:server', 'copy:styles' ], test: [ 'copy:styles' ], dist: [ 'compass', 'copy:styles', 'imagemin', 'svgmin' ] } }); grunt.registerTask('serve', function (target) { if (target === 'dist') { return grunt.task.run(['build', 'connect:dist:keepalive']); } grunt.task.run([ 'clean:server', 'concurrent:server', 'autoprefixer', 'connect:livereload', 'watch' ]); }); grunt.registerTask('server', function (target) { grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.'); grunt.task.run([target ? ('serve:' + target) : 'serve']); }); grunt.registerTask('test', function (target) { if (target !== 'watch') { grunt.task.run([ 'clean:server', 'concurrent:test', 'autoprefixer' ]); } grunt.task.run([ 'connect:test', 'mocha' ]); }); grunt.registerTask('build', [ 'clean:dist', 'useminPrepare', 'concurrent:dist', 'autoprefixer', 'concat', 'cssmin', 'uglify', 'copy:dist', 'modernizr', 'rev', 'usemin', 'htmlmin' ]); grunt.registerTask('default', [ 'newer:jshint', 'test', 'build' ]); }; ================================================ FILE: README.md ================================================ 100day-canvas-bootcamp-training =============================== ### PROJECT URL: [http://codepen.io/kenjiSpecial/](http://codepen.io/kenjiSpecial/) ![Image of project](https://raw.githubusercontent.com/kenjiSpecial/100day-canvas-bootcamp-training/master/images/screen01.png) This is my project for create one canvas animation work until I finish 100 work. All codes for js which are for animation works are at app/script. Hopefuly I want to create a small work every day, but sometime it takes a few day to make it. ## Demos and Codes. ### common file: html : [index.html](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/index.html) | scss : [main.scss](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/styles/main.scss) ### Day 1 - Day 10 - Day1. [rect animation](http://codepen.io/kenjiSpecial/pen/phiBu) | [ js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/1-squash.js) - Day2. [squash & strech](http://codepen.io/kenjiSpecial/pen/hjsdG)| [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/2-squash.js) - Day3. [squash & stretch + staging](http://codepen.io/kenjiSpecial/pen/Bapfi) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/3-stage.js) - Day4. [squash & stretch + anticipation](http://codepen.io/kenjiSpecial/pen/uidbC) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/4-anticipation.js) - Day5. [Pose to Pose.](http://codepen.io/kenjiSpecial/pen/tfnEh) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/5-pose-to-pos.js) - Day6. [Pose to Pose.](http://codepen.io/kenjiSpecial/pen/wIhqf) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/6-pose-to-pos.js) - Day7. [Pose to Pose.](http://codepen.io/kenjiSpecial/pen/yiBJw) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/7-pose-to-pose.js) - Day8. [just skect it.](http://codepen.io/kenjiSpecial/pen/hiLfs) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/8-arcs.js) - Day9. [arc](http://codepen.io/kenjiSpecial/pen/Frazi) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/9-arcs.js) - Day10. [Just sketch.](http://codepen.io/kenjiSpecial/pen/ghfwL) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/10-animation.js) ### Day 11 - Day 20 - Day11. [animation](http://codepen.io/kenjiSpecial/pen/xEIwr) | [js code](http://codepen.io/kenjiSpecial/pen/xEIwr) - Day12. [animation](http://codepen.io/kenjiSpecial/pen/chGgL) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/12-secondary-action.js) - Day13. [secondary action](http://codepen.io/kenjiSpecial/pen/eyCkt) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/13-secondary-action.js) - Day14. [undefined](http://codepen.io/kenjiSpecial/pen/nxKhm) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/14-undefined.js) - Day15. [undefined](http://codepen.io/kenjiSpecial/pen/qfLdD) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/15-undefined.js) - Day16. [June 2?](http://codepen.io/kenjiSpecial/pen/uIjnH) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/16-undefined.js) - Day17. [undefined](http://codepen.io/kenjiSpecial/pen/zxqDv) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/17-undefined.js) - Day18. [undefined](http://codepen.io/kenjiSpecial/pen/dvHIq) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/18-undefined.js) - Day19. [undefined](http://codepen.io/kenjiSpecial/pen/vDfKi) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/19-undefined.js) - Day20. [undefined](http://codepen.io/kenjiSpecial/pen/tnmCc) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/20-undefined.js) ### Day 21 - Day 30 - Day21. [undefined](http://codepen.io/kenjiSpecial/pen/dkLho) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/21-undefined.js) - Day22. [undefined](http://codepen.io/kenjiSpecial/pen/zsGrB) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/22-undefined.js) - Day23. [undefined](http://codepen.io/kenjiSpecial/pen/BGhrm) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/22-undefined.js) - Day24. [undefined](http://codepen.io/kenjiSpecial/pen/aIhmB) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/1-illusion-of-life/23-undefined.js) - Day25. [undefined](http://codepen.io/kenjiSpecial/pen/kCoEq) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/2-numbers/24-number0.js) - Day26. [undefined](http://codepen.io/kenjiSpecial/pen/ysChe) - Day27. [undefined](http://codepen.io/kenjiSpecial/pen/dwypc) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/99-hobby/26-undefined.js) - Day28. [undefined](http://codepen.io/kenjiSpecial/pen/yLFwi) - Day29. [Combination](http://codepen.io/kenjiSpecial/pen/qsipv) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/99-hobby/28-02-combination.js) - Day30. [boid animation](http://codepen.io/kenjiSpecial/pen/efgzI) | js code ### Day 31 - Day 40 - Day31. [Move Mouse](http://codepen.io/kenjiSpecial/pen/AJxDc) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/99-hobby/30-mouse-boid.js) - Day32. [Colorful boids.](http://codepen.io/kenjiSpecial/pen/DerBc) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/99-hobby/32-boid-collection.js) - Day33. [undefined](http://codepen.io/kenjiSpecial/pen/atAoE) | [js code](https://github.com/kenjiSpecial/100day-canvas-bootcamp-training/blob/master/app/scripts/3-algorithm/35-undefined.js) - Day34. [undefined](http://codepen.io/kenjiSpecial/pen/qBbEv) - Day35. [undefined](http://codepen.io/kenjiSpecial/pen/ulBCG) - Day35. [undefined](http://codepen.io/kenjiSpecial/pen/bzGkJ) - Day36. [undefined](http://codepen.io/kenjiSpecial/pen/vrfuJ) - Day37. [undefined](http://codepen.io/kenjiSpecial/pen/qimgz) - Day38. [Loop](http://codepen.io/kenjiSpecial/pen/vIHFG) - Day39. [Loop](http://codepen.io/kenjiSpecial/pen/FlcaB) - Day40. [Loop](http://codepen.io/kenjiSpecial/pen/enrbq) ### Day 41 - Day 50 - Day41. [Loop](http://codepen.io/kenjiSpecial/pen/agGIs) - Day42. [Loop](http://codepen.io/kenjiSpecial/pen/AwJjt) - Day43. [Loop](http://codepen.io/kenjiSpecial/pen/saAjL) - Day44. [Clock with gray scott model.](http://codepen.io/kenjiSpecial/pen/AExmF) - Day45. [Loop](http://codepen.io/kenjiSpecial/pen/DpCjF) - Day46. [undefined](http://codepen.io/kenjiSpecial/pen/FpvCj) - Day47. [Clock with shader](http://codepen.io/kenjiSpecial/pen/IFCzK) - Day48. [undefined](http://codepen.io/kenjiSpecial/pen/pwIdm) - Day49. [Typography Animation.](http://codepen.io/kenjiSpecial/pen/JqGdE) - Day50. [awwwards logo animation.](http://codepen.io/kenjiSpecial/pen/GsLwn) ### Day 51 - Day 60 - Day51. [Color](http://codepen.io/kenjiSpecial/pen/azOXEa) - Day52. [Image Slider](http://codepen.io/kenjiSpecial/pen/EaVxdx) - Day53. [Image Gallery.](http://codepen.io/kenjiSpecial/pen/YPyyVq) - Day54. [WebGL Particle Animation.](http://codepen.io/kenjiSpecial/pen/vELOrM) - Day55. [WebGL Particle Animation#2.](http://codepen.io/kenjiSpecial/pen/yyeaKm) - Day56. [WebGL Particle Animation#3.](http://codepen.io/kenjiSpecial/pen/zxrRZz) - Day57. [Hello with three.js.](http://codepen.io/kenjiSpecial/pen/jEWorO) - Day58. [Particle Clock.](http://codepen.io/kenjiSpecial/pen/gbrvpK) - Day59. [WebGL Particle Animation#4.](http://codepen.io/kenjiSpecial/pen/EaKLyB) - Day60. [WebGL Animation.](http://codepen.io/kenjiSpecial/pen/WbwJZy) ### Day 60 - Day 70 - Day61. [Particle Animation](http://codepen.io/kenjiSpecial/pen/ogzdxO) - Day62. [Shader experience](http://codepen.io/kenjiSpecial/pen/ByWxGy) - Day63. [Shader experience](http://codepen.io/kenjiSpecial/pen/YPyyVq) #### Referrence - [http://the12principles.tumblr.com/](http://the12principles.tumblr.com/) - [http://fyprocessing.tumblr.com/](http://fyprocessing.tumblr.com/) - [http://centolodigiani.tumblr.com/](http://centolodigiani.tumblr.com/) - [http://beesandbombs.tumblr.com/](http://beesandbombs.tumblr.com/) - [https://github.com/edankwan/PerspectiveTransform.js](https://github.com/edankwan/PerspectiveTransform.js) ##### WEBGL - [https://github.com/tombye/3d-testground](https://github.com/tombye/3d-testground) - [https://github.com/mrdoob/webgl-blendfunctions](https://github.com/mrdoob/webgl-blendfunctions) - [https://github.com/KhronosGroup/WebGL](https://github.com/KhronosGroup/WebGL) - [https://github.com/greggman/webgl-fundamentals](https://github.com/greggman/webgl-fundamentals) - [http://www.rozengain.com/blog/2010/02/22/beginning-webgl-step-by-step-tutorial/](http://www.rozengain.com/blog/2010/02/22/beginning-webgl-step-by-step-tutorial/) ================================================ FILE: app/.htaccess ================================================ # Apache Server Configs v2.2.0 | MIT License # https://github.com/h5bp/server-configs-apache # (!) Using `.htaccess` files slows down Apache, therefore, if you have access # to the main server config file (usually called `httpd.conf`), you should add # this logic there: http://httpd.apache.org/docs/current/howto/htaccess.html. # ############################################################################## # # CROSS-ORIGIN RESOURCE SHARING (CORS) # # ############################################################################## # ------------------------------------------------------------------------------ # | Cross-domain AJAX requests | # ------------------------------------------------------------------------------ # Allow cross-origin AJAX requests. # http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity # http://enable-cors.org/ # # Header set Access-Control-Allow-Origin "*" # # ------------------------------------------------------------------------------ # | CORS-enabled images | # ------------------------------------------------------------------------------ # Send the CORS header for images when browsers request it. # https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image # http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html # http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/ SetEnvIf Origin ":" IS_CORS Header set Access-Control-Allow-Origin "*" env=IS_CORS # ------------------------------------------------------------------------------ # | Web fonts access | # ------------------------------------------------------------------------------ # Allow access to web fonts from all domains. Header set Access-Control-Allow-Origin "*" # ############################################################################## # # ERRORS # # ############################################################################## # ------------------------------------------------------------------------------ # | 404 error prevention for non-existing redirected folders | # ------------------------------------------------------------------------------ # Prevent Apache from returning a 404 error as the result of a rewrite # when the directory with the same name does not exist. # http://httpd.apache.org/docs/current/content-negotiation.html#multiviews # http://www.webmasterworld.com/apache/3808792.htm Options -MultiViews # ------------------------------------------------------------------------------ # | Custom error messages / pages | # ------------------------------------------------------------------------------ # Customize what Apache returns to the client in case of an error. # http://httpd.apache.org/docs/current/mod/core.html#errordocument ErrorDocument 404 /404.html # ############################################################################## # # INTERNET EXPLORER # # ############################################################################## # ------------------------------------------------------------------------------ # | Better website experience | # ------------------------------------------------------------------------------ # Force Internet Explorer to render pages in the highest available mode # in the various cases when it may not. # http://hsivonen.iki.fi/doctype/ie-mode.pdf Header set X-UA-Compatible "IE=edge" # `mod_headers` cannot match based on the content-type, however, this # header should be send only for HTML pages and not for the other resources Header unset X-UA-Compatible # ------------------------------------------------------------------------------ # | Cookie setting from iframes | # ------------------------------------------------------------------------------ # Allow cookies to be set from iframes in Internet Explorer. # http://msdn.microsoft.com/en-us/library/ms537343.aspx # http://www.w3.org/TR/2000/CR-P3P-20001215/ # # Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"" # # ############################################################################## # # MIME TYPES AND ENCODING # # ############################################################################## # ------------------------------------------------------------------------------ # | Proper MIME types for all files | # ------------------------------------------------------------------------------ # Audio AddType audio/mp4 m4a f4a f4b AddType audio/ogg oga ogg opus # Data interchange AddType application/json json map AddType application/ld+json jsonld # JavaScript # Normalize to standard type. # http://tools.ietf.org/html/rfc4329#section-7.2 AddType application/javascript js # Video AddType video/mp4 f4v f4p m4v mp4 AddType video/ogg ogv AddType video/webm webm AddType video/x-flv flv # Web fonts AddType application/font-woff woff AddType application/vnd.ms-fontobject eot # Browsers usually ignore the font MIME types and simply sniff the bytes # to figure out the font type. # http://mimesniff.spec.whatwg.org/#matching-a-font-type-pattern # Chrome however, shows a warning if any other MIME types are used for # the following fonts. AddType application/x-font-ttf ttc ttf AddType font/opentype otf # Make SVGZ fonts work on the iPad. # https://twitter.com/FontSquirrel/status/14855840545 AddType image/svg+xml svgz AddEncoding gzip svgz # Other AddType application/octet-stream safariextz AddType application/x-chrome-extension crx AddType application/x-opera-extension oex AddType application/x-web-app-manifest+json webapp AddType application/x-xpinstall xpi AddType application/xml atom rdf rss xml AddType image/webp webp AddType image/x-icon cur AddType text/cache-manifest appcache manifest AddType text/vtt vtt AddType text/x-component htc AddType text/x-vcard vcf # ------------------------------------------------------------------------------ # | UTF-8 encoding | # ------------------------------------------------------------------------------ # Use UTF-8 encoding for anything served as `text/html` or `text/plain`. AddDefaultCharset utf-8 # Force UTF-8 for certain file formats. AddCharset utf-8 .atom .css .js .json .jsonld .rss .vtt .webapp .xml # ############################################################################## # # URL REWRITES # # ############################################################################## # ------------------------------------------------------------------------------ # | Rewrite engine | # ------------------------------------------------------------------------------ # Turn on the rewrite engine and enable the `FollowSymLinks` option (this is # necessary in order for the following directives to work). # If your web host doesn't allow the `FollowSymlinks` option, you may need to # comment it out and use `Options +SymLinksIfOwnerMatch`, but be aware of the # performance impact. # http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks # Also, some cloud hosting services require `RewriteBase` to be set. # http://www.rackspace.com/knowledge_center/frequently-asked-question/why-is-mod-rewrite-not-working-on-my-site Options +FollowSymlinks # Options +SymLinksIfOwnerMatch RewriteEngine On # RewriteBase / # ------------------------------------------------------------------------------ # | Suppressing / Forcing the `www.` at the beginning of URLs | # ------------------------------------------------------------------------------ # The same content should never be available under two different URLs, # especially not with and without `www.` at the beginning. This can cause # SEO problems (duplicate content), and therefore, you should choose one # of the alternatives and redirect the other one. # By default `Option 1` (no `www.`) is activated. # http://no-www.org/faq.php?q=class_b # If you would prefer to use `Option 2`, just comment out all the lines # from `Option 1` and uncomment the ones from `Option 2`. # IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME! # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Option 1: rewrite www.example.com → example.com RewriteCond %{HTTPS} !=on RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Option 2: rewrite example.com → www.example.com # Be aware that the following might not be a good idea if you use "real" # subdomains for certain parts of your website. # # RewriteCond %{HTTPS} !=on # RewriteCond %{HTTP_HOST} !^www\. [NC] # RewriteCond %{SERVER_ADDR} !=127.0.0.1 # RewriteCond %{SERVER_ADDR} !=::1 # RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] # # ############################################################################## # # SECURITY # # ############################################################################## # ------------------------------------------------------------------------------ # | Clickjacking | # ------------------------------------------------------------------------------ # Protect website against clickjacking. # The example below sends the `X-Frame-Options` response header with the value # `DENY`, informing browsers not to display the web page content in any frame. # This might not be the best setting for everyone. You should read about the # other two possible values for `X-Frame-Options`: `SAMEORIGIN` & `ALLOW-FROM`. # http://tools.ietf.org/html/rfc7034#section-2.1 # Keep in mind that while you could send the `X-Frame-Options` header for all # of your site’s pages, this has the potential downside that it forbids even # non-malicious framing of your content (e.g.: when users visit your site using # a Google Image Search results page). # Nonetheless, you should ensure that you send the `X-Frame-Options` header for # all pages that allow a user to make a state changing operation (e.g: pages # that contain one-click purchase links, checkout or bank-transfer confirmation # pages, pages that make permanent configuration changes, etc.). # Sending the `X-Frame-Options` header can also protect your website against # more than just clickjacking attacks: https://cure53.de/xfo-clickjacking.pdf. # http://tools.ietf.org/html/rfc7034 # http://blogs.msdn.com/b/ieinternals/archive/2010/03/30/combating-clickjacking-with-x-frame-options.aspx # https://www.owasp.org/index.php/Clickjacking # # Header set X-Frame-Options "DENY" # # Header unset X-Frame-Options # # # ------------------------------------------------------------------------------ # | Content Security Policy (CSP) | # ------------------------------------------------------------------------------ # Mitigate the risk of cross-site scripting and other content-injection attacks. # This can be done by setting a `Content Security Policy` which whitelists # trusted sources of content for your website. # The example header below allows ONLY scripts that are loaded from the current # site's origin (no inline scripts, no CDN, etc). This almost certainly won't # work as-is for your site! # For more details on how to craft a reasonable policy for your site, read: # http://html5rocks.com/en/tutorials/security/content-security-policy (or the # specification: http://w3.org/TR/CSP). Also, to make things easier, you can # use an online CSP header generator such as: http://cspisawesome.com/. # # Header set Content-Security-Policy "script-src 'self'; object-src 'self'" # # Header unset Content-Security-Policy # # # ------------------------------------------------------------------------------ # | File access | # ------------------------------------------------------------------------------ # Block access to directories without a default document. # You should leave the following uncommented, as you shouldn't allow anyone to # surf through every directory on your server (which may includes rather private # places such as the CMS's directories). Options -Indexes # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Block access to hidden files and directories. # This includes directories used by version control systems such as Git and SVN. RewriteCond %{SCRIPT_FILENAME} -d [OR] RewriteCond %{SCRIPT_FILENAME} -f RewriteRule "(^|/)\." - [F] # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Block access to files that can expose sensitive information. # By default, block access to backup and source files that may be left by some # text editors and can pose a security risk when anyone has access to them. # http://feross.org/cmsploit/ # IMPORTANT: Update the `` regular expression from below to include # any files that might end up on your production server and can expose sensitive # information about your website. These files may include: configuration files, # files that contain metadata about the project (e.g.: project dependencies), # build scripts, etc.. # Apache < 2.3 Order allow,deny Deny from all Satisfy All # Apache ≥ 2.3 Require all denied # ------------------------------------------------------------------------------ # | Reducing MIME-type security risks | # ------------------------------------------------------------------------------ # Prevent some browsers from MIME-sniffing the response. # This reduces exposure to drive-by download attacks and should be enable # especially if the web server is serving user uploaded content, content # that could potentially be treated by the browser as executable. # http://blogs.msdn.com/b/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx # http://msdn.microsoft.com/en-us/library/ie/gg622941.aspx # http://mimesniff.spec.whatwg.org/ # # Header set X-Content-Type-Options "nosniff" # # ------------------------------------------------------------------------------ # | Reflected Cross-Site Scripting (XSS) attacks | # ------------------------------------------------------------------------------ # (1) Try to re-enable the Cross-Site Scripting (XSS) filter built into the # most recent web browsers. # # The filter is usually enabled by default, but in some cases it may be # disabled by the user. However, in Internet Explorer for example, it can # be re-enabled just by sending the `X-XSS-Protection` header with the # value of `1`. # # (2) Prevent web browsers from rendering the web page if a potential reflected # (a.k.a non-persistent) XSS attack is detected by the filter. # # By default, if the filter is enabled and browsers detect a reflected # XSS attack, they will attempt to block the attack by making the smallest # possible modifications to the returned web page. # # Unfortunately, in some browsers (e.g.: Internet Explorer), this default # behavior may allow the XSS filter to be exploited, thereby, it's better # to tell browsers to prevent the rendering of the page altogether, instead # of attempting to modify it. # # http://hackademix.net/2009/11/21/ies-xss-filter-creates-xss-vulnerabilities # # IMPORTANT: Do not rely on the XSS filter to prevent XSS attacks! Ensure that # you are taking all possible measures to prevent XSS attacks, the most obvious # being: validating and sanitizing your site's inputs. # # http://blogs.msdn.com/b/ie/archive/2008/07/02/ie8-security-part-iv-the-xss-filter.aspx # http://blogs.msdn.com/b/ieinternals/archive/2011/01/31/controlling-the-internet-explorer-xss-filter-with-the-x-xss-protection-http-header.aspx # https://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29 # # # (1) (2) # Header set X-XSS-Protection "1; mode=block" # # Header unset X-XSS-Protection # # # ------------------------------------------------------------------------------ # | Secure Sockets Layer (SSL) | # ------------------------------------------------------------------------------ # Rewrite secure requests properly in order to prevent SSL certificate warnings. # E.g.: prevent `https://www.example.com` when your certificate only allows # `https://secure.example.com`. # # RewriteCond %{SERVER_PORT} !^443 # RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L] # # ------------------------------------------------------------------------------ # | HTTP Strict Transport Security (HSTS) | # ------------------------------------------------------------------------------ # Force client-side SSL redirection. # If a user types `example.com` in his browser, the above rule will redirect # him to the secure version of the site. That still leaves a window of # opportunity (the initial HTTP connection) for an attacker to downgrade or # redirect the request. # The following header ensures that browser will ONLY connect to your server # via HTTPS, regardless of what the users type in the address bar. # http://tools.ietf.org/html/draft-ietf-websec-strict-transport-sec-14#section-6.1 # http://www.html5rocks.com/en/tutorials/security/transport-layer-security/ # IMPORTANT: Remove the `includeSubDomains` optional directive if the subdomains # are not using HTTPS. # # Header set Strict-Transport-Security "max-age=16070400; includeSubDomains" # # ------------------------------------------------------------------------------ # | Server software information | # ------------------------------------------------------------------------------ # Avoid displaying the exact Apache version number, the description of the # generic OS-type and the information about Apache's compiled-in modules. # ADD THIS DIRECTIVE IN THE `httpd.conf` AS IT WILL NOT WORK IN THE `.htaccess`! # ServerTokens Prod # ############################################################################## # # WEB PERFORMANCE # # ############################################################################## # ------------------------------------------------------------------------------ # | Compression | # ------------------------------------------------------------------------------ # Force compression for mangled headers. # http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding # Compress all output labeled with one of the following MIME-types # (for Apache versions below 2.3.7, you don't need to enable `mod_filter` # and can remove the `` and `` lines # as `AddOutputFilterByType` is still in the core directives). AddOutputFilterByType DEFLATE application/atom+xml \ application/javascript \ application/json \ application/ld+json \ application/rss+xml \ application/vnd.ms-fontobject \ application/x-font-ttf \ application/x-web-app-manifest+json \ application/xhtml+xml \ application/xml \ font/opentype \ image/svg+xml \ image/x-icon \ text/css \ text/html \ text/plain \ text/x-component \ text/xml # ------------------------------------------------------------------------------ # | Content transformations | # ------------------------------------------------------------------------------ # Prevent mobile network providers from modifying the website's content. # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5. # # Header set Cache-Control "no-transform" # # ------------------------------------------------------------------------------ # | ETags | # ------------------------------------------------------------------------------ # Remove `ETags` as resources are sent with far-future expires headers. # http://developer.yahoo.com/performance/rules.html#etags. # `FileETag None` doesn't work in all cases. Header unset ETag FileETag None # ------------------------------------------------------------------------------ # | Expires headers | # ------------------------------------------------------------------------------ # The following expires headers are set pretty far in the future. If you # don't control versioning with filename-based cache busting, consider # lowering the cache time for resources such as style sheets and JavaScript # files to something like one week. ExpiresActive on ExpiresDefault "access plus 1 month" # CSS ExpiresByType text/css "access plus 1 year" # Data interchange ExpiresByType application/json "access plus 0 seconds" ExpiresByType application/ld+json "access plus 0 seconds" ExpiresByType application/xml "access plus 0 seconds" ExpiresByType text/xml "access plus 0 seconds" # Favicon (cannot be renamed!) and cursor images ExpiresByType image/x-icon "access plus 1 week" # HTML components (HTCs) ExpiresByType text/x-component "access plus 1 month" # HTML ExpiresByType text/html "access plus 0 seconds" # JavaScript ExpiresByType application/javascript "access plus 1 year" # Manifest files ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds" ExpiresByType text/cache-manifest "access plus 0 seconds" # Media ExpiresByType audio/ogg "access plus 1 month" ExpiresByType image/gif "access plus 1 month" ExpiresByType image/jpeg "access plus 1 month" ExpiresByType image/png "access plus 1 month" ExpiresByType video/mp4 "access plus 1 month" ExpiresByType video/ogg "access plus 1 month" ExpiresByType video/webm "access plus 1 month" # Web feeds ExpiresByType application/atom+xml "access plus 1 hour" ExpiresByType application/rss+xml "access plus 1 hour" # Web fonts ExpiresByType application/font-woff "access plus 1 month" ExpiresByType application/vnd.ms-fontobject "access plus 1 month" ExpiresByType application/x-font-ttf "access plus 1 month" ExpiresByType font/opentype "access plus 1 month" ExpiresByType image/svg+xml "access plus 1 month" # ------------------------------------------------------------------------------ # | Filename-based cache busting | # ------------------------------------------------------------------------------ # If you're not using a build process to manage your filename version revving, # you might want to consider enabling the following directives to route all # requests such as `/css/style.12345.css` to `/css/style.css`. # To understand why this is important and a better idea than `*.css?v231`, read: # http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring # # RewriteCond %{REQUEST_FILENAME} !-f # RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpe?g|gif)$ $1.$3 [L] # # ------------------------------------------------------------------------------ # | File concatenation | # ------------------------------------------------------------------------------ # Allow concatenation from within specific style sheets and JavaScript files. # e.g.: # # If you have the following content in a file # # # # # Apache will replace it with the content from the specified files. # # # Options +Includes # AddOutputFilterByType INCLUDES application/javascript application/json # SetOutputFilter INCLUDES # # # Options +Includes # AddOutputFilterByType INCLUDES text/css # SetOutputFilter INCLUDES # # ================================================ FILE: app/404.html ================================================ Page Not Found :(

Not found :(

Sorry, but the page you were trying to view does not exist.

It looks like this was the result of either:

================================================ FILE: app/gl-html/gl00.html ================================================ ================================================ FILE: app/gl-html/gl01.html ================================================ ================================================ FILE: app/gl-html/gl57.html ================================================ ================================================ FILE: app/gl-html/three58.html ================================================ == three58 == ================================================ FILE: app/gl-html/three64.html ================================================ Three.js ================================================ FILE: app/gl-index.html ================================================ WebGL TEST ================================================ FILE: app/index.html ================================================ 201405 ================================================ FILE: app/json/awwwrd.js ================================================ var l1Pt0 = [ [0.6905, 0.534], [0.648, 0.534], [0.638, 0.565], [0.6154999999999999, 0.565], [0.6579999999999999, 0.4445], [0.6809999999999999, 0.4445], [0.7234999999999999, 0.565], [0.701, 0.565], [0.6905, 0.534] ] ; var l1Pt1 = [ [0.6695, 0.46549999999999997], [0.6695, 0.46549999999999997, 0.667, 0.4775,0.6645, 0.484], [0.654, 0.5165], [0.6855000000000001, 0.5165], [0.6750000000000002, 0.484], [0.6725, 0.4775, 0.6695, 0.46549999999999997,0.6695, 0.46549999999999997], [0.6695, 0.46549999999999997] ]; var l2Pt0 = [ [0.7559999999999999, 0.4445], [0.795, 0.4445], [0.8079999999999999, 0.4445, 0.8140000000000001, 0.44550000000000006,0.8195, 0.44800000000000006], [0.8315, 0.4535, 0.8390000000000001, 0.4650000000000001,0.8390000000000001, 0.48100000000000004], [0.8390000000000001, 0.49550000000000005, 0.8315, 0.509,0.8185000000000001, 0.514], [0.8185000000000001, 0.5145], [0.8185000000000001, 0.5145, 0.8200000000000002, 0.5159999999999999,0.8225000000000001, 0.5205], [0.8475000000000001, 0.5655], [0.8230000000000001, 0.5655], [0.799, 0.5205], [0.7780000000000001, 0.5205], [0.7780000000000001, 0.5655], [0.7560000000000001, 0.5655], [0.7559999999999999, 0.4445], [0.7559999999999999, 0.4445] ]; var l2Pt1 = [ [0.7975, 0.501], [0.809, 0.501, 0.8165, 0.494,0.8165, 0.48200000000000004], [0.8165, 0.47050000000000003, 0.8115000000000001, 0.4635,0.7945, 0.4635], [0.778, 0.4635], [0.778, 0.501], [0.7975, 0.501], [0.7975, 0.501] ] ; var l3Pt0 = [ [0.885, 0.4445], [0.9259999999999999, 0.4445], [0.963, 0.4445, 0.9875, 0.4665000000000001,0.9875, 0.5045000000000001], [0.9875, 0.5425, 0.963, 0.565,0.9259999999999999, 0.565], [0.885, 0.565], [0.885, 0.4445] ] ; var l3Pt1 = [ [0.9245, 0.5465], [0.9490000000000001, 0.5465, 0.9645, 0.5319999999999999,0.9645, 0.505], [0.9645, 0.478, 0.9485000000000001, 0.4635,0.9245, 0.4635], [0.9065000000000001, 0.4635], [0.9065000000000001, 0.5465000000000001], [0.9245, 0.5465000000000001] ]; var l4 = [ [1.0265, 0.534], [1.0265, 0.534, 1.0395, 0.5469999999999999,1.0565, 0.5469999999999999], [1.0655000000000001, 0.5469999999999999, 1.074, 0.5425,1.074, 0.5325], [1.074, 0.5109999999999999, 1.0170000000000001, 0.5145,1.0170000000000001, 0.4774999999999999], [1.0170000000000001, 0.4574999999999999, 1.0345, 0.44249999999999995,1.0575, 0.44249999999999995], [1.0815000000000001, 0.44249999999999995, 1.0935, 0.4554999999999999,1.0935, 0.4554999999999999], [1.0839999999999999, 0.47349999999999987], [1.0839999999999999, 0.47349999999999987, 1.0724999999999998, 0.4629999999999999,1.0574999999999999, 0.4629999999999999], [1.0474999999999999, 0.4629999999999999, 1.0394999999999999, 0.4689999999999999,1.0394999999999999, 0.4774999999999999], [1.0394999999999999, 0.4989999999999999, 1.0964999999999998, 0.49349999999999994,1.0964999999999998, 0.5325], [1.0964999999999998, 0.5514999999999999, 1.0819999999999999, 0.568,1.0565, 0.568], [1.0294999999999999, 0.568, 1.015, 0.5514999999999999,1.015, 0.5514999999999999], [1.0265, 0.534] ]; var l5 = [ [0.4435, 0.4445], [0.4235, 0.528], [0.42200000000000004, 0.535, 0.4215, 0.5405000000000001,0.4215, 0.5405000000000001], [0.42100000000000004, 0.5405000000000001], [0.42100000000000004, 0.5405000000000001, 0.42050000000000004, 0.5345,0.419, 0.528], [0.3975, 0.4445], [0.3785, 0.4445], [0.3565, 0.528], [0.3545, 0.535, 0.3545, 0.5405000000000001,0.3545, 0.5405000000000001], [0.354, 0.5405000000000001], [0.354, 0.5405000000000001, 0.35350000000000004, 0.5345,0.352, 0.528], [0.33799999999999997, 0.4655], [0.3275, 0.511], [0.341, 0.565], [0.3665, 0.565], [0.385, 0.4935], [0.387, 0.48550000000000004, 0.38799999999999996, 0.4775,0.38799999999999996, 0.4775], [0.38849999999999996, 0.4775], [0.38849999999999996, 0.4775, 0.38949999999999996, 0.4855,0.3914999999999999, 0.4935], [0.4099999999999999, 0.565], [0.435, 0.565], [0.466, 0.4445], [0.4435, 0.4445], [0.4435, 0.4445] ]; var l6 = [ [0.5795, 0.4445], [0.5595, 0.528], [0.558, 0.535, 0.5575, 0.5405000000000001,0.5575, 0.5405000000000001], [0.557, 0.5405000000000001], [0.557, 0.5405000000000001, 0.5565000000000001, 0.5345,0.555, 0.528], [0.5335, 0.4445], [0.5145000000000001, 0.4445], [0.4925, 0.528], [0.4905, 0.535, 0.4905, 0.5405000000000001,0.4905, 0.5405000000000001], [0.49, 0.5405000000000001], [0.49, 0.5405000000000001, 0.48950000000000005, 0.5345,0.488, 0.528], [0.474, 0.465], [0.4635, 0.5105], [0.47700000000000004, 0.565], [0.5025, 0.565], [0.521, 0.4935], [0.523, 0.48550000000000004, 0.524, 0.4775,0.524, 0.4775], [0.5245, 0.4775], [0.5245, 0.4775, 0.5255, 0.4855,0.5275, 0.4935], [0.5459999999999999, 0.565], [0.5714999999999999, 0.565], [0.6024999999999999, 0.4445], [0.5795, 0.4445], [0.5795, 0.4445] ]; var l7 = [ [0.13, 0.534], [0.0875, 0.534], [0.0775, 0.565], [0.055, 0.565], [0.0975, 0.4445], [0.12050000000000001, 0.4445], [0.163, 0.565], [0.1405, 0.565], [0.13, 0.534], [0.109, 0.46549999999999997], [0.109, 0.46549999999999997, 0.1065, 0.4775,0.10400000000000001, 0.484], [0.0935, 0.5165], [0.125, 0.5165], [0.11449999999999999, 0.484], [0.11199999999999999, 0.4775, 0.109, 0.46549999999999997,0.109, 0.46549999999999997], [0.109, 0.46549999999999997] ]; var l8 = [ [0.2825, 0.528], [0.2845, 0.535, 0.2845, 0.5405,0.2845, 0.5405], [0.285, 0.5405], [0.285, 0.5405, 0.28550000000000003, 0.5345,0.287, 0.528], [0.307, 0.44449999999999995], [0.3295, 0.44449999999999995], [0.2985, 0.565], [0.273, 0.565], [0.2545, 0.4935], [0.2525, 0.48550000000000004, 0.2515, 0.4775,0.2515, 0.4775], [0.251, 0.4775], [0.251, 0.4775, 0.24999999999999997, 0.4855,0.24799999999999997, 0.4935], [0.22949999999999998, 0.565], [0.204, 0.565], [0.174, 0.4445], [0.19649999999999998, 0.4445], [0.21549999999999997, 0.528], [0.21699999999999997, 0.535, 0.21749999999999997, 0.5405000000000001,0.21749999999999997, 0.5405000000000001], [0.21799999999999997, 0.5405000000000001], [0.21799999999999997, 0.5405000000000001, 0.21849999999999997, 0.5345,0.21999999999999997, 0.528], [0.24199999999999997, 0.4445], [0.26099999999999995, 0.4445], [0.2825, 0.528] ]; ================================================ FILE: app/robots.txt ================================================ # robotstxt.org/ User-agent: * ================================================ FILE: app/scripts/0-components/boilerplate.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ // ================ init(); loop(); function init(){ prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/0-components/output.js ================================================ ================================================ FILE: app/scripts/0-components/path.js ================================================ // ============= function forEach(array, fn){ for(var i = 0; i< array.length; i++){ fn(array[i]); } } // ============= var fs = require('fs'); var thClonedArr = []; var th = "M100,75.603c0,50.12-18.593,77.779-51.246,77.779c-28.794,0-48.302-26.985-48.754-75.739C0,28.216,21.316,1,51.246,1C82.312,1,100,28.668,100,75.603z M19.959,77.874c0,38.322,11.789,60.09,29.93,60.09c20.412,0,30.161-23.809,30.161-61.447c0-36.281-9.296-60.1-29.93-60.1C32.653,16.417,19.959,37.734,19.959,77.874z"; var thArr = th.split(/[A-Z]/); forEach(thArr, function(val){ thClonedArr.push(val); }); // console.log(thClonedArr); // var outputArr = []; outputArr.push([]); forEach(thClonedArr, function(val){ if(val.search(/[a-y]/) > 0){ var count = 0; var textArr = val.split(/[a-y]/); var firstVal; forEach(textArr, function(val){ val = val.replace(/-/g, ',-'); if(count === 0){ outputArr[outputArr.length - 1].push(val); var ptArr = val.split(/,/); firstArr = ptArr; }else{ var ptArr = val.split(/,/); var hosei = ptArr.length % 2; var ptTemArr = []; for(var ii = hosei; ii < ptArr.length; ii+= 2){ var ptX = parseFloat(ptArr[ii + 0]) + parseFloat(firstArr[0]); var ptY = parseFloat(ptArr[ii + 1]) + parseFloat(firstArr[1]); ptTemArr.push(ptX); ptTemArr.push(ptY); } firstArr = [ptArr[ptArr.length - 2], ptArr[ptArr.length - 1]]; var pointText = ""; var pointCnt = 0; forEach( ptTemArr, function(val){ if(pointCnt == 0){ pointText += String(val); }else{ pointText += ',' + String(val); } pointCnt++; }); outputArr[outputArr.length - 1].push(pointText); } count++; }); }else{ if(val.search(/z/) > 0){ var text = val.split(/z/); outputArr[outputArr.length - 1].push(text[0]); outputArr.push([]); }else{ //console.log(val); if(val.length > 0){ outputArr[outputArr.length - 1].push(val); } } } }); console.log(outputArr); var '[[' for(var ii = 0; ii < outputArr.length; ii++){ var pathArr = outputArr[ii]; if(pathArr.length > 0){ for(var j = 0; j } } fs.open('./data.js', 'w', function(err, fd) { if(err) throw err; var buf = new Buffer(thArr); fs.write(fd, buf, 0, buf.length, null, function(err, written, buffer) { if(err) throw err; console.log(err, written, buffer); fs.close(fd, function() { console.log('Done'); }); }); }); ================================================ FILE: app/scripts/1-illusion-of-life/1-squash.js ================================================ function backingScale(context) { if ('devicePixelRatio' in window) { if (window.devicePixelRatio > 1) { return window.devicePixelRatio; } } return 1; } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; var Rect = function( ctx, x, y, wid, hig ){ this.ctx = ctx; this.x = x - wid/2; this.y = y; this.wid = wid; this.hig = hig; this.vel = 100; }; Rect.prototype = { update : function(dt){ this.y += this.vel * dt; }, draw : function(){ this.ctx.beginPath(); this.ctx.fillStyle = '#fff'; this.ctx.fillRect(this.x, this.y, this.wid, this.hig); this.ctx.closePath(); } }; // --------------- var Rect1 = function(ctx, x, y, wid, hig){ Rect.call(this, ctx, x, y, wid, hig); this.vel = 20; this.acl = 100; }; Rect1.prototype = Object.create(Rect.prototype); Rect1.prototype = { update : function(dt){ this.vel += this.acl * dt; Rect.prototype.update.call(this, dt); }, draw : function(){ Rect.prototype.draw.call(this); } }; // --------------- var Rect2 = function(ctx, x, y, wid, hig){ Rect.call(this, ctx, x, y, wid, hig); }; Rect2.prototype = Object.create(Rect.prototype); var width, height, previousTime; var rect, rect1; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var scaleFactor = backingScale(ctx); width = window.innerWidth * scaleFactor; height = window.innerHeight * scaleFactor; canvas.width = width; canvas.height = height; init(); loop(); function init(){ previousTime = +new Date; rect = new Rect( ctx, width/2 - 200, 0, 100, 100); rect1 = new Rect1( ctx, width/2 - 50, 0, 100, 100); } function loop(){ var curTime = +new Date; var dt = (curTime - previousTime) / 1000; this.ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); rect.update(dt); rect.draw(); rect1.update(dt); rect1.draw(); previousTime = curTime; requestAnimationFrame(loop); } ================================================ FILE: app/scripts/1-illusion-of-life/10-animation.js ================================================ function backingScale(context) { if ('devicePixelRatio' in window) { if (window.devicePixelRatio > 1) { return window.devicePixelRatio; } } return 1; } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; var width, height, previousTime; var side1, side2; var side1Wid, side1Hig; var rect; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var scaleFactor = backingScale(ctx); width = window.innerWidth * scaleFactor; height = window.innerHeight * scaleFactor; side1 = 100; side2 = 180; var sideHig = 10 * scaleFactor; var duration1 = .8; var duration2 = .6; canvas.width = width; canvas.height = height; var Rect = function(ctx){ this.ctx = ctx; this.col = '#fff'; this.width = this.baseWidth = 15 * scaleFactor; this.penWidth = 14.5 * scaleFactor; this.height = 100 * scaleFactor; this.pt1 = {x : width / 2, y: height}; this.pt2 = {x : width / 2, y: height - this.height}; this.anchorPt = {x : width /2, y: (this.pt1.y + this.pt2.y) / 2}; this.anchorTheta1 = 0; this.anchorTheta2 = 0; }; Rect.prototype = { div : -2, val : 0, update : function(){ this.anchorTheta1 += 0.1; if(this.pt2.y <= 0){ this.div = 2; } if(this.pt2.y >= height - 100*scaleFactor){ this.div = -2; } this.pt2.y += this.div; this.width = this.baseWidth + this.penWidth * Math.sin(this.anchorTheta1); this.val -= this.div / 2; this.pt2.x = width / 2 - 30 * scaleFactor * Math.cos(this.anchorTheta1); this.anchorPt.x = width / 2 + (50 + this.val) * scaleFactor * Math.cos(this.anchorTheta1); this.anchorPt.y = (this.pt1.y + this.pt2.y) / 2; }, draw : function(){ this.ctx.fillStyle = this.col; this.ctx.beginPath(); this.ctx.moveTo(this.pt1.x - this.width / 2, this.pt1.y); this.ctx.quadraticCurveTo(this.anchorPt.x - this.width / 2, this.anchorPt.y, this.pt2.x - this.width / 2, this.pt2.y); this.ctx.lineTo(this.pt2.x + this.width / 2, this.pt2.y); this.ctx.quadraticCurveTo(this.anchorPt.x + this.width / 2, this.anchorPt.y, this.pt1.x + this.width / 2, this.pt1.y); this.ctx.fill(); this.ctx.closePath(); }, debugDraw : function(){ this.ctx.strokeStyle = this.col; this.ctx.beginPath(); this.ctx.moveTo(this.pt1.x, this.pt1.y); this.ctx.quadraticCurveTo(this.anchorPt.x, this.anchorPt.y, this.pt2.x, this.pt2.y); this.ctx.stroke(); this.ctx.closePath(); } }; var rect; init(); loop(); function init(){ rect = new Rect(ctx); } function loop(){ ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); rect.update(); rect.draw(); requestAnimationFrame(loop); } ================================================ FILE: app/scripts/1-illusion-of-life/11-animation-2.js ================================================ function backingScale(context) { if ('devicePixelRatio' in window) { if (window.devicePixelRatio > 1) { return window.devicePixelRatio; } } return 1; } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; // -------------------------- var Rect = function(ctx, x, y, i){ this.color = '#fff'; this.ctx = ctx; this.side = 200; this.x = this.originX = x - this.side/2; this.y = this.originY = y - this.side/2; if(i % 2 == 0) this.rad = 170; else this.rad = 90; }; Rect.prototype = { sec : 0, rad : 100 + 200 * Math.random(), update : function(){ this.sec += .1; this.x = this.originX + this.rad * Math.cos(this.sec); if(this.x > width) this.x = -this.side; this.ctx.strokeStyle = this.color; this.ctx.strokeRect(this.x, this.y, this.side, this.side); } }; var Point = function(x1, y1, x2, y2){ this.status = 'triangle'; this.point = { 'circle' : {x : x1, y: y1}, 'triangle' : {x : x2, y: y2} }; }; Point.prototype = { get : function(){ return this.point[this.status] } }; var Shape = function(ctx, x, y, rad){ this.ctx = ctx; this.x = x; this.y = y; this.rad = rad; this.pointArr = []; this.num = 120; var triangle = this.num / 3; var circlePtArr = [ {x : this.rad * Math.cos(0), y: this.rad * Math.sin(0) }, {x : this.rad * Math.cos(2/3*Math.PI), y: this.rad * Math.sin(2/3*Math.PI) }, {x : this.rad * Math.cos(4/3*Math.PI), y: this.rad * Math.sin(4/3*Math.PI) } ]; for(var i = 0; i < this.num; i++){ // circle var ptX = this.rad * Math.cos(i / this.num * Math.PI * 2); var ptY = this.rad * Math.sin(i / this.num * Math.PI * 2); // triangle var triangleNum1 = parseInt(i / triangle); var triangleNum2 = (triangleNum1 + 1) % 3; var circleI = i % triangle; var ptTriX = circlePtArr[triangleNum1].x * (1 - circleI / triangle) + circlePtArr[triangleNum2].x * (0 + circleI / triangle); var ptTriY = circlePtArr[triangleNum1].y * (1 - circleI / triangle) + circlePtArr[triangleNum2].y * (0 + circleI / triangle); var pt = new Point(ptX, ptY, ptTriX, ptTriY); this.pointArr[i] = pt; } }; Shape.prototype = { vel:8, update : function(rectArr){ this.x += this.vel; if(this.x > width + 100) this.x = - 100; // update // this.x - this.rad -- this.x + this.rad for(var i = 0; i < this.num; i++){ this.pointArr[i].status = 'circle'; } for(var j = 0; j < rectArr.length; j++){ var rect = rectArr[j]; for(var i = 0; i < this.num; i++){ var ptX = this.pointArr[i]['point']['circle'].x + this.x; if(ptX > (rect.x) && ptX < (rect.x + rect.side) ) this.pointArr[i].status = 'triangle'; //else this.pointArr[i].status = 'circle'; } } // draw this.ctx.save(); this.ctx.beginPath(); this.ctx.translate(this.x, this.y); this.ctx.moveTo(this.pointArr[0].get().x, this.pointArr[0].get().y); for(var i = 1; i < this.num; i++){ this.ctx.lineTo(this.pointArr[i].get().x, this.pointArr[i].get().y); } this.ctx.lineTo(this.pointArr[0].get().x, this.pointArr[0].get().y); this.ctx.fillStyle = '#fff'; this.ctx.stroke(); this.ctx.closePath(); this.ctx.restore(); } }; // -------------------------- var width, height, previousTime; var side1, side2; var side1Wid, side1Hig; var rect, rectArr = []; var shape, shapeArr = []; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var scaleFactor = backingScale(ctx); width = window.innerWidth; height = window.innerHeight; side1 = 100; side2 = 180; var sideHig = 10 * scaleFactor; var duration1 = .8; var duration2 = .6; canvas.width = width; canvas.height = height; init(); loop(); function init(){ for(var i = 0; i < 3; i++){ rect = new Rect(ctx, width/2 + 300 * i - 300, height/2, i); rectArr.push(rect); } for(var i = 0;i < 8; i++){ shape = new Shape(ctx, width/2, height/2, 8 + 12 * i); shapeArr.push(shape); } } function loop(){ //ctx.clearRect(0, 0, width, height); ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); for(var i in rectArr){ rect = rectArr[i]; rect.update(); } //console.log('shape update'); for(var i in shapeArr){ shape = shapeArr[i]; shape.update(rectArr); } //console.log('shape update'); requestAnimationFrame(loop); } ================================================ FILE: app/scripts/1-illusion-of-life/12-secondary-action.js ================================================ window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; // -------------------------- var Pt = function(theta){ this.rad = side; this.theta = theta; }; Pt.prototype = { setTheta : function(val){ this.futureTheta = val; TweenLite.to(this,.5, { theta : val, ease: Power3.easeInOut}); } } Object.defineProperty(Pt.prototype, 'theta', { get : function(){ return this._theta; }, set : function(val){ this._theta = val; this.x = this.rad * Math.cos(this._theta); this.y = this.rad * Math.sin(this._theta); } }); var Shape = function(ctx, x, y){ _.bindAll(this, 'add'); this.x = x; this.y = y; this.ctx = ctx; this.col = '#fff'; this.triArr = []; this.shapeType = { 3 : [[0, 1, 2]], 4 : [[0, 1, 2], [3, 1, 2]] }; for(var i = 0; i < this.triNum; i++){ var pt = new Pt( i / this.triNum * 2 * Math.PI ); this.triArr.push(pt); } setInterval(this.add, 600); }; Shape.prototype = { triNum : 2, inc : 1, theta : 0, add : function(){ // clone pt if(this.triArr.length > 12) this.inc = -1; if(this.triArr.length < 3) this.inc = 1; if(this.inc == 1){ var clonedPt = new Pt(this.triArr[this.triArr.length - 1].theta); this.triArr.push(clonedPt); for(var i in this.triArr){ this.triArr[i].setTheta(2 * Math.PI * i / this.triArr.length); } }else{ for(var i in this.triArr){ this.triArr[i].setTheta(2 * Math.PI * i / (this.triArr.length -1)); } var self = this; setTimeout(function(){ self.triArr.shift(); }, 400 ); } var val = this.theta + 1/3 * Math.PI; TweenLite.to(this,.3, { theta : val}); }, update : function(){ this.ctx.save(); this.ctx.translate(this.x, this.y); this.ctx.rotate(this.theta); this.ctx.strokeStyle = this.col; for(var i in this.triArr){ var pt1 = this.triArr[i] for(var j = i; j < this.triArr.length; j++){ var pt2 = this.triArr[j]; this.ctx.beginPath(); this.ctx.moveTo(pt1.x, pt1.y); this.ctx.lineTo(pt2.x, pt2.y); this.ctx.stroke(); this.ctx.closePath(); } } this.ctx.restore(); } }; // -------------------------- var width, height, previousTime; var side1, side2; var shape; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var side; width = window.innerWidth; height = window.innerHeight; side = Math.min(width, height) * .45; canvas.width = width; canvas.height = height; init(); loop(); function init(){ shape = new Shape(ctx, width/2, height/2); } function loop(){ //ctx.clearRect(0, 0, width, height); ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); shape.update(); requestAnimationFrame(loop); } ================================================ FILE: app/scripts/1-illusion-of-life/13-secondary-action.js ================================================ window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; // -------------------------- var Pt = function(rad, theta){ this.rad = rad; this.theta = theta; }; Pt.prototype = { setTheta : function(val){ this.futureTheta = val; TweenLite.to(this,.5, { theta : val, ease: Elastic.easeInOut}); }, } Object.defineProperty(Pt.prototype, 'theta', { get : function(){ return this._theta; }, set : function(val){ this._theta = val; this.x = this.rad * Math.cos(this._theta); this.y = this.rad * Math.sin(this._theta); } }); var Rect = function(ctx, x, y){ _.bindAll(this, 'rotationComplete'); this.x = this.originX = x; this.y = y; //console.log(this.x, this.y); this.transX = 0; this.side = 60; this.halfSide = this.side / 2 * -1; this.ctx = ctx; this.col = '#fff'; this.rotate = 0; this.thetaArr = [0, Math.PI, Math.PI * 5 / 4, Math.PI * 3 / 2]; this.ptArr =[ new Pt(0, 0), new Pt(this.side, Math.PI), new Pt(this.side * Math.sqrt(2), Math.PI * (5/4)), new Pt(this.side, Math.PI * (3/2)), ]; this.rotation(); }; Rect.prototype = { rotation : function(){ this.rotate = Math.PI/2; for(var i = 0; i < this.ptArr.length; i++){ var pt = this.ptArr[i]; var theta = this.thetaArr[i]; TweenLite.to(pt, 1, { theta : (theta + this.rotate)}); } TweenLite.to(this, 1, { x : (this.originX - 60), onComplete : this.rotationComplete}); }, rotationComplete : function(){ this.ptArr =[ new Pt(0, 0), new Pt(this.side, Math.PI), new Pt(this.side * Math.sqrt(2), Math.PI * (5/4)), new Pt(this.side, Math.PI * (3/2)), ]; this.x = this.originX; this.rotation(); }, update : function(){ this.ctx.save(); this.ctx.translate(this.x + this.side /2, this.y + this.side /2); this.ctx.beginPath(); this.ctx.strokeStyle = this.col; this.ctx.moveTo(this.ptArr[0].x, this.ptArr[0].y); for(var i = 0; i < this.ptArr.length; i++ ){ var number = (i + 1) % this.ptArr.length; this.ctx.lineTo(this.ptArr[number].x, this.ptArr[number].y); } this.ctx.stroke(); this.ctx.closePath(); this.ctx.restore(); } }; var RectTop1 = function(ctx, x, y, rect){ _.bindAll(this, 'rotationComplete'); this.x = this.originX = x; this.y = y; this.side = 60; this.baseRect = rect; this.ctx = ctx; this.col = '#fff'; this.rotate = 0; this.thetaArr = [0, Math.PI * 3 / 2, Math.PI * 7 / 4, Math.PI * 2]; this.ptArr =[ new Pt(0, 0), new Pt(this.side, Math.PI* (3/2)), new Pt(this.side * Math.sqrt(2), Math.PI * (7/4)), new Pt(this.side, Math.PI * 2), ]; this.rotation(); }; RectTop1.prototype = { rotation : function(){ this.rotate = -Math.PI/2; for(var i = 0; i < this.ptArr.length; i++){ var pt = this.ptArr[i]; var theta = this.thetaArr[i]; TweenLite.to(pt, 1, { theta : (theta + this.rotate)}); } TweenLite.to(this, 1, { x : (this.originX ), onComplete : this.rotationComplete}); }, rotationComplete : function(){ this.ptArr =[ new Pt(0, 0), new Pt(this.side, Math.PI* (3/2)), new Pt(this.side * Math.sqrt(2), Math.PI * (7/4)), new Pt(this.side, Math.PI * 2), ]; this.x = this.originX; this.rotation(); }, update : function(){ this.ctx.save(); //this.ctx.translate(this.x + this.baseRect.ptArr[2].x - this.side/2, this.y + this.baseRect.ptArr[2].y + this.side/2); this.x = this.baseRect.x + this.baseRect.ptArr[2].x + this.side / 2; this.y = this.baseRect.y + this.baseRect.ptArr[2].y + this.side/2; this.ctx.translate( this.x, this.y); this.ctx.beginPath(); this.ctx.strokeStyle = this.col; this.ctx.moveTo(this.ptArr[0].x, this.ptArr[0].y); for(var i = 0; i < this.ptArr.length; i++ ){ var number = (i + 1) % this.ptArr.length; this.ctx.lineTo(this.ptArr[number].x, this.ptArr[number].y); } this.ctx.stroke(); this.ctx.closePath(); this.ctx.restore(); } }; var RectTop2 = function(ctx, x, y, rect){ _.bindAll(this, 'rotationComplete'); this.x = this.originX = x; this.y = y; this.side = 60; this.baseRect = rect; this.ctx = ctx; this.col = '#fff'; this.rotate = 0; this.thetaArr = [0, Math.PI, Math.PI * 5 / 4, Math.PI * 3 / 2]; this.ptArr =[ new Pt(0, 0), new Pt(this.side, Math.PI), new Pt(this.side * Math.sqrt(2), Math.PI * (5/4)), new Pt(this.side, Math.PI * (3/2)), ]; this.rotation(); }; RectTop2.prototype = { rotation : function(){ this.rotate = Math.PI/2; for(var i = 0; i < this.ptArr.length; i++){ var pt = this.ptArr[i]; var theta = this.thetaArr[i]; TweenLite.to(pt, 1, { theta : (theta + this.rotate)}); } TweenLite.to(this, 1, { x : (this.originX ), onComplete : this.rotationComplete}); }, rotationComplete : function(){ this.ptArr =[ new Pt(0, 0), new Pt(this.side, Math.PI), new Pt(this.side * Math.sqrt(2), Math.PI * (5/4)), new Pt(this.side, Math.PI * (3/2)), ]; this.x = this.originX; this.rotation(); }, update : function(){ this.ctx.save(); this.x = this.baseRect.x + this.baseRect.ptArr[2].x; this.y = this.baseRect.y + this.baseRect.ptArr[2].y; this.ctx.translate( this.x, this.y ); this.ctx.beginPath(); this.ctx.strokeStyle = this.col; this.ctx.moveTo(this.ptArr[0].x, this.ptArr[0].y); for(var i = 0; i < this.ptArr.length; i++ ){ var number = (i + 1) % this.ptArr.length; this.ctx.lineTo(this.ptArr[number].x, this.ptArr[number].y); } this.ctx.stroke(); this.ctx.closePath(); this.ctx.restore(); } }; var Road = function(ctx, x, y){ var line; var lineWidth = 20; var lineWidthMargin = 10; this.ctx = ctx; this.width = window.innerWidth; this.x = x; this.y = y; this.lineArr = []; this.mask = {x: - this.num /2 * (lineWidth + lineWidthMargin), width: this.num * (lineWidth + lineWidthMargin)} for(var i = 0; i <= this.num; i++){ line = new Line(this.ctx, (lineWidth + lineWidthMargin) * (i - this.num/2), 0, lineWidth, {minX: this.mask.x, maxX: this.mask.x + this.mask.width}) this.lineArr.push(line); } }; Road.prototype = { num : 20, lineArr : null, update : function(){ this.ctx.save(); this.ctx.translate(this.x, this.y); for(var i = 0; i < this.lineArr.length; i++){ this.lineArr[i].update(); } var grd = this.ctx.createLinearGradient(this.mask.x * 2, 0, this.mask.width, 0); grd.addColorStop(0.25, 'rgba(51, 51, 51, 1)'); grd.addColorStop(0.3, 'rgba(51, 51, 51, 0)'); grd.addColorStop(0.5, 'rgba(51, 51, 51, 0)'); grd.addColorStop(0.7, 'rgba(51, 51, 51, 0)'); grd.addColorStop(0.75, 'rgba(51, 51, 51, 1)'); this.ctx.fillStyle = grd; this.ctx.fillRect(-this.x, -15, this.width, 30); this.ctx.restore(); } }; var Line = function(ctx, x, y, width, range){ this.x = x; this.range = range; this.ctx = ctx; this.col = '#fff'; this.width = width; this.prevTime = + new Date; }; Line.prototype = { update : function(){ this.x -= 1; if(this.x < this.range.minX) this.x = this.range.maxX; this.ctx.strokeStyle = this.col; this.ctx.beginPath(); this.ctx.moveTo(this.x - this.width / 2, 0); this.ctx.lineTo(this.x + this.width / 2, 0); this.ctx.stroke(); this.ctx.closePath(); } }; // -------------------------- var width, height, previousTime; var side1, side2; var rect, rectTop1, rectTop2, side, road; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; side = Math.min(width, height) / 8; canvas.width = width; canvas.height = height; init(); loop(); function init(){ rect = new Rect(ctx, width / 2, height *.9); rectTop1 = new RectTop1(ctx, width/2, height*.9, rect); rectTop2 = new RectTop2(ctx, width/2, height*.9, rectTop1); road = new Road(ctx, width/2, height *.9 + 30 + 2); } function loop(){ //ctx.clearRect(0, 0, width, height); ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); rect.update(); rectTop1.update(); rectTop2.update(); road.update(); requestAnimationFrame(loop); } ================================================ FILE: app/scripts/1-illusion-of-life/14-undefined.js ================================================ // -------------------------- var Pt = function(x, y){ this.x = x; this.y = y; }; var Line = function(ctx, pt1, pt2, pt3, pt4, i){ _.bindAll(this, 'changeAnimation1', 'changeAnimation1Complete', 'changeAnimation2', 'changeAnimation2Complete'); this.curPt1 = new Pt(pt1.x, pt1.y); this.curPt2 = new Pt(pt2.x, pt2.y); this.col = 'rgba(255, 255, 255, .3)'; this.ctx = ctx; this.pt1 = pt1; this.pt2 = pt2; this.pt3 = pt3; this.pt4 = pt4; //this.duration = i/ 20 * .3 + .2; this.duration = .5; this.wait = (.8 - this.duration) * 1000; setTimeout(this.changeAnimation1, 500); }; Line.prototype = { changeAnimation1 : function(){ TweenLite.to(this.curPt1, this.duration, { x : (this.pt3.x ), onComplete : this.changeAnimation1Complete, ease: Power3.easeInOut}); TweenLite.to(this.curPt2, this.duration, { y : (this.pt4.y ), ease: Power3.easeInOut}); }, changeAnimation1Complete : function(){ setTimeout(this.changeAnimation2, this.wait); }, changeAnimation2 : function(){ TweenLite.to(this.curPt1, this.duration, { x : (this.pt1.x ), onComplete : this.changeAnimation2Complete, ease: Power3.easeInOut}); TweenLite.to(this.curPt2, this.duration, { y : (this.pt2.y ), ease: Power3.easeInOut}); }, changeAnimation2Complete : function(){ setTimeout(this.changeAnimation1, this.wait); }, update : function(){ this.ctx.strokeStyle = this.col; this.ctx.beginPath(); this.ctx.moveTo(this.curPt1.x, this.curPt1.y); this.ctx.lineTo(this.curPt2.x, this.curPt2.y); this.ctx.stroke(); this.ctx.closePath(); } }; var side = 100; var RightRect = function(ctx, x, y){ var ptX, ptY, pt1, pt2, pt3, pt4 ,line, i; this.ctx = ctx; this.x = x; this.y = y; this.lineArr = []; for(var j = 0; i < 4; i++){ } // --------- for(var i = 0; i < this.num; i++){ ptX = (i) / (this.num-1) * side; ptY = (i) / (this.num-1) * side; pt1 = new Pt( 0, -side); pt2 = new Pt( side, -side); pt3 = new Pt( ptX, -side); pt4 = new Pt( 0, ptY -side); line = new Line(this.ctx, pt1, pt2, pt3, pt4, i); this.lineArr.push(line); } for(var i = 0; i < this.num; i++){ ptX = (i) / (this.num-1) * side; ptY = (i) / (this.num-1) * side; pt1 = new Pt( side, -side); pt2 = new Pt( side, side-side); pt3 = new Pt( ptX, -side); pt4 = new Pt( 0, ptY-side); line = new Line(this.ctx, pt1, pt2, pt3, pt4, i); this.lineArr.push(line); } // --------- for(var i = 0; i < this.num; i++){ ptX = (i) / (this.num-1) * side; ptY = (i) / (this.num-1) * side; pt1 = new Pt( 0, side); pt2 = new Pt( side, side); pt3 = new Pt( ptX, side); pt4 = new Pt( 0, -ptY + side); line = new Line(this.ctx, pt1, pt2, pt3, pt4, i); this.lineArr.push(line); } for(var i = 0; i < this.num; i++){ ptX = (i) / (this.num-1) * side; ptY = (i) / (this.num-1) * side; pt1 = new Pt( side, side); pt2 = new Pt( side, 0); pt3 = new Pt( side - ptX, side); pt4 = new Pt( side, ptY); line = new Line(this.ctx, pt1, pt2, pt3, pt4, i); this.lineArr.push(line); } // --------- for(var i = 0; i < this.num; i++){ ptX = (i) / (this.num-1) * side * -1; ptY = (i) / (this.num-1) * side; pt1 = new Pt( 0, -side); pt2 = new Pt( -side, -side); pt3 = new Pt( ptX, -side); pt4 = new Pt( 0, ptY -side); line = new Line(this.ctx, pt1, pt2, pt3, pt4, i); this.lineArr.push(line); } for(var i = 0; i < this.num; i++){ ptX = (i) / (this.num-1) * side * -1; ptY = (i) / (this.num-1) * side; pt1 = new Pt( -side, -side); pt2 = new Pt( -side, side-side); pt3 = new Pt( ptX, -side); pt4 = new Pt( 0, ptY-side); line = new Line(this.ctx, pt1, pt2, pt3, pt4, i); this.lineArr.push(line); } // ---------- for(var i = 0; i < this.num; i++){ ptX = (i) / (this.num-1) * side * -1; ptY = (i) / (this.num-1) * side; pt1 = new Pt( 0, side); pt2 = new Pt( -side, side); pt3 = new Pt( ptX, side); pt4 = new Pt( 0, -ptY + side); line = new Line(this.ctx, pt1, pt2, pt3, pt4, i); this.lineArr.push(line); } for(var i = 0; i < this.num; i++){ ptX = (i) / (this.num-1) * side; ptY = (i) / (this.num-1) * side; pt1 = new Pt( -side, side); pt2 = new Pt( -side, 0); pt3 = new Pt( ptX - side, side); pt4 = new Pt( 0, ptY); line = new Line(this.ctx, pt1, pt2, pt3, pt4, i); this.lineArr.push(line); } }; RightRect.prototype = { num : 20, update : function(){ this.ctx.save(); this.ctx.translate(this.x, this.y); for(var i = 0; i < this.lineArr.length; i++){ var line = this.lineArr[i]; line.update(); } this.ctx.restore(); } }; // -------------------------- var width, height, previousTime; var side1, side2; var rightRect; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; init(); loop(); function init(){ rightRect = new RightRect( ctx, width/2, height/2 ); } function loop(){ //ctx.clearRect(0, 0, width, height); ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); rightRect.update(); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/1-illusion-of-life/15-undefined.js ================================================ window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; var col = '#fff'; var Circle = function( ctx, x, y, rad ){ this.ctx = ctx; this.x = x; this.y = y; this.rad = rad; }; Circle.prototype = { update : function(){ this.ctx.fillStyle = col; this.ctx.beginPath(); this.ctx.arc(this.x, this.y, this.rad, 0, 2 * Math.PI, false); this.ctx.fill(); this.ctx.closePath(); } }; var DynamicCircle = function(ctx, x, y, rad, dis){ this.shuuki = .3; this.dis = dis; this.vel = dis / this.shuuki; this.duration = 0; this.shinpuku = rad * 3; this.originY = y; Circle.call(this, ctx, x, y, rad/2); }; DynamicCircle.prototype = Object.create(Circle.prototype); DynamicCircle.prototype = { update : function(dt, shapeArr){ this.duration += dt; var times = parseInt(this.duration / (this.shuuki * 2)) this.x = this.x + this.vel * dt; if(this.x >= maxX){ var dis = this.x - maxX; this.x = minX + dis - this.dis; } var globalAlpha = 1; if(this.x >= (maxX-this.dis) ){ globalAlpha = (maxX - this.x )/ this.dis if(globalAlpha < 0) globalAlpha = 0; } this.y = -1 * Math.cos(this.duration / this.shuuki * Math.PI ) * this.shinpuku + this.originY; var circleNumber = (times * 2 + 1) % shapeArr.length; var shapeRatio = (this.duration - times * this.shuuki * 2) * Math.PI * 2; if(shapeRatio > Math.PI) shapeRatio = Math.PI; shapeArr[circleNumber].y = this.rad * 4 *Math.sin(shapeRatio); this.ctx.save(); this.ctx.globalAlpha = globalAlpha; Circle.prototype.update.call(this); this.ctx.restore(); } }; var DynamicCircle2= function(ctx, x, y, rad, dis){ this.shuuki = .3; this.dis = dis; this.vel = -1 * dis / this.shuuki; this.duration = 0; this.shinpuku = rad * 3; this.originY = y; Circle.call(this, ctx, x, y, rad/2); }; DynamicCircle2.prototype = Object.create(Circle.prototype); DynamicCircle2.prototype = { update : function(dt, shapeArr){ this.duration += dt; var times = parseInt(this.duration / (this.shuuki * 2)) this.x = this.x + this.vel * dt; this.y = 1 * Math.cos(this.duration / this.shuuki * Math.PI ) * this.shinpuku + this.originY; // if(this.x >= maxX){ // var dis = this.x - maxX; // this.x = minX + dis - this.dis; // } if(this.x <= minX){ var dis = minX - this.x; this.x = maxX - dis + this.dis; } var globalAlpha = 1; if(this.x <= (minX+this.dis) ){ globalAlpha = (this.x - minX )/ this.dis; if(globalAlpha < 0) globalAlpha = 0; } // // var circleNumber = (times * 2 ) % shapeArr.length; circleNumber = shapeArr.length - 2 - circleNumber; if(circleNumber < 0) circleNumber =shapeArr.length + circleNumber; var shapeRatio = (this.duration - times * this.shuuki * 2) * Math.PI * 2; if(shapeRatio > Math.PI) shapeRatio = Math.PI; shapeArr[circleNumber].y = this.rad * 4 *Math.sin(shapeRatio) * -1; // this.ctx.save(); this.ctx.globalAlpha = globalAlpha; Circle.prototype.update.call(this); this.ctx.restore(); } }; var Rect = function( ctx, x, y, rad ){ this.ctx = ctx; this.x = x; this.y = y; this.rad = rad * 2; }; Rect.prototype = { update : function(){ this.ctx.fillStyle = col; this.ctx.beginPath(); this.ctx.fillRect(this.x - this.rad/2, this.y - this.rad/2, this.rad, this.rad); this.ctx.closePath(); } }; // -------------------------- var width, height, previousTime; var side1, side2; var colNum = 19; var shapeArr = []; var dynamicCircle, dynamicCircle2; var prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; var minX = 1/(colNum + 1) * width - .5*width; var maxX = colNum/(colNum + 1) * width - .5*width; init(); loop(); function init(){ var shape; var xPos; var yPos = 0; var rad = parseInt(width / colNum / 2 * .6); var dis = 1/(colNum+1) * width; var rectX; for(var i = 0; i < colNum; i++){ xPos = ((i + 1) / (colNum + 1) -.5) * width; if(i % 2 == 0) { shape = new Rect(ctx, xPos, yPos, rad ); }else{ shape = new Circle(ctx, xPos, yPos, rad ); } shapeArr.push(shape); } dynamicCircle = new DynamicCircle(ctx, minX, yPos - rad * 3, rad, dis); dynamicCircle2= new DynamicCircle2(ctx, maxX, yPos + rad * 3, rad, dis); prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; //ctx.clearRect(0, 0, width, height); ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); ctx.save(); ctx.translate(width/2, height/2); for(var i in shapeArr){ var shape = shapeArr[i]; shape.update(); } dynamicCircle.update(duration, shapeArr); dynamicCircle2.update(duration, shapeArr); ctx.restore(); requestAnimationFrame(loop); } ================================================ FILE: app/scripts/1-illusion-of-life/16-undefined.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var apple = [ [5, 5, 5, 5, 5, 5, 5, 5, 5, 5 , 4, 3, 2 ,1], [5, 5, 5, 5, 5, 5, 5, 5, 5, 4 , 3, 2, 1], [5, 5, 5, 5, 5, 5, 5, 5, 4, 2 , 1], [5, 5, 5, 5, 5, 5, 5, 5, 3, 1], [5, 5, 5, 5, 5, 5, 5, 4, 2, 1], [5, 5, 5, 5, 5, 5, 5, 3, 2, 1], [5, 5, 5, 5, 5, 5, 5, 3, 2, 1], [5, 5, 5, 5, 5, 5, 5, 3, 2, 1], [5, 5, 5, 5, 5, 5, 5, 3, 2, 1], [5, 5, 5, 5, 5, 5, 5, 3, 2, 1], // ============= =================== [5, 5, 5, 5, 5, 5, 5, 3, 2, 1], [5, 5, 5, 5, 5, 5, 5, 3, 2, 1], [5, 5, 5, 5, 5, 5, 5, 4, 3, 2, 1], [5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 2, 1], [5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 2, 1], [5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 2, 1], [5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 2, 1], [5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 2, 1], [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 1], [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 2, 1], // ============= =================== [5, 4, 3, 3, 3, 3, 3, 4, 5, 5, 4, 3, 2, 1], [4, 3, 2, 2, 2, 2, 2, 3, 4, 5, 4, 3, 2, 1], [2, 1, 0, 0, 0, 1, 2, 3, 4, 5, 4, 3, 2, 1], [0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 4, 3, 2, 1], [0, 0, 0, 0, 0, 1, 3, 4, 4, 5, 4, 2, 1], [0, 0, 0, 0, 0, 2, 3, 4, 5, 4, 3, 1], [0, 0, 0, 0, 0, 2, 3, 4, 5, 4, 3, 1], [0, 0, 0, 0, 1, 2, 4, 5, 5, 4, 3, 1], [0, 0, 0, 1, 3, 4, 5, 5, 4, 3, 1], [0, 0, 1, 3, 4, 5, 5, 5, 4, 3, 1], // ============= =================== [0, 1, 3, 4, 5, 5, 5, 5, 4, 3, 1], [1, 3, 4, 5, 5, 5, 5, 4, 3, 1], [2, 4, 5, 5, 5, 5, 5, 4, 3, 1], [4, 5, 5, 5, 5, 5, 5, 4, 3, 1], [5, 5, 5, 5, 5, 5, 5, 4, 3, 1], [5, 5, 5, 5, 5, 5, 5, 4, 3, 1], [5, 5, 5, 5, 5, 5, 5, 4, 3, 1], [5, 5, 5, 5, 5, 5, 5, 4, 3, 1], [5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 1], [5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 2], // =========== =============== [5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 2], [5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 2], [5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 1], ]; var rectWidth = 860; var rectHeight = 476; var Apple = function(ctx, x, y){ _.bindAll(this, 'updateTile'); //this.bgRect = new BgRect(ctx, x, y); this.ctx = ctx; this.tiles = new Tiles(ctx); //setTimeout(this.showBg, 300); setTimeout(this.updateTile, 1000); }; Apple.prototype = { updateTile : function(){ this.tiles.changeSize(); }, update : function(){ this.tiles.update(); this.ctx.fillStyle = '#fff'; this.ctx.font = "24px sans-serif"; this.ctx.fillText('Is it in June 2nd?', width/2 - 90, height/2 + 200) } }; var Tiles = function(ctx){ this.tileArr = []; var margin = 2; for(var i = 0; i < 43; i++){ this.tileArr[i] = []; var visualArr = apple[i]; for(var j = 0; j < 24; j++){ var number = visualArr[j] ? visualArr[j] : 0; var tile = new Tile(ctx, i * 20 + 10 - rectWidth/2, j * 20 + 10 - rectHeight/2, number, i, j); this.tileArr[i].push(tile); } } }; Tiles.prototype = { changeSize : function(){ for(var i in this.tileArr){ var tileArr = this.tileArr[i]; for(var j in tileArr){ tileArr[j].changeSize(); } } }, update : function(){ for(var i in this.tileArr){ var tileArr = this.tileArr[i]; for(var j in tileArr){ tileArr[j].update(); } } } }; var Tile = function(ctx, x, y, number, i, j){ _.bindAll(this, 'onCompleteAnimation', 'changeSize'); this.xId = i; this.yId = j; this.ctx = ctx; this.x = x; this.y = y; this.number = number; this.firstWidth = this.side = 21; this.secondWidth = 16; this.grd = this.ctx.createLinearGradient( -rectWidth/2-this.x, 0, rectWidth, 0); this.grd.addColorStop(0, 'rgba(181, 240, 83, 1)'); this.grd.addColorStop(0.15, 'rgba(0, 215, 171, 1)'); this.grd.addColorStop(0.3, 'rgba(151, 69, 219, 1)'); this.grd.addColorStop(0.40, 'rgba(254, 91, 81, 1)'); this.grd.addColorStop(0.5, 'rgba(255, 216, 59, 1)'); }; Tile.prototype = { animationDuration :.3, anchor : 0, update : function(){ this.ctx.save(); this.ctx.translate(this.x + width/2, this.y + height/2); this.ctx.fillStyle = this.grd; this.ctx.beginPath(); this.ctx.moveTo(-this.side/2 + this.anchor, -this.side/2); this.ctx.lineTo(this.side/2 - this.anchor, -this.side/2); this.ctx.quadraticCurveTo(this.side/2, -this.side/2, this.side/2, this.anchor - this.side/2); this.ctx.lineTo(this.side/2, this.side/2- this.anchor); this.ctx.quadraticCurveTo(this.side/2, this.side/2, this.side/2 - this.anchor, this.side/2); this.ctx.lineTo(- this.side/2 + this.anchor, this.side/2); this.ctx.quadraticCurveTo(-this.side/2, this.side/2, -this.side/2, this.side/2 - this.anchor); this.ctx.lineTo(-this.side/2, -this.side/2 + this.anchor); this.ctx.quadraticCurveTo(-this.side/2, -this.side/2, -this.side/2 + this.anchor, -this.side/2); this.ctx.fill(); this.ctx.closePath(); this.ctx.restore(); }, delay : 0, changeSize : function(){ TweenLite.to(this, this.animationDuration, {side : 16, anchor: 4, onComplete: this.onCompleteAnimation, delay: this.delay}); }, restart : function(){ if(this.number > 0){ TweenLite.to(this, this.animationDuration, {side : 0, anchor: 0 }); } this.delay = 1; TweenLite.to(this, this.animationDuration, {side : 21, delay: 2, onComplete: this.changeSize }); }, onCompleteAnimation : function(){ var self = this; setTimeout(function(){ self.restart(); },3000); var sid, anch; switch (this.number){ case 0: sid = 0; anch = 0; break; case 1: sid = 2, anch = .5; break; case 2: sid = 4, anch = 1; break; case 3: sid = 8, anch = 2; break; case 4: sid = 12, anch = 3; break; case 5: return; break; } TweenLite.to(this, this.animationDuration * 3, {side : sid, anchor: anch, delay:.5 }); } }; // ================ var apple; init(); loop(); function init(){ apple = new Apple(ctx, width/2, height/2); prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#fff'; ctx.fillRect(0, 0, width, height); apple.update(duration); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/1-illusion-of-life/17-undefined.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ sw = 1000; sh = 1000; var dtr = function(v) {return v * Math.PI/180;} var camera = { focus : 10, self : { x : 0, y : 0, z : 0 }, rotate : { x : 0, y : 0, z : 0 }, up : { x : 0, y : 1, z : 0 }, zoom : 1, display : { x : width/2, y : height/2, z : 0 } }; var Circles = function(ctx){ var circle; this.circles = []; var side = 300; for(var x = 0; x < this.sideNum; x++){ for(var y = 0; y < this.sideNum; y++){ if(x % 3 == 0 && y % 3 == 0) circle = new Rect(ctx, side * (x - this.sideNum/2), side * (y - this.sideNum/2)) else circle = new Circle(ctx, side * (x - this.sideNum/2), side * (y - this.sideNum/2)) this.circles.push(circle); } } }; Circles.prototype = { sideNum : 24, t : 0, update : function(){ this.t += .01; camera.focus = 50 - 40 * Math.cos(this.t); for(var i in this.circles){ this.circles[i].update(); } } }; var Circle = function(ctx, x, y){ this.ctx = ctx; this.x = x; this.y = y; this.z = -100; this.rad =100; this.col = '#fff'; }; Circle.prototype = { update : function(){ this.ctx.fillStyle = '#fff'; var scale = ((camera.focus-camera.self.z) / ((camera.focus-camera.self.z) - this.z))* camera.zoom; var xPos = this.x * scale; var yPos = this.y * scale; var rad = this.rad * scale; this.ctx.save(); this.ctx.translate(camera.display.x, camera.display.y); this.ctx.beginPath(); this.ctx.arc(xPos, yPos, rad, 0, 2 * Math.PI, false); this.ctx.fill(); this.ctx.closePath(); this.ctx.restore(); } }; var Rect = function(ctx, x, y){ this.ctx = ctx; this.x = x; this.y = y; this.z = -100; this.rad =100; this.col = '#fff'; }; Rect.prototype = { update : function(){ this.ctx.fillStyle = '#fff'; var scale = ((camera.focus-camera.self.z) / ((camera.focus-camera.self.z) - this.z))* camera.zoom; var xPos = this.x * scale; var yPos = this.y * scale; var rad = this.rad * scale; this.ctx.save(); this.ctx.translate(camera.display.x, camera.display.y); this.ctx.beginPath(); this.ctx.fillRect(xPos - rad, yPos -rad , rad * 2, rad * 2); this.ctx.closePath(); this.ctx.restore(); } }; // ================ var circles; init(); loop(); function init(){ circles = new Circles(ctx); prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); circles.update(); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/1-illusion-of-life/18-undefined.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var isSoundPlay = true; width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var dtr = function(v) {return v * Math.PI/180;} var camera = { focus : 100, self : { x : 0, y : 0, z : 0 }, rotate : { x : 0, y : 0, z : 0 }, up : { x : 0, y : 1, z : 0 }, zoom : 1, display : { x : width/2, y : height/2, z : 0 } }; var Point = function(x, y, z){ this.x = x; this.y = y; this.z = z; }; var Shape = function(ctx, z){ _.bindAll(this, 'updateRotation', 'onTweenComplete'); this.normalPtArr = this.ptArr = []; this.ctx = ctx; this.x = 0; this.y = 0; this.z = z; this.theta = Math.PI / 2; var side = this.side = 200; this.sideNum = 3; // 200 200 // ---------- ---------- // \ / | | // \ / | | // \ / | | // \ / | | // \/ ---------- // triangle var angle = function(number){ return (number - 2) / Math.PI / number / 2 }; this.sideList = { 3 : side / Math.cos(angle(3)), 4 : side / Math.cos(angle(4)), 5 : side / Math.cos(angle(5)), 6 : side / Math.cos(angle(6)) }; var gosa=0; switch(this.sideNum){ case 3: gosa = -90 / 180 * Math.PI; break; } for(var i = 0; i < this.sideNum; i++){ var theta = i / this.sideNum * 2 * Math.PI; var pt = new Point( this.sideList[this.sideNum] * Math.cos(theta + gosa), this.sideList[this.sideNum] * Math.sin(theta + gosa), 0); this.normalPtArr.push(pt); } this.translateZ = this.originTranslateZ = this.sideList[this.sideNum]; this.theta = Math.PI/2; var self = this; this.count = 0; this.sideNum = 0; setTimeout(function(){ self.updateRotation(0); } , 1000); }; Shape.prototype = { updateRotation : function(){ this.count++; if(this.count % 2 == 0) TweenLite.to(this, .5, {theta: Math.PI/2, translateZ: this.originTranslateZ, onComplete: this.onTweenComplete}); else{ TweenLite.to(this, .5, {theta: 0, translateZ: 0}); setTimeout(this.updateRotation, 600); } }, onTweenComplete : function(){ this.sideNum = (this.sideNum + 1) % 4; var sideNum = this.sideNum + 3; var rad = this.sideList[sideNum]; var gosa=0; switch(sideNum){ case 3: gosa = -90 / 180 * Math.PI; break; case 4: gosa = 45 / 180 * Math.PI; break; } this.normalPtArr = []; for(var i = 0; i < sideNum; i++){ var theta = i / sideNum * 2 * Math.PI; var pt = new Point( rad * Math.cos(theta + gosa), rad * Math.sin(theta + gosa), 0); this.normalPtArr.push(pt); } this.translateZ = this.originTranslateZ = rad * Math.cos( Math.PI / (sideNum * 2) ); this.theta = Math.PI/2; this.updateRotation(); }, duration : 0, update : function(dt){ this.duration += dt; this.ctx.fillStyle = '#fff'; this.ctx.strokeStyle = '#fff'; var side = this.side * scale; this.ctx.save(); this.ctx.translate(camera.display.x, camera.display.y); this.ctx.rotate(this.duration/3); this.ctx.beginPath(); for(var i = 0; i < this.ptArr.length; i++){ var pt = this.ptArr[i]; var scale = ((camera.focus-camera.self.z) / ((camera.focus-camera.self.z) - pt.z))* camera.zoom; var xPos = pt.x * scale; var yPos = pt.y * scale; if(i == 0){ this.ctx.moveTo(xPos, yPos); }else{ this.ctx.lineTo(xPos, yPos); } } this.ctx.closePath(); this.ctx.fill(); this.ctx.stroke(); this.ctx.restore(); } }; Object.defineProperty(Shape.prototype, 'theta', { get : function(){ return this._theta; }, set : function(val){ this._theta = val; this.ptArr = []; for(var i = 0; i < this.normalPtArr.length; i++){ var normalPt = this.normalPtArr[i]; var rotateX = normalPt.x; var rotateY = Math.cos(val) * normalPt.y - Math.sin(val) * normalPt.z; var rotateZ = Math.sin(val) * normalPt.y + Math.cos(val) * normalPt.z; var rotatePt = new Point(rotateX, rotateY, rotateZ - this.translateZ); this.ptArr.push(rotatePt); } } }); // ================ init(); loop(); var shape; function init(){ prevTime = +new Date; shape = new Shape(ctx, 1000); } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); shape.update(duration); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/1-illusion-of-life/19-undefined.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var Point = function(x, y){ this.x = x; this.y = y; } var Circle = function(ctx, x, y, rad, val){ this.ctx = ctx; this.rad = rad; this.pt = new Point(x, y); this.isFill = val; }; Circle.prototype = { col : 'rgba(0, 0, 0, 0)', update : function(){ this.ctx.beginPath(); this.ctx.arc(this.pt.x, this.pt.y, this.rad, 0, 2 * Math.PI, false); if(this.isFill){ this.ctx.fillStyle = this.col; this.ctx.fill(); }else{ this.ctx.strokeStyle = this.col; this.ctx.stroke(); } this.ctx.closePath(); } }; var SmallCircle = function(i, ctx, bigRad, theta, rad ){ this.type = i % 2; this.bigRad = bigRad; this.theta = theta; this.count = 0; if(i % 2 == 0) { this.vel = this.originalVel = 0.01; this.fure = 0.02; this.countVel = 0.02; this.col = 'rgba(0, 0, 0, 0)'; }else{ this.vel = this.originalVel = 0.02; this.fure = 0.01; this.countVel = 0.01; this.col = 'rgba(0, 0, 0, 0)'; } var x = this.bigRad * Math.cos(this.theta); var y = this.bigRad * Math.sin(this.theta); Circle.call(this, ctx, x, y, rad, true); }; SmallCircle.prototype = Object.create(Circle.prototype); SmallCircle.prototype = { velocityTheta : 0, update : function(){ this.count++; this.vel = this.originalVel + this.fure * Math.cos(this.count * this.countVel); this.theta += this.vel; this.pt.x = this.bigRad * Math.cos(this.theta); this.pt.y = this.bigRad * Math.sin(this.theta); Circle.prototype.update.call(this); } }; var AnimationCircle = function(smallCircle, curRad){ this.parentCircle = smallCircle; this.minRad = -200; this.maxRad = 200; this.curRad = curRad; var x = this.curRad * Math.cos(this.parentCircle); var y = this.curRad * Math.sin(this.parentCircle); this.type = this.parentCircle.type; if(this.type % 2 == 0) this.col = '#999'; else this.col = '#fff'; this.vel = .5; Circle.call(this, smallCircle.ctx, x, y, smallCircle.rad/3, true); }; AnimationCircle.prototype = Object.create(Circle.prototype); AnimationCircle.prototype = { update : function(){ this.curRad -= this.vel; if(this.curRad < this.minRad){ //this.curRad = this.curRad + (this.minRad -this.curRad); this.vel = -.5 } if(this.curRad > this.maxRad){ //this.curRad = this.curRad - (this.maxRad -this.curRad); this.vel = .5; } this.pt.x = this.curRad * Math.cos(this.parentCircle.theta); this.pt.y = this.curRad * Math.sin(this.parentCircle.theta); Circle.prototype.update.call(this); } }; var MainCircle = function(ctx, x, y){ this.ctx = ctx; this.point = new Point(x, y); this.bigCircle = new Circle(ctx, 0, 0, this.rad, false); this.circleArr = []; this.animCircleArr = []; for(var i = 0; i < this.circleNum; i++){ var theta = i / this.circleNum * Math.PI * 2; var circle = new SmallCircle( i, ctx, this.rad, theta, this.smallRad); this.circleArr.push(circle); for(var j = 0; j < 11; j++){ var animCircle = new AnimationCircle(circle, -j * 40 + 200); this.animCircleArr.push(animCircle); } } }; MainCircle.prototype = { rad : 200, smallRad : 8, circleArr : null, circleNum : 24, count : 0, update : function(){ this.count = this.count + 0.01; this.val = Math.sin(this.count) * .5 + Math.sin(this.count/2) * .3 + 1; this.ctx.save(); this.ctx.translate(this.point.x, this.point.y); this.ctx.scale(this.val, this.val) this.bigCircle.update(); for(var i = 0; i < this.circleArr.length; i++){ this.circleArr[i].update(); } for(i = 0; i < this.animCircleArr.length; i++){ this.animCircleArr[i].update(); } this.ctx.restore(); } }; // ================ var mainCircle; init(); loop(); function init(){ mainCircle = new MainCircle(ctx, width/2, height/2); prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); mainCircle.update(); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/1-illusion-of-life/2-squash.js ================================================ function backingScale(context) { if ('devicePixelRatio' in window) { if (window.devicePixelRatio > 1) { return window.devicePixelRatio; } } return 1; } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; var Rect = function( ctx, x, y, wid, hig ){ this.ctx = ctx; this.x = x; this.y = y; this.wid = wid; this.hig = hig; this.vel = 100; }; Rect.prototype = { draw : function(){ this.ctx.beginPath(); this.ctx.fillStyle = '#fff'; this.ctx.save(); this.ctx.translate(this.x, this.y); this.ctx.fillRect(- this.wid / 2, -this.hig, this.wid, this.hig); this.ctx.closePath(); this.ctx.restore(); } }; // --------------- var width, height, previousTime; var side1, side2; var rect, rect1, rect2; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var scaleFactor = backingScale(ctx); width = window.innerWidth * scaleFactor; height = window.innerHeight * scaleFactor; side1 = 100; side2 = 180; var duration1 = .8; var duration2 = .6; canvas.width = width; canvas.height = height; init(); function init(){ previousTime = +new Date; rect1 = new Rect( ctx, width/2 - 200, height, side1, 50); rect = new Rect( ctx, width/2, 0, side1, 200); rect2 = new Rect( ctx, width/2 + 200, height, side1, 50); TweenLite.to(rect, duration1, { y : height, onComplete: onTween1Complete, onUpdate: onTween1Update }); TweenLite.to(rect, duration2, { wid: side2, hig: 50, delay: .2}); TweenLite.to(rect1, duration1, { y : 200}); TweenLite.to(rect1, duration2, { wid: side1, hig:200}); TweenLite.to(rect2, duration1, { y : 200 }); TweenLite.to(rect2, duration2, { wid: side1, hig: 200}); } function onTween1Update(){ ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); rect.draw(); rect1.draw(); rect2.draw(); } function onTween1Complete(){ TweenLite.to(rect, duration1, { y : 200, onComplete: onTween2Complete, onUpdate: onTween1Update, delay:.2}); TweenLite.to(rect, duration2, { wid: side1, hig: 200, delay: .2}); TweenLite.to(rect1, duration1, { y : height, delay:.2}); TweenLite.to(rect1, duration2, { wid: side2, hig:50, delay:.4}); TweenLite.to(rect2, duration1, { y : height, delay:.2 }); TweenLite.to(rect2, duration2, { wid: side2, hig: 50, delay:.4}); } function onTween2Complete(){ TweenLite.to(rect, duration1, { y : height, onComplete: onTween1Complete, onUpdate: onTween1Update, delay:.2 }); TweenLite.to(rect, duration2, { wid: side2, hig: 50, delay:.4}); TweenLite.to(rect1, duration1, { y : 200, delay:.2}); TweenLite.to(rect1, duration2, { wid: side1, hig:200, delay:.2}); TweenLite.to(rect2, duration1, { y : 200, delay:.2 }); TweenLite.to(rect2, duration2, { wid: side1, hig: 200, delay:.2}); } ================================================ FILE: app/scripts/1-illusion-of-life/20-undefined.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var Point = function( x, y){ this.x = x; this.y = y; } var Circle = function( ctx, pt){ this.ctx = ctx; this.pt = pt; }; Circle.prototype = { fillCol : '#333', strokeCol : '#fff', rad : 2, update : function(){ this.ctx.fillStyle = this.fillCol; this.ctx.strokeStyle = this.strokeCol; this.ctx.beginPath(); this.ctx.arc(this.pt.x, this.pt.y, this.rad, 0, 2 * Math.PI, false); this.ctx.stroke(); this.ctx.fill(); this.ctx.closePath(); } }; var Shape = function( ctx, x, y){ this.ctx = ctx; this.center = new Point(x, y); this.line = new Line(ctx); this.circleArr = []; this.circleArr.push(new Circle(ctx, this.line.startPt)); this.circleArr.push(new Circle(ctx, this.line.endPt)); var self = this; setTimeout(function(){ self.add(); }, 800); }; Shape.prototype = { circleArr : null, count : 0, angle : 0, add : function(){ this.line.addPt(); this.circleArr.push(new Circle(this.ctx, this.line.ptArr[this.line.ptArr.length - 1])); var self = this; this.count++; if(this.count > 8){ setTimeout(function(){ self.shrink(); }, 2000); }else{ setTimeout(function(){ self.add(); }, 800); } }, init : function(){ this.count = 0; this.line.init(); this.circleArr = []; this.circleArr.push(new Circle(ctx, this.line.startPt)); this.circleArr.push(new Circle(ctx, this.line.endPt)); var self = this; this.line.animate(); setTimeout(function(){ self.add(); }, 1600); }, shrink : function(){ this.line.shrink(); var self = this; setTimeout(function(){ self.init(); }, 1000); }, update : function(){ this.angle += 0.01; this.ctx.save(); this.ctx.translate(this.center.x, this.center.y); this.ctx.rotate(this.angle); this.line.update(); for(var i in this.circleArr){ this.circleArr[i].update(); } this.ctx.restore(); } }; // ------ var Line = function(ctx){ this.ctx = ctx; this.startPt = new Point( 0, 0); this.endPt = new Point( 0, 0); this.ptArr = []; var self = this; setTimeout(function(){ self.animate(); }, 300); }; Line.prototype = { col : '#fff', animateDuration :.5, side : 100, ptArr : null, init : function(){ this.side = 100; this.ptArr = []; }, addPt : function(){ var pt = new Point(this.startPt.x, this.startPt.y); this.ptArr.push(pt); var sum = this.ptArr.length + 2; this.side += 10; for(var i = 0; i < sum; i++){ var theta = i / sum * 2 * Math.PI; var x = Math.cos(theta) * this.side; var y = Math.sin(theta) * this.side; switch (i){ case 0: TweenLite.to(this.startPt, this.animateDuration, {x : x, y: y}); break; case 1: TweenLite.to(this.endPt, this.animateDuration, {x : x, y: y}); break; default : TweenLite.to(this.ptArr[i - 2], this.animateDuration, {x : x, y: y}); } } }, shrink : function(){ var sum = this.ptArr.length + 2; for(var i = 0; i < sum; i++){ switch (i){ case 0: TweenLite.to(this.startPt, this.animateDuration, {x : 0, y: 0}); break; case 1: TweenLite.to(this.endPt, this.animateDuration, {x : 0, y: 0}); break; default : TweenLite.to(this.ptArr[i - 2], this.animateDuration, {x : 0, y: 0}); } } }, animate : function(){ TweenLite.to(this.startPt, this.animateDuration, {x : this.side}); TweenLite.to(this.endPt, this.animateDuration, {x : -this.side}); }, update : function(){ this.ctx.beginPath(); this.ctx.strokeStyle = this.col; this.ctx.moveTo(this.endPt.x, this.endPt.y); if(this.ptArr.length > 0){ for(var i = 0; i < this.ptArr.length; i++){ this.ctx.lineTo(this.ptArr[i].x, this.ptArr[i].y); } } this.ctx.lineTo(this.startPt.x, this.startPt.y); this.ctx.lineTo(this.endPt.x, this.endPt.y); this.ctx.stroke(); this.ctx.closePath(); } } // ================ var shape; init(); loop(); function init(){ shape = new Shape(ctx, width/2, height/2); prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); shape.update(); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/1-illusion-of-life/21-undefined.js ================================================ window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame // --------------------- var width, height, prevTime; var mousePos; var particleAnimation; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // --------------------- var Point = function(x, y){ this.x = this.origX = x; this.y = this.origY = y; }; var AnimationPoint = function(ctx, x, y){ this.ctx = ctx; this.x = this.origX = x; this.y = this.origY = y; this.isDraw = true; }; AnimationPoint.prototype = { rad1 : height/2 * .9, theta1 : 0, rad2 : 100, theta2 : 0, rad : 3, update : function(){ this.theta1 += .04 * Math.random(); this.theta2 += Math.random() * .02; this.x = this.origX + this.rad2 * Math.cos(this.theta2); this.y = this.origY + this.rad1 * Math.sin(this.theta1); if(this.isDraw) this.draw(); }, draw : function(){ this.ctx.beginPath(); this.ctx.fillStyle = '#000'; this.ctx.arc(this.x, this.y, this.rad, 0, 2 * Math.PI, false); this.ctx.fill(); this.ctx.closePath(); } }; var AnimationPoint2 = function(ctx, x, y){ this.ctx = ctx; this.x = this.origX = x; this.y = this.origY = y; this.isDraw = true; }; AnimationPoint2.prototype = { rad1 : width/2 * .9, theta1 : 0, rad2 : 200, theta2 : 0, rad : 3, update : function(){ this.theta1 += .04 * Math.random(); this.theta2 += Math.random() * .02; this.x = this.origX + this.rad1 * Math.cos(this.theta1) ; this.y = this.origY + this.rad2 * Math.sin(this.theta2); if(this.isDraw) this.draw(); }, draw : function(){ this.ctx.beginPath(); this.ctx.fillStyle = '#000'; this.ctx.arc(this.x, this.y, this.rad, 0, 2 * Math.PI, false); this.ctx.fill(); this.ctx.closePath(); } }; var Particle = function(ctx, x, y){ this.ctx = ctx; this.x = x; this.y = y; this.vel = new Point(0, 0); } Particle.prototype = { k : .95, col : '#fff', update : function( dt, particleAnimation){ var acl if(!this.isRandom) acl = particleAnimation.getPosition(this.x, this.y); else acl = this.random; this.vel.x += acl.x * dt; this.vel.y += acl.y * dt; this.vel.x *= this.k; this.vel.y *= this.k; this.x += this.vel.x * dt; this.y += this.vel.y * dt; if(this.x < 0) this.x = width; if(this.x > width) this.x = 0; if(this.y < 0) this.y = height; if(this.y > height)this.y = 0; var col = parseInt(255 * this.x / width); this.ctx.beginPath(); this.ctx.fillStyle = 'hsl(' + col + ', 100%, 70%)'; this.ctx.arc(this.x, this.y, 1, 0, 2*Math.PI, false); this.ctx.fill(); this.ctx.closePath(); }, randomStart : function(){ this.isRandom = true; this.random = {x : 5000 * (Math.random() - .5), y: 5000 * (Math.random() - .5)}; }, randomStop : function(){ this.isRandom = false; } } var Particles = function(ctx){ _.bindAll(this, 'interval'); this.ctx = ctx; this.arr = []; for(var i = 0; i < this.num; i++){ var particle = new Particle(ctx, width * Math.random(), height * Math.random()); this.arr.push(particle); } this.interval(); setInterval(this.interval, 4000); } Particles.prototype = { num : 1000, update : function(dt, particleAnimation){ for(var i = 0; i < this.num; i++){ this.arr[i].update(dt, particleAnimation); } }, interval : function(){ for(var i = 0; i < this.num; i++){ this.arr[i].randomStart(); } var self = this; setTimeout(function(){ self.randomStop(); }, 500); }, randomStop : function(){ for(var i = 0; i < this.num; i++){ this.arr[i].randomStop(); } } }; var ParticleAnimation = function(ctx){ this.ctx = ctx; this.gridWid = width / (this.gridNums - 1); this.gridHig = height / (this.gridNums - 1); this.range = this.gridWid * 3; this.points = []; for(var _x = 0; _x < this.gridNums; _x++){ for(var _y = 0; _y < this.gridNums; _y++){ var posX, posY, particle; posX = this.gridWid * _x + this.gridWid/2; posY = this.gridHig * _y + this.gridHig/2; particle = new Point(posX, posY) this.points.push(particle); } } this.animationPt = new AnimationPoint(this.ctx, width/2, height/2); this.animationPt2 = new AnimationPoint2(this.ctx, width/2, height/2); this.isDraw = true; }; ParticleAnimation.prototype = { gridNums : 21, points : [], isDraw : false, speed : 800, update : function(){ this.animationPt.update(); this.animationPt2.update(); for(var i = 0; i < this.points.length; i++){ var dx, dy, distance; var pointX1, pointY1, pointX2, pointY2; var pointX, pointY; var pt = this.points[i]; dx = this.animationPt.x - pt.x; dy = this.animationPt.y - pt.y; distance = Math.sqrt(dx * dx + dy * dy); pt.x = (pt.x - (dx / distance) * (this.range / distance) * this.speed) - ((pt.x - pt.origX) / 2); pt.y = (pt.y - (dy / distance) * (this.range / distance) * this.speed) - ((pt.y - pt.origY) / 2); } for(var i = 0; i < this.points.length; i++){ var dx, dy, distance; var pointX1, pointY1, pointX2, pointY2; var pointX, pointY; var pt = this.points[i]; dx = this.animationPt2.x - pt.x; dy = this.animationPt2.y - pt.y; distance = Math.sqrt(dx * dx + dy * dy); pt.x = (pt.x - (dx / distance) * (this.range / distance) * this.speed) - ((pt.x - pt.origX) / 2); pt.y = (pt.y - (dy / distance) * (this.range / distance) * this.speed) - ((pt.y - pt.origY) / 2); } // -------------- if(this.isDraw) this.draw(); }, getPosition : function(x, y){ var xPos = parseInt(x / this.gridWid); var yPos = parseInt(y / this.gridHig); var arrayNum = xPos + yPos * this.gridNums; var point = this.points[arrayNum]; var vector = {x : point.x - point.origX, y: point.y - point.origY}; return vector; }, draw : function(){ this.ctx.strokeStyle = 'rgba(0, 0, 0, .1)'; for(var i = 0; i < this.points.length; i++){ var pt = this.points[i]; var dx = (pt.x - pt.origX)/20; var dy = (pt.y - pt.origY)/20; this.ctx.beginPath(); this.ctx.moveTo(pt.origX + dx, pt.origY + dy); this.ctx.lineTo(pt.origX, pt.origY); this.ctx.stroke(); this.ctx.closePath(); } } }; // --------------------- var particles; init(); loop(); function init(){ particles = new Particles(ctx); particleAnimation = new ParticleAnimation(ctx); prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; var alp = .15 + .1 * Math.cos(curTime * .01); ctx.fillStyle = 'rgba( 60, 60, 60,' + alp + ')'; ctx.fillRect(0, 0, width, height); particleAnimation.update(); particles.update(duration, particleAnimation); requestAnimationFrame(loop); } canvas.addEventListener("mousemove", function (evt) { mousePos = {x: evt.clientX, y: evt.clientY}; }, false); ================================================ FILE: app/scripts/1-illusion-of-life/22-sine-cos.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var Point = function(theta){ this.theta = theta | 0; }; Point.prototype = { rad : 10, _theta : null, }; Object.defineProperty(Point.prototype, 'theta', { get : function(){ return this._theta; }, set : function(val){ this._theta = val; this.x = this.rad * Math.cos(this._theta); this.y = this.rad * Math.sin(this._theta); } }); var Line = function(ctx, x, y){ this.ctx = ctx; this.x = x; this.y = y; this.theta = 0; this.startPt = new Point(this.theta); this.endPt = new Point((this.theta + Math.PI)); }; Line.prototype = { strokeCol : '#fff', update : function(){ this.ctx.save(); this.ctx.translate(this.x, this.y); this.ctx.beginPath(); this.ctx.fillStyle = this.strokeCol; this.ctx.moveTo(this.startPt.x, this.startPt.y); this.ctx.lineTo(this.endPt.x, this.endPt.y); this.ctx.stroke(); this.ctx.closePath(); this.ctx.restore(); } }; var LineCollection = function(ctx){ this.ctx = ctx; this.widNum = parseInt(width / (Point.rad * 2)) + 1; this.higNum = parseInt(height / (Point.rad * 2)) + 1; this.lineArr = []; for(var i = 0; i < this.widNum; i++){ var lineArr = []; var x = Point.rad * ( 1 + 2 * i); for(var j = 0;j < this.higNum; j++){ var y = Point.rad * (1 + 2 * j); var line = new Line(this.ctx, x, y); lineArr.push(line); } this.lineArr.push(lineArr); } }; LineCollection.prototype = { lineArr: null, widNum : null, higNum : null, } // ================ init(); loop(); function init(){ prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/1-illusion-of-life/22-undefined.js ================================================ window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame // --------------------- /** * Created with JetBrains WebStorm. * User: kenjisaito * Date: 12/14/12 * Time: 3:41 PM * To change this template use File | Settings | File Templates. */ var Circle = function(rad, centerPoint){ this.rad = rad; this.centerPoint = centerPoint; }; //define the point class var DelaunayDataSet = function( vertex, context){ this.vertex = vertex; this.context = context; this.fillTriangleColor = "rgba(30, 30, 30, .2)"; this.fillTriangleCheck = false; this.strokeTriangleColor = "rgba( 200, 200, 200, .05)"; this.strokeTriangleCheck = true; }; DelaunayDataSet.prototype.addPoints = function(ptArr){ for(var i = 0; i < ptArr.length; i++){ this.vertex.push(ptArr[i]); } }; DelaunayDataSet.prototype.drawTriangle = function(){ for (var i = 0; i < this.triangleVertexNumber.length; i += 3) { if(this.triangleVertexNumber[i] !== 0 && this.triangleVertexNumber[i] !== 1 && this.triangleVertexNumber[i] !== 2 && this.triangleVertexNumber[i + 1] !== 0 && this.triangleVertexNumber[i + 1] !== 1 && this.triangleVertexNumber[i + 1] !== 2&& this.triangleVertexNumber[i + 2] !== 0&& this.triangleVertexNumber[i + 2] !== 1 && this.triangleVertexNumber[i + 2] !== 2){ this.context.beginPath(); // console.log(this.triangleVertexNumber[i]); this.context.moveTo(this.vertex[this.triangleVertexNumber[i]].x, this.vertex[this.triangleVertexNumber[i]].y); // console.log(this.triangleVertexNumber[i + 1]); this.context.lineTo(this.vertex[this.triangleVertexNumber[i + 1]].x, this.vertex[this.triangleVertexNumber[i + 1]].y); // console.log(this.triangleVertexNumber[i + 2]); this.context.lineTo(this.vertex[this.triangleVertexNumber[i + 2]].x, this.vertex[this.triangleVertexNumber[i + 2]].y); this.context.lineTo(this.vertex[this.triangleVertexNumber[i]].x, this.vertex[this.triangleVertexNumber[i]].y); if (this.fillTriangleCheck) { this.context.fillStyle = this.fillTriangleColor; this.context.fill(); } if (this.strokeTriangleCheck) { this.context.strokeStyle = this.strokeTriangleColor; this.context.stroke(); } this.context.closePath(); } } }; DelaunayDataSet.prototype.update = function(){ var vertexNumber = this.vertex.length; this.triangleVertexNumber = [ 0, 1, 2]; this.circumCircles = []; var firstCircle = calculationCircle( this.vertex[0], this.vertex[1], this.vertex[2]); this.circumCircles.push(firstCircle); for(var i = 3; i < vertexNumber; i++){ calTriangles(this, i); if(i > 3){ removeTriangle(this, i); } } }; // define the method which is very useful function distanceBetweenPoints(pt1, pt2){ var dx = pt2.x - pt1.x; var dy = pt2.y - pt1.y; return Math.sqrt(dx * dx + dy * dy); } function distanceBetweenPointAndCircle(pt, circle){ var dx = pt.x - circle.centerPoint.x; var dy = pt.y - circle.centerPoint.y; return Math.sqrt(dx * dx + dy * dy); } function judgeBetweenDistance(_pt, _circle) { var dis = distanceBetweenPointAndCircle(_pt, _circle); var circleJudge = false; if (dis < _circle.rad) { circleJudge = true; } return circleJudge; } //this is the process of 3 ( separating of the triangles, add the circum circles, and deleting the extra triangle function calTriangles( _delaunayDataSet, num){ var newNumber = num; var pt = _delaunayDataSet.vertex[newNumber]; var tempVertexNumber = []; var tempCircles = []; var tempNumbers =[]; for(var i = 0; i < _delaunayDataSet.circumCircles.length; i++){ // console.log("i: " + i); if(judgeBetweenDistance(pt, _delaunayDataSet.circumCircles[i])){ tempNumbers.push(i); var selectingNum01 = _delaunayDataSet.triangleVertexNumber[3 * i]; var selectingNum02 = _delaunayDataSet.triangleVertexNumber[3 * i + 1]; var selectingNum03 = _delaunayDataSet.triangleVertexNumber[3 * i + 2]; // push the number to pointNumbers array tempVertexNumber.push(selectingNum01); tempVertexNumber.push(selectingNum02); tempVertexNumber.push(newNumber); tempVertexNumber.push(selectingNum02); tempVertexNumber.push(selectingNum03); tempVertexNumber.push(newNumber); tempVertexNumber.push(selectingNum03); tempVertexNumber.push(selectingNum01); tempVertexNumber.push(newNumber); var ct01circle1 = calculationCircle( _delaunayDataSet.vertex[selectingNum01], _delaunayDataSet.vertex[selectingNum02], _delaunayDataSet.vertex[newNumber]); var ct01circle2 = calculationCircle( _delaunayDataSet.vertex[selectingNum02], _delaunayDataSet.vertex[selectingNum03], _delaunayDataSet.vertex[newNumber]); var ct01circle3 = calculationCircle( _delaunayDataSet.vertex[selectingNum03], _delaunayDataSet.vertex[selectingNum01], _delaunayDataSet.vertex[newNumber]); tempCircles.push(ct01circle1); tempCircles.push(ct01circle2); tempCircles.push(ct01circle3); } } for(i = 0; i < tempVertexNumber.length; i++){ _delaunayDataSet.triangleVertexNumber.push(tempVertexNumber[i]); } for(i = 0; i < tempCircles.length; i++){ _delaunayDataSet.circumCircles.push(tempCircles[i]); } for (i = 0; i < tempNumbers.length; i++) { var num = tempNumbers[i] - i; var slicedObjectPtNumbers; var slicedCircles; if (num == 0) { slicedObjectPtNumbers = _delaunayDataSet.triangleVertexNumber.slice(3); slicedCircles = _delaunayDataSet.circumCircles.slice(1); } else { var slicedObjectPtNumberBefore = _delaunayDataSet.triangleVertexNumber.slice(0, 3 * num); var slicedObjectPtNumberAfter = _delaunayDataSet.triangleVertexNumber.slice(3 * num + 3); slicedObjectPtNumbers = slicedObjectPtNumberBefore.concat(slicedObjectPtNumberAfter); var slicedCircleBefore = _delaunayDataSet.circumCircles.slice(0, num); var slicedCircleAfter = _delaunayDataSet.circumCircles.slice(1 + num); slicedCircles = slicedCircleBefore.concat(slicedCircleAfter); } _delaunayDataSet.triangleVertexNumber = slicedObjectPtNumbers; _delaunayDataSet.circumCircles = slicedCircles; } } function calculationCircle(pt01, pt02, pt03) { var x1 = pt01.x; var y1 = pt01.y; var x2 = pt02.x; var y2 = pt02.y; var x3 = pt03.x; var y3 = pt03.y; var c = 2.0 * ((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1)); var tempX = ((y3 - y1) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) + (y1 - y2) * (x3 * x3 - x1 * x1 + y3 * y3 - y1 * y1)) / c; var tempY = ((x1 - x3) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) + (x2 - x1) * (x3 * x3 - x1 * x1 + y3 * y3 - y1 * y1)) / c; var tempPt = new Point(tempX, tempY); var tempRad = Math.sqrt(Math.pow(tempX - x1, 2) + Math.pow(tempY - y1, 2)); return new Circle(tempRad, tempPt); } function removeTriangle( _delaunayDataSet, tempVertexNum){ var circumcircleArrays = _delaunayDataSet.circumCircles; var ommitCircumCircleNumbers = []; for( var i = 0; i < circumcircleArrays.length;i++){ var vertexNum01 = _delaunayDataSet.triangleVertexNumber[i * 3]; var vertexNum02 = _delaunayDataSet.triangleVertexNumber[i * 3 + 1]; var vertexNum03 = _delaunayDataSet.triangleVertexNumber[i * 3 + 2]; for(var num = 0; num < tempVertexNum; num++){ if(num != vertexNum01 && num != vertexNum02 && num != vertexNum03){ if(judgeBetweenDistance(_delaunayDataSet.vertex[num], circumcircleArrays[i])){ ommitCircumCircleNumbers.push(i); break; } } } } //omit var tempCircumCircleArray = []; var tempTriagneNumberArray = []; for( i = 0; i < circumcircleArrays.length; i++){ for(var j = 0; j < ommitCircumCircleNumbers.length; j++){ if(ommitCircumCircleNumbers[j] == i){ break; } } if(j == ommitCircumCircleNumbers.length){ tempTriagneNumberArray.push( _delaunayDataSet.triangleVertexNumber[3 * i]); tempTriagneNumberArray.push( _delaunayDataSet.triangleVertexNumber[3 * i + 1]); tempTriagneNumberArray.push( _delaunayDataSet.triangleVertexNumber[3 * i + 2]); tempCircumCircleArray.push( _delaunayDataSet.circumCircles[i]); } } // console.log("tempTriagneNumberArray.length: " + tempTriagneNumberArray.length); _delaunayDataSet.triangleVertexNumber = []; for( i = 0; i < tempTriagneNumberArray.length; i++){ _delaunayDataSet.triangleVertexNumber[i] = tempTriagneNumberArray[i]; } _delaunayDataSet.circumCircles = []; for( i = 0; i < tempCircumCircleArray.length; i++){ _delaunayDataSet.circumCircles[i] = tempCircumCircleArray[i]; } } function initTriangle(context, recWid, recHig, recTop, recLeft){ var vertex = []; var bigRad = Math.sqrt(Math.pow(recWid, 2) + Math.pow(recHig, 2)) / 2; var bigCirclePos = new Point(recWid / 2 + recLeft, recHig / 2 + recTop); vertex.push(new Point(bigCirclePos.x - Math.sqrt(3) * bigRad, bigCirclePos.y - bigRad)); vertex.push(new Point(bigCirclePos.x + Math.sqrt(3) * bigRad, bigCirclePos.y - bigRad)); vertex.push(new Point(bigCirclePos.x, bigCirclePos.y + bigRad * 2)); var tempPt; tempPt = new Point(0, 0); vertex.push(tempPt); tempPt = new Point( width, 0); vertex.push(tempPt); tempPt = new Point(0, height); vertex.push(tempPt); tempPt = new Point( width, height); vertex.push(tempPt); // setting DelaunayDataSet with the vertex. return new DelaunayDataSet( vertex, context); } var width, height, prevTime; var mousePos; var particleAnimation; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // --------------------- var Point = function(x, y){ this.x = this.origX = x; this.y = this.origY = y; }; var AnimationPoint = function(ctx, x, y){ this.ctx = ctx; this.x = this.origX = x; this.y = this.origY = y; this.isDraw = false; }; AnimationPoint.prototype = { rad1 : height/2 * .9, theta1 : 0, rad2 : 100, theta2 : 0, rad : 3, update : function(){ this.theta1 += .04 * Math.random(); this.theta2 += Math.random() * .02; this.x = this.origX + this.rad2 * Math.cos(this.theta2); this.y = this.origY + this.rad1 * Math.sin(this.theta1); if(this.isDraw) this.draw(); }, draw : function(){ this.ctx.beginPath(); this.ctx.fillStyle = '#000'; this.ctx.arc(this.x, this.y, this.rad, 0, 2 * Math.PI, false); this.ctx.fill(); this.ctx.closePath(); } }; var AnimationPoint2 = function(ctx, x, y){ this.ctx = ctx; this.x = this.origX = x; this.y = this.origY = y; this.isDraw = false; }; AnimationPoint2.prototype = { rad1 : width/2 * .9, theta1 : 0, rad2 : 200, theta2 : 0, rad : 3, update : function(){ this.theta1 += .04 * Math.random(); this.theta2 += Math.random() * .02; this.x = this.origX + this.rad1 * Math.cos(this.theta1) ; this.y = this.origY + this.rad2 * Math.sin(this.theta2); if(this.isDraw) this.draw(); }, draw : function(){ this.ctx.beginPath(); this.ctx.fillStyle = '#000'; this.ctx.arc(this.x, this.y, this.rad, 0, 2 * Math.PI, false); this.ctx.fill(); this.ctx.closePath(); } }; var Particle = function(ctx, x, y){ this.ctx = ctx; this.x = x; this.y = y; this.vel = new Point(0, 0); } Particle.prototype = { k : .95, col : '#fff', update : function( dt, particleAnimation){ var acl if(!this.isRandom) acl = particleAnimation.getPosition(this.x, this.y); else acl = this.random; this.vel.x += acl.x * dt; this.vel.y += acl.y * dt; this.vel.x *= this.k; this.vel.y *= this.k; this.x += this.vel.x * dt; this.y += this.vel.y * dt; if(this.x < 0) this.x = width; if(this.x > width) this.x = 0; if(this.y < 0) this.y = height; if(this.y > height)this.y = 0; var col = parseInt(255 * this.x / width); this.ctx.beginPath(); this.ctx.fillStyle = 'hsl(' + col + ', 100%, 70%)'; this.ctx.arc(this.x, this.y, 1, 0, 2*Math.PI, false); this.ctx.fill(); this.ctx.closePath(); }, randomStart : function(){ this.isRandom = true; this.random = {x : 5000 * (Math.random() - .5), y: 5000 * (Math.random() - .5)}; }, randomStop : function(){ this.isRandom = false; } }; var Particles = function(ctx){ _.bindAll(this, 'interval'); this.ctx = ctx; this.arr = []; for(var i = 0; i < this.num; i++){ var particle = new Particle(ctx, width/2, height /2); this.arr.push(particle); } this.interval(); setInterval(this.interval, 4000); }; Particles.prototype = { num : 100, update : function(dt, particleAnimation){ for(var i = 0; i < this.num; i++){ this.arr[i].update(dt, particleAnimation); } }, interval : function(){ for(var i = 0; i < this.num; i++){ this.arr[i].randomStart(); } var self = this; setTimeout(function(){ self.randomStop(); }, 500); }, randomStop : function(){ for(var i = 0; i < this.num; i++){ this.arr[i].randomStop(); } } }; var ParticleAnimation = function(ctx){ this.ctx = ctx; this.gridWid = width / (this.gridNums - 1); this.gridHig = height / (this.gridNums - 1); this.range = this.gridWid * 3; this.points = []; for(var _x = 0; _x < this.gridNums; _x++){ for(var _y = 0; _y < this.gridNums; _y++){ var posX, posY, particle; posX = this.gridWid * _x + this.gridWid/2; posY = this.gridHig * _y + this.gridHig/2; particle = new Point(posX, posY) this.points.push(particle); } } this.animationPt = new AnimationPoint(this.ctx, width/2, height/2); this.animationPt2 = new AnimationPoint2(this.ctx, width/2, height/2); }; ParticleAnimation.prototype = { gridNums : 11, points : [], isDraw : false, speed : 800, update : function(){ this.animationPt.update(); this.animationPt2.update(); for(var i = 0; i < this.points.length; i++){ var dx, dy, distance; var pointX1, pointY1, pointX2, pointY2; var pointX, pointY; var pt = this.points[i]; dx = this.animationPt.x - pt.x; dy = this.animationPt.y - pt.y; distance = Math.sqrt(dx * dx + dy * dy); pt.x = (pt.x - (dx / distance) * (this.range / distance) * this.speed) - ((pt.x - pt.origX) / 2); pt.y = (pt.y - (dy / distance) * (this.range / distance) * this.speed) - ((pt.y - pt.origY) / 2); } for(var i = 0; i < this.points.length; i++){ var dx, dy, distance; var pointX1, pointY1, pointX2, pointY2; var pointX, pointY; var pt = this.points[i]; dx = this.animationPt2.x - pt.x; dy = this.animationPt2.y - pt.y; distance = Math.sqrt(dx * dx + dy * dy); pt.x = (pt.x - (dx / distance) * (this.range / distance) * this.speed) - ((pt.x - pt.origX) / 2); pt.y = (pt.y - (dy / distance) * (this.range / distance) * this.speed) - ((pt.y - pt.origY) / 2); } if(mousePos){ for(var i = 0; i < this.points.length; i++){ var dx, dy, distance; var pointX1, pointY1, pointX2, pointY2; var pointX, pointY; var pt = this.points[i]; dx = mousePos.x - pt.x; dy = mousePos.y - pt.y; distance = Math.sqrt(dx * dx + dy * dy); pt.x = (pt.x - (dx / distance) * (this.range / distance) * this.speed * 5) - ((pt.x - pt.origX) / 2); pt.y = (pt.y - (dy / distance) * (this.range / distance) * this.speed * 5) - ((pt.y - pt.origY) / 2); } } // -------------- if(this.isDraw) this.draw(); }, getPosition : function(x, y){ var xPos = parseInt(x / this.gridWid); var yPos = parseInt(y / this.gridHig); var arrayNum = xPos + yPos * this.gridNums; var point = this.points[arrayNum]; var vector = {x : point.x - point.origX, y: point.y - point.origY}; return vector; }, draw : function(){ this.ctx.strokeStyle = 'rgba(0, 0, 0, .1)'; for(var i = 0; i < this.points.length; i++){ var pt = this.points[i]; var dx = (pt.x - pt.origX)/20; var dy = (pt.y - pt.origY)/20; this.ctx.beginPath(); this.ctx.moveTo(pt.origX + dx, pt.origY + dy); this.ctx.lineTo(pt.origX, pt.origY); this.ctx.stroke(); this.ctx.closePath(); } } }; // --------------------- var delaunay; var particles; init(); loop(); function init(){ delaunay = initTriangle(ctx, width, height, 0, 0); particles = new Particles(ctx); ctx.fillStyle = 'rgba( 60, 60, 60,.5)'; ctx.fillRect(0, 0, width, height); particleAnimation = new ParticleAnimation(ctx); delaunay.addPoints(particles.arr); prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; var alp = .15 + .1 * Math.cos(curTime * .01); ctx.fillStyle = 'rgba( 60, 60, 60,' + alp + ')'; ctx.fillRect(0, 0, width, height); particleAnimation.update(); particles.update(duration, particleAnimation); delaunay.update(); delaunay.drawTriangle(); requestAnimationFrame(loop); } canvas.addEventListener("mousemove", function (evt) { mousePos = {x: evt.clientX, y: evt.clientY}; }, false); ================================================ FILE: app/scripts/1-illusion-of-life/23-undefined.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var Shape = function( ctx, x, y){ this.ctx = ctx; this.x = x; this.y = y; this.circlrRawArr = []; var minRad = 30; var maxRad = Math.min(width, height) / 2 * .9; for(var i = 0; i < this.circlrRawNum; i++){ var theta = 2 * Math.PI * i / this.circlrRawNum; var circleRaw = new CircleRaw( ctx, minRad, maxRad, theta); this.circlrRawArr.push(circleRaw); } }; Shape.prototype = { circlrRawArr : null, circlrRawNum : 60, update : function(){ this.ctx.save(); this.ctx.translate(this.x, this.y); for(var i = 0; i < this.circlrRawNum; i++){ var circleRaw = this.circlrRawArr[i]; circleRaw.update(); } this.ctx.restore(); } }; var CircleRaw = function( ctx, minRad, maxRad, theta){ var difRad; this.ctx = ctx; this.rad = {min : minRad, max: maxRad}; difRad = (maxRad - minRad); this.theta = theta; this.circleArr = []; for(var i = 0; i < this.rawNum; i++){ var rate = i / this.rawNum; var curRad = difRad * rate + minRad; var circle = new Circle( this.ctx, this.theta, curRad, maxRad); this.circleArr.push(circle); } this.count = theta; } CircleRaw.prototype = { rate : 0, rawNum : 20, count : 0, update : function(){ this.count += 0.04; for( var i = 0; i < this.rawNum; i++){ var circle = this.circleArr[i]; circle.update(this.count); } } } var Circle = function( ctx, theta, minRad, maxRad ){ this.ctx = ctx; this.theta = theta; this.curRad = minRad; this.minRad = minRad; this.maxRad = maxRad; this.difRad = (this.maxRad - this.minRad); }; Circle.prototype = { col : '#fff', rad : 2, update : function(count){ var rate = ( 1 + Math.sin(count))/2 * .8; // var otherRate = (1 + Math.cos(count * 2))/2; // var otherRate2 = (1 + Math.sin(count * 4))/2; var rad = this.difRad * rate + this.minRad; var xPos = rad * Math.cos(this.theta); var yPos = rad * Math.sin(this.theta); var col = parseInt(100 + 155 * rate); this.ctx.beginPath(); this.ctx.fillStyle = 'rgb( ' + col + ', ' + col + ', ' + col + ')'; this.ctx.arc( xPos, yPos, this.rad, 0, 2 * Math.PI, false); this.ctx.fill(); this.ctx.closePath(); } }; // ================ var shape; init(); loop(); function init(){ shape = new Shape( ctx, width/2, height/2); prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); shape.update(); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/1-illusion-of-life/3-stage.js ================================================ function backingScale(context) { if ('devicePixelRatio' in window) { if (window.devicePixelRatio > 1) { return window.devicePixelRatio; } } return 1; } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; var width, height, previousTime; var side1, side2; var rect, rect1, rect2; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var scaleFactor = backingScale(ctx); var Rect = function( ctx, i, x ){ var self = this; this.ctx = ctx; this.x = x; this.y = 0; this.i = i; this.y2 = window.innerHeight* scaleFactor - i * this.height3; this.height2 = this.y2 *0.8; this.wid = this.width1; this.hig = this.height1; setTimeout(function(){ self.verticalAnimation(); }, 500 * this.i); }; Rect.prototype = { color : '#fff', width1 : 50* scaleFactor, width2 : 90* scaleFactor, height1 : 50* scaleFactor, height2 : null, height3 : 30* scaleFactor, rad1 : 80 * scaleFactor, rad2 : 105 * scaleFactor, y2: null, duration1 : 0.4, duration2 : 0.3, duration3 : 0.2, lineRate1 : 0, lineRate2 : 0, isStage : false, reset : function(){ if(this.color == '#fff') this.color = '#333'; else this.color = '#fff'; var self = this; this.y = 0; this.y2 = window.innerHeight* scaleFactor - this.i * this.height3; this.height2 = this.y2 *0.8; this.wid = this.width1; this.hig = this.height1; setTimeout(function(){ self.verticalAnimation(); }, 400 * this.i); }, verticalAnimation : function(){ var self = this; this.lineRate1 = 0; this.lineRate2 = 0; TweenLite.to(this, this.duration1, {hig: this.height2, y: this.height2, ease: Power2.easeIn}); TweenLite.to(this, this.duration2, {y: this.y2, delay: this.duration1 }); TweenLite.to(this, this.duration2, {wid: this.width2, hig : this.height3, delay: this.duration1 }); TweenLite.to(this, this.duration3, {lineRate1 : 1, delay: this.duration1 + this.duration2, ease: Power3.easeInOut }); TweenLite.to(this, this.duration3, {lineRate2 : 1, delay: this.duration1 + this.duration2, ease: Power3.easeOut }); setTimeout(function(){ self.isStage = true; }, (this.duration1 + this.duration2) * 1000 ); setTimeout(function(){ self.isStage = false; }, (this.duration1 + this.duration2 + this.duration3) * 1000 ); }, draw : function(){ this.ctx.beginPath(); this.ctx.fillStyle = this.color; this.ctx.lineWidth = 3; this.ctx.save(); this.ctx.translate(this.x, this.y); this.ctx.fillRect(- this.wid / 2, -this.hig, this.wid, this.hig); this.ctx.closePath(); if(this.isStage){ for(var ii = 0; ii < 7; ii++){ var theta = (190 + 25 * ii)/180 * Math.PI; var rad1 = (this.rad2 - this.rad1) * this.lineRate1 + this.rad1; var rad2 = (this.rad2 - this.rad1) * this.lineRate2 + this.rad1; var x1 = Math.cos(theta) * rad1; var y1 = Math.sin(theta) * rad1; var x2 = Math.cos(theta) * rad2; var y2 = Math.sin(theta) * rad2; this.ctx.strokeStyle = '#999'; this.ctx.beginPath(); this.ctx.moveTo(x1, y1); this.ctx.lineTo(x2, y2); this.ctx.stroke(); this.ctx.closePath(); } } this.ctx.restore(); } }; // --------------- width = window.innerWidth * scaleFactor; height = window.innerHeight * scaleFactor; side1 = 100; side2 = 180; var duration1 = .8; var duration2 = .6; canvas.width = width; canvas.height = height; var isReset = false; var resetColor = '#333'; var rectWidth = 90 * scaleFactor; var rects = []; var rectNumber = parseInt(window.innerHeight / 30) + 1; init(); loop(); function init(){ for(var i = 0; i < rectNumber; i++){ var rectangle = new Rect( ctx, i, width/2); rects.push(rectangle); } setTimeout(function(){ reset() }, 500 * rectNumber + 500); } function reset(){ isReset = true; if(resetColor == '#fff') resetColor = '#333'; else resetColor = '#fff'; for(var i = 0; i < rectNumber; i++){ rects[i].reset(); } setTimeout(function(){ reset() }, 500 * rectNumber + 1000); } function loop(){ ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); if(isReset){ ctx.fillStyle = resetColor; ctx.fillRect((width - rectWidth)/2, 0, rectWidth, height); } for(var i = 0; i < rectNumber; i++){ rects[i].draw(); } requestAnimationFrame(loop); } ================================================ FILE: app/scripts/1-illusion-of-life/4-anticipation.js ================================================ function backingScale(context) { if ('devicePixelRatio' in window) { if (window.devicePixelRatio > 1) { return window.devicePixelRatio; } } return 1; } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; var width, height, previousTime; var side1, side2; var rect, rect1, rect2; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var scaleFactor = backingScale(ctx); var Rect = function( ctx, i, x ){ var self = this; this.ctx = ctx; this.x = x; this.y = 0; this.i = i; this.originX = x; this.wid = this.width1; this.hig = this.height1; if((i % 2) == 0 ){ setTimeout(function(){ self.anticipationAnimation(); }, 7 * 1000 * this.duration1); }else{ this.anticipationAnimation(); } }; Rect.prototype = { color : '#aaa', x : null, y : null, width1 : 10 * scaleFactor, width2 : 5 * scaleFactor, width3 : window.innerWidth / 10 * scaleFactor, height1 : window.innerHeight* scaleFactor, originX : null, y2: null, duration1 : 0.3, duration2 : 0.3, duration3 : 0.3, lineRate1 : 0, lineRate2 : 0, isStage : false, reset : function(){ if(this.color == '#fff') this.color = '#333'; else this.color = '#fff'; var self = this; this.y = 0; this.y2 = window.innerHeight* scaleFactor - this.i * this.height3; this.height2 = this.y2 *0.8; this.wid = this.width1; this.hig = this.height1; }, anticipationAnimation : function(){ var scaleX1 = 20 * scaleFactor; var scaleX2 = 20 * scaleFactor; var scaleX3 = 60 * scaleFactor; this.originX = this.x; if(this.originX < 0){ this.x = window.innerWidth * scaleFactor - this.originX; this.originX = this.x; } TweenLite.to(this, this.duration1, { x: this.originX - scaleX1, ease: Power3.easeInOut }); TweenLite.to(this, this.duration1, { x: this.originX + scaleX1, delay: this.duration1, ease: Power3.easeInOut}); TweenLite.to(this, this.duration2, { x: this.originX - scaleX2, delay: this.duration1 * 2, ease: Power3.easeInOut}); TweenLite.to(this, this.duration3, { x: this.originX + scaleX3, delay: this.duration1 * 2 + this.duration2, ease: Power3.easeInOut}); TweenLite.to(this, this.duration3, { wid: this.width2, x: this.originX + scaleX3 + (this.width1 - this.width2)/2 ,delay: this.duration1 * 4}); TweenLite.to(this, this.duration3, { wid: this.width3, x: this.originX + scaleX3 + (this.width1 - this.width3)/2 ,delay: this.duration1 * 5, ease: Power3.easeInOut}); TweenLite.to(this, this.duration3, { wid: this.width1, x: this.originX + scaleX3 + (this.width1 - this.width3) ,delay: this.duration1 * 6, ease: Power3.easeInOut}); var self = this; setTimeout(function(){ self.anticipationAnimation(); }, this.duration1 * 14 * 1000); }, verticalAnimation : function(){ var self = this; this.lineRate1 = 0; this.lineRate2 = 0; TweenLite.to(this, this.duration1, {hig: this.height2, y: this.height2, ease: Power2.easeIn}); TweenLite.to(this, this.duration2, {y: this.y2, delay: this.duration1 }); TweenLite.to(this, this.duration2, {wid: this.width2, hig : this.height3, delay: this.duration1 }); TweenLite.to(this, this.duration3, {lineRate1 : 1, delay: this.duration1 + this.duration2, ease: Power3.easeInOut }); TweenLite.to(this, this.duration3, {lineRate2 : 1, delay: this.duration1 + this.duration2, ease: Power3.easeOut }); setTimeout(function(){ self.isStage = true; }, (this.duration1 + this.duration2) * 1000 ); setTimeout(function(){ self.isStage = false; }, (this.duration1 + this.duration2 + this.duration3) * 1000 ); }, draw : function(){ this.ctx.beginPath(); this.ctx.fillStyle = this.color; this.ctx.lineWidth = 3; this.ctx.save(); this.ctx.translate(this.x, this.y); this.ctx.fillRect(- this.wid / 2, 0, this.wid, this.hig); this.ctx.closePath(); if(this.isStage){ for(var ii = 0; ii < 7; ii++){ var theta = (190 + 25 * ii)/180 * Math.PI; var rad1 = (this.rad2 - this.rad1) * this.lineRate1 + this.rad1; var rad2 = (this.rad2 - this.rad1) * this.lineRate2 + this.rad1; var x1 = Math.cos(theta) * rad1; var y1 = Math.sin(theta) * rad1; var x2 = Math.cos(theta) * rad2; var y2 = Math.sin(theta) * rad2; this.ctx.strokeStyle = '#999'; this.ctx.beginPath(); this.ctx.moveTo(x1, y1); this.ctx.lineTo(x2, y2); this.ctx.stroke(); this.ctx.closePath(); } } this.ctx.restore(); } }; // --------------- width = window.innerWidth * scaleFactor; height = window.innerHeight * scaleFactor; side1 = 100; side2 = 180; var duration1 = .8; var duration2 = .6; canvas.width = width; canvas.height = height; var rectangle; var isReset = false; var resetColor = '#333'; var rectWidth = 90 * scaleFactor; var rects = []; var rectNumber = parseInt(window.innerHeight / 30) + 1; var num = 40; init(); loop(); function init(){ for(var i = 0; i < num; i++){ rectangle = new Rect( ctx, i, width * (i + 1) / (num + 1)); rects.push(rectangle); } } function loop(){ ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); for(var i = 0; i < num; i++){ rects[i].draw(); } requestAnimationFrame(loop); } ================================================ FILE: app/scripts/1-illusion-of-life/5-pose-to-pos.js ================================================ function backingScale(context) { if ('devicePixelRatio' in window) { if (window.devicePixelRatio > 1) { return window.devicePixelRatio; } } return 1; } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; var width, height, previousTime; var side1, side2; var rect, rect1, rect2; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var scaleFactor = backingScale(ctx); var Form = function( ctx, x, y, rad ){ _.bindAll(this, 'onUpdateTween', 'onCompleteTween'); this.ctx = ctx; this.x = x; this.y = y; this.rad = rad; this.triangle(); this.rect(); this.circle(); this.formType = { 'triangle' : this.trianglePts, 'rectangle' : this.rectanglePts, 'circle' : this.circlePts }; this.curType = 'circle'; for(var i = 0; i < this.ptNumber; i++){ this.pts[i] = {x: this.x, y: this.y} } }; Form.prototype = { color : '#fff', ptNumber : 120, pts : [], oldPts : [], trianglePts : [], rectanglePts : [], circlePts : [], rate : 0, transform : function(toType){ this.rate = 0; this.toType = toType; TweenLite.to(this,.6, { rate: 1, ease: Power2.easeInOut, onComplete: this.onCompleteTween, onUpdate: this.onUpdateTween }); }, onUpdateTween : function(){ for(var i = 0;i < this.ptNumber; i++){ this.pts[i].x = ( 1- this.rate) * this.formType[this.curType][i].x + this.rate * this.formType[this.toType][i].x; this.pts[i].y = ( 1- this.rate) * this.formType[this.curType][i].y + this.rate * this.formType[this.toType][i].y; } }, onCompleteTween : function(){ for(var i = 0;i < this.ptNumber; i++){ this.pts[i].x = this.formType[this.toType][i].x; this.pts[i].y = this.formType[this.toType][i].y; } this.curType = this.toType; }, triangle : function(){ var x, y, rate, pt; var pt0 = { x : this.rad * Math.cos(30 / 180 * Math.PI), y : this.rad * Math.sin(30 / 180 * Math.PI)}; var pt1 = { x : this.rad * Math.cos(150 / 180 * Math.PI), y : this.rad * Math.sin(150 / 180 * Math.PI)}; var pt2 = { x : this.rad * Math.cos(270 / 180 * Math.PI), y : this.rad * Math.sin(270/ 180 * Math.PI)}; for(var i = 0; i < this.ptNumber; i++){ if(i < this.ptNumber / 6){ rate = .5 + i / (this.ptNumber / 6) * .5; x = pt0.x * (1 - rate) + pt1.x * rate; y = pt0.y * (1 - rate) + pt1.y * rate; }else if(i >= this.ptNumber /6 && i < this.ptNumber / 2){ rate = (i - this.ptNumber/6) / (this.ptNumber / 3); x = pt1.x * (1 - rate) + pt2.x * rate; y = pt1.y * (1 - rate) + pt2.y * rate; }else if(i >= this.ptNumber /2 && i < this.ptNumber * 5 /6){ rate = (i - this.ptNumber/2) / (this.ptNumber / 3); x = pt2.x * (1 - rate) + pt0.x * rate; y = pt2.y * (1 - rate) + pt0.y * rate; }else{ rate = (i - this.ptNumber * 5/6) / (this.ptNumber / 3); x = pt0.x * (1 - rate) + pt1.x * rate; y = pt0.y * (1 - rate) + pt1.y * rate; } pt = {x : x + this.x, y: y + this.y}; this.trianglePts.push(pt); } }, rect : function(){ var theta, pt; var side = this.rad * Math.cos(45 / 180 * Math.PI); for(var i = 0; i < this.ptNumber; i++){ if(i < this.ptNumber / 8){ pt = {x : side , y : side * i / (this.ptNumber / 8) }; }else if(i >= this.ptNumber/8 && i < this.ptNumber * 3 / 8){ pt = {x : side - side * (i - this.ptNumber / 8) / (this.ptNumber / 8), y : side }; }else if( i >= this.ptNumber * 3 / 8 && i < this.ptNumber * 5 / 8) { pt = {x : -side , y : side - side * (i - 3 * this.ptNumber / 8) / (this.ptNumber / 8) }; }else if( i >= this.ptNumber * 5 / 8 && i < this.ptNumber * 7 / 8) { pt = {x :-side + side * (i - 5 * this.ptNumber / 8) / (this.ptNumber / 8), y: -side}; }else{ pt = {x : side, y : -side + side * (i - 7 * this.ptNumber / 8) / (this.ptNumber / 8)}; } pt.x += this.x; pt.y += this.y; this.rectanglePts.push(pt); } }, circle : function(){ var theta, pt; this.nextPts = []; for(var i = 0; i < this.ptNumber; i++){ theta = i / this.ptNumber * 2 * Math.PI; pt = {x : this.rad * Math.cos(theta) + this.x, y : this.rad * Math.sin(theta) + this.y}; this.circlePts[i] = pt; } }, draw : function(){ this.ctx.fillStyle = this.color; this.ctx.beginPath(); this.ctx.moveTo(this.pts[0].x, this.pts[0].y); for(var i = 1; i < this.pts.length; i++){ this.ctx.lineTo(this.pts[i].x, this.pts[i].y); } this.ctx.fill(); this.ctx.closePath(); }, }; // --------------- width = window.innerWidth * scaleFactor; height = window.innerHeight * scaleFactor; side1 = 100; side2 = 180; var duration1 = .8; var duration2 = .6; var types = ['triangle','rectangle', 'circle']; canvas.width = width; canvas.height = height; var form; init(); loop(); function init(){ form = new Form(ctx, width / 2, height / 2, Math.sqrt( width* width /20+ height * height / 20)); var nextType = form.curType; while(nextType == form.curType){ nextType = types[parseInt(types.length * Math.random())]; } console.log(nextType); form.transform(nextType); setInterval(function(){ var nextType = form.curType; while(nextType == form.curType){ nextType = types[parseInt(types.length * Math.random())]; } form.transform(nextType); }, 800); } function loop(){ ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); form.draw(); requestAnimationFrame(loop); } ================================================ FILE: app/scripts/1-illusion-of-life/6-pose-to-pose.js ================================================ function backingScale(context) { if ('devicePixelRatio' in window) { if (window.devicePixelRatio > 1) { return window.devicePixelRatio; } } return 1; } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; var width, height, previousTime; var side1, side2; var rect, rect1, rect2; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var scaleFactor = backingScale(ctx); var Forms = function(ctx, x, y){ _.bindAll(this, 'onUpdateInitTween', 'onCompleteInitTween', 'onUpdateIncrementTween', 'onCompleteIncrementTween', 'increment'); this.MAX_RAD = Math.min(window.innerWidth / 3, window.innerHeight / 3); this.ctx = ctx; this.x = x; this.y = y; this.currentNumber = 0; this.pointNumber = 288 * 3; this.numberArr = [1, 4, 9, 16]; this.isTransfrom = false; this.initialize(); this.pts = []; //types = ['triangle','rectangle', 'circle']; this.formType = { 'triangle' : this.trianglePts, 'rectangle' : this.rectanglePts, 'circle' : this.circlePts }; this.currentType = ['circle']; for(var i = 0; i < this.pointNumber; i++){ this.pts[i] = {x: this.x, y: this.y} }; }; Forms.prototype = { color : '#fff', trianglePts : [], rectanglePts : [], circlePts : [], initialize : function(){ this.initializeCircle(); this.initializeAnimation(); }, initializeCircle : function(){ var side, number, pointNumber, rad, centerPoint; var points, theta, pt; var arr = this.numberArr; for(var i = 0; i < arr.length; i++){ number = this.numberArr[i]; side = Math.sqrt(arr[i]); rad = this.MAX_RAD / side; pointNumber = this.pointNumber / side; // 1 2 3 4 points = []; console.log(this.x); console.log(side); for(var x = 0; x < side; x++){ for(var y = 0; y < side; y++){ var center = (side - 1)/ 2; centerPoint = { x : this.x + 2 * rad * (x - center), y : this.y + 2 * rad * (y - center) }; for(var j = 0; j < (this.pointNumber / number); j++){ theta = j / (this.pointNumber / number) * 2 * Math.PI; pt = {x : rad * Math.cos(theta) + centerPoint.x, y : rad * Math.sin(theta) + centerPoint.y}; points.push(pt); } } } this.circlePts.push(points); } }, initializeAnimation : function(){ this.rate = 01 this.toType = 'circle'; TweenLite.to(this,.6, { rate: 0, ease: Power2.easeInOut, onComplete: this.onCompleteInitTween, onUpdate: this.onUpdateInitTween }); }, onUpdateInitTween : function(){ for(var i = 0;i < this.pointNumber; i++){ this.pts[i].x = (1-this.rate) * this.formType[this.toType][this.currentNumber][i].x + (this.rate) * this.x; this.pts[i].y = (1-this.rate) * this.formType[this.toType][this.currentNumber][i].y + (this.rate) * this.y; } }, onCompleteInitTween : function(){ for(var i = 0;i < this.pointNumber; i++){ this.pts[i].x = this.formType[this.toType][this.currentNumber][i].x; this.pts[i].y = this.formType[this.toType][this.currentNumber][i].y; } this.curType = this.toType; var self = this; setTimeout(function(){ self.increment(); }, 300); }, increment : function(){ this.currentNumber = (this.currentNumber + 1) % this.numberArr.length ; this.isTransfrom = true; this.rate = 0; TweenLite.to(this, .6, { rate: 1, ease: Power2.easeInOut, onComplete: this.onCompleteIncrementTween, onUpdate: this.onUpdateIncrementTween }); }, onUpdateIncrementTween : function(){ var prevNumber = this.currentNumber - 1; if(prevNumber < 0) prevNumber += this.numberArr.length; for(var i = 0;i < this.pointNumber; i++){ this.pts[i].x = this.rate * this.formType[this.toType][this.currentNumber][i].x + (1 - this.rate) * this.formType[this.toType][prevNumber][i].x; this.pts[i].y = this.rate * this.formType[this.toType][this.currentNumber][i].y + (1 - this.rate) * this.formType[this.toType][prevNumber][i].y; } }, onCompleteIncrementTween : function(){ this.isTransfrom = false; for(var i = 0;i < this.pointNumber; i++){ this.pts[i].x = this.formType[this.toType][this.currentNumber][i].x; this.pts[i].y = this.formType[this.toType][this.currentNumber][i].y; } TweenLite.to(this, .6, { rate: 0, ease: Power2.easeInOut, onComplete: this.increment}); }, draw : function(){ if(this.isTransfrom){ var previousNumber = this.currentNumber - 1; if(previousNumber < 0) previousNumber += this.numberArr.length; currentNumber = this.numberArr[previousNumber]; inc = this.pointNumber / currentNumber; for(var i = 0; i < this.pointNumber ; i+= inc){ this.ctx.fillStyle = 'rgba(255, 255, 255, ' + (1-this.rate) + ")" ; this.ctx.beginPath(); this.ctx.moveTo(this.pts[i].x, this.pts[i].y); for(var j = 1; j < inc; j++){ this.ctx.lineTo(this.pts[i + j].x, this.pts[i + j].y); } this.ctx.fill(); this.ctx.closePath(); } }else{ var currentNumber = this.numberArr[this.currentNumber]; var inc = this.pointNumber / currentNumber; for(var i = 0; i < this.pointNumber ; i+= inc){ this.ctx.fillStyle = 'rgba(255, 255, 255, ' + (1-this.rate )+ ")" ; this.ctx.beginPath(); this.ctx.moveTo(this.pts[i].x, this.pts[i].y); for(var j = 1; j < inc; j++){ this.ctx.lineTo(this.pts[i + j].x, this.pts[i + j].y); } this.ctx.fill(); this.ctx.closePath(); } } } }; // --------------- width = window.innerWidth * scaleFactor; height = window.innerHeight * scaleFactor; side1 = 100; side2 = 180; var duration1 = .8; var duration2 = .6; var types = ['triangle','rectangle', 'circle']; canvas.width = width; canvas.height = height; var forms; init(); loop(); function init(){ forms = new Forms(ctx, width / 2, height / 2 ); } function loop(){ ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); forms.draw(); requestAnimationFrame(loop); } ================================================ FILE: app/scripts/1-illusion-of-life/7-pose-to-pose.js ================================================ function backingScale(context) { if ('devicePixelRatio' in window) { if (window.devicePixelRatio > 1) { return window.devicePixelRatio; } } return 1; } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; var width, height, previousTime; var side1, side2; var rect, rect1, rect2; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var scaleFactor = backingScale(ctx); var Form = function( ctx, x, y, rad ){ _.bindAll(this, 'onUpdateTween', 'onCompleteTween'); this.ctx = ctx; this.x = x; this.y = y; this.rad = rad; this.triangle(); this.rect(); this.circle(); this.formType = { 'triangle' : this.trianglePts, 'rectangle' : this.rectanglePts, 'circle' : this.circlePts }; this.curType = 'circle'; for(var i = 0; i < this.ptNumber; i++){ this.pts[i] = {x: this.x, y: this.y} } }; Form.prototype = { color : '#fff', ptNumber : 120, pts : [], oldPts : [], trianglePts : [], rectanglePts : [], circlePts : [], rate : 0, transform : function(toType){ this.rate = 0; this.toType = toType; TweenLite.to(this,.6, { rate: 1, ease: Power2.easeInOut, onComplete: this.onCompleteTween, onUpdate: this.onUpdateTween }); }, onUpdateTween : function(){ for(var i = 0;i < this.ptNumber; i++){ this.pts[i].x = ( 1- this.rate) * this.formType[this.curType][i].x + this.rate * this.formType[this.toType][i].x; this.pts[i].y = ( 1- this.rate) * this.formType[this.curType][i].y + this.rate * this.formType[this.toType][i].y; } }, onCompleteTween : function(){ for(var i = 0;i < this.ptNumber; i++){ this.pts[i].x = this.formType[this.toType][i].x; this.pts[i].y = this.formType[this.toType][i].y; } this.curType = this.toType; }, triangle : function(){ var x, y, rate, pt; var pt0 = { x : this.rad * Math.cos(30 / 180 * Math.PI), y : this.rad * Math.sin(30 / 180 * Math.PI)}; var pt1 = { x : this.rad * Math.cos(150 / 180 * Math.PI), y : this.rad * Math.sin(150 / 180 * Math.PI)}; var pt2 = { x : this.rad * Math.cos(270 / 180 * Math.PI), y : this.rad * Math.sin(270/ 180 * Math.PI)}; for(var i = 0; i < this.ptNumber; i++){ if(i < this.ptNumber / 6){ rate = .5 + i / (this.ptNumber / 6) * .5; x = pt0.x * (1 - rate) + pt1.x * rate; y = pt0.y * (1 - rate) + pt1.y * rate; }else if(i >= this.ptNumber /6 && i < this.ptNumber / 2){ rate = (i - this.ptNumber/6) / (this.ptNumber / 3); x = pt1.x * (1 - rate) + pt2.x * rate; y = pt1.y * (1 - rate) + pt2.y * rate; }else if(i >= this.ptNumber /2 && i < this.ptNumber * 5 /6){ rate = (i - this.ptNumber/2) / (this.ptNumber / 3); x = pt2.x * (1 - rate) + pt0.x * rate; y = pt2.y * (1 - rate) + pt0.y * rate; }else{ rate = (i - this.ptNumber * 5/6) / (this.ptNumber / 3); x = pt0.x * (1 - rate) + pt1.x * rate; y = pt0.y * (1 - rate) + pt1.y * rate; } pt = {x : x + this.x, y: y + this.y}; this.trianglePts.push(pt); } }, rect : function(){ var theta, pt; var side = this.rad * Math.cos(45 / 180 * Math.PI); for(var i = 0; i < this.ptNumber; i++){ if(i < this.ptNumber / 8){ pt = {x : side , y : side * i / (this.ptNumber / 8) }; }else if(i >= this.ptNumber/8 && i < this.ptNumber * 3 / 8){ pt = {x : side - side * (i - this.ptNumber / 8) / (this.ptNumber / 8), y : side }; }else if( i >= this.ptNumber * 3 / 8 && i < this.ptNumber * 5 / 8) { pt = {x : -side , y : side - side * (i - 3 * this.ptNumber / 8) / (this.ptNumber / 8) }; }else if( i >= this.ptNumber * 5 / 8 && i < this.ptNumber * 7 / 8) { pt = {x :-side + side * (i - 5 * this.ptNumber / 8) / (this.ptNumber / 8), y: -side}; }else{ pt = {x : side, y : -side + side * (i - 7 * this.ptNumber / 8) / (this.ptNumber / 8)}; } pt.x += this.x; pt.y += this.y; this.rectanglePts.push(pt); } }, circle : function(){ var theta, pt; this.nextPts = []; for(var i = 0; i < this.ptNumber; i++){ theta = i / this.ptNumber * 2 * Math.PI; pt = {x : this.rad * Math.cos(theta) + this.x, y : this.rad * Math.sin(theta) + this.y}; this.circlePts[i] = pt; } }, draw : function(){ this.ctx.fillStyle = this.color; this.ctx.beginPath(); this.ctx.moveTo(this.pts[0].x, this.pts[0].y); for(var i = 1; i < this.pts.length; i++){ this.ctx.lineTo(this.pts[i].x, this.pts[i].y); } this.ctx.fill(); this.ctx.closePath(); }, }; var Panel = function(ctx, y){ this.ctx = ctx; this.y = y; this.height = 30 * scaleFactor; this.pts = []; window.pts = this.pts; } Panel.prototype = { count : 0, draw : function(form){ // calculate the rate var newPtArr = []; this.count++; if(this.count % 15 == 0){ for(var i = 0; i < form.pts.length; i++){ var pt = form.pts[i]; var xRate = ( pt.x - (form.x - form.rad) ) / (form.rad * 2); var yRate = ( pt.y - (form.y - form.rad) ) / (form.rad * 2); var posX = window.innerWidth * scaleFactor + xRate*this.height ; var posY = yRate * this.height + this.y; var newPt = {x : posX, y: posY}; newPtArr.push(newPt); } this.pts.push(newPtArr); } for(var i = 0; i < this.pts.length; i++){ var ptArr = this.pts[i]; for(var j = 0; j < ptArr.length; j++){ //var pt = ptArr[j]; ptArr[j].x -= 1; } } this.ctx.strokeStyle = 'rgba(255, 255, 255, .6)'; this.ctx.beginPath(); for(var i = 0; i < this.pts.length; i++){ var ptArr = this.pts[i]; this.ctx.moveTo( ptArr[0].x, ptArr[0].y); for(var j = 1; j < ptArr.length; j++){ this.ctx.lineTo(ptArr[j].x, ptArr[j].y); } } this.ctx.stroke(); this.ctx.closePath(); } }; // --------------- width = window.innerWidth * scaleFactor; height = window.innerHeight * scaleFactor; side1 = 100; side2 = 180; var duration1 = .8; var duration2 = .6; var types = ['triangle','rectangle', 'circle']; canvas.width = width; canvas.height = height; var form; var panel; init(); loop(); function init(){ var rad = Math.min( width/3, height/3); form = new Form(ctx, width / 2, height / 2, rad ); panel = new Panel(ctx, height / 2 + rad + 30 * scaleFactor); var nextType = form.curType; while(nextType == form.curType){ nextType = types[parseInt(types.length * Math.random())]; } form.transform(nextType); setInterval(function(){ var nextType = form.curType; while(nextType == form.curType){ nextType = types[parseInt(types.length * Math.random())]; } form.transform(nextType); }, 800); } function loop(){ ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); form.draw(); panel.draw(form); requestAnimationFrame(loop); } ================================================ FILE: app/scripts/1-illusion-of-life/8-arcs.js ================================================ function backingScale(context) { if ('devicePixelRatio' in window) { if (window.devicePixelRatio > 1) { return window.devicePixelRatio; } } return 1; } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; var Rect = function( ctx, x, y, wid, hig, rad, i ){ _.bindAll(this, 'tweenOnUpdate1', 'tweenOnComplete1'); this.ctx = ctx; this.x = x; this.y = y; this.wid = wid; this.hig = hig; this.vel = 100; this.arcRate = 0; this.rad1 = 100 * scaleFactor; this.rad2 = rad; this.isArcAnimation = false; this.duration1 = i * .05; var col = 255 - parseInt(255 / 100 * i); this.col = 'rgb(' + col + ', ' + col + ', ' + col + ')'; }; Rect.prototype = { duration1 : 1, isArcAnimation : null, draw : function(){ this.ctx.beginPath(); this.ctx.fillStyle = this.col; this.ctx.save(); this.ctx.translate(this.x, this.y); if(this.isArcAnimation){ this.ctx.moveTo(0, 0); this.ctx.arc(0, 0, this.rad2, this.theta1, this.theta2 ); this.ctx.fill(); this.ctx.closePath(); this.ctx.beginPath(); this.ctx.fillStyle = '#333'; this.ctx.moveTo(0, 0); this.ctx.arc(0, 0, this.rad1, 0, 2 * Math.PI ); this.ctx.fill(); this.ctx.closePath(); }else{ this.ctx.fillRect( this.rad1 , -this.hig, this.wid, this.hig); } this.ctx.restore(); }, startArcAnimation : function(){ this.isArcAnimation = true; this.arcRate = 0; TweenLite.to(this, this.duration1, { arcRate : 1, onUpdate: this.tweenOnUpdate1, onComplete: this.tweenOnComplete1 }); }, tweenOnUpdate1 : function(){ this.theta1 = this.arcRate * Math.PI * -1 + 2 * Math.PI; this.theta2 = this.arcRate * this.arcRate * this.arcRate * Math.PI * -1 + 2 * Math.PI; }, tweenOnComplete1 : function(){ } }; var width, height, previousTime; var side1, side2; var side1Wid, side1Hig; var rect; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var scaleFactor = backingScale(ctx); var arcs = []; width = window.innerWidth * scaleFactor; height = window.innerHeight * scaleFactor; side1 = 100; side2 = 180; //side1Wid = 100; side1Wid = 200; side1Hig = 50; var duration1 = .8; var duration2 = .6; canvas.width = width; canvas.height = height; init(); loop(); function init(){ var rad = Math.min(width/2, height/2); for(var i = 0;i < 100; i++){ rect = new Rect(ctx, width/2, height, side1Wid, side1Hig, rad/100* (1 + i), i); rect.startArcAnimation(); arcs.push(rect); } setInterval(function(){ for(var i = 0; i < arcs.length; i++){ arcs[i].startArcAnimation(); } }, 100 *.05 * 1000); } function loop(){ ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); for(var i = 0;i < arcs.length; i++){ arcs[i].draw(); } requestAnimationFrame(loop); } ================================================ FILE: app/scripts/1-illusion-of-life/9-arcs.js ================================================ function backingScale(context) { if ('devicePixelRatio' in window) { if (window.devicePixelRatio > 1) { return window.devicePixelRatio; } } return 1; } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; var Rect = function( i, ctx, x, y, prevWid, wid, hig ){ _.bindAll(this, 'tweenOnUpdate1', 'tweenOnUpdate2', 'tweenOnComplete1'); this.ctx = ctx; this.x = x; this.y = y; this.wid = (wid-prevWid); this.hig = hig; this.vel = 100; this.arcRate = 0; this.oriRad1 = this.rad1 = prevWid + 10*scaleFactor; this.oriRad2 = this.rad2 = this.rad1 + this.wid; this.theta3 = Math.atan2( this.hig, this.rad2); this.theta4 = Math.atan2( this.hig, this.rad1); //console.log(this.theta4) this.animTheta0 = 0; this.animTheta1 = 0; this.animTheta3 = 0; this.animTheta4 = 0; this.theta00 = 0; this.theta11 = 0; this.oriRad3 = this.rad3 = 1/Math.cos(this.theta3) * (this.rad2); this.oriRad4 = this.rad4 = 1/Math.cos(this.theta4) * (this.rad1); this.isReverse = false; this.isArcAnimation = false; this.id = i; //var col = parseInt(255 * i / (number - 1)); var col = 255; this.col = 'rgb(' + col + ', ' + col + ', ' + col + ')'; this.delay = .3 * (number - i) / (number - 1); }; var co = Math.cos; var si = Math.sin; Rect.prototype = { duration1 :.5, duration2 : .4, isArcAnimation : null, draw : function(){ this.ctx.beginPath(); this.ctx.fillStyle = this.col; this.ctx.save(); this.ctx.translate(this.x, this.y); this.ctx.moveTo(this.rad1 * co( this.theta00 + this.animTheta0 ), -this.rad1 * si( this.theta00 + this.animTheta0) ); this.ctx.lineTo(this.rad2 * co( this.theta11 + this.animTheta1 ), -this.rad2 * si( this.theta11 + this.animTheta1) ); this.ctx.lineTo(this.rad3 * co( this.theta3 + this.animTheta3 + this.theta11), -this.rad3 * si(this.theta3 + this.animTheta3 + this.theta11) ); this.ctx.lineTo(this.rad4 * co( this.theta4 + this.animTheta4 + this.theta00), -this.rad4 * si(this.theta4 + this.animTheta4 + this.theta00) ); this.ctx.fill(); this.ctx.restore(); }, startArcAnimation : function(){ var self = this; setTimeout(function(){ self.isArcAnimation = true; self.arcRate1 = 0; self.arcRate2 = 0; self.originaLRate1 = 0; self.originaLRate2 = 0; TweenLite.to(self, self.duration1 +.03 * self.id, { arcRate1 : self.arcRate1 +1, onUpdate: self.tweenOnUpdate1, ease: Power3.easeOut}); TweenLite.to(self, self.duration2 +.03 * self.id, { arcRate2 : self.arcRate1 +1, onUpdate: self.tweenOnUpdate2, onComplete: self.tweenOnComplete1}); }, 300); }, tweenOnUpdate1 : function(){ //this.theta1 = this.arcRate1 * (Math.PI - this.theta11) * -1 + 2 * Math.PI - this.theta; this.animTheta3 = this.arcRate1 *Math.PI ; this.animTheta4 = this.arcRate1 *Math.PI ; //this.rad4 = this.oriRad4 * (1-this.arcRate1 + this.originaLRate1) + this.oriRad1 * (this.arcRate1 - this.originaLRate1); //this.rad3 = this.oriRad3 * (1-this.arcRate1 + this.originaLRate1) + this.oriRad2 * (this.arcRate1 - this.originaLRate1) }, tweenOnUpdate2 : function(){ //this.theta2 = this.arcRate2 * (Math.PI - this.theta) * -1 + 2 * Math.PI ; this.animTheta0 = this.arcRate2 *Math.PI ; this.animTheta1 = this.arcRate2 *Math.PI ; //this.rad1 = this.oriRad1 * (1-this.arcRate2 + this.originaLRate2) + this.oriRad4 * (this.arcRate2 - this.originaLRate2); //this.rad2 = this.oriRad2 * (1-this.arcRate2 + this.originaLRate2) + this.oriRad3 * (this.arcRate2 - this.originaLRate2); }, tweenOnComplete1 : function(){ this.originaLRate1 = this.arcRate1; this.originaLRate2 = this.arcRate2; TweenLite.to(this, this.duration1 +.03 * this.id, { arcRate1 : this.arcRate1 + 1, onUpdate: this.tweenOnUpdate1, ease: Power3.easeOut, delay: this.delay}); TweenLite.to(this, this.duration2 +.03 * this.id, { arcRate2 : this.arcRate2 + 1, onUpdate: this.tweenOnUpdate2, onComplete: this.tweenOnComplete1, delay: this.delay}); }, test : function(){ } }; var width, height, previousTime; var side1, side2; var side1Wid, side1Hig; var rect; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var scaleFactor = backingScale(ctx); var arcs = []; width = window.innerWidth * scaleFactor; height = window.innerHeight * scaleFactor; side1 = 100; side2 = 180; //side1Wid = 100; var number = 30; var sideHig = 10 * scaleFactor; var duration1 = .8; var duration2 = .6; canvas.width = width; canvas.height = height; init(); loop(); function init(){ var prevRad = 10*scaleFactor; for(var i = 0; i < number; i++){ var rad = (i + 1) / number * (width/3 - 10 * scaleFactor) + 10 * scaleFactor; rect = new Rect(i, ctx, width/2, height/2, prevRad, rad, sideHig); rect.startArcAnimation(); arcs.push(rect); prevRad = rad; } } function loop(){ ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); for(var i = number; i > 0; i--){ arcs[i-1].draw() } requestAnimationFrame(loop); } ================================================ FILE: app/scripts/2-numbers/24-number0.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var Point = function(x, y){ this.x = this.origX = x; this.y = this.origY = y; }; var AnimationPoint = function(ctx){ this.ctx = ctx; this.x = this.origX = width/2; this.y = this.origY = height/2; this.isDraw = true; }; AnimationPoint.prototype = { rad1 : height/2 * .6, theta1 : 0, rad2 : width /2 * .6, theta2 : 0, rad : 3, update : function(){ this.theta1 += .04; this.theta2 += .02; this.x = this.origX + this.rad2 * Math.cos(this.theta2); this.y = this.origY + this.rad1 * Math.sin(this.theta1); if(this.isDraw) this.draw(); }, draw : function(){ this.ctx.beginPath(); this.ctx.fillStyle = '#fff'; this.ctx.arc(this.x, this.y, this.rad, 0, 2 * Math.PI, false); this.ctx.fill(); this.ctx.closePath(); } }; var DIVIDE_X = 20; var DIVIDE_Y = 20; var Shape = function(ctx){ this.ctx = ctx; this.nodeArr = []; for(var i = 0; i < this.ny; i++){ this.nodeArr[i] = []; for(var j = 0; j < this.nx; j++){ var node = new Node(); node.ox = node.x = i * width / DIVIDE_X; node.oy = node.y = j * height/ DIVIDE_Y; this.nodeArr[i].push(node); } } for(var i = 0; i < this.ny; i++){ for(var j = 0; j < this.nx; j++){ node = this.nodeArr[i][j]; var bounds = []; bounds[0] = (i == 0) ? true : false; bounds[1] = (j == this.nx-1) ? true : false; bounds[2] = (i == this.ny-1) ? true : false; bounds[3] = (j == 0) ? true : false; // ===================== node.nn[0] = ( bounds[0] ) ? null : this.nodeArr[i - 1][j ]; node.nn[1] = ( bounds[0] || bounds[1] ) ? null : this.nodeArr[i - 1][j + 1]; node.nn[2] = ( bounds[1] ) ? null : this.nodeArr[i ][j + 1]; node.nn[3] = ( bounds[1] || bounds[2] ) ? null : this.nodeArr[i + 1][j + 1]; node.nn[4] = ( bounds[2] ) ? null : this.nodeArr[i + 1][j ]; node.nn[5] = ( bounds[3] || bounds[2] ) ? null : this.nodeArr[i + 1][j + 1]; node.nn[6] = ( bounds[3] ) ? null : this.nodeArr[i ][j - 1]; node.nn[7] = ( bounds[3] || bounds[0] ) ? null : this.nodeArr[i - 1][j - 1]; var isFirst, oldNode; if(!this.first){ this.first = node; oldNode = node; }else{ oldNode.next = node; oldNode = node; } } } }; Shape.prototype = { first : null, col : '#444', count : 0, nx : DIVIDE_X + 1, ny : DIVIDE_Y + 1, SPRING : .2, FRICTION : .05, nodeArr : null, update : function(pt){ var dx, dy, dist; var node = this.first; do{ dx = node.ox - pt.x; dy = node.oy - pt.y; dist = Math.sqrt(dx * dx + dy * dy) + 1; tx = node.ox + dx / dist * 10; ty = node.oy + dy / dist * 10; node.vx += (tx - node.x) * this.SPRING; node.vy += (ty - node.y) * this.SPRING; node.x += node.vx * this.FRICTION; node.y += node.vy * this.FRICTION; }while(node = node.next); this.draw(); }, draw : function(){ var n1, n2, n3, n4; var node = this.first; this.count += 1; var col = this.count % 255; this.ctx.save(); this.ctx.globalAlpha = .1; this.ctx.beginPath(); this.ctx.strokeStyle = 'hsl(' + col + ', 100%, 70%)'; do{ var px = node.x; var py = node.y; n1 = node.nn[1]; n2 = node.nn[2]; n3 = node.nn[3]; n4 = node.nn[4]; if(n1){ this.ctx.beginPath(); this.ctx.moveTo(px, py); this.ctx.lineTo(n1.x, n1.y); this.ctx.stroke(); this.ctx.closePath(); } if(n2){ this.ctx.beginPath(); this.ctx.moveTo(px, py); this.ctx.lineTo(n2.x, n2.y); this.ctx.stroke(); this.ctx.closePath(); } if(n3){ this.ctx.beginPath(); this.ctx.moveTo(px, py); this.ctx.lineTo(n3.x, n3.y); this.ctx.stroke(); this.ctx.closePath(); } if(n4){ this.ctx.beginPath(); this.ctx.moveTo(px, py); this.ctx.lineTo(n4.x, n4.y); this.ctx.stroke(); this.ctx.closePath(); } }while(node = node.next); this.ctx.restore(); } }; var Node = function(){ this.nn = []; } Node.prototype = { x : 0, y : 0, vx: 0, vy: 0, ox: 0, oy: 0, nn : null, next : null, }; // ================ var animationPt; var shape; init(); loop(); function init(){ shape = new Shape(ctx); animationPt = new AnimationPoint( ctx); ctx.fillStyle = 'rgb(30, 30, 30)'; ctx.fillRect(0, 0, width, height); prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = 'rgba(30, 30, 30, .1)'; ctx.fillRect(0, 0, width, height); animationPt.update(); shape.update(animationPt); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/2-numbers/25-number0.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var NumberZero = function(ctx){ 'use strict'; this.ctx = ctx; this.x = width/2; this.y = height/2; }; NumberZero.prototype = { update : function(){ 'use strict'; this.ctx.beginPath(); this.ctx.stroke(); this.ctx. } }; // ================ var shape; init(); loop(); function init(){ shape = new NumberZero(ctx): prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); shape.update(duration); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/3-algorithm/-1-43-undefined-botsu.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ VectorManipulator = { sub : function(main, other){ var x = main.x - other.x; var y = main.y - other.y; var vec = new Vector(x, y); return vec; } }; var Vector = function(x, y){ this.x = x || 0; this.y = y || 0; }; Vector.prototype = { sub : function(vec){ this.x = this.x - vec.x; this.y = this.y - vec.y; }, add : function(vec){ this.x = this.x + vec.x; this.y = this.y + vec.y; }, mag : function(){ var magnitude = Math.sqrt(this.x * this.x + this.y * this.y); return magnitude; }, getAngle : function(){ var theta = Math.atan2(this.y, this.x); return theta; } }; var friction = 1; // ---------------- var Circle = function(x, y, rad){ this.rad = rad; this.velocity = new Vector(); this.position = new Vector(x, y); }; Circle.prototype = { g : 1, m : 1, rad : null, velocity : null, position : null, setVelocity : function(x, y){ this.velocity.x = x; this.velocity.y = y; }, setMass : function(val){ this.m = val; }, update : function(){ this.velocity.y += this.g; this.position.add(this.velocity); this.updateForBoarder(); }, updateForBoarder : function(){ var dis; var masatsu = .8; if(this.position.x -this.rad < 0){ dis = -1 * (this.position.x - this.rad); this.position.x += dis; this.velocity.x *= -masatsu; } if(this.position.x + this.rad > width){ dis = this.position.x + this.rad - width; this.position.x -= dis; this.velocity.x *= -masatsu; } if(this.position.y - this.rad < 1/3 * height){ dis = -1 * (this.position.y - this.rad); this.position.y += dis; this.velocity.y *= -masatsu; } if(this.position.y + this.rad > height){ dis = this.position.y + this.rad - height; this.position.y -= dis; this.velocity.y *= -masatsu; } }, checkCollision : function(circle){ var bVector = VectorManipulator.sub( circle.position, this.position); var dis = bVector.mag(); //console.log(circle.rad); if(dis < this.rad + circle.rad){ var theta = bVector.getAngle(); var sine = Math.sin(theta); var cosine = Math.cos(theta); var tempVec0 = new Vector(); var tempVec1 = new Vector(); tempVec1.x = cosine * bVector.x + sine * bVector.y; tempVec1.y = cosine * bVector.y - sine * bVector.x; var vTempVec0 = new Vector(); var vTempVec1 = new Vector(); vTempVec0.x = cosine * this.velocity.x + sine * this.velocity.y; vTempVec0.y = cosine * this.velocity.y - sine * this.velocity.x; vTempVec1.x = cosine * circle.velocity.x + sine * circle.velocity.y; vTempVec1.y = cosine * circle.velocity.y - sine * circle.velocity.x; var vFinal0 = new Vector(); var vFinal1 = new Vector(); //vFinal0.x = ((this.m - circle.m) * vTempVec0.x + 2 * circle.m * vTempVec1.x) / (this.m + circle.m); vFinal0.x = ((this.m - friction * circle.m) * vTempVec0.x + (1 + friction) * circle.m * vTempVec1.x) / (this.m + circle.m); vFinal0.y = vTempVec1.y; // final rotated velocity for b[0] vFinal1.x = ((circle.m - friction * this.m) * vTempVec1.x + (friction + 1) * this.m * vTempVec0.x) / (this.m + circle.m); vTempVec1.y = vTempVec1.y; tempVec0.x += vFinal0.x; tempVec1.x += vFinal1.x; var bFinal0 = new Vector(); var bFinal1 = new Vector(); bFinal0.x = cosine * tempVec0.x - sine * tempVec0.y; bFinal0.y = cosine * tempVec0.y + sine * tempVec0.x; bFinal1.x = cosine * tempVec1.x - sine * tempVec1.y; bFinal1.y = cosine * tempVec1.y + sine * tempVec1.x; circle.position.x = this.position.x + bFinal1.x; circle.position.y = this.position.y + bFinal1.y; this.position.add(bFinal0); this.velocity.x = cosine * vFinal0.x - sine * vFinal0.y; this.velocity.y = cosine * vFinal0.y + sine * vFinal0.x; circle.velocity.x = cosine * vFinal1.x - sine * vFinal1.y; circle.velocity.y = cosine * vFinal1.y + sine * vFinal1.x; } }, draw : function(){ ctx.beginPath(); ctx.fillStyle = "#fff"; ctx.arc(this.position.x, this.position.y, this.rad, 0, 2 * Math.PI, false); ctx.fill(); ctx.beginPath(); } }; //================ var circleArr = []; var circleNum = 10; init(); loop(); function init(){ for(var i = 0; i < circleNum; i++){ var xPos = (.1 + .8 * Math.random()) * width; var yPos = (1/3 + 2/3 * (Math.random() * .8 +.1))*height; var rad = parseInt(10 + 25 * Math.random()); var circle = new Circle(xPos, yPos, rad); circle.m = rad; circleArr.push(circle); } prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = "#fff"; ctx.fillRect( 0, 0, width, height/3); ctx.fillStyle = '#333'; ctx.fillRect( 0, height/3, width, height * 2 / 3); circleArr.forEach((function(element, index){ element.update(); for(var i = 0; i < circleArr.length; i++){ element.checkCollision(circleArr[i]); } })); circleArr.forEach((function(element, index){ element.draw(); })); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/3-algorithm/33-bubble-sort.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; var randoms; // ================ var Circle = function(num, x, y){ this.number = num; var colNum = parseInt(this.number); this.col = 'rgb(' + colNum + ', ' + colNum + ', ' + 0 + ')'; this.rad = 10; this.x = x; this.y = y; }; Circle.prototype = { draw : function(){ ctx.fillStyle = this.col; ctx.strokeStyle = '#fff'; ctx.beginPath(); ctx.arc(this.x, this.y, this.rad, 0, 2 * Math.PI); ctx.fill(); ctx.closePath(); }, transform : function(xPos){ TweenLite.to(this,.2, {x: xPos}); }, slowTransform : function(xPos){ TweenLite.to(this, 1.4, {x: xPos}); } }; var side = 80; var Circles = function(){ this.circleArr = []; this.NUM = parseInt(width / side) - 1; if(typeof randoms === 'undefined'){ randoms = []; for(var i = 0; i < this.NUM; i++){ randoms.push(Math.random() * 255); } } for(var i = 0; i < this.NUM; i++){ var circle = new Circle( randoms[i], side + side * i, this.y); this.circleArr.push(circle); } //this.bubbleSort(); }; Circles.prototype = { y : height/2, NUM : null, k : 0, draw : function(){ this.circleArr.forEach(function(element){ element.draw(); }); } }; var Circles1 = function(){ this.y = height/4; Circles.call(this); _.bindAll(this, 'bubbleSort'); this.bubbleSort(); }; Circles1.prototype = Object.create(Circles.prototype); Circles1.prototype.bubbleSort = function(){ for(var i = 0; i < this.NUM-1-this.k; i++){ if(this.circleArr[i].number > this.circleArr[i+1].number){ var temp = this.circleArr[i]; this.circleArr[i] = this.circleArr[i+1]; this.circleArr[i+1] = temp; this.circleArr[i].transform(this.circleArr[i+1].x); this.circleArr[i+1].transform(this.circleArr[i].x); setTimeout(this.bubbleSort, 300); return; } } }; var Circles2 = function(){ this.y = height * 3/4; Circles.call(this); _.bindAll(this, 'quickSort'); this.quickSort(0, this.circleArr.length); }; Circles2.prototype = Object.create(Circles.prototype); Circles2.prototype.quickSort = function(start, end){ if(start >= end) return; var left = [], right = [], pivot = this.circleArr[start]; for(var i = start + 1; i < end; i++){ this.circleArr[i].number < pivot.number ? left.push(this.circleArr[i]) : right.push(this.circleArr[i]); } var leftNum = left.length + start; var rightNum = leftNum + 1; if(start > 0 && end < this.circleArr.length){ var temp1 = this.circleArr.slice(0, start); var temp2 = this.circleArr.slice(end, this.circleArr.length); this.circleArr = temp1.concat(left, pivot, right, temp2); }else if(start > 0){ var temp = this.circleArr.slice(0, start); this.circleArr = temp.concat(left, pivot, right); }else if(end < this.circleArr.length){ var temp = this.circleArr.slice(end, this.circleArr.length); this.circleArr = left.concat(pivot, right, temp); }else{ this.circleArr = left.concat(pivot, right); } for(var i = 0; i < this.circleArr.length; i++){ var xPos = side + side * i; if(xPos != this.circleArr[i].x) this.circleArr[i].slowTransform(xPos); } var self=this; setTimeout(function(){ self.quickSort(start, leftNum); self.quickSort(rightNum, end); }, 1500); /* for (var i = 1; i < a.length; i++) { a[i] < pivot ? left.push(a[i]) : right.push(a[i]); } return qsort(left).concat(pivot, qsort(right));*/ } // ================ var circles1, circles2; var circles; init(); loop(); function init(){ circles = new Circles(); circles1 = new Circles1(); circles2 = new Circles2(); prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); circles.draw(); circles1.draw(); circles2.draw(); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/3-algorithm/34-search.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var Circle = function(number, x){ this.number = number; this.x = x; this.y = 120; }; Circle.prototype = { rad : 15, fillCol : '#fff', fontCol : '#333', fontStyle : "12px Arial", draw : function(){ ctx.fillStyle = this.fillCol; ctx.beginPath(); ctx.arc(this.x, this.y, this.rad, 0, 2*Math.PI); ctx.fill(); ctx.closePath(); ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.font = this.fontStyle; ctx.fillStyle = this.fontCol; ctx.fillText(this.number, this.x, this.y); } }; var Circles = function(){ _.bindAll(this, 'binarySearch', 'shuffleDone'); this.translate = 0; this.number = 101; this.kankaku = 50; this.circles = []; this.translate = width/2; for(var i = 0; i < this.number; i++ ){ var circle = new Circle(i, i * this.kankaku); this.circles.push(circle); } }; Circles.prototype = { startToSearch : function(){ this.start = 0; this.end = this.number - 1; this.circles[this.shuffle.number].fillCol = '#e74c3c'; this.binarySearch(); }, binarySearch : function(){ if(this.start > this.end) return; var prev = this.middle; if(!prev) prev = 0; this.circles[prev].fillCol = '#fff'; this.middle = parseInt((this.start + this.end)/2); if(this.middle != this.shuffle.number) this.circles[this.middle].fillCol = '#3498db'; var xPos = this.middle * -1 * this.kankaku + width/2; var second = Math.abs((this.middle - prev) / 20) > .5 ? Math.abs((this.middle - prev)/20) : .5; var duration = (second + 1) * 1000; var self= this; TweenLite.to(this, second, { translate: xPos}); if(this.shuffle.number > this.middle){ this.start = this.middle + 1; setTimeout(function(){ self.binarySearch() }, duration) return; } if(this.shuffle.number < this.middle){ this.end = this.middle - 1; setTimeout(function(){ self.binarySearch() }, duration) return; } // setDone setTimeout(this.shuffleDone, duration); }, shuffleDone : function(){ this.circles[this.shuffle.number].fillCol = '#fff'; this.shuffle.shuffleStart(); }, draw : function(){ ctx.save(); ctx.translate(this.translate, 0); this.circles.forEach(function(element){ element.draw(); }); ctx.restore(); } }; var Shuffle = function(circles){ _.bindAll(this, 'shuffle'); this.number = 0; this.circles = circles; this.shuffleStart(); }; Shuffle.prototype = { fontStyle : 'bold 42px Arial', fontCol : '#fff', shuffleStart : function(){ this.shuffleCount = 0; this.shuffle(); }, shuffle : function(){ this.number = parseInt(100 * Math.random()); this.shuffleCount++; if(this.shuffleCount < 50) setTimeout(this.shuffle, 20); else { var self = this; setTimeout(function(){ self.circles.startToSearch(); }, 800) } }, draw : function(){ ctx.textAlign = 'center'; ctx.textBaseline = 'top'; ctx.font = this.fontStyle; ctx.fillStyle = this.fontCol; ctx.fillText(this.number, width/2, 20); } }; // ================ var circles, shuffle; init(); loop(); function init(){ circles = new Circles(); shuffle = new Shuffle(); shuffle.circles = circles; circles.shuffle = shuffle; prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); shuffle.draw(); circles.draw(); ctx.strokeStyle = '#fff'; ctx.beginPath(); ctx.moveTo(width/2, 85); ctx.lineTo(width/2, 95); ctx.stroke(); ctx.closePath(); ctx.beginPath(); ctx.moveTo(width/2, 145); ctx.lineTo(width/2, 155); ctx.stroke(); ctx.closePath(); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/3-algorithm/35-undefined.js ================================================ // -------------------------- var width, height, prevTime, rad; var sound220, sound440, sound880; var isBlack = true; var soundLoopCount = 0; var soundCount = 0; var soundLoopDuration = 600; var tweenAnimationDuration = .4; var isSoundPlay = true; var SOUND_MAX_COUNT = 3; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; rad = Math.min(width *.4, height *.4); document.getElementById("button").addEventListener("click", function(){ isSoundPlay = !isSoundPlay; }); // ================ var Line = function(){ }; Line.prototype = { _theta1 : 0, _theta2 : 0, isBlack : false, opacity : Math.random() *.8, init1 : function(){ this.y1 = .2 * height; this.y2 = .8 * height; this.x1 = Math.random() * width; this.x2 = Math.random() * width; }, update : function(){ if(this.isBlack) ctx.strokeStyle = "rgba(0, 0, 0, " + this.opacity * (Math.random()) + ")"; else ctx.strokeStyle = "rgba(255, 255, 255, " + this.opacity * (Math.random()) + ")"; ctx.beginPath(); ctx.moveTo(this.x1, this.y1); ctx.lineTo(this.x2, this.y2); ctx.closePath(); ctx.stroke(); }, zero : function(){ var opacity = Math.random() *.8; TweenLite.to(this, tweenAnimationDuration/2, {x1: width/2, x2: width/2, y1: height/2, y2: height/2, opacity: opacity, ease: "Power1.easeOut"}); //TweenLite.to(this, tweenAnimationDuration/2, {x1: width * Math.random(), x2: width * Math.random(), y1: height * Math.random(), y2: height * Math.random(), ease: "Power1.easeOut"}); }, changeState0 : function(){ var opacity = Math.random() *.8; var x1 = (.8 * Math.random() +.1) * width; var x2 = (.8 * Math.random() +.1)* width; var y1 = .2 * height; var y2 = .8 * height; TweenLite.to(this, tweenAnimationDuration, {x1: x1, x2: x2, y1: y1, y2: y2, opacity: opacity, ease: "Power1.easeOut"}); }, changeState1 : function(){ var opacity = Math.random() *.8; var x1 = .2 * width; var x2 = .8 * width; var y1 = (.8 * Math.random() +.1) * height; var y2 = (.8 * Math.random() +.1)* height; TweenLite.to(this, tweenAnimationDuration, {x1: x1, x2: x2, y1: y1, y2: y2,opacity: opacity, ease: "Power1.easeOut"}); }, changeState2 : function(){ var opacity = Math.random() *.8; var theta1 = 2 * Math.PI * Math.random(); var theta2 = 2 * Math.PI * Math.random(); this._theta1 = theta1; this._theta2 = theta2; var x1 = width / 2 + rad * Math.cos(theta1); var y1 = height /2 + rad * Math.sin(theta1); var x2 = width / 2 + rad * Math.cos(theta2); var y2 = height/2 + rad * Math.sin(theta2); TweenLite.to(this, tweenAnimationDuration, {x1: x1, x2: x2, y1: y1, y2: y2, opacity: opacity, ease: "Power1.easeOut"}); }, move0 : function(){ var opacity = Math.random() *.8; TweenLite.to(this, tweenAnimationDuration, {x1: (Math.random() * .8 +.1) * width, x2: (Math.random() *.8 +.1) * width, opacity: opacity, ease: "Power1.easeOut"}); }, move1 : function(){ var opacity = Math.random() *.8; TweenLite.to(this, tweenAnimationDuration, {y1: (Math.random() * .8 +.1) * height, y2: (Math.random() * .8 +.1) * height, opacity: opacity, ease: "Power1.easeOut"}); }, move2 : function(){ var opacity = Math.random() *.8; var theta1 = 2 * Math.PI * Math.random(); var theta2 = 2 * Math.PI * Math.random(); TweenLite.to(this, tweenAnimationDuration, { theta1: theta1, theta2: theta2, opacity: opacity, ease: "Power1.easeOut"}); }, changeColor : function(){ this.isBlack = !this.isBlack; } }; Object.defineProperty(Line.prototype, 'theta1', { get : function(){ return this._theta1; }, set : function(val){ this._theta1 = val; this.x1 = width / 2 + rad * Math.cos(val); this.y1 = height / 2 + rad * Math.sin(val); } }); Object.defineProperty(Line.prototype, 'theta2', { get : function(){ return this._theta2; }, set : function(val){ this._theta2 = val; this.x2 = width / 2 + rad * Math.cos(val); this.y2 = height / 2 + rad * Math.sin(val); } }); var App = function(){ this.lines = []; this.currentState = 0; for(var i = 0; i < 200; i ++){ var line = new Line(); line.init1(); this.lines.push(line); } } App.prototype = { MAX_STAGE: 3, isBlack : true, isChangeColor : false, rad : 0, update : function(){ if(this.isChangeColor){ if(this.isBlack) ctx.fillStyle = "#000"; else ctx.fillStyle = "#fff"; ctx.beginPath(); ctx.arc(width/2, height/2, this.rad, 0, 2 * Math.PI, false); ctx.fill(); ctx.closePath(); } for(var i = 0; i < this.lines.length; i++){ this.lines[i].update(); } }, changeState : function(){ this.currentState = (this.currentState + 1) % this.MAX_STAGE; this.changeStates[this.currentState].call(this); }, changeStates : [ function(){ for(var i = 0; i < this.lines.length; i++){ this.lines[i].changeState0(); } }, function(){ for(var i = 0; i < this.lines.length; i++){ this.lines[i].changeState1(); } }, function(){ for(var i = 0; i < this.lines.length; i++){ this.lines[i].changeState2(); } }, ], changeColor : function(){ this.isChangeColor = true; this.isBlack = !this.isBlack; this.rad = 0; var rad = Math.sqrt(width/2 * width/2 + height/2 * height/2); TweenLite.to(this, tweenAnimationDuration, { rad: rad, ease: "Power1.easeOut"}); for(var i = 0; i < this.lines.length; i++){ this.lines[i].changeColor(); } }, zero : function(){ for(var i = 0; i < this.lines.length; i++){ this.lines[i].zero(); } }, soundPlay : function(){ this.soundPlays[this.currentState].call(this); }, soundPlays : [ function(){ for(var i = 0; i < this.lines.length; i++){ this.lines[i].move0(); } }, function(){ for(var i = 0; i < this.lines.length; i++){ this.lines[i].move1(); } }, function(){ for(var i = 0; i < this.lines.length; i++){ this.lines[i].move2(); } } ] }; // ================ //init(); //loop(); var app = new App() ctx.fillStyle = '#00'; ctx.fillRect(0, 0, width, height); sound220 = new Howl({ urls: ['https://dl.dropboxusercontent.com/u/7630890/sounds/sound220.mp3', 'https://dl.dropboxusercontent.com/u/7630890/sounds/sound220.ogg', 'https://dl.dropboxusercontent.com/u/7630890/sounds/sound220.wav'], volume : 1, onload : function(){ soundCount++; if(soundCount === SOUND_MAX_COUNT) init(); } }); sound440 = new Howl({ urls: ['https://dl.dropboxusercontent.com/u/7630890/sounds/sound440.mp3', 'https://dl.dropboxusercontent.com/u/7630890/sounds/sound440.ogg', 'https://dl.dropboxusercontent.com/u/7630890/sounds/sound440.wav'], volume : 1, onload : function(){ soundCount++; if(soundCount === SOUND_MAX_COUNT) init(); } }); sound880 = new Howl({ urls: ['https://dl.dropboxusercontent.com/u/7630890/sounds/sound880.mp3', 'https://dl.dropboxusercontent.com/u/7630890/sounds/sound880.ogg', 'https://dl.dropboxusercontent.com/u/7630890/sounds/sound880.wav'], volume: 1, onload : function(){ soundCount++; if(soundCount === SOUND_MAX_COUNT) init(); } }); function init(){ prevTime = +new Date; soundLoop(); loop(); } function loop(){ if(isBlack) ctx.fillStyle = 'rgb(0, 0, 0)'; else ctx.fillStyle = 'rgb(255, 255, 255)'; ctx.fillRect(0, 0, width, height); app.update(); requestAnimationFrame(loop); } function soundLoop(){ soundLoopCount++; if(soundLoopCount % 12 == 0) { if(isSoundPlay)sound880.play(); app.zero(); setTimeout(function(){ if(isSoundPlay)sound880.play(); app.changeColor(); app.changeState(); // setTimeout(soundLoop, soundLoopDuration); }, soundLoopDuration/2); setTimeout(function(){ isBlack = !isBlack; }, soundLoopDuration); setTimeout(soundLoop, soundLoopDuration); }else if(soundLoopCount % 4 == 0){ if(isSoundPlay) sound880.play(); app.changeState(); setTimeout(soundLoop, soundLoopDuration); }else{ if(isSoundPlay) sound440.play(); app.soundPlay(); setTimeout(soundLoop, soundLoopDuration); } } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/3-algorithm/36-undefined.js ================================================ // -------------------------- var width, height, prevTime, rad; var sound220, sound440, sound880; var isBlack = true; var soundLoopCount = 0; var soundCount = 0; var soundLoopDuration = 600; var tweenAnimationDuration = .4; var isSoundPlay = true; var SOUND_MAX_COUNT = 3; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; rad = Math.min(width *.4, height *.4); document.getElementById("button").addEventListener("click", function(){ isSoundPlay = !isSoundPlay; }); // ================ var Line = function(i){ this.id = i; this.type = i % 4; this.x = this.prevX = width / 2; this.y = this.prevY = height / 2; }; Line.prototype = { curState : 0, isBlack : false, isAcl : false, kasoku : 0, opacity : .8, init : function(){ this.inits[this.curState].call(this); }, inits : [ function(){ this.x = this.prevX = width/2; this.y = this.prevY = height/2; }, function(){ if(this.type == 0){ this.x = this.prevX = width * Math.random(); this.y = this.prevY = height + 20 * Math.random(); } if(this.type == 1){ this.x = this.prevX = width * Math.random(); this.y = this.prevY = 0 - 20 * Math.random(); } if(this.type == 2){ this.x = this.prevX = -20 * Math.random(); this.y = this.prevY = height * Math.random(); } if(this.type == 3){ this.x = this.prevX = width + 20 * Math.random(); this.y = this.prevY = height * Math.random(); } }, function(){ this.y = height * Math.random(); this.velY = 1.5 - 3 * Math.random(); } ], update : function(){ this.updates[this.curState].call(this); }, updates : [ function(){ this.prevX = this.x;/// this.prevY = this.y; this.x += Math.random() * 20 - 10 + this.kasoku1; this.y += Math.random() * 20 - 10 + this.kasoku2; this.kasoku1 *= .8; this.kasoku2 *= .8; //ctx.strokeStyle = "rgba(255, 255, 255, " + this.opacity * (Math.random()) + ")"; ctx.strokeStyle = "#fff"; ctx.beginPath(); ctx.moveTo(this.prevX, this.prevY); ctx.lineTo(this.x, this.y); ctx.closePath(); ctx.stroke(); }, function(){ this.prevX = this.x; this.prevY = this.y; if(this.type == 0){ this.x += Math.random() * 20 - 10 + this.kasoku1; this.y -= 5 + 5 * Math.random(); this.kasoku1 *= .8; } if(this.type == 1){ this.x += Math.random() * 20 - 10 + this.kasoku1; this.y += 5 + 5 * Math.random(); this.kasoku1 *= .8; } if(this.type == 2){ this.x += 5 + 5 * Math.random(); this.y += Math.random() * 20 - 10 + this.kasoku1; this.kasoku1 *= .8; } if(this.type == 3){ this.x -= 5 + 5 * Math.random(); this.y += Math.random() * 20 - 10 + this.kasoku1; this.kasoku1 *= .8; } //ctx.strokeStyle = "rgba(255, 255, 255, " + this.opacity * (Math.random()) + ")"; ctx.strokeStyle = "#fff"; ctx.beginPath(); ctx.moveTo(this.prevX, this.prevY); ctx.lineTo(this.x, this.y); ctx.closePath(); ctx.stroke(); }, function(){ if(this.id % 12 == 0){ this.prevX = this.x; this.prevY = this.y; this.y -= this.velY + this.kasoku1; this.kasoku1 *= .8; ctx.fillStyle = "rgba(255, 255, 255, .1)"; ctx.beginPath(); ctx.moveTo(0, this.prevY); ctx.lineTo(width, this.prevY); ctx.lineTo(width, this.y); ctx.lineTo(0, this.y); ctx.lineTo(0, this.prevY); ctx.closePath(); ctx.fill(); } } ], acl : function(){ this.kasoku1 = -50 + 100 * Math.random(); this.kasoku2 = -50 + 100 * Math.random(); this.isAcl = true; }, changeState : function(){ this.curState = (this.curState + 1) % SOUND_MAX_COUNT; this.init(); this.acl(); } }; var App = function(){ this.lines = []; for(var i = 0; i < 300; i++){ var line = new Line(i); this.lines.push(line); } }; App.prototype = { MAX_STAGE: 3, isBlack : true, isChangeColor : false, rad : 0, update : function(){ ctx.fillStyle = "rgba(0, 0, 0, .1)"; ctx.fillRect(0, 0, width, height); for(var i = 0; i < this.lines.length; i++){ this.lines[i].update(); } }, start : function(){ for(var i = 0; i < this.lines.length; i++){ this.lines[i].acl(); } }, changeState : function(){ for(var i = 0; i < this.lines.length; i++){ this.lines[i].changeState(); } } }; // ================ //init(); //loop(); var app = new App() ctx.fillStyle = '#00'; ctx.fillRect(0, 0, width, height); sound220 = new Howl({ urls: ['https://dl.dropboxusercontent.com/u/7630890/sounds/sound220.mp3', 'https://dl.dropboxusercontent.com/u/7630890/sounds/sound220.ogg', 'https://dl.dropboxusercontent.com/u/7630890/sounds/sound220.wav'], volume : 1, onload : function(){ soundCount++; if(soundCount === SOUND_MAX_COUNT) init(); } }); sound440 = new Howl({ urls: ['https://dl.dropboxusercontent.com/u/7630890/sounds/sound440.mp3', 'https://dl.dropboxusercontent.com/u/7630890/sounds/sound440.ogg', 'https://dl.dropboxusercontent.com/u/7630890/sounds/sound440.wav'], volume : 1, onload : function(){ soundCount++; if(soundCount === SOUND_MAX_COUNT) init(); } }); sound880 = new Howl({ urls: ['https://dl.dropboxusercontent.com/u/7630890/sounds/sound880.mp3', 'https://dl.dropboxusercontent.com/u/7630890/sounds/sound880.ogg', 'https://dl.dropboxusercontent.com/u/7630890/sounds/sound880.wav'], volume: 1, onload : function(){ soundCount++; if(soundCount === SOUND_MAX_COUNT) init(); } }); function init(){ soundLoop(); loop(); } function loop(){ app.update(); requestAnimationFrame(loop); } function soundLoop(){ soundLoopCount++; if(soundLoopCount % 12 == 0) { if(isSoundPlay)sound880.play(); ctx.fillStyle = '#000'; ctx.fillRect(0, 0, width, height); app.changeState(); setTimeout(function(){ if(isSoundPlay)sound880.play(); }, soundLoopDuration/2); setTimeout(soundLoop, soundLoopDuration); }else if(soundLoopCount % 4 == 0){ if(isSoundPlay) sound880.play(); ctx.fillStyle = '#000'; ctx.fillRect(0, 0, width, height); app.changeState(); setTimeout(soundLoop, soundLoopDuration); }else{ app.start(); if(isSoundPlay) sound440.play(); setTimeout(soundLoop, soundLoopDuration); } } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/3-algorithm/37-undefined.js ================================================ // -------------------------- var width, height, prevTime, rad; var sound220, sound440, sound880; var isBlack = true; var soundLoopCount = 0; var soundCount = 0; var soundLoopDuration = 600; var tweenAnimationDuration = .4; var isSoundPlay = true; var SOUND_MAX_COUNT = 2; var LOOP_MAX_COUNT = 3; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; rad = Math.min(width *.4, height *.4); document.getElementById("button").addEventListener("click", function(){ isSoundPlay = !isSoundPlay; }); // ================ var App = function(){ this.scale = 20; this.x = 0; this.y = 0; this.rad = 10; }; App.prototype = { update : function(){ ctx.fillStyle = "#fff"; ctx.save(); ctx.translate(width/2, height/2); ctx.scale(this.scale, this.scale); ctx.beginPath(); ctx.arc(this.x, this.y, this.rad, 0, 2 *Math.PI, false); ctx.closePath(); ctx.fill(); ctx.restore(); }, scaleDown : function(){ TweenLite.to(this, 10, {scale: 1, ease: "Power1.easeOut"}); } }; // ================ //init(); //loop(); var app = new App(); ctx.fillStyle = '#00'; ctx.fillRect(0, 0, width, height); // ============= sound440 = new Howl({ urls: ['https://dl.dropboxusercontent.com/u/7630890/sounds/sound440.mp3', 'https://dl.dropboxusercontent.com/u/7630890/sounds/sound440.ogg', 'https://dl.dropboxusercontent.com/u/7630890/sounds/sound440.wav'], volume : 1, onload : function(){ soundCount++; if(soundCount === SOUND_MAX_COUNT) init(); } }); sound880 = new Howl({ urls: ['https://dl.dropboxusercontent.com/u/7630890/sounds/sound880.mp3', 'https://dl.dropboxusercontent.com/u/7630890/sounds/sound880.ogg', 'https://dl.dropboxusercontent.com/u/7630890/sounds/sound880.wav'], volume: 1, onload : function(){ soundCount++; if(soundCount === SOUND_MAX_COUNT) init(); } }); // ============= function init(){ app.scaleDown(); soundLoop(); loop(); } function loop(){ app.update(); requestAnimationFrame(loop); } function soundLoop(){ /** soundLoopCount++; if(soundLoopCount % 12 == 0) { if(isSoundPlay)sound880.play(); ctx.fillStyle = '#000'; ctx.fillRect(0, 0, width, height); app.changeState(); setTimeout(function(){ if(isSoundPlay)sound880.play(); }, soundLoopDuration/2); setTimeout(soundLoop, soundLoopDuration); }else if(soundLoopCount % 4 == 0){ if(isSoundPlay) sound880.play(); ctx.fillStyle = '#000'; ctx.fillRect(0, 0, width, height); app.changeState(); setTimeout(soundLoop, soundLoopDuration); }else{ app.impulse(); if(isSoundPlay) sound440.play(); setTimeout(soundLoop, soundLoopDuration); } */ } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/3-algorithm/38-undefined.js ================================================ // -------------------------- var width, height, prevTime; var side, rad; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var ptArr = []; var ptNumber = 120; width = window.innerWidth; height = window.innerHeight; side = Math.min(width, height) * .9; rad = side / 2 * .8; canvas.width = width; canvas.height = height; var virtualCanvas = document.createElement("canvas"); var virtualLeft, virtualTop; var maxRad = Math.sqrt(side * side + side * side) / 2; var sideNum = 5; virtualCanvas.width = side; virtualCanvas.height = side; virtualLeft = (width - side) / 2; virtualTop = (height - side) / 2; var virtualCtx = virtualCanvas.getContext("2d"); // ================ var Circles = function(){ this.circles = []; for(var yPos = 0; yPos < sideNum; yPos++){ this.circles[yPos] = []; for(var xPos = 0; xPos < sideNum; xPos++){ this.circles[yPos][xPos] = new Circle(); } } }; Circles.prototype = { count : 0, update : function(){ this.count += .01; var scale = (6 - 4 * Math.cos(this.count))/10; virtualCtx.save(); virtualCtx.translate(side/2, side/2); virtualCtx.scale(scale, scale); for(var yPos = 0; yPos < sideNum; yPos++) { for (var xPos = 0; xPos < sideNum; xPos++) { var centerNum = (sideNum - 1)/2; var xx = (xPos - centerNum) * side; var yy = (yPos - centerNum) * side; virtualCtx.save(); virtualCtx.translate(xx, yy); this.circles[yPos][xPos].update(); virtualCtx.restore(); } } virtualCtx.restore(); } }; var Circle = function(){ this.tempCanvas = document.createElement("canvas"); this.tempCanvas.width = side; this.tempCanvas.height = side; this.tempCtx = this.tempCanvas.getContext("2d"); for(var i = 0; i < ptNumber; i++){ this.sides[i] = rad * (.8 +.2 * Math.random()); this.randomSides[i] = rad / 3 * (Math.random() -.5); } }; Circle.prototype = { sides : [], randomSides : [], count : 0, rot : 0, update : function(){ this.count += 0.1; var theta; this.tempCtx.clearRect(0, 0, side, side); for(var i = 0; i < ptNumber; i++){ var num = i; var randomRad = this.randomSides[i] * Math.cos(this.count); theta = i / ptNumber * 2 * Math.PI; this.tempCtx.beginPath(); this.tempCtx.strokeStyle = "#ff0000"; this.tempCtx.moveTo( (this.sides[num] + randomRad) * Math.cos(theta) + side / 2, (this.sides[num] + randomRad) * Math.sin(theta) + side / 2); this.tempCtx.lineTo( maxRad * Math.cos(theta) + side / 2, maxRad * Math.sin(theta) + side / 2); this.tempCtx.stroke(); this.tempCtx.closePath(); } virtualCtx.save(); virtualCtx.drawImage(this.tempCanvas, -side/2, -side/2); virtualCtx.restore(); } }; // ================ var circle; init(); loop(); function init(){ circle = new Circles(); ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; clear(); circle.update(); ctx.drawImage( virtualCanvas, virtualLeft, virtualTop); requestAnimationFrame(loop); } function clear(){ virtualCtx.fillStyle = '#fff'; virtualCtx.fillRect(0, 0, side, side); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/3-algorithm/39-undefined.js ================================================ // -------------------------- var width, height, prevTime; var virtualWidth, virtualHeight, virtualLeft, virtualRight; var widthNumber, heightNumber; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // 100pix random var intervalX = 100; virtualWidth = parseInt(width / intervalX) * intervalX + intervalX * 4; virtualLeft = (width - virtualWidth) / 2; virtualRight = virtualLeft + virtualWidth; widthNumber = virtualWidth / 100; heightNumber = parseInt(height / 2 / 100) + 1; // ================ var obj = {}; obj.rad = 15; var velY = -200; var LeftCircle = function( xPos, yPos ){ this.ctx = ctx; this.x = xPos; this.y = yPos; this.theta = 0; }; LeftCircle.prototype = { col : "#fff", update : function(){ this.ctx.save(); this.ctx.translate(this.x, this.y); this.ctx.rotate(this.theta); this.ctx.beginPath(); this.ctx.moveTo( 0, 0); this.ctx.lineTo( obj.rad * Math.cos(Math.PI * 3/2), obj.rad * Math.sin(Math.PI*3/2) ); this.ctx.arc(0, 0, obj.rad, Math.PI * 3/2, Math.PI * 2, false); this.ctx.lineTo( obj.rad * Math.cos( 2 * Math.PI), obj.rad * Math.sin(2 * Math.PI) ); this.ctx.closePath(); this.ctx.fillStyle = this.col; this.ctx.fill(); this.ctx.beginPath(); this.ctx.moveTo( 0, 0); this.ctx.lineTo( obj.rad * Math.cos(Math.PI /2), obj.rad * Math.sin(Math.PI/2) ); this.ctx.arc(0, 0, obj.rad, Math.PI /2, Math.PI, false); this.ctx.lineTo( obj.rad * Math.cos(Math.PI), obj.rad * Math.sin(Math.PI) ); this.ctx.closePath(); this.ctx.fillStyle = this.col; this.ctx.fill(); this.ctx.restore(); }, rotate : function(){ var theta = this.theta + Math.PI; TweenLite.to(this, .6, { theta: theta}); } }; var CircleTopLeft = function( xPos, yPos ){ _.bindAll(this, "rotate", "onCompleteRotation"); this.ctx = ctx; this.x = xPos; this.y = yPos; this.acl = (velY * -2) / 0.6; this.thetaVal = Math.PI * 2 / .6; this.velX = 100 / .6; }; CircleTopLeft.prototype = { theta : 0, col : "#fff", acl : null, originX : null, originY : null, originTheta : null, changePos : function(){ }, update : function(dt){ if(this.isRotation){ this.x -= this.velX * dt; if(this.x < this.originX - intervalX) this.x = this.originX - intervalX; this.velY += this.acl * dt; this.y -= this.velY * dt; if(this.y < this.originY) this.y = this.originY; this.theta += this.thetaVal * dt; } this.ctx.save(); this.ctx.translate(this.x, this.y); this.ctx.rotate(this.theta); this.ctx.beginPath(); this.ctx.moveTo( 0, 0); this.ctx.lineTo( obj.rad * Math.cos(Math.PI), obj.rad * Math.sin(Math.PI) ); this.ctx.arc(0, 0, obj.rad, Math.PI, Math.PI * 3 / 2, false); this.ctx.lineTo( obj.rad * Math.cos(3 / 2 * Math.PI), obj.rad * Math.sin(3 / 2 * Math.PI) ); this.ctx.closePath(); this.ctx.fillStyle = this.col; this.ctx.fill(); this.ctx.restore(); }, rotate : function(){ var duration = 0.6; this.velY = velY; this.isRotation = true; this.originX = this.x; this.originY = this.y; this.originTheta = this.theta; setTimeout(this.onCompleteRotation, 600); }, onCompleteRotation : function(){ this.isRotation = false; this.x = this.originX - intervalX; this.y = this.originY; this.theta = this.originTheta; if(this.x <= virtualLeft) this.x += virtualWidth; } }; var CircleBottomRight = function( xPos, yPos ){ _.bindAll(this, "rotate", "onCompleteRotation"); this.ctx = ctx; this.x = xPos; this.y = yPos; this.acl = (velY * -2) / 0.6; this.thetaVal = Math.PI * 2 / .6; this.velX = 100 / .6; console.log(this.x); }; CircleBottomRight.prototype = { theta : 0, col : "#fff", acl : null, originX : null, originY : null, originTheta : null, update : function(dt){ if(this.isRotation){ this.x += this.velX * dt; if(this.x > this.originX + intervalX) this.x = this.originX + intervalX; this.velY += this.acl * dt; this.y += this.velY * dt; if(this.y > this.originY) this.y = this.originY; this.theta += this.thetaVal * dt; } this.ctx.save(); this.ctx.translate(this.x, this.y); this.ctx.rotate(this.theta); this.ctx.beginPath(); this.ctx.moveTo( 0, 0); this.ctx.lineTo( obj.rad * Math.cos(0), obj.rad * Math.sin(0) ); this.ctx.arc(0, 0, obj.rad, 0, Math.PI / 2, false); this.ctx.lineTo( obj.rad * Math.cos(1 / 2 * Math.PI), obj.rad * Math.sin(1 / 2 * Math.PI) ); this.ctx.closePath(); this.ctx.fillStyle = this.col; this.ctx.fill(); this.ctx.restore(); }, rotate : function(){ var duration = 0.6; this.velY = velY; this.isRotation = true; this.originX = this.x; this.originY = this.y; this.originTheta = this.theta; setTimeout(this.onCompleteRotation, 600); }, onCompleteRotation : function(){ this.isRotation = false; this.x = this.originX + intervalX; this.y = this.originY; this.theta = this.originTheta; if(this.x >= virtualRight) this.x -= virtualWidth; } }; // ================ var circleTopLeft; //var circleArr = []; var circleWidthArr = []; var circleBotArr = []; var circleLeftArr = []; var count = 0; var i, j; circleWidthArr[count] = []; circleBotArr[count] = []; circleLeftArr[count] = []; for(i = 0; i < widthNumber; i++){ xPos = (i + 1) * intervalX + virtualLeft; xPos2 = i * intervalX + virtualLeft; yPos = height / 2; circleWidthArr[count][i] = new CircleTopLeft( xPos, yPos ); circleBotArr[count][i] = new CircleBottomRight( xPos2, yPos ) } for(var i = 1; i < widthNumber - 1; i++){ var xPos = i * intervalX + virtualLeft; var yPos = height / 2; circleLeftArr[count][i - 1] = new LeftCircle(xPos, yPos); } if(heightNumber > 0) { var yPos1, yPos2; var xPos1, xPos2; var yPos, xPos; for (j = 1; j < heightNumber; j++) { yPos1 = height / 2 - intervalX * j; yPos2 = height / 2 + intervalX * j; var tempCount = 2 * count + 1; for(var k = 0; k < 2; k++) { circleWidthArr[tempCount] = []; circleBotArr[tempCount] = []; circleLeftArr[tempCount] = []; if(k == 0) yPos = yPos1; if(k == 1) yPos = yPos2; for (i = 0; i < widthNumber; i++) { if (j % 2 == 1) xPos1 = (i + 1) * intervalX + intervalX / 2 + virtualLeft; else xPos1 = (i + 1) * intervalX + virtualLeft; if (j % 2 == 1) xPos2 = i * intervalX + virtualLeft - intervalX / 2; else xPos2 = i * intervalX + virtualLeft; circleWidthArr[tempCount][i] = new CircleTopLeft(xPos1, yPos); circleBotArr[tempCount][i] = new CircleBottomRight(xPos1, yPos); } for (i = 1; i < widthNumber - 1; i++) { if (j % 2 == 1) xPos = i * intervalX + intervalX / 2 + virtualLeft; else xPos = i * intervalX + virtualLeft; circleLeftArr[tempCount][i - 1] = new LeftCircle(xPos, yPos); } tempCount++; } count++; } } // ================ init(); loop(); function init(){ prevTime = +new Date; movement(); setTimeout(timer, 1000); } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); for(var j = 0; j < circleWidthArr.length; j++) { for (var i = 0; i < circleWidthArr[j].length; i++) { circleWidthArr[j][i].update(duration); circleBotArr[j][i].update(duration); } for (var i = 0; i < circleLeftArr[j].length; i++) { circleLeftArr[j][i].update(duration); } } requestAnimationFrame(loop); } function timer(){ var randomRad = 5 + parseInt(Math.random() * 45); TweenLite.to( obj, 1, { rad: randomRad }); setTimeout(timer, 2000); } function movement(){ for(var j = 0; j < circleWidthArr.length; j++) { for (var i = 0; i < circleWidthArr[j].length; i++) { circleWidthArr[j][i].rotate(); circleBotArr[j][i].rotate(); } for (var i = 0; i < circleLeftArr[j].length; i++) { circleLeftArr[j][i].rotate(); } } setTimeout(movement, 2000); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/3-algorithm/40-undefined.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ // ================ var xNum = 15; var yNum = 7; var halfXNum = 8; var halfYNum = 4; var kankaku = 20; var xPosArr = []; var yPosArr = []; init(); loop(); var curRad = 20; function init(){ var halfWidth = width/2; var halfHeight = height/2; for(var xx = 0; xx < xNum; xx++){ xPosArr[xx] = []; yPosArr[xx] = []; for(var yy = 0; yy < yNum; yy++){ var xPos = halfWidth + (xx - halfXNum) * kankaku; var yPos = halfHeight + (yy - halfYNum) * kankaku; xPosArr[xx][yy] = xPos; yPosArr[xx][yy] = yPos; } } prevTime = +new Date; timer() } function timer(){ var rad = curRad + 20; if(rad > 300) rad = 20; TweenLite.to(this,.5, { curRad: rad}); setTimeout(timer, 600); } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.globalCompositeOperation = 'source-over'; ctx.fillStyle = '#fff'; ctx.fillRect(0, 0, width, height); for(var xx = 0; xx < xNum; xx++) { for (var yy = 0; yy < yNum; yy++) { //xPosArr[xx][yy] += Math.random() - .5; //yPosArr[xx][yy] += Math.random() - .5; ctx.globalCompositeOperation = 'xor'; ctx.beginPath(); ctx.fillStyle = "#000000"; ctx.arc(xPosArr[xx][yy], yPosArr[xx][yy], curRad, 0, 2*Math.PI, false); ctx.fill(); ctx.closePath(); } } requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/3-algorithm/41-undefined.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; var bigRad = 200; // ================ var Circle = function(baseTheta){ this.ctx = ctx; this.rad = parseInt(100 + 30 * Math.random()); this.theta = 0; this.tehtaVel = Math.PI / 20; this.baseTheta = baseTheta | 0; this.x = width/2 + Math.cos(baseTheta) * bigRad; this.y = height/2 + Math.sin(baseTheta) * bigRad; this.ptX = this.x + this.rad * Math.cos(this.theta); this.ptY = this.y + this.rad * Math.sin(this.theta); this.ptRad = 10; this.velTheta = Math.random() * 0.05 + 0.01; }; Circle.prototype = { update : function(){ this.baseTheta += 0.01; this.theta += this.velTheta; this.x = width/2 + Math.cos(this.baseTheta) * bigRad; this.y = height/2 + Math.sin(this.baseTheta) * bigRad; this.ptX = this.x + this.rad * Math.cos(this.theta); this.ptY = this.y + this.rad * Math.sin(this.theta); this.ctx.save(); this.ctx.beginPath(); this.ctx.strokeStyle = "#fff"; this.ctx.arc(this.x, this.y, this.rad, 0, 2*Math.PI, false); this.ctx.stroke(); this.ctx.closePath(); this.ctx.beginPath(); this.ctx.fillStyle = "#fff"; this.ctx.arc(this.ptX, this.ptY, this.ptRad, 0, 2 * Math.PI, false); this.ctx.fill(); this.ctx.closePath(); this.ctx.restore(); } }; // ================ var circle1; var circle2; var circle3; init(); loop(); function init(){ circle1 = new Circle(0); circle2 = new Circle(2/3*Math.PI); circle3 = new Circle(4/3*Math.PI); prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); circle1.update(); circle2.update(); circle3.update(); ctx.beginPath(); ctx.strokeStyle = '#fff'; ctx.moveTo(circle1.ptX, circle1.ptY); ctx.lineTo(circle2.ptX, circle2.ptY); ctx.lineTo(circle3.ptX, circle3.ptY); ctx.lineTo(circle1.ptX, circle1.ptY); ctx.stroke(); ctx.closePath(); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/3-algorithm/42-undefined.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var app; width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var Shape1 = function(){ _.bindAll(this, "tweenOnComplete1", "tweenOnComplete2"); this.x = -this.sideRad; this.y = height/2 - this.sideRad; TweenLite.to(this, 1, { x : width/2, onComplete : this.tweenOnComplete1, ease:"Power2.easeOut", delay:.2 }); }; Shape1.prototype = { type : "circle1", sideRad : 50, rect : 100, update : function(){ switch (this.type){ case "circle1": this.circle1Update(); break; case "circle2": this.circle2Update(); break; } }, circle1Update : function(){ if(this.x > width/2 - this.sideRad * 2){ var side = this.x - (width/2 - this.sideRad * 2); if(side > 0){ side = this.sideRad - side; }else{ side *= -1; } var rectHeight = Math.sqrt(this.sideRad * this.sideRad - side * side); var theta = Math.atan2( rectHeight, side); ctx.save(); ctx.fillStyle = "#fff"; ctx.beginPath(); ctx.arc(this.x, this.y, this.sideRad, 0, 2 * Math.PI, false); ctx.closePath(); ctx.fill(); ctx.restore(); ctx.save(); ctx.fillStyle = "#000"; ctx.beginPath(); ctx.moveTo(this.x + this.sideRad * Math.cos( - theta), this.y + this.sideRad * Math.sin( - theta)); ctx.arc(this.x, this.y, this.sideRad, -theta, theta, false); ctx.lineTo(this.x + this.sideRad * Math.cos(theta), this.y + this.sideRad * Math.sin( theta)); ctx.closePath(); ctx.fill(); ctx.restore(); }else{ ctx.save(); ctx.fillStyle = "#fff"; ctx.beginPath(); ctx.arc(this.x, this.y, this.sideRad, 0, 2 * Math.PI, false); ctx.closePath(); ctx.fill(); ctx.restore(); } }, circle2Update : function(){ if(this.y < window.innerHeight/2 + this.sideRad){ var startY = window.innerHeight/2 - this.sideRad * 2; var height = (this.y - this.sideRad) - startY; //console.log(height) ctx.save(); ctx.fillStyle = "#000"; ctx.beginPath(); ctx.fillRect(width/2 - this.sideRad - 1, startY, this.rect + 2, height); ctx.closePath(); }else{ var startY = window.innerHeight/2 - this.sideRad * 2; ctx.save(); ctx.fillStyle = "#000"; ctx.beginPath(); ctx.fillRect(width/2 - this.sideRad - 1, startY, this.rect + 2, this.sideRad * 2); ctx.closePath(); } //console.log(this.y); ctx.save(); ctx.fillStyle = "#000"; ctx.beginPath(); ctx.arc(this.x, this.y, this.sideRad, 0, 2 * Math.PI, false); ctx.closePath(); ctx.fill(); ctx.restore(); }, tweenOnComplete1 : function(){ this.type = "circle2"; TweenLite.to(this, 1, { y : height + this.sideRad, ease:"Power2.easeIn",onComplete : this.tweenOnComplete2 }); }, tweenOnComplete2 : function(){ this.type = "circle1"; this.x = -this.sideRad; this.y = height/2 - this.sideRad; TweenLite.to(this, 1, { x : width/2, onComplete : this.tweenOnComplete1, ease:"Power2.easeOut", delay:.5 }); } }; // --------------- var Shape = function(){ _.bindAll(this, 'tweenOnComplete1'); this.x = width/2; this.y = height + this.sideRad; TweenLite.to(this, 1, { y : height/2 - this.sideRad , onComplete : this.tweenOnComplete1 , ease:"Power2.easeOut"}); }; Shape.prototype = { type : "rect", sideRect : 100, sideRad : 50, update : function(){ switch (this.type){ case "circle": this.drawCircle(); break; case "rect": this.drawRect(); break; } }, drawRect : function(){ if(this.y < height / 2 + this.sideRad){ var rectHeight = height/2 + this.sideRad - this.y; var rectWidth, theta; var circleHeight, circleWidth; ctx.save(); ctx.fillStyle = "#000"; ctx.beginPath(); ctx.arc(this.x, this.y, this.sideRad, 0, 2 * Math.PI, false); ctx.closePath(); ctx.fill(); ctx.restore(); ctx.save(); ctx.fillStyle = "#fff"; ctx.fillRect(this.x - this.sideRad, this.y - this.sideRad, this.sideRect, rectHeight); ctx.restore(); }else{ ctx.save(); ctx.fillStyle = "#000"; ctx.beginPath(); ctx.arc(this.x, this.y, this.sideRad, 0, 2 * Math.PI, false); ctx.fill(); ctx.closePath(); ctx.restore(); } }, drawCircle : function(){ }, tweenOnComplete1 : function(){ var self = this; setTimeout(function(){ self.y = height + self.sideRad; TweenLite.to(self, 1, { y : height/2 - self.sideRad , onComplete : self.tweenOnComplete1 , ease:"Power2.easeOut", delay:.5}); }, 1000); }, }; var Floor = function(){ this.y = height/2; this.height = height/2; }; Floor.prototype = { update : function(){ ctx.fillStyle = "#fff"; ctx.save(); ctx.fillRect(0, this.y, width, this.height); ctx.restore(); } }; // ---------------- var App = function(){ this.Floor = new Floor(); this.shape = new Shape(); this.shape1 = new Shape1(); }; App.prototype = { update : function(){ this.Floor.update(); this.shape.update(); this.shape1.update(); } }; // ================ init(); loop(); function init(){ app = new App(); prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#000'; ctx.fillRect(0, 0, width, height); app.update(); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/4-webgl/0-test-three-js-example.js ================================================ /** * * Created by kenji-special on 9/22/14. */ //if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); var container, stats; var camera, scene, renderer; var mesh; init(); animate(); function init() { container = document.getElementById( 'container' ); // camera = new THREE.PerspectiveCamera( 27, window.innerWidth / window.innerHeight, 1, 4000 ); camera.position.z = 2750; scene = new THREE.Scene(); var segments = 10000; var geometry = new THREE.BufferGeometry(); var material = new THREE.LineBasicMaterial({ vertexColors: true }); geometry.addAttribute( 'position', new Float32Array( segments * 3 ), 3 ); geometry.addAttribute( 'color', new Float32Array( segments * 3 ), 3 ); var positions = geometry.getAttribute( 'position' ).array; var colors = geometry.getAttribute( 'color' ).array; var r = 800; for ( var i = 0; i < segments; i ++ ) { var x = Math.random() * r - r / 2; var y = Math.random() * r - r / 2; var z = Math.random() * r - r / 2; // positions positions[ i * 3 ] = x; positions[ i * 3 + 1 ] = y; positions[ i * 3 + 2 ] = z; // colors colors[ i * 3 ] = ( x / r ) + 0.5; colors[ i * 3 + 1 ] = ( y / r ) + 0.5; colors[ i * 3 + 2 ] = ( z / r ) + 0.5; } geometry.computeBoundingSphere(); mesh = new THREE.Line( geometry, material ); scene.add( mesh ); // renderer = new THREE.WebGLRenderer( { antialias: false, canvas: document.getElementById('c') } ); renderer.setSize( window.innerWidth, window.innerHeight ); renderer.gammaInput = true; renderer.gammaOutput = true; //container.appendChild( renderer.domElement ); // stats = new Stats(); stats.domElement.style.position = 'absolute'; stats.domElement.style.top = '0px'; //container.appendChild( stats.domElement ); document.body.appendChild(stats.domElement); // window.addEventListener( 'resize', onWindowResize, false ); } function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize( window.innerWidth, window.innerHeight ); } // function animate() { requestAnimationFrame( animate ); render(); stats.update(); } function render() { var time = Date.now() * 0.001; mesh.rotation.x = time * 0.25; mesh.rotation.y = time * 0.5; renderer.render( scene, camera ); } ================================================ FILE: app/scripts/4-webgl/1-test-three-js-example.js ================================================ var container, stats; var camera, scene, renderer; var mesh, parent_node; var line; var radius, segments, material, geometry; init(); animate(); function init() { //container = document.getElementById( 'container' ); camera = new THREE.PerspectiveCamera( 27, window.innerWidth / window.innerHeight, 1, 10000 ); camera.position.z = 9000; scene = new THREE.Scene(); var geometry = new THREE.BufferGeometry(); var material = new THREE.LineBasicMaterial({ vertexColors: true }); var positions = []; var next_positions_index = 0; var colors = []; var indices_array = []; // -------------------------------- var iteration_count = 4; var rangle = 60 * Math.PI / 180.0; function add_vertex(v) { if (next_positions_index == 0xffff) throw new Error("Too many points"); positions.push(v.x, v.y, v.z); colors.push(Math.random()*0.5+0.5, Math.random()*0.5+0.5, 1); return next_positions_index++; } // simple Koch curve function snowflake_iteration(p0, p4, depth) { if (--depth < 0) { var i = next_positions_index-1; // p0 already there add_vertex(p4); indices_array.push(i, i+1); return; } var v = p4.clone().sub(p0); var v_tier = v.clone().multiplyScalar(1.0/3.0); var p1 = p0.clone().add(v_tier); var angle = Math.atan2(v.y, v.x) + rangle; var length = v_tier.length(); var p2 = p1.clone(); p2.x += Math.cos(angle) * length; p2.y += Math.sin(angle) * length; var p3 = p0.clone().add(v_tier).add(v_tier); snowflake_iteration(p0, p1, depth); snowflake_iteration(p1, p2, depth); snowflake_iteration(p2, p3, depth); snowflake_iteration(p3, p4, depth); } function snowflake(points, loop, x_offset) { for (var iteration = 0; iteration != iteration_count; ++iteration) { add_vertex(points[0]); for (var p_index=0, p_count=points.length-1; p_index != p_count; ++p_index) { snowflake_iteration(points[p_index], points[p_index+1], iteration); } if (loop) snowflake_iteration(points[points.length-1], points[0], iteration); // translate input curve for next iteration for (var p_index=0, p_count=points.length; p_index != p_count; ++p_index) { points[p_index].x += x_offset; } } } var y = 0; snowflake ( [ new THREE.Vector3(0, y+0, 0), new THREE.Vector3(500, y+0, 0) ], false, 600 ); y += 600; snowflake ( [ new THREE.Vector3(0, y+0, 0), new THREE.Vector3(250, y+400, 0), new THREE.Vector3(500, y+0, 0) ], true, 600 ); y += 600; snowflake ( [ new THREE.Vector3(0, y+0, 0), new THREE.Vector3(500, y, 0), new THREE.Vector3(500, y+500, 0), new THREE.Vector3(0, y+500, 0), ], true, 600 ); y += 1000; snowflake ( [ new THREE.Vector3(250, y+0, 0), new THREE.Vector3(500, y+0, 0), new THREE.Vector3(250, y+0, 0), new THREE.Vector3(250, y+250, 0), new THREE.Vector3(250, y+0, 0), new THREE.Vector3(0, y, 0), new THREE.Vector3(250, y+0, 0), new THREE.Vector3(250, y-250, 0), new THREE.Vector3(250, y+0, 0), ], false, 600 ); // -------------------------------- geometry.addAttribute( 'index', new Uint16Array( indices_array ), 1 ); geometry.addAttribute( 'position', new Float32Array( positions ), 3 ); geometry.addAttribute( 'color', new Float32Array( colors ), 3 ); geometry.computeBoundingSphere(); mesh = new THREE.Line( geometry, material, THREE.LinePieces ); mesh.position.x -= 1200; mesh.position.y -= 1200; parent_node = new THREE.Object3D(); // parent_node.add(mesh); //scene.add( parent_node ); radius = 100, segments = 64, material = new THREE.LineBasicMaterial( { color: 0x0000ff } ), geometry = new THREE.CircleGeometry( radius, segments ); console.log(geometry); // Remove center vertex geometry.vertices.shift(); line = new THREE.Line( geometry, material ); console.log(line.geometry); scene.add( line ); renderer = new THREE.WebGLRenderer( { antialias: false, canvas: document.getElementById('c') } ); renderer.setSize( window.innerWidth, window.innerHeight ); renderer.gammaInput = true; renderer.gammaOutput = true; //container.appendChild( renderer.domElement ); // stats = new Stats(); stats.domElement.style.position = 'absolute'; stats.domElement.style.top = '0px'; document.body.appendChild( stats.domElement ); // window.addEventListener( 'resize', onWindowResize, false ); } function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize( window.innerWidth, window.innerHeight ); } // function animate() { requestAnimationFrame( animate ); render(); stats.update(); } function render() { //line.geometry.parameters.radius = 100 + 100 * Math.random(); line.scale.x += .1; var time = Date.now() * 0.001; //mesh.rotation.x = time * 0.25; //mesh.rotation.y = time * 0.5; parent_node.rotation.z = time * 0.5; renderer.render( scene, camera ); } ================================================ FILE: app/scripts/4-webgl/2-test-three-js-example.js ================================================ var container, stats; var camera, scene, renderer; var group; var mouseX = 0, mouseY = 0; var windowHalfX = window.innerWidth / 2; var windowHalfY = window.innerHeight / 2; var mesh1, mesh2, mesh3; init(); animate(); function init() { //container = document.getElementById( 'container' ); camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 2000 ); camera.position.z = 500; scene = new THREE.Scene(); group = new THREE.Object3D(); scene.add( group ); // earth var loader = new THREE.TextureLoader(); loader.load( 'image/earth.jpg', function ( texture ) { var geometry = new THREE.SphereGeometry( 40, 40, 40 ); var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } ); var mesh = new THREE.Mesh( geometry, material ); mesh.position.x = 0; //group.add( mesh ); scene.add(mesh); mesh1 = mesh; } ); loader.load( 'image/portfolio.jpg', function(texture){ var geometry = new THREE.SphereGeometry( 40, 40, 40 ); var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } ); var mesh = new THREE.Mesh( geometry, material ); mesh.position.x = -200; //group.add( mesh ); scene.add(mesh); mesh2 = mesh; }); loader.load("image/pony.jpg", function(texture){ var geometry = new THREE.SphereGeometry( 40, 40, 40 ); var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } ); var mesh = new THREE.Mesh( geometry, material ); mesh.position.x = 200; //group.add( mesh ); scene.add(mesh); mesh3 = mesh; }); // shadow var canvas = document.createElement( 'canvas' ); canvas.width = 128; canvas.height = 128; var context = canvas.getContext( '2d' ); var gradient = context.createRadialGradient( canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2 ); gradient.addColorStop( 0.1, 'rgba(210,210,210,1)' ); gradient.addColorStop( 1, 'rgba(255,255,255,1)' ); context.fillStyle = gradient; context.fillRect( 0, 0, canvas.width, canvas.height ); var texture = new THREE.Texture( canvas ); texture.needsUpdate = true; var geometry = new THREE.PlaneGeometry( 300, 300, 3, 3 ); var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } ); var mesh = new THREE.Mesh( geometry, material ); mesh.position.y = - 250; mesh.rotation.x = - Math.PI / 2; //group.add( mesh ); renderer = new THREE.WebGLRenderer({ antialias: true, canvas: document.getElementById('c'), alpha: true }); renderer.setClearColor( 0x000,.2 ); renderer.setSize( window.innerWidth, window.innerHeight ); //container.appendChild( renderer.domElement ); stats = new Stats(); stats.domElement.style.position = 'absolute'; stats.domElement.style.top = '0px'; // document.body.appendChild( stats.domElement ); document.addEventListener( 'mousemove', onDocumentMouseMove, false ); // window.addEventListener( 'resize', onWindowResize, false ); } function onWindowResize() { windowHalfX = window.innerWidth / 2; windowHalfY = window.innerHeight / 2; camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize( window.innerWidth, window.innerHeight ); } function onDocumentMouseMove( event ) { mouseX = ( event.clientX - windowHalfX ); mouseY = ( event.clientY - windowHalfY ); } // function animate() { requestAnimationFrame( animate ); render(); stats.update(); } function render() { //camera.position.x += ( mouseX - camera.position.x ) * 0.05; //camera.position.y += ( - mouseY - camera.position.y ) * 0.05; camera.lookAt( scene.position ); mesh1.rotation.y -= 0.005; mesh2.rotation.y -= 0.005; mesh3.rotation.y -= 0.005; renderer.render( scene, camera ); } ================================================ FILE: app/scripts/4-webgl/48-three-js-shader.js ================================================ var scene, camera, renderer; var vertexShaderString, fragmentShaderString; var character = null; var width, height, prevTime; var canvas = document.getElementById('c'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; var yoCanvas = document.createElement("canvas") yoCanvas.width = width; yoCanvas.height = height; var yoCtx = yoCanvas.getContext('2d'); var canvasTexture; // ================== var mRenderer; var mScene; var mCamera; var mUniforms; var mColors; var mColorsNeedUpdate = true; var mLastTime = 0; var mTexture1, mTexture2; var mGSMaterial, mScreenMaterial; var mScreenQuad; var mToggled = false; var mMinusOnes = new THREE.Vector2(-1, -1); /* var presets = [ { // Default //feed: 0.018, //kill: 0.051 feed: 0.037, kill: 0.06 }, { // Holes feed: 0.039, kill: 0.058 }, { // Chaos and holes (by clem) feed: 0.034, kill: 0.056 }, { // The U-Skate World feed: 0.062, kill: 0.06093 } ]; */ var presets = [ { // Default //feed: 0.018, //kill: 0.051 feed: 0.037, kill: 0.06 }, { // Solitons feed: 0.03, kill: 0.062 }, { // Pulsating solitons feed: 0.025, kill: 0.06 }, { // Worms. feed: 0.078, kill: 0.061 }, { // Mazes feed: 0.029, kill: 0.057 }, { // Holes feed: 0.039, kill: 0.058 }, { // Chaos feed: 0.026, kill: 0.051 }, { // Chaos and holes (by clem) feed: 0.034, kill: 0.056 }, { // Moving spots. feed: 0.014, kill: 0.054 }, { // Spots and loops. feed: 0.018, kill: 0.051 }, { // Waves feed: 0.014, kill: 0.045 }, { // The U-Skate World feed: 0.062, kill: 0.06093 } ] // Configuration. var count = 0; var feed = presets[count].feed; var kill = presets[count].kill; function init() { setText(); setCanvasTexture(); var canvas = document.getElementById("c"); mRenderer = new THREE.WebGLRenderer({canvas: canvas, preserveDrawingBuffer: true, alpha: true}); mScene = new THREE.Scene(); mCamera = new THREE.OrthographicCamera(-0.5, 0.5, 0.5, -0.5, -10000, 10000); mCamera.position.z = 100; mScene.add(mCamera); mUniforms = { screenWidth: {type: "f", value: undefined}, screenHeight: {type: "f", value: undefined}, tSource: {type: "t", value: undefined}, canvasSource : {type: "t", value: canvasTexture}, delta: {type: "f", value: 1.0}, feed: {type: "f", value: feed}, kill: {type: "f", value: kill}, brush: {type: "v2", value: new THREE.Vector2(-10, -10)}, color1: {type: "v4", value: new THREE.Vector4(0, 0, 0.0, 0)}, color2: {type: "v4", value: new THREE.Vector4(0.1, .1, .1, 0.2)}, color3: {type: "v4", value: new THREE.Vector4(1.0,1.0, 1.0, 0.4)}, color4: {type: "v4", value: new THREE.Vector4(.1,.1,.1, 0.7)}, color5: {type: "v4", value: new THREE.Vector4(1.0,1.0,1.0, 0.9)} }; mColors = [mUniforms.color1, mUniforms.color2, mUniforms.color3, mUniforms.color4, mUniforms.color5]; mGSMaterial = new THREE.ShaderMaterial({ uniforms: mUniforms, vertexShader: [ "varying vec2 vUv;", "void main(){", "vUv = uv;", "gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);}" ].join("\n"), fragmentShader: [ "varying vec2 vUv;", "uniform float screenWidth;", "uniform float screenHeight;", "uniform sampler2D tSource;", "uniform sampler2D canvasSource;", "uniform float delta;", "uniform float feed;", "uniform float kill;", "uniform vec2 brush;", "vec2 texel = vec2(1.0/screenWidth, 1.0/screenHeight);", "float step_x = 1.0/screenWidth;", "float step_y = 1.0/screenHeight;", "void main()", "{", " if(brush.x < -5.0)", " {", " //gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);", " //return;", " }", " ", " ", " vec2 uv = texture2D(tSource, vUv).rg;", " vec2 uv0 = texture2D(tSource, vUv+vec2(-step_x, 0.0)).rg;", " vec2 uv1 = texture2D(tSource, vUv+vec2(step_x, 0.0)).rg;", " vec2 uv2 = texture2D(tSource, vUv+vec2(0.0, -step_y)).rg;", " vec2 uv3 = texture2D(tSource, vUv+vec2(0.0, step_y)).rg;", " ", " vec2 lapl = (uv0 + uv1 + uv2 + uv3 - 4.0*uv);//10485.76;", " float du = /*0.00002*/0.2097*lapl.r - uv.r*uv.g*uv.g + feed*(1.0 - uv.r);", " float dv = /*0.00001*/0.105*lapl.g + uv.r*uv.g*uv.g - (feed+kill)*uv.g;", " vec2 dst = uv + delta*vec2(du, dv);", " ", " if(brush.x > 0.0)", " {", " vec2 diff = (vUv - brush)/texel;", " float dist = dot(diff, diff);", " if(dist < 10.0)", " dst.g = 0.9;", " }", " float canvasValue = texture2D(canvasSource, vUv).g;", " if(canvasValue < 0.1){ dst.g = 0.0; }", /* " if(vUv.x < 0.2)", " {", " dst.g = 0.0;", " }", " ", */ " gl_FragColor = vec4(dst.r, dst.g, 0.0, 0);", "}" ].join("\n") }); mScreenMaterial = new THREE.ShaderMaterial({ uniforms: mUniforms, vertexShader: [ "varying vec2 vUv;", "void main(){", "vUv = uv;", "gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);}" ].join("\n"), fragmentShader: [ "varying vec2 vUv;", "uniform vec2 brush;", "uniform float screenWidth;", "uniform float screenHeight;", "uniform sampler2D tSource;", "uniform sampler2D canvasSource;", "uniform float delta;", "uniform float feed;", "uniform float kill;", "uniform vec4 color1;", "uniform vec4 color2;", "uniform vec4 color3;", "uniform vec4 color4;", "uniform vec4 color5;", "vec2 texel = vec2(1.0/screenWidth, 1.0/screenHeight);", "void main()", "{", " float value = texture2D(tSource, vUv).g;", " //int step = int(floor(value));", " //float a = fract(value);", " float a;", " vec3 col;", " ", " if(value <= color1.a)", " col = color1.rgb;", " if(value > color1.a && value <= color2.a)", " {", " a = (value - color1.a)/(color2.a - color1.a);", " col = mix(color1.rgb, color2.rgb, a);", " }", " if(value > color2.a && value <= color3.a)", " {", " a = (value - color2.a)/(color3.a - color2.a);", " col = mix(color2.rgb, color3.rgb, a);", " }", " if(value > color3.a && value <= color4.a)", " {", " a = (value - color3.a)/(color4.a - color3.a);", " col = mix(color3.rgb, color4.rgb, a);", " }", " if(value > color4.a && value <= color5.a)", " {", " a = (value - color4.a)/(color5.a - color4.a);", " col = mix(color4.rgb, color5.rgb, a);", " }", " if(value > color5.a)", " col = color5.rgb;", " ", " gl_FragColor = vec4( col.r, col.g, col.b, 1.0);", "}" ].join("\n") }); var plane = new THREE.PlaneGeometry(1.0, 1.0); mScreenQuad = new THREE.Mesh(plane, mScreenMaterial); mScene.add(mScreenQuad); mTexture1 = new THREE.WebGLRenderTarget(width / 2, height / 2, {minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, type: THREE.FloatType}); mTexture2 = new THREE.WebGLRenderTarget(width / 2, height / 2, {minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, type: THREE.FloatType}); mTexture1.wrapS = THREE.RepeatWrapping; mTexture1.wrapT = THREE.RepeatWrapping; mTexture2.wrapS = THREE.RepeatWrapping; mTexture2.wrapT = THREE.RepeatWrapping; mUniforms.screenWidth.value = width / 2; mUniforms.screenHeight.value = height / 2; loop(0); mUniforms.brush.value = new THREE.Vector2(0.5, 0.5); mLastTime = new Date().getTime(); setTimeout(updateScott, 3000); setTimeout(updateClear, 1000); } function updateClear(){ mUniforms.brush.value = new THREE.Vector2(0.5, 0.5); //mUniforms.brush.value = new THREE.Vector2(-10, -10); setTimeout(updateClear, 1000); } function updateScott(){ count = (count + 1) % presets.length; console.log(count) feed = presets[count].feed; kill = presets[count].kill; /* setTimeout(function(){ mUniforms.brush.value = new THREE.Vector2(0.5, 0.5); }, 100);*/ setTimeout(updateScott, 3000); } function setCanvasTexture(){ canvasTexture = new THREE.Texture(yoCanvas); canvasTexture.magFilter = THREE.NearestFilter; canvasTexture.needsUpdate = true; } function setText(){ yoCtx.fillStyle = "#fff"; yoCtx.fillRect( 0, 0, width, height ); /* yoCtx.fillStyle = "#000000"; yoCtx.fillRect(width/4, height/4, width/2, height/4); */ var textLeft; var textTop; var xPos, yPos; var txt="YO"; yoCtx.font = "Bold 80px Arial"; var textWidth = yoCtx.measureText(txt); var textExtraWidth = textWidth.width * 2; var extraHeight = 100 ; for(var yy = 0; yy < height/extraHeight; yy++){ for(var xx = 0; xx < width / textExtraWidth; xx++){ yoCtx.fillStyle = '#000'; if(yy % 2 == 0) xPos = textExtraWidth * xx; else xPos = textExtraWidth * (xx - .5); yPos = extraHeight * yy + 40; yoCtx.save(); yoCtx.translate(xPos, yPos); yoCtx.fillText(txt,0,0); yoCtx.restore(); } } //canvasTexture.needsUpdate = true; } function loop(time) { var dt = (time - mLastTime) / 20.0; if (dt > 0.8 || dt <= 0) dt = 0.8; dt = .8; mLastTime = time; //mUniforms.brush.value = new THREE.Vector2(0.5, 0.5); mScreenQuad.material = mGSMaterial; mUniforms.delta.value = 1; mUniforms.feed.value = feed; mUniforms.kill.value = kill; for (var i = 0; i < 60; ++i) { if (!mToggled) { mUniforms.tSource.value = mTexture1; mRenderer.render(mScene, mCamera, mTexture2, true); mUniforms.tSource.value = mTexture2; } else { mUniforms.tSource.value = mTexture2; mRenderer.render(mScene, mCamera, mTexture1, true); mUniforms.tSource.value = mTexture1; } mToggled = !mToggled; mUniforms.brush.value = mMinusOnes; //mUniforms.brush.value = new THREE.Vector2(0.5, 0.5); } mScreenQuad.material = mScreenMaterial; mRenderer.render(mScene, mCamera); requestAnimationFrame(loop); } // init(); ================================================ FILE: app/scripts/4-webgl/49-three-js.js ================================================ // -------------------------- var width, height, prevTime; var angularSpeed; var renderer, camera, scene, plane; var app, collections; var canvas = document.getElementById('c'); angularSpeed = 0.2; prevTime = (new Date()).getTime(); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var Collections = function(){ _.bindAll(this, "start"); this.widthNum = parseInt(width/this.side) + 1; this.heightNum = parseInt(height/this.side) + 1; console.log("width: " + this.widthNum + ", height: " + this.heightNum); this.planes = []; this.scores = []; var maxScore = 10; for(var yy = 0; yy < this.heightNum; yy++){ this.planes[yy] = []; this.scores[yy] = []; for(var xx = 0; xx < this.widthNum; xx++){ plane = new THREE.Mesh(new THREE.PlaneGeometry(this.side, this.side), new THREE.MeshBasicMaterial({color: 0xffffff, side: THREE.DoubleSide})); plane.position.x = xx * this.side - width/2; plane.position.y = yy * this.side - height/2; //plane.rotation.x = Math.PI/3; plane.rotation.y = -Math.PI; //plane.rotation.z= Math.PI/2; plane.overdraw = true; this.planes[yy][xx] = plane; scene.add(plane); //this.scores[yy][xx] = {x: xx, y: yy, score: yy}; var score = parseInt(maxScore * Math.random()); this.scores[yy][xx] = score; //maxScore = Math.max(maxScore, yy); } } this.maxScore = maxScore; // 0 : {x: 10, y: 10}, 1 : {} this.scorePosArr = []; for(var i = 0; i <= maxScore; i++){ this.scorePosArr[i] = []; for(var yy = 0; yy < this.scores.length; yy++){ for(var xx = 0; xx < this.scores[yy].length; xx++){ if(i == this.scores[yy][xx]){ var pos = {x: xx, y: yy}; this.scorePosArr[i].push(pos); } } } }; setTimeout(this.start, 2000); }; Collections.prototype = { side : 100, count : 0, planes : null, update : function(){ for(var yy = 0; yy < this.heightNum; yy++){ for(var xx = 0; xx < this.widthNum; xx++){ this.planes[yy][xx].position.x += Math.random() * 2 - 1; this.planes[yy][xx].position.y += Math.random() * 2 - 1; this.planes[yy][xx].position.z += Math.random() * 2 - 1; } } }, start : function(){ /* for(var yy = 0; yy < this.planes.length; yy++){ for(var xx = 0; xx < this.planes[yy].length; xx++){ TweenLite.to(this.planes[yy][xx].rotation, 1, {x: Math.PI* 2, delay:.4}); } }*/ for(var i = 0; i < this.scorePosArr[this.count].length; i++){ var pos = this.scorePosArr[this.count][i]; TweenLite.to(this.planes[pos.y][pos.x].rotation, .3 + Math.random() *.5, {x: Math.random() * Math.PI* 2, y: Math.random() * Math.PI, onComplete: function(){ TweenLite.to(this.target,.5, {x: 0, y: 0, ease:"Power2.easeOut"}) }}); } this.count = (this.count + 1) % (this.maxScore + 1); if(this.count == 0){ setTimeout(this.start,3000); }else{ setTimeout(this.start,300); } } }; // ================ init(); loop(); function init(){ renderer = new THREE.WebGLRenderer({canvas: canvas, antialias: true}); renderer.setSize(width, height); // camera //camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000); camera = new THREE.PerspectiveCamera( 27, window.innerWidth / window.innerHeight, 1, 5000 ) //camera = new THREE.PerspectiveCamera( 15, 60, 100, 2000); //camera = new THREE.OrthographicCamera( width/-2, width/2, height/2, height/-2, 1, 1000); camera.position.y = 0; camera.position.z = 3000; //camera.rotation.x = 45 * (Math.PI / 180); scene = new THREE.Scene(); camera.lookAt(scene.position); // plane collections = new Collections; } function loop(){ var time = (new Date()).getTime(); var dt = time - prevTime; /* camera.position.z += Math.random() * 20 - 10; camera.position.x = 300 * Math.cos(time/100); camera.position.y = 300 * Math.sin(time/100); */ collections.update(); renderer.render( scene, camera ); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/4-webgl/50-three-js-with-shader.js ================================================ // -------------------------- var width, height, prevTime; var velArr; var xPosArr; var isText = false; var totalWidth = 0; var canvas = document.getElementById('c'); var canvasTexture; var textureCanvas = document.createElement("canvas"); textureCanvas.width = window.innerWidth; textureCanvas.height = window.innerHeight; var textureCtx = textureCanvas.getContext("2d"); var camera, scene, renderer; var uniforms; width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; var col = {bl: 100}; var tl = new TimelineLite(); tl.to( col, 2, {bl: 200, onComplete: onComplete1}); function onComplete1(){ tl.to( col, 2, {bl: 100, onComplete: onComplete2, delay:.5}); } function onComplete2(){ tl.to( col, 2, {bl: 200, onComplete: onComplete1, delay:.5}); } // ================ // ================ init(); loop(); function init(){ setCanvasTexture(); setText(); camera = new THREE.Camera(); camera.position.z = 1; scene = new THREE.Scene(); var geometry = new THREE.PlaneGeometry( 2, 2 ); uniforms = { canvasSource : {type: 't', value: canvasTexture}, time : {type: "f", value: 1.0}, resolution : { type: "v2", value: new THREE.Vector2() } }; var material = new THREE.ShaderMaterial({ uniforms : uniforms, vertexShader: document.getElementById( 'vertexShader' ).textContent, fragmentShader: document.getElementById( 'fragmentShader' ).textContent }); var mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); renderer = new THREE.WebGLRenderer({canvas: canvas}); uniforms.resolution.value.x = window.innerWidth; uniforms.resolution.value.y = window.innerHeight; renderer.setSize( window.innerWidth, window.innerHeight ); } function loop(){ uniforms.time.value += 0.05; setText(); renderer.render( scene, camera ); requestAnimationFrame(loop); } function setText(){ textureCtx.fillStyle = "#fff"; textureCtx.fillRect( 0, 0, width, height ); /* yoCtx.fillStyle = "#000000"; yoCtx.fillRect(width/4, height/4, width/2, height/4); */ var date = new Date(); var curHour = date.getHours(); var curHourStr = curHour < 10 ? "0" + curHour : curHour; var curMin = date.getMinutes(); var curMinStr = curMin <10 ? "0" + curMin : curMin; var curSec = date.getSeconds(); var curSecStr = curSec < 10 ? "0" + curSec : curSec; var curTime = curHourStr + ":" + curMinStr + ":" + curSecStr; var textLeft; var textTop; var xPos, yPos; textureCtx.font = "Bold 80px Helvetica"; var textWidth = textureCtx.measureText(curTime); var textExtraWidth = textWidth.width * 1.2; var extraHeight = 80 ; if(!velArr){ velArr = []; for(var yy = 0; yy < height/extraHeight + 1; yy++){ velArr[yy] = -Math.random() - .5; } xPosArr = []; for(var yy = 0; yy < height/extraHeight + 1; yy++){ xPosArr[yy] = []; for(var xx = 0; xx < width / textExtraWidth + 2; xx++){ xPos = textExtraWidth * xx + Math.random()*10 - 5 + velArr[yy]; xPosArr[yy][xx] = xPos; } } totalWidth += parseInt(width / textExtraWidth + 3) * textExtraWidth; } var colNum = parseInt(col.bl) var colRgb = "rgb(" + colNum + ", " + colNum + ", " + colNum + ")"; textureCtx.fillStyle = colRgb; for(var yy = 0; yy < height/extraHeight + 1; yy++){ for(var xx = 0; xx < width / textExtraWidth + 2; xx++){ textureCtx.font = "Bold 80px Helvetica"; xPosArr[yy][xx] += velArr[yy]; if(xPosArr[yy][xx] < -textExtraWidth) xPosArr[yy][xx] += totalWidth; yPos = extraHeight * yy ; //var fontNum = parseInt(75 + 10 *Math.random()); //yoCtx.font = "Bold 80px Arial"; textureCtx.save(); textureCtx.translate(xPosArr[yy][xx], yPos); textureCtx.fillText(curTime,0,0); textureCtx.restore(); } } if(canvasTexture) canvasTexture.needsUpdate = true; } function setCanvasTexture(){ canvasTexture = new THREE.Texture(textureCanvas); canvasTexture.magFilter = THREE.NearestFilter; canvasTexture.needsUpdate = true; } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/4-webgl/55-gl.js ================================================ window.onload = loadScene; function backingScale(context) { if ('devicePixelRatio' in window) { if (window.devicePixelRatio > 1) { return window.devicePixelRatio; } } return 1; } var tempCanvas = document.createElement('canvas'); var tempCtx = tempCanvas.getContext('2d'); var scaleFactor = backingScale(tempCtx); var canvas, gl, ratio, vertices, velocities, freqArr, cw, ch, colorLoc, thetaArr, velThetaArr, velRadArr, boldRateArr, drawType, numLines = 80000; var targetArr = []; var randomTargetXArr = [], randomTargetYArr = []; drawType = 2; /** * Initialises WebGL and creates the 3D scene. */ function Target(rad){ this.x = 0; this.y = 0; this.rotate = 0; this.radius = 0; this.baseRad = rad; this.update(); }; Target.prototype = { update : function() { this.rotate_speed = .001 + Math.random() * 0.05;//Math.random(1) * 0.2 + 0.001; //this.friction = Math.random(1) * 0.8 + 0.1; this.speed = Math.random(1) * 0.2 + 0.03; this.step = Math.random() * 0.1 + 0.2; this.freq = 1; this.bold_rate = this.baseRad * (.8 + Math.random()*.3) ; } } function loadScene() { // Get the canvas element canvas = document.getElementById("c"); // Get the WebGL context gl = canvas.getContext("experimental-webgl"); // Check whether the WebGL context is available or not // if it's not available exit if (!gl) { alert("There's no WebGL context available."); return; } // Set the viewport to the canvas width and height cw = window.innerWidth; ch = window.innerHeight; canvas.width = cw; canvas.height = ch; gl.viewport(0, 0, canvas.width, canvas.height); var vertexShaderScript = document.getElementById("shader-vs"); var vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vertexShaderScript.text); gl.compileShader(vertexShader); if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { alert("Couldn't compile the vertex shader"); gl.deleteShader(vertexShader); return; } var fragmentShaderScript = document.getElementById("shader-fs"); var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fragmentShaderScript.text); gl.compileShader(fragmentShader); if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { alert("Couldn't compile the fragment shader"); gl.deleteShader(fragmentShader); return; } // Create a shader program. gl.program = gl.createProgram(); gl.attachShader(gl.program, vertexShader); gl.attachShader(gl.program, fragmentShader); gl.linkProgram(gl.program); if (!gl.getProgramParameter(gl.program, gl.LINK_STATUS)) { alert("Unable to initialise shaders"); gl.deleteProgram(gl.program); gl.deleteProgram(vertexShader); gl.deleteProgram(fragmentShader); return; } gl.useProgram(gl.program); var vertexPosition = gl.getAttribLocation(gl.program, "vertexPosition"); gl.enableVertexAttribArray(vertexPosition); gl.clearColor(0.1, 0.1, 0.12, 1.0); gl.clearDepth(1.0); gl.enable(gl.BLEND); gl.disable(gl.DEPTH_TEST); gl.blendFunc(gl.SRC_ALPHA, gl.ONE); var vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); // ------------------ setup(); // ------------------ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.DYNAMIC_DRAW); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Define the viewing frustum parameters // More info: http://en.wikipedia.org/wiki/Viewing_frustum // More info: http://knol.google.com/k/view-frustum var fieldOfView = 30.0; var aspectRatio = canvas.width / canvas.height; var nearPlane = 1.0; var farPlane = 10000.0; var top = nearPlane * Math.tan(fieldOfView * Math.PI / 360.0); var bottom = -top; var right = top * aspectRatio; var left = -right; // Create the perspective matrix. The OpenGL function that's normally used for this, // glFrustum() is not included in the WebGL API. That's why we have to do it manually here. // More info: http://www.cs.utk.edu/~vose/c-stuff/opengl/glFrustum.html var a = (right + left) / (right - left); var b = (top + bottom) / (top - bottom); var c = (farPlane + nearPlane) / (farPlane - nearPlane); var d = (2 * farPlane * nearPlane) / (farPlane - nearPlane); var x = (2 * nearPlane) / (right - left); var y = (2 * nearPlane) / (top - bottom); var perspectiveMatrix = [ x, 0, a, 0, 0, y, b, 0, 0, 0, c, d, 0, 0, -1, 0 ]; // Create the modelview matrix // More info about the modelview matrix: http://3dengine.org/Modelview_matrix // More info about the identity matrix: http://en.wikipedia.org/wiki/Identity_matrix var modelViewMatrix = [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ]; // Get the vertex position attribute location from the shader program var vertexPosAttribLocation = gl.getAttribLocation(gl.program, "vertexPosition"); // Specify the location and format of the vertex position attribute gl.vertexAttribPointer(vertexPosAttribLocation, 3.0, gl.FLOAT, false, 0, 0); //gl.vertexAttribPointer(colorLoc, 4.0, gl.FLOAT, false, 0, 0); // Get the location of the "modelViewMatrix" uniform variable from the // shader program var uModelViewMatrix = gl.getUniformLocation(gl.program, "modelViewMatrix"); // Get the location of the "perspectiveMatrix" uniform variable from the // shader program var uPerspectiveMatrix = gl.getUniformLocation(gl.program, "perspectiveMatrix"); // Set the values gl.uniformMatrix4fv(uModelViewMatrix, false, new Float32Array(perspectiveMatrix)); gl.uniformMatrix4fv(uPerspectiveMatrix, false, new Float32Array(modelViewMatrix)); animate(); setTimeout(timer, 1500); } var count = 0; var cn = 0; function animate() { requestAnimationFrame(animate); drawScene(); } function drawScene() { draw(); gl.lineWidth(2); gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.DYNAMIC_DRAW); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); //gl.drawArrays( gl.LINES_STRIP, 0, numLines ); gl.drawArrays(gl.LINES, 0, numLines); //gl.drawArrays( gl.QUAD_STRIP, 0, numLines ); gl.flush(); } // =================================== function setup() { setup00(); } function draw() { /* switch (drawType) { case 0: draw0(); break; case 1: draw1(); break; case 2: draw2(); break; } */ draw00(); } // =================================== function setup00() { vertices = []; velThetaArr = []; velRadArr = []; ratio = cw / ch; velocities = []; thetaArr = []; freqArr = []; boldRateArr = []; // ------------------------------- //var minSize = Math.min(window.innerWidth, scale.innerHeight); var widthScale = window.innerWidth / window.innerHeight; var height = 340 * scaleFactor; var X_MAX_NUM = parseInt(window.innerWidth / height); var Y_MAX_NUM = parseInt(window.innerHeight / height); // 2 -> window.innerHeight // ? -> 50 var targetRad = height / 2 / (2 * window.innerHeight) * 2; var xPos, yPos; for(var xx = -X_MAX_NUM + 1; xx < X_MAX_NUM; xx++){ for(var yy = -Y_MAX_NUM + 1; yy < Y_MAX_NUM; yy++){ //var rad = targetRad / Y_MAX_NUM; var target = new Target(targetRad); target.x = xx / X_MAX_NUM * widthScale; target.y = yy / Y_MAX_NUM; targetArr.push(target); } } for(var ii = 0; ii < numLines; ii++){ vertices.push( 0, 0, 1.83); vertices.push( 0, 0, 1.83); } vertices = new Float32Array(vertices); velocities = new Float32Array(velocities); } // ------------------------------- function draw00(){ for(var ii = 0; ii < targetArr.length; ii++ ){ targetArr[ii].rotate += targetArr[ii].rotate_speed; } var tRad, tX, tY; var bp, px, py; var target; for(var ii = 0; ii < numLines * 2; ii += 2){ bp = ii * 3; // copy old positions //vertices[bp] = vertices[bp + 3]; //vertices[bp + 1] = vertices[bp + 4]; target = targetArr[ii % targetArr.length]; tRad = Math.cos(target.rotate * 2.321 + target.freq * ii ) * target.bold_rate + target.radius; tX = target.x + Math.cos(target.rotate + target.step * ii) * tRad; tY = target.y + Math.sin(target.rotate + target.step * ii) * tRad; px = vertices[bp + 3]; py = vertices[bp + 4]; px += (tX - px) * .1; py += (tY - py) * .1; vertices[bp + 3] = px; vertices[bp + 4] = py; vertices[bp ] = px-0.001; vertices[bp + 1] = py-0.001; } } // =================================== // ------------------------------- function timer() { /* for(var ii = 0; ii < targetArr.length; ii++) { targetArr[ii].update(); } setTimeout(timer, 1500);*/ } ================================================ FILE: app/scripts/4-webgl/56-gl.js ================================================ window.onload = loadScene; function backingScale(context) { if ('devicePixelRatio' in window) { if (window.devicePixelRatio > 1) { return window.devicePixelRatio; } } return 1; } var tempCanvas = document.createElement('canvas'); var tempCtx = tempCanvas.getContext('2d'); var scaleFactor = backingScale(tempCtx); var canvas, gl, ratio, vertices, velocities, freqArr, cw, ch, colorLoc, thetaArr, velThetaArr, velRadArr, boldRateArr, drawType, numLines = 80000; var targetArr = []; var randomTargetXArr = [], randomTargetYArr = []; drawType = 2; /** * Initialises WebGL and creates the 3D scene. */ function Target(rad){ this.x = 0; this.y = 0; this.rotate = 0; this.radius = 0; this.baseRad = rad; this.update(); }; Target.prototype = { freqSpecial : 0.0, update : function() { this.rotate_speed = curObject.rotateSpeed + Math.random() * curObject.rotateSpeedRandom;//Math.random(1) * 0.2 + 0.001; //this.friction = Math.random(1) * 0.8 + 0.1; this.speed = Math.random(1) * curObject.speed + curObject.speed; this.step = Math.random() * curObject.stepRandom + curObject.step; this.freq = curObject.freq + curObject.freqRandom * Math.random() + this.freqSpecial; this.bold_rate = this.baseRad * (curObject.boldRate + Math.random()*curObject.boldRandom) ; //console.log(this.) } } var curObject = { rotateSpeed : 0.000, rotateSpeedRandom: 0, speed : 0.03, speedRandom : 0.0, step : 0, stepRandom : 0.0, freq : 0.01, freqSpecial : 0.0, freqRandom : 0.00, boldRate : 1.0, boldRandom :0, update : function(){ onControllerChange(0); } }; var onControllerChange = function(value){ for(var ii = 0; ii < targetArr.length; ii++) { targetArr[ii].update(); } }; var gui = new dat.GUI(); var rotSpeedController = gui.add(curObject, 'rotateSpeed', 0.000, 0.005); var rotSpeedRandomController = gui.add(curObject, 'rotateSpeedRandom', 0.00, 0.1); var stepController = gui.add(curObject, 'step', 0.0, 1); var stepRandomController = gui.add(curObject, 'stepRandom', 0.0, 1); var speedController = gui.add(curObject, 'speed', 0, 0.2); var speedRandomController = gui.add(curObject, 'speedRandom', 0, 0.6); var freqController = gui.add(curObject, 'freq', 0.00, 1); var freqRandomController = gui.add(curObject, 'freqRandom', 0.00,.1); var boldRateController = gui.add(curObject, "boldRate", 0, 1.0); var bolRandomController = gui.add(curObject, "boldRandom", 0, 1.0); var updateController = gui.add(curObject, 'update'); rotSpeedController.onChange(onControllerChange); rotSpeedRandomController.onChange(onControllerChange); speedController.onChange(onControllerChange); speedRandomController.onChange(onControllerChange); boldRateController.onChange(onControllerChange); bolRandomController.onChange(onControllerChange); freqController.onChange(onControllerChange); freqRandomController.onChange(onControllerChange); stepController.onChange(onControllerChange); stepRandomController.onChange(onControllerChange); var incNum = 0.02; var incSign = +1; var count = 0; function onChangeTimer(){ curObject.step += incNum * incSign * (count + 1); curObject.freq += incNum * incSign * (count + 1); onControllerChange(0); //count = count + count + 1; count++; if(count < 4) setTimeout(onChangeTimer, 500); else setTimeout(backTimer, 500); } circleCount = 1; function backTimer(){ circleCount++; if(circleCount > 7){ circleCount = 1; targetArr = []; var targetRad = 1.0; var target = new Target(targetRad); targetArr.push(target); }else { for (var ii = (circleCount - 1) * (circleCount - 1); ii < circleCount * circleCount; ii++) { var targetRad = 1.0; var target = new Target(targetRad); targetArr.push(target); } var targetNumber = targetArr.length; var kankaku = 2.0 / ( circleCount ); for (var xx = 0; xx < circleCount; xx++) { for (var yy = 0; yy < circleCount; yy++) { var num = xx + yy * circleCount; targetArr[num].baseRad = .9 / circleCount; targetArr[num].x = 1.0 - kankaku * (xx + .5); targetArr[num].y = 1.0 - kankaku * (yy + .5); targetArr[num].freqSpecial = (xx + yy) * 0.01; } } } count = 0; curObject.step = 0.00; curObject.freq = 0.01; onControllerChange(0); setTimeout(onChangeTimer, 300); } /* rotSpeedController.onChange(function(value) { // Fires on every change, drag, keypress, etc. console.log("change") }); */ function loadScene() { // Get the canvas element canvas = document.getElementById("c"); // Get the WebGL context gl = canvas.getContext("experimental-webgl"); // Check whether the WebGL context is available or not // if it's not available exit if (!gl) { alert("There's no WebGL context available."); return; } // Set the viewport to the canvas width and height cw = window.innerWidth; ch = window.innerHeight; canvas.width = cw; canvas.height = ch; gl.viewport(0, 0, canvas.width, canvas.height); var vertexShaderScript = document.getElementById("shader-vs"); var vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vertexShaderScript.text); gl.compileShader(vertexShader); if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { alert("Couldn't compile the vertex shader"); gl.deleteShader(vertexShader); return; } var fragmentShaderScript = document.getElementById("shader-fs"); var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fragmentShaderScript.text); gl.compileShader(fragmentShader); if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { alert("Couldn't compile the fragment shader"); gl.deleteShader(fragmentShader); return; } // Create a shader program. gl.program = gl.createProgram(); gl.attachShader(gl.program, vertexShader); gl.attachShader(gl.program, fragmentShader); gl.linkProgram(gl.program); if (!gl.getProgramParameter(gl.program, gl.LINK_STATUS)) { alert("Unable to initialise shaders"); gl.deleteProgram(gl.program); gl.deleteProgram(vertexShader); gl.deleteProgram(fragmentShader); return; } gl.useProgram(gl.program); var vertexPosition = gl.getAttribLocation(gl.program, "vertexPosition"); gl.enableVertexAttribArray(vertexPosition); gl.clearColor(0.1, 0.1, 0.12, 1.0); gl.clearDepth(1.0); gl.enable(gl.BLEND); gl.disable(gl.DEPTH_TEST); gl.blendFunc(gl.SRC_ALPHA, gl.ONE); var vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); // ------------------ setup(); // ------------------ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.DYNAMIC_DRAW); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Define the viewing frustum parameters // More info: http://en.wikipedia.org/wiki/Viewing_frustum // More info: http://knol.google.com/k/view-frustum var fieldOfView = 30.0; var aspectRatio = canvas.width / canvas.height; var nearPlane = 1.0; var farPlane = 10000.0; var top = nearPlane * Math.tan(fieldOfView * Math.PI / 360.0); var bottom = -top; var right = top * aspectRatio; var left = -right; // Create the perspective matrix. The OpenGL function that's normally used for this, // glFrustum() is not included in the WebGL API. That's why we have to do it manually here. // More info: http://www.cs.utk.edu/~vose/c-stuff/opengl/glFrustum.html var a = (right + left) / (right - left); var b = (top + bottom) / (top - bottom); var c = (farPlane + nearPlane) / (farPlane - nearPlane); var d = (2 * farPlane * nearPlane) / (farPlane - nearPlane); var x = (2 * nearPlane) / (right - left); var y = (2 * nearPlane) / (top - bottom); var perspectiveMatrix = [ x, 0, a, 0, 0, y, b, 0, 0, 0, c, d, 0, 0, -1, 0 ]; // Create the modelview matrix // More info about the modelview matrix: http://3dengine.org/Modelview_matrix // More info about the identity matrix: http://en.wikipedia.org/wiki/Identity_matrix var modelViewMatrix = [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ]; // Get the vertex position attribute location from the shader program var vertexPosAttribLocation = gl.getAttribLocation(gl.program, "vertexPosition"); // Specify the location and format of the vertex position attribute gl.vertexAttribPointer(vertexPosAttribLocation, 3.0, gl.FLOAT, false, 0, 0); //gl.vertexAttribPointer(colorLoc, 4.0, gl.FLOAT, false, 0, 0); // Get the location of the "modelViewMatrix" uniform variable from the // shader program var uModelViewMatrix = gl.getUniformLocation(gl.program, "modelViewMatrix"); // Get the location of the "perspectiveMatrix" uniform variable from the // shader program var uPerspectiveMatrix = gl.getUniformLocation(gl.program, "perspectiveMatrix"); // Set the values gl.uniformMatrix4fv(uModelViewMatrix, false, new Float32Array(perspectiveMatrix)); gl.uniformMatrix4fv(uPerspectiveMatrix, false, new Float32Array(modelViewMatrix)); animate(); setTimeout(timer, 1500); } var count = 0; var cn = 0; function animate() { requestAnimationFrame(animate); drawScene(); } function drawScene() { draw(); gl.lineWidth(2); gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.DYNAMIC_DRAW); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); //gl.drawArrays( gl.LINES_STRIP, 0, numLines ); gl.drawArrays(gl.LINES, 0, numLines); //gl.drawArrays( gl.QUAD_STRIP, 0, numLines ); gl.flush(); } // =================================== function setup() { setup00(); setTimeout(onChangeTimer, 300); } function draw() { /* switch (drawType) { case 0: draw0(); break; case 1: draw1(); break; case 2: draw2(); break; } */ draw00(); } // =================================== function setup00() { vertices = []; velThetaArr = []; velRadArr = []; ratio = cw / ch; velocities = []; thetaArr = []; freqArr = []; boldRateArr = []; // ------------------------------- //var minSize = Math.min(window.innerWidth, scale.innerHeight); var widthScale = window.innerWidth / window.innerHeight; var height = 340 * scaleFactor; var X_MAX_NUM = parseInt(window.innerWidth / height); var Y_MAX_NUM = parseInt(window.innerHeight / height); // 2 -> window.innerHeight // ? -> 50 var targetRad = 1.0; var xPos, yPos; var target = new Target(targetRad); target.x = 0; target.y = 0; targetArr.push(target); for(var ii = 0; ii < numLines; ii++){ vertices.push( 0, 0, 1.83); vertices.push( 0, 0, 1.83); } vertices = new Float32Array(vertices); velocities = new Float32Array(velocities); } // ------------------------------- function draw00(){ for(var ii = 0; ii < targetArr.length; ii++ ){ targetArr[ii].rotate += targetArr[ii].rotate_speed; } var tRad, tX, tY; var bp, px, py; var target; var side = .5 / window.innerHeight; for(var ii = 0; ii < numLines * 2; ii += 2){ bp = ii * 3; target = targetArr[ (ii/2) % targetArr.length]; tRad = Math.cos(target.rotate * 2.321 + target.freq * ii ) * target.bold_rate ; tX = target.x + Math.cos(target.rotate + target.step * ii) * tRad; tY = target.y + Math.sin(target.rotate + target.step * ii) * tRad; px = vertices[bp + 3]; py = vertices[bp + 4]; px += (tX - px) * .3; py += (tY - py) * .3; vertices[bp + 3] = px; vertices[bp + 4] = py; vertices[bp ] = px-side; vertices[bp + 1] = py-side; } } // =================================== // ------------------------------- function timer() { /* for(var ii = 0; ii < targetArr.length; ii++) { targetArr[ii].update(); } setTimeout(timer, 1500);*/ } ================================================ FILE: app/scripts/4-webgl/57-gl.js ================================================ window.onload = loadScene; var canvas, gl, ratio, vertices, velocities, freqArr, cw, ch, colorLoc, thetaArr, velThetaArr, velRadArr0, velRadArr1, boldRateArr, drawType, numLines = 30000; var colorArr = []; var colorVbo; var target = []; var type = []; var randomTargetXArr = [], randomTargetYArr = []; drawType = 2; /** * Initialises WebGL and creates the 3D scene. */ function loadScene() { // Get the canvas element canvas = document.getElementById("c"); // Get the WebGL context gl = canvas.getContext("experimental-webgl"); // Check whether the WebGL context is available or not // if it's not available exit if (!gl) { alert("There's no WebGL context available."); return; } // Set the viewport to the canvas width and height cw = window.innerWidth; ch = window.innerHeight; canvas.width = cw; canvas.height = ch; gl.viewport(0, 0, canvas.width, canvas.height); // Load the vertex shader that's defined in a separate script // block at the top of this page. // More info about shaders: http://en.wikipedia.org/wiki/Shader_Model // More info about GLSL: http://en.wikipedia.org/wiki/GLSL // More info about vertex shaders: http://en.wikipedia.org/wiki/Vertex_shader // Grab the script element var vertexShaderScript = document.getElementById("shader-vs"); var vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vertexShaderScript.text); gl.compileShader(vertexShader); if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { alert("Couldn't compile the vertex shader"); gl.deleteShader(vertexShader); return; } // Load the fragment shader that's defined in a separate script // More info about fragment shaders: http://en.wikipedia.org/wiki/Fragment_shader var fragmentShaderScript = document.getElementById("shader-fs"); var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fragmentShaderScript.text); gl.compileShader(fragmentShader); if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { alert("Couldn't compile the fragment shader"); gl.deleteShader(fragmentShader); return; } // Create a shader program. gl.program = gl.createProgram(); gl.attachShader(gl.program, vertexShader); gl.attachShader(gl.program, fragmentShader); gl.linkProgram(gl.program); if (!gl.getProgramParameter(gl.program, gl.LINK_STATUS)) { alert("Unable to initialise shaders"); gl.deleteProgram(gl.program); gl.deleteProgram(vertexShader); gl.deleteProgram(fragmentShader); return; } gl.useProgram(gl.program); //var vertexPosition = gl.getAttribLocation(gl.program, "a_position"); gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clearDepth(1.0); gl.enable(gl.BLEND); gl.disable(gl.DEPTH_TEST); gl.blendFunc(gl.SRC_ALPHA, gl.ONE); ; //color vbo // ------------------ setup(); // ------------------ vertices = new Float32Array(vertices); velocities = new Float32Array(velocities); //console.log(c) colorArr = new Float32Array(colorArr); console.log(colorArr.length) /* thetaArr = new Float32Array(thetaArr); velThetaArr = new Float32Array(velThetaArr); velRadArr = new Float32Array(velRadArr);*/ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); var colorVBO = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, colorVBO); gl.bufferData(gl.ARRAY_BUFFER, colorArr, gl.STATIC_DRAW); var colorPosAttrbLocation = gl.getAttribLocation(gl.program, "a_color"); gl.enableVertexAttribArray(colorPosAttrbLocation); gl.vertexAttribPointer(colorPosAttrbLocation, 4.0, gl.FLOAT, false, 0, 0); var vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer) gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.DYNAMIC_DRAW); var vertexPosAttribLocation = gl.getAttribLocation(gl.program, "a_position"); gl.enableVertexAttribArray(vertexPosAttribLocation); gl.vertexAttribPointer(vertexPosAttribLocation, 2.0, gl.FLOAT, false, 0, 0); var resolutionLocation = gl.getUniformLocation( gl.program, "u_resolution" ); gl.uniform2f( resolutionLocation, window.innerWidth, window.innerHeight ); gl.enable(gl.BLEND); gl.disable(gl.DEPTH_TEST); gl.blendFunc(gl.SRC_ALPHA, gl.ONE); animate(); //setTimeout(timer, 1500); } var count = 0; var cn = 0; function animate() { requestAnimationFrame(animate); drawScene(); } function drawScene() { draw(); gl.lineWidth(1); gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.DYNAMIC_DRAW); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.drawArrays(gl.LINES, 0, numLines); gl.flush(); } // =================================== var centerRadX = 90; var centerRadY = 120; var centerTheta = 0; var centerVelTheta = .03; function setup() { vertices = []; velThetaArr = []; velRadArr0 = []; velRadArr1 = []; ratio = cw / ch; velocities = []; thetaArr = []; freqArr = []; boldRateArr = []; // ------------------------------- for (var ii = 0; ii < numLines; ii++) { var rad, rad2; var random1 = Math.random(); var random2 = Math.random(); if(random1 < .33) rad = 10; else if(random1 < .66) rad = 60; else rad = 120; if(random2 < .33) rad2 = 60; else if(random2 < .66) rad2 = 100; else rad2 = 140; var theta = Math.random() * Math.PI * 2; var freq = Math.random() * 0.12 + 0.03; var boldRate = Math.random() * .04 + .01; var randomPosX = (Math.random() * 2 - 1) * window.innerWidth / window.innerHeight; var randomPosY = Math.random() * 2 - 1; vertices.push(rad * Math.cos(theta), rad * Math.sin(theta)); vertices.push(rad * Math.cos(theta), rad * Math.sin(theta)); thetaArr.push(theta); velRadArr0.push(rad); velRadArr1.push(rad2); freqArr.push(freq); boldRateArr.push(boldRate); randomTargetXArr.push(randomPosX); randomTargetYArr.push(randomPosY); var colRand = Math.random(); var col; if(colRand < 1/3) { type.push(0); col = [0.8, 0.0, 0.0]; var velTheta = (Math.random() * .2 + .8) * Math.PI * 2 / 300; } else if(colRand < 2/3) { type.push(1); col = [0.0, 0.8, 0.0]; var velTheta = (Math.random() * .2 + .8) * Math.PI * 2 / 100; }else { type.push(2); col = [0.0, 0.0, 0.8]; var velTheta = (Math.random() * .2 + .8) * Math.PI * 2 / 200; } colorArr.push(col[0], col[1], col[2], 0.06 ); colorArr.push(col[0], col[1], col[2], 0.06 ); velThetaArr.push(velTheta); } freqArr = new Float32Array(freqArr); } // ------------------------------- // =================================== // ------------------------------- var theta1 = 0, theta2 = 0; var rCount = Math.PI/2; function draw() { cn += .1; var i, n = vertices.length, p, bp; var px, py; var cenX, cenY; var pTheta; var rad; var num; rCount += 0.03; var rRad = 10 * Math.sin(rCount); var transX, transY; centerTheta += centerVelTheta; cenX = centerRadX * Math.cos(centerTheta); cenY = centerRadY * Math.sin(centerTheta); theta1 += .01; theta2 += .02; for (i = 0; i < numLines * 2; i += 2) { bp = i * 2; num = parseInt(i / 2); if(type[num] == 0){ transX = rRad * Math.cos(0); transY = rRad * Math.sin(0); }else if(type[num] == 2){ transX = rRad * Math.cos(120/180*Math.PI); transY = rRad * Math.sin(120/180*Math.PI); }else{ transX = rRad * Math.cos(240/180*Math.PI); transY = rRad * Math.sin(240/180*Math.PI); } pTheta = thetaArr[num]; pTheta = pTheta + velThetaArr[num]; thetaArr[num] = pTheta; rad = velRadArr0[num]; px = rad * Math.cos(pTheta - theta2) + transX; py = rad * Math.sin(pTheta - theta1) + transY; vertices[bp + 2] = px + cenX; vertices[bp + 3] = py + cenY; rad = velRadArr1[num]; px = rad * Math.cos(pTheta + theta1 ) +transX; py = rad * Math.sin(pTheta + theta2 ) +transY; vertices[bp] = px; vertices[bp + 1] = py; } } // ------------------------------- function timer() { drawType = (drawType + 1) % 3; setTimeout(timer, 1500); } ================================================ FILE: app/scripts/4-webgl/58-three-js.js ================================================ /** * Created by kenji-special on 12/26/14. */ var scene, camera, renderer; var geometry, material, mesh; var prevSecondTheta; var hour, min, second; var secondTheta; var secondHandGeometry, secondHandMaterial, secondHandLine; var id; init(); animate(); function init() { scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera( 100, window.innerWidth / window.innerHeight, 100, 10000 ); camera.position.z = 300; geometry = new THREE.BoxGeometry( 200, 200, 200 ); material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } ); mesh = new THREE.Mesh( geometry, material ); //scene.add( mesh ); secondHandGeometry = new THREE.Geometry(); secondHandGeometry.vertices.push(new THREE.Vector3( 0, 200, 0)); secondHandGeometry.vertices.push(new THREE.Vector3( 0, -20, 0)); secondHandMaterial = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 1 } ); secondHandLine = new THREE.Line(secondHandGeometry, secondHandMaterial); scene.add(secondHandLine); renderer = new THREE.WebGLRenderer({canvas: document.getElementById("c")}); renderer.setSize( window.innerWidth, window.innerHeight ); //document.body.appendChild( renderer.domElement ); keyEvent.on(ESC_DOWN, onEscapeDonwHandler); } function animate() { id = requestAnimationFrame( animate ); var dd = new Date(); second = dd.getSeconds(); secondTheta = second / 60 * 2 * Math.PI * -1; secondHandLine.rotation.set(0, 0, secondTheta); // calculation of the area of the animation. // ---------------------------- prevSecondTheta = secondTheta; renderer.render( scene, camera ); } function onEscapeDonwHandler(){ cancelRequestAnimFrame(id); //cancelAnimationFrame(requestId); } ================================================ FILE: app/scripts/4-webgl/64-three-js.js ================================================ var container, stats; var camera, scene, renderer; var sqLength = 80; var yy = 0; var group; var meshArr = []; var targetRotation = 0; var targetRotationOnMouseDown = 0; var mouseX = 0; var mouseXOnMouseDown = 0; var windowHalfX = window.innerWidth / 2; var windowHalfY = window.innerHeight / 2; var width = window.innerWidth; var height = window.innerHeight; init(); animate(); function init() { container = document.createElement('div'); document.body.appendChild(container); scene = new THREE.Scene(); //camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 ); camera = new THREE.OrthographicCamera(width / -2, width / 2, height / 2, height / -2, 1, 1000); camera.position.set(0, 150, 500); scene.add(camera); var light = new THREE.PointLight(0xffffff, 0.8); camera.add(light); function addShape(shape, extrudeSettings, color, x, y, z) { var points = shape.createPointsGeometry(); var spacedPoints = shape.createSpacedPointsGeometry(50); // flat shape var geometry = new THREE.ShapeGeometry(shape); var mesh = new THREE.Mesh(geometry, new THREE.MeshPhongMaterial({ color: color, ambient: color, side: THREE.DoubleSide })); mesh.position.set(x, y, 0); scene.add(mesh); return mesh; } // Square var squareShape = new THREE.Shape(); squareShape.moveTo(-sqLength / 2, -sqLength / 2); squareShape.lineTo(-sqLength / 2, sqLength / 2); squareShape.lineTo(sqLength / 2, sqLength / 2); squareShape.lineTo(sqLength / 2, -sqLength / 2); squareShape.lineTo(-sqLength / 2, -sqLength / 2); var extrudeSettings = {amount: 8, bevelEnabled: true, bevelSegments: 2, steps: 2, bevelSize: 1, bevelThickness: 1}; // addShape( shape, color, x, y, z, rx, ry,rz, s ); var countX = 0; var countY = 0; for (var xx = -10; xx <= 10; xx++) { var addValue; meshArr[countX] = []; for (var yy = -10; yy <= 10; yy++) { if (yy % 2 == 0) addValue = 1; else addValue = 0; var xPos = sqLength * (xx * 2 + addValue); var yPos = sqLength * yy ; var squareMesh = addShape(squareShape, extrudeSettings, 0x000000, xPos, yPos, 0); squareMesh.originalX = xPos; squareMesh.originalY = yPos; meshArr[countX][countY] = squareMesh; countY++; } countX++; countY = 0; } randomGenerator(); // renderer = new THREE.WebGLRenderer({antialias: true}); renderer.setClearColor(0xf0f0f0); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(window.innerWidth, window.innerHeight); container.appendChild(renderer.domElement); document.addEventListener('mousedown', onDocumentMouseDown, false); document.addEventListener('touchstart', onDocumentTouchStart, false); document.addEventListener('touchmove', onDocumentTouchMove, false); // window.addEventListener('resize', onWindowResize, false); } function onWindowResize() { windowHalfX = window.innerWidth / 2; windowHalfY = window.innerHeight / 2; camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } // function onDocumentMouseDown(event) { event.preventDefault(); document.addEventListener('mousemove', onDocumentMouseMove, false); document.addEventListener('mouseup', onDocumentMouseUp, false); document.addEventListener('mouseout', onDocumentMouseOut, false); mouseXOnMouseDown = event.clientX - windowHalfX; targetRotationOnMouseDown = targetRotation; } function onDocumentMouseMove(event) { mouseX = event.clientX - windowHalfX; targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02; } function onDocumentMouseUp(event) { document.removeEventListener('mousemove', onDocumentMouseMove, false); document.removeEventListener('mouseup', onDocumentMouseUp, false); document.removeEventListener('mouseout', onDocumentMouseOut, false); } function onDocumentMouseOut(event) { document.removeEventListener('mousemove', onDocumentMouseMove, false); document.removeEventListener('mouseup', onDocumentMouseUp, false); document.removeEventListener('mouseout', onDocumentMouseOut, false); } function onDocumentTouchStart(event) { if (event.touches.length == 1) { event.preventDefault(); mouseXOnMouseDown = event.touches[0].pageX - windowHalfX; targetRotationOnMouseDown = targetRotation; } } function onDocumentTouchMove(event) { if (event.touches.length == 1) { event.preventDefault(); mouseX = event.touches[0].pageX - windowHalfX; targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05; } } // function animate() { requestAnimationFrame(animate); for(var ii = 0; ii < meshArr.length; ii++){ //meshArr[ii][yy].position.x ++; meshArr[ii][yy].position.y = meshArr[ii][yy].originalY + sqLength * (2 * (Math.random() + Math.random() +Math.random())/3 - 1); } render(); } function render() { renderer.render(scene, camera); } function randomGenerator(){ yy++;// = (Math.random() * 12 ) | 0; setTimeout(randomGenerator, 1000); } ================================================ FILE: app/scripts/4-webgl/99-00-gl-learning.js ================================================ // canvasエレメントを取得 var c = document.getElementById('canvas'); c.width = 300; c.height = 300; // webglコンテキストを取得 var gl = c.getContext('webgl') || c.getContext('experimental-webgl'); // canvasを初期化する色を設定する gl.clearColor(0.0, 0.0, 0.0, 1.0); // canvasを初期化する際の深度を設定する gl.clearDepth(1.0); // canvasを初期化 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // 頂点シェーダとフラグメントシェーダの生成 var v_shader = create_shader('vs'); var f_shader = create_shader('fs'); // プログラムオブジェクトの生成とリンク var prg = create_program(v_shader, f_shader); // attributeLocationの取得 var attLocation = gl.getAttribLocation(prg, 'position'); // attributeの要素数(この場合は xyz の3要素) var attStride = 3; // モデル(頂点)データ var vertex_position = [ 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0 ]; // VBOの生成 var vbo = create_vbo(vertex_position); // VBOをバインド gl.bindBuffer(gl.ARRAY_BUFFER, vbo); // attribute属性を有効にする gl.enableVertexAttribArray(attLocation); // attribute属性を登録 gl.vertexAttribPointer(attLocation, attStride, gl.FLOAT, false, 0, 0); // minMatrix.js を用いた行列関連処理 // matIVオブジェクトを生成 var m = new matIV(); // 各種行列の生成と初期化 var mMatrix = m.identity(m.create()); var vMatrix = m.identity(m.create()); var pMatrix = m.identity(m.create()); var mvpMatrix = m.identity(m.create()); // ビュー座標変換行列 m.lookAt([0.0, 1.0, 3.0], [0, 0, 0], [0, 1, 0], vMatrix); // プロジェクション座標変換行列 m.perspective(90, c.width / c.height, 0.1, 100, pMatrix); // 各行列を掛け合わせ座標変換行列を完成させる m.multiply(pMatrix, vMatrix, mvpMatrix); m.multiply(mvpMatrix, mMatrix, mvpMatrix); // uniformLocationの取得 var uniLocation = gl.getUniformLocation(prg, 'mvpMatrix'); // uniformLocationへ座標変換行列を登録 gl.uniformMatrix4fv(uniLocation, false, mvpMatrix); // モデルの描画 gl.drawArrays(gl.TRIANGLES, 0, 3); // コンテキストの再描画 gl.flush(); // シェーダを生成する関数 function create_shader(id){ // シェーダを格納する変数 var shader; // HTMLからscriptタグへの参照を取得 var scriptElement = document.getElementById(id); // scriptタグが存在しない場合は抜ける if(!scriptElement){return;} // scriptタグのtype属性をチェック switch(scriptElement.type){ // 頂点シェーダの場合 case 'x-shader/x-vertex': shader = gl.createShader(gl.VERTEX_SHADER); break; // フラグメントシェーダの場合 case 'x-shader/x-fragment': shader = gl.createShader(gl.FRAGMENT_SHADER); break; default : return; } // 生成されたシェーダにソースを割り当てる gl.shaderSource(shader, scriptElement.text); // シェーダをコンパイルする gl.compileShader(shader); // シェーダが正しくコンパイルされたかチェック if(gl.getShaderParameter(shader, gl.COMPILE_STATUS)){ // 成功していたらシェーダを返して終了 return shader; }else{ // 失敗していたらエラーログをアラートする alert(gl.getShaderInfoLog(shader)); } } // プログラムオブジェクトを生成しシェーダをリンクする関数 function create_program(vs, fs){ // プログラムオブジェクトの生成 var program = gl.createProgram(); // プログラムオブジェクトにシェーダを割り当てる gl.attachShader(program, vs); gl.attachShader(program, fs); // シェーダをリンク gl.linkProgram(program); // シェーダのリンクが正しく行なわれたかチェック if(gl.getProgramParameter(program, gl.LINK_STATUS)){ // 成功していたらプログラムオブジェクトを有効にする gl.useProgram(program); // プログラムオブジェクトを返して終了 return program; }else{ // 失敗していたらエラーログをアラートする alert(gl.getProgramInfoLog(program)); } } // VBOを生成する関数 function create_vbo(data){ // バッファオブジェクトの生成 var vbo = gl.createBuffer(); // バッファをバインドする gl.bindBuffer(gl.ARRAY_BUFFER, vbo); // バッファにデータをセット gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW); // バッファのバインドを無効化 gl.bindBuffer(gl.ARRAY_BUFFER, null); // 生成した VBO を返して終了 return vbo; } ================================================ FILE: app/scripts/4-webgl/vendors/minMatrix.js ================================================ // ------------------------------------------------------------------------------------------------ // minMatrix.js // version 0.0.1 // Copyright (c) doxas // ------------------------------------------------------------------------------------------------ function matIV(){ this.create = function(){ return new Float32Array(16); }; this.identity = function(dest){ dest[0] = 1; dest[1] = 0; dest[2] = 0; dest[3] = 0; dest[4] = 0; dest[5] = 1; dest[6] = 0; dest[7] = 0; dest[8] = 0; dest[9] = 0; dest[10] = 1; dest[11] = 0; dest[12] = 0; dest[13] = 0; dest[14] = 0; dest[15] = 1; return dest; }; this.multiply = function(mat1, mat2, dest){ var a = mat1[0], b = mat1[1], c = mat1[2], d = mat1[3], e = mat1[4], f = mat1[5], g = mat1[6], h = mat1[7], i = mat1[8], j = mat1[9], k = mat1[10], l = mat1[11], m = mat1[12], n = mat1[13], o = mat1[14], p = mat1[15], A = mat2[0], B = mat2[1], C = mat2[2], D = mat2[3], E = mat2[4], F = mat2[5], G = mat2[6], H = mat2[7], I = mat2[8], J = mat2[9], K = mat2[10], L = mat2[11], M = mat2[12], N = mat2[13], O = mat2[14], P = mat2[15]; dest[0] = A * a + B * e + C * i + D * m; dest[1] = A * b + B * f + C * j + D * n; dest[2] = A * c + B * g + C * k + D * o; dest[3] = A * d + B * h + C * l + D * p; dest[4] = E * a + F * e + G * i + H * m; dest[5] = E * b + F * f + G * j + H * n; dest[6] = E * c + F * g + G * k + H * o; dest[7] = E * d + F * h + G * l + H * p; dest[8] = I * a + J * e + K * i + L * m; dest[9] = I * b + J * f + K * j + L * n; dest[10] = I * c + J * g + K * k + L * o; dest[11] = I * d + J * h + K * l + L * p; dest[12] = M * a + N * e + O * i + P * m; dest[13] = M * b + N * f + O * j + P * n; dest[14] = M * c + N * g + O * k + P * o; dest[15] = M * d + N * h + O * l + P * p; return dest; }; this.scale = function(mat, vec, dest){ dest[0] = mat[0] * vec[0]; dest[1] = mat[1] * vec[0]; dest[2] = mat[2] * vec[0]; dest[3] = mat[3] * vec[0]; dest[4] = mat[4] * vec[1]; dest[5] = mat[5] * vec[1]; dest[6] = mat[6] * vec[1]; dest[7] = mat[7] * vec[1]; dest[8] = mat[8] * vec[2]; dest[9] = mat[9] * vec[2]; dest[10] = mat[10] * vec[2]; dest[11] = mat[11] * vec[2]; dest[12] = mat[12]; dest[13] = mat[13]; dest[14] = mat[14]; dest[15] = mat[15]; return dest; }; this.translate = function(mat, vec, dest){ dest[0] = mat[0]; dest[1] = mat[1]; dest[2] = mat[2]; dest[3] = mat[3]; dest[4] = mat[4]; dest[5] = mat[5]; dest[6] = mat[6]; dest[7] = mat[7]; dest[8] = mat[8]; dest[9] = mat[9]; dest[10] = mat[10]; dest[11] = mat[11]; dest[12] = mat[0] * vec[0] + mat[4] * vec[1] + mat[8] * vec[2] + mat[12]; dest[13] = mat[1] * vec[0] + mat[5] * vec[1] + mat[9] * vec[2] + mat[13]; dest[14] = mat[2] * vec[0] + mat[6] * vec[1] + mat[10] * vec[2] + mat[14]; dest[15] = mat[3] * vec[0] + mat[7] * vec[1] + mat[11] * vec[2] + mat[15]; return dest; }; this.rotate = function(mat, angle, axis, dest){ var sq = Math.sqrt(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]); if(!sq){return null;} var a = axis[0], b = axis[1], c = axis[2]; if(sq != 1){sq = 1 / sq; a *= sq; b *= sq; c *= sq;} var d = Math.sin(angle), e = Math.cos(angle), f = 1 - e, g = mat[0], h = mat[1], i = mat[2], j = mat[3], k = mat[4], l = mat[5], m = mat[6], n = mat[7], o = mat[8], p = mat[9], q = mat[10], r = mat[11], s = a * a * f + e, t = b * a * f + c * d, u = c * a * f - b * d, v = a * b * f - c * d, w = b * b * f + e, x = c * b * f + a * d, y = a * c * f + b * d, z = b * c * f - a * d, A = c * c * f + e; if(angle){ if(mat != dest){ dest[12] = mat[12]; dest[13] = mat[13]; dest[14] = mat[14]; dest[15] = mat[15]; } } else { dest = mat; } dest[0] = g * s + k * t + o * u; dest[1] = h * s + l * t + p * u; dest[2] = i * s + m * t + q * u; dest[3] = j * s + n * t + r * u; dest[4] = g * v + k * w + o * x; dest[5] = h * v + l * w + p * x; dest[6] = i * v + m * w + q * x; dest[7] = j * v + n * w + r * x; dest[8] = g * y + k * z + o * A; dest[9] = h * y + l * z + p * A; dest[10] = i * y + m * z + q * A; dest[11] = j * y + n * z + r * A; return dest; }; this.lookAt = function(eye, center, up, dest){ var eyeX = eye[0], eyeY = eye[1], eyeZ = eye[2], upX = up[0], upY = up[1], upZ = up[2], centerX = center[0], centerY = center[1], centerZ = center[2]; if(eyeX == centerX && eyeY == centerY && eyeZ == centerZ){return this.identity(dest);} var x0, x1, x2, y0, y1, y2, z0, z1, z2, l; z0 = eyeX - center[0]; z1 = eyeY - center[1]; z2 = eyeZ - center[2]; l = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); z0 *= l; z1 *= l; z2 *= l; x0 = upY * z2 - upZ * z1; x1 = upZ * z0 - upX * z2; x2 = upX * z1 - upY * z0; l = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); if(!l){ x0 = 0; x1 = 0; x2 = 0; } else { l = 1 / l; x0 *= l; x1 *= l; x2 *= l; } y0 = z1 * x2 - z2 * x1; y1 = z2 * x0 - z0 * x2; y2 = z0 * x1 - z1 * x0; l = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); if(!l){ y0 = 0; y1 = 0; y2 = 0; } else { l = 1 / l; y0 *= l; y1 *= l; y2 *= l; } dest[0] = x0; dest[1] = y0; dest[2] = z0; dest[3] = 0; dest[4] = x1; dest[5] = y1; dest[6] = z1; dest[7] = 0; dest[8] = x2; dest[9] = y2; dest[10] = z2; dest[11] = 0; dest[12] = -(x0 * eyeX + x1 * eyeY + x2 * eyeZ); dest[13] = -(y0 * eyeX + y1 * eyeY + y2 * eyeZ); dest[14] = -(z0 * eyeX + z1 * eyeY + z2 * eyeZ); dest[15] = 1; return dest; }; this.perspective = function(fovy, aspect, near, far, dest){ var t = near * Math.tan(fovy * Math.PI / 360); var r = t * aspect; var a = r * 2, b = t * 2, c = far - near; dest[0] = near * 2 / a; dest[1] = 0; dest[2] = 0; dest[3] = 0; dest[4] = 0; dest[5] = near * 2 / b; dest[6] = 0; dest[7] = 0; dest[8] = 0; dest[9] = 0; dest[10] = -(far + near) / c; dest[11] = -1; dest[12] = 0; dest[13] = 0; dest[14] = -(far * near * 2) / c; dest[15] = 0; return dest; }; this.transpose = function(mat, dest){ dest[0] = mat[0]; dest[1] = mat[4]; dest[2] = mat[8]; dest[3] = mat[12]; dest[4] = mat[1]; dest[5] = mat[5]; dest[6] = mat[9]; dest[7] = mat[13]; dest[8] = mat[2]; dest[9] = mat[6]; dest[10] = mat[10]; dest[11] = mat[14]; dest[12] = mat[3]; dest[13] = mat[7]; dest[14] = mat[11]; dest[15] = mat[15]; return dest; }; this.inverse = function(mat, dest){ var a = mat[0], b = mat[1], c = mat[2], d = mat[3], e = mat[4], f = mat[5], g = mat[6], h = mat[7], i = mat[8], j = mat[9], k = mat[10], l = mat[11], m = mat[12], n = mat[13], o = mat[14], p = mat[15], q = a * f - b * e, r = a * g - c * e, s = a * h - d * e, t = b * g - c * f, u = b * h - d * f, v = c * h - d * g, w = i * n - j * m, x = i * o - k * m, y = i * p - l * m, z = j * o - k * n, A = j * p - l * n, B = k * p - l * o, ivd = 1 / (q * B - r * A + s * z + t * y - u * x + v * w); dest[0] = ( f * B - g * A + h * z) * ivd; dest[1] = (-b * B + c * A - d * z) * ivd; dest[2] = ( n * v - o * u + p * t) * ivd; dest[3] = (-j * v + k * u - l * t) * ivd; dest[4] = (-e * B + g * y - h * x) * ivd; dest[5] = ( a * B - c * y + d * x) * ivd; dest[6] = (-m * v + o * s - p * r) * ivd; dest[7] = ( i * v - k * s + l * r) * ivd; dest[8] = ( e * A - f * y + h * w) * ivd; dest[9] = (-a * A + b * y - d * w) * ivd; dest[10] = ( m * u - n * s + p * q) * ivd; dest[11] = (-i * u + j * s - l * q) * ivd; dest[12] = (-e * z + f * x - g * w) * ivd; dest[13] = ( a * z - b * x + c * w) * ivd; dest[14] = (-m * t + n * r - o * q) * ivd; dest[15] = ( i * t - j * r + k * q) * ivd; return dest; }; } ================================================ FILE: app/scripts/5-loop/43-loop.js ================================================ // -------------------------- var NUM_BALLS = 130, DAMPING = 0.3, GRAVITY = 1, MOUSE_SIZE = 50, SPEED = 1; var TWO_PI = Math.PI * 2; var count = 0; var balls = []; var walls = []; var firstWidth; var leftWidth; var reset = { y : null }; var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var isNormal = true; width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var Wall = function(left, right, top, bot){ this.left = left; this.right = right; this.top = top; this.bot = bot; }; var Ball = function(x, y, radius, wall) { this.x = x; this.y = y; this.px = x; this.py = y; this.fx = 0; this.fy = 0; this.radius = 0; TweenLite.to(this, 1, {radius: radius}); }; Ball.prototype.apply_force = function(delta) { delta *= delta; this.fy += GRAVITY; this.x += this.fx * delta; this.y += this.fy * delta; this.fx = this.fy = 0; }; Ball.prototype.verlet = function() { var nx = (this.x * 2) - this.px; var ny = (this.y * 2) - this.py; this.px = this.x; this.py = this.y; this.x = nx; this.y = ny; }; Ball.prototype.draw = function(ctx) { ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, TWO_PI); ctx.fill(); }; //--------------------------------------- var resolve_collisions = function(ip) { var i = balls[count].length; while (i--) { var ball_1 = balls[count][i]; var n = balls[count].length; while (n--) { if (n == i) continue; var ball_2 = balls[count][n]; var diff_x = ball_1.x - ball_2.x; var diff_y = ball_1.y - ball_2.y; var length = diff_x * diff_x + diff_y * diff_y; var dist = Math.sqrt(length); var real_dist = dist - (ball_1.radius + ball_2.radius); if (real_dist < 0) { var vel_x1 = ball_1.x - ball_1.px; var vel_y1 = ball_1.y - ball_1.py; var vel_x2 = ball_2.x - ball_2.px; var vel_y2 = ball_2.y - ball_2.py; var depth_x = diff_x * (real_dist / dist); var depth_y = diff_y * (real_dist / dist); ball_1.x -= depth_x * 0.5; ball_1.y -= depth_y * 0.5; ball_2.x += depth_x * 0.5; ball_2.y += depth_y * 0.5; if (ip) { var pr1 = DAMPING * (diff_x*vel_x1+diff_y*vel_y1) / length, pr2 = DAMPING * (diff_x*vel_x2+diff_y*vel_y2) / length; vel_x1 += pr2 * diff_x - pr1 * diff_x; vel_x2 += pr1 * diff_x - pr2 * diff_x; vel_y1 += pr2 * diff_y - pr1 * diff_y; vel_y2 += pr1 * diff_y - pr2 * diff_y; ball_1.px = ball_1.x - vel_x1; ball_1.py = ball_1.y - vel_y1; ball_2.px = ball_2.x - vel_x2; ball_2.py = ball_2.y - vel_y2; } } } } }; var check_walls = function(wall) { var i = balls[count].length; while (i--) { var ball = balls[count][i]; if (ball.x < wall.left + ball.radius) { var vel_x = ball.px - ball.x; ball.x = wall.left + ball.radius; ball.px = ball.x - vel_x * DAMPING; } else if (ball.x + ball.radius > wall.right) { var vel_x = ball.px - ball.x; ball.x = wall.right - ball.radius; ball.px = ball.x - vel_x * DAMPING; } if (ball.y + ball.radius > wall.bot) { var vel_y = ball.py - ball.y; ball.y = wall.bot - ball.radius; ball.py = ball.y - vel_y * DAMPING; } } }; // ================ var add_ball = function(x, y, r) { var x = x || Math.random() * (firstWidth), r = r || leftWidth * .4 * (.1 +.8*Math.random()) + 1; if(r > 100) r = 90 * Math.random() + 10; var y = y || -Math.random() * 100 + 50, s = true, i = balls[count].length; if (s) balls[count].push(new Ball(x, y, r)); }; var totalWidth = 0; function init(){ firstWidth = width; totalWidth = width /2; leftWidth = width - totalWidth; var wall = new Wall(0, width, 0, height) walls.push(wall); balls[count] = []; for(var i = 0; i < 20; i++){ add_ball(); } var dis = leftWidth / 500; TweenLite.to(wall, dis, {left: leftWidth, delay: 2, ease:"Power2.easeOut", onComplete: addNew}); } function addNew(){ setTimeout(function(){ count++; firstWidth = width - totalWidth; var wall = new Wall(0, firstWidth, 0, height) walls.push(wall); balls[count] = []; if(count < 3) totalWidth += (width - totalWidth)/2; leftWidth = width - totalWidth; for(var i = 0; i < 20; i++){ add_ball(); } if(count < 3) { var dis = leftWidth / 500; if(dis < .3) dis = .3; TweenLite.to(wall, dis, {left: leftWidth, delay: 1, ease:"Power2.easeOut", onComplete: addNew}); }else{ setTimeout(function(){ isNormal = false; reset.y = window.innerHeight; TweenLite.to(reset, 1, {y: 0, delay:.5, ease:"Power2.easeOut", onUpdate: onUpdateResetHandler, onComplete: onCompleteResetHandler}) setTimeout(function(){ for(var i = 0; i < balls.length; i++){ for(var j = 0; j < balls[i].length; j++){ balls[i][j].fy = -150 - 150 * Math.random(); } } }, 500); }, 2000) } }, 1000); } function onUpdateResetHandler(){ walls.forEach(function(element){ element.bot = reset.y; }); }; function onCompleteResetHandler(){ count = 0; walls = []; balls = []; isNormal = true; init(); } function loop() { if(isNormal) normalLoop(); else resetLoop(); requestAnimationFrame(loop); } function normalLoop(){ for(var j = 0; j < balls.length; j++){ count = j; var iter = 6; var delta = SPEED / iter; while (iter--) { var i = balls[count].length; while (i--) { balls[count][i].apply_force(delta); balls[count][i].verlet(); } resolve_collisions(); check_walls(walls[count]); var i = balls[count].length; while (i--) balls[count][i].verlet(); resolve_collisions(1); check_walls(walls[count]); } } count = balls.length - 1; if(count % 2 == 0)ctx.fillStyle = '#fff'; else ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); for(var j = 0; j < count + 1;j++){ if(j % 2 == 0) ctx.fillStyle = '#333'; else ctx.fillStyle = "#fff"; ctx.fillRect(walls[j].left, 0, walls[j].right - walls[j].left, height); var i = balls[j].length; if(j % 2 == 0) ctx.fillStyle = '#fff'; else ctx.fillStyle = '#333'; while (i--) balls[j][i].draw(ctx) } } function resetLoop(){ normalLoop(); ctx.fillStyle = "#333"; ctx.fillRect(0, reset.y, width, height - reset.y); } init(); loop(); window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/5-loop/44-loop.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var App = function(){ this.transX = width/2; this.transY = height/2; //this.shape = new Shape(0, 0); this.widthNum = parseInt(width / 50) + 1; this.heightNum = parseInt(height / 50) + 1; this.shapes = []; for(var yy = 0; yy < this.heightNum; yy++){ for(var xx = 0; xx < this.widthNum; xx++){ var xPos = xx* 50 - width/2; var yPos = yy * 50 - height/2; var duration = Math.abs(xx - this.widthNum/2 + yy - this.heightNum/2); var shape = new Shape(xPos, yPos, duration); this.shapes.push(shape); } } }; App.prototype = { update : function(){ this.shapes.forEach(function(element){ element.update(); }); this.draw(); }, draw : function(){ ctx.save(); ctx.translate(this.transX, this.transY); this.shapes.forEach(function(element){ element.draw(); }); ctx.restore(); } }; var Shape = function(x, y, duration){ _.bindAll(this, "onChangeStateHandler"); this.count = 0; this.x = x; this.y = y; this.side = 50; this.startX = this.x + this.side/2; this.startY = this.y - this.side/2; this.endX = this.x + this.side/2; this.endY = this.y + this.side/2; var dur = duration * 20 + 300; setTimeout(this.onChangeStateHandler, dur); }; Shape.prototype = { update : function(){ }, draw : function(){ ctx.beginPath(); ctx.strokeStyle = "#fff"; ctx.moveTo( this.startX, this.startY); ctx.lineTo( this.endX, this.endY ); ctx.stroke(); ctx.closePath(); }, onChangeStateHandler : function(){ switch (this.count){ case 0: TweenLite.to(this,.6, { startX : this.x - this.side/2, ease:"Power2.easeOut"}); TweenLite.to(this,.6, { endY : this.y - this.side/2, ease:"Power2.easeOut"}); break; case 1: TweenLite.to(this, .6, { startY : this.y + this.side/2, ease: "Power2.easeOut"}); TweenLite.to(this,.6, { endX : this.x - this.side/2, ease: "Power2.easeOut" }); break; case 2: TweenLite.to(this, .6, { startX : this.x + this.side/2, ease: "Power2.easeOut"}); TweenLite.to(this, .6, { endY : this.y + this.side/2, ease: "Power2.easeOut" }); break; case 3: TweenLite.to(this, .6, { startY : this.y - this.side/2, ease: "Power2.easeOut"}); TweenLite.to(this, .6, { endX : this.x + this.side/2, ease: "Power2.easeOut" }); break; } this.count = (this.count + 1) % 4; setTimeout(this.onChangeStateHandler, 800); } }; // ================ var app; init(); loop(); function init(){ app = new App(); prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); app.update(); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/5-loop/45-loop.js ================================================ // -------------------------- var TWO_PI = Math.PI * 2; var NUM_BALLS = 130, DAMPING = 0.8, GRAVITY = 1.5, MOUSE_SIZE = 50, SPEED = .5; var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var Ball = function (x, y, radius, wall) { this.x = x || 0; this.y = y || 0; this.px = x; this.py = y; this.fx = 0; this.fy = 0; this.radius = radius || 10; //TweenLite.to(this, 1, {radius: radius}); }; Ball.prototype.init = function () { this.px = this.x; this.py = this.y; this.fx = 0; this.fy = 0; } Ball.prototype.apply_force = function (delta) { delta *= delta; this.fy += GRAVITY; this.x += this.fx * delta; this.y += this.fy * delta; this.fx = this.fy = 0; }; Ball.prototype.verlet = function () { var nx = (this.x * 2) - this.px; var ny = (this.y * 2) - this.py; this.px = this.x; this.py = this.y; this.x = nx; this.y = ny; }; Ball.prototype.draw = function () { ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, TWO_PI); ctx.fill(); }; var OutsideCircle = function () { this.rad = rad; }; OutsideCircle.prototype = { update: function () { }, draw: function () { ctx.beginPath(); ctx.strokeStyle = "#fff"; ctx.arc(0, 0, this.rad, 0, TWO_PI); ctx.stroke(); ctx.closePath(); }, checkCollision : function(cricles){ var self = this; cricles.forEach(function(element){ var dis1 = Math.sqrt(element.x * element.x + element.y * element.y); if(dis1 + element.radius > self.rad){ var theta = Math.atan2(element.y, element.x); var vel_x = element.px - element.x; var vel_y = element.py - element.y; var vel_xx = Math.cos(Math.PI / 2 - theta) * vel_x - vel_y * Math.cos(Math.PI / 2 - theta); var vel_yy = Math.sin(Math.PI / 2 - theta) * vel_x + vel_y * Math.sin(Math.PI / 2 - theta); vel_yy*= -DAMPING; vel_x = Math.cos(theta - Math.PI/2) * vel_xx - Math.cos(theta - Math.PI/2) * vel_yy; vel_y = Math.sin(theta - Math.PI/2) * vel_xx + Math.sin(theta - Math.PI/2) * vel_yy; element.x = (self.rad - element.radius -.5) * Math.cos(theta); element.y = (self.rad - element.radius -.5) * Math.sin(theta); element.px = element.x - DAMPING * vel_x; element.py = element.y - DAMPING * vel_y; } }); } }; //--------------------------------------- var resolve_collisions = function(ip, balls) { var i = balls.length; while (i--) { var ball_1 = balls[i]; var n = balls.length; while (n--) { if (n == i) continue; var ball_2 = balls[n]; var diff_x = ball_1.x - ball_2.x; var diff_y = ball_1.y - ball_2.y; var length = diff_x * diff_x + diff_y * diff_y; var dist = Math.sqrt(length); var real_dist = dist - (ball_1.radius + ball_2.radius); if (real_dist < 0) { var vel_x1 = ball_1.x - ball_1.px; var vel_y1 = ball_1.y - ball_1.py; var vel_x2 = ball_2.x - ball_2.px; var vel_y2 = ball_2.y - ball_2.py; var depth_x = diff_x * (real_dist / dist); var depth_y = diff_y * (real_dist / dist); ball_1.x -= depth_x * 0.5; ball_1.y -= depth_y * 0.5; ball_2.x += depth_x * 0.5; ball_2.y += depth_y * 0.5; if (ip) { var pr1 = DAMPING * (diff_x*vel_x1+diff_y*vel_y1) / length, pr2 = DAMPING * (diff_x*vel_x2+diff_y*vel_y2) / length; vel_x1 += pr2 * diff_x - pr1 * diff_x; vel_x2 += pr1 * diff_x - pr2 * diff_x; vel_y1 += pr2 * diff_y - pr1 * diff_y; vel_y2 += pr1 * diff_y - pr2 * diff_y; ball_1.px = ball_1.x - vel_x1; ball_1.py = ball_1.y - vel_y1; ball_2.px = ball_2.x - vel_x2; ball_2.py = ball_2.y - vel_y2; } } } } } // --------------------------------- var Balls = function () { this.balls = []; for (var i = 0; i < this.ballNum; i++) { var ball = new Ball(); this.balls.push(ball); } this.outSide = new OutsideCircle(); this.init(); }; Balls.prototype = { ballNum: 30, init: function () { this.balls[0].x = 0; this.balls[0].y = 0; for (var i = 1; i < this.ballNum; i++) { var theta = TWO_PI * Math.random(); var rr = 5 + 55 * Math.random(); var randomRad = (rad - maxRad - rr * 2) * Math.random(); var xx = Math.cos(theta) * (maxRad + rr + randomRad); var yy = Math.sin(theta) * (maxRad + rr + randomRad); if(rr > rad /5) rr = 1 + Math.random() * rad/5; this.balls[i].x = xx; this.balls[i].y = yy; this.balls[i].radius = rr; } this.balls.forEach(function (element) { element.init(); }); }, update: function () { var iter = 6; var delta = SPEED / iter; while (iter--) { var i = this.balls.length; while (i--) { this.balls[i].apply_force(delta); this.balls[i].verlet(); } resolve_collisions(false, this.balls); this.outSide.checkCollision(this.balls); var i = this.balls.length; while (i--) this.balls[i].verlet(); resolve_collisions(true, this.balls); this.outSide.checkCollision(this.balls); } }, draw: function () { this.balls.forEach(function (element) { element.draw(); }); this.outSide.draw(); } }; var Cross = function(){ _.bindAll(this, "secondRotation"); }; Cross.prototype = { theta : 0, isRotationDraw : false, reset : function(){ this.isRotationDraw = false; this.theta = 0; }, rotation : function(){ TweenLite.to(this, 1.5, {theta: Math.PI * 2, onComplete: this.secondRotation}); }, secondRotation : function(){ this.isRotationDraw = true; this.theta = 0; TweenLite.to(this, 1, {theta: Math.PI /2,ease: "Power2.easeOut" }); }, update : function(){ }, draw : function(){ if(this.isRotationDraw){ for(var i = 0; i < 4; i++){ var baseTheta = i * Math.PI/2; ctx.beginPath(); ctx.moveTo(0, 0) ctx.lineTo(rad * Math.cos(baseTheta), rad * Math.sin(baseTheta)); ctx.arc( 0, 0, rad, baseTheta, baseTheta + this.theta ); ctx.lineTo(rad * Math.cos(baseTheta + this.theta), rad * Math.sin(baseTheta + this.theta)); ctx.stroke(); ctx.fill(); ctx.closePath(); } } } }; // --------------------------------- var App = function () { _.bindAll(this, "step1", "reset", "start"); this.centerX = width / 2; this.centerY = height / 2; //this.ball = new Ball(); this.balls = new Balls(); this.scale = INIT_SCALE; this.cross = new Cross(); setTimeout(this.start, 500); //this.start(); }; App.prototype = { col: "#fff", isStop : true, reset : function(){ this.scale = INIT_SCALE; this.balls.init(); this.cross.reset(); this.start(); }, start: function () { this.isStop = true; TweenLite.to(this, 1, {scale: 1, ease: "Power2.easeOut", onComplete: this.step1}); }, step1: function () { this.isStop = false; this.cross.rotation(); setTimeout(this.reset, 3000); }, update: function () { if (!this.isStop) { this.balls.update(); } }, draw: function () { ctx.save(); ctx.fillStyle = "#fff"; ctx.translate(this.centerX, this.centerY); ctx.scale(this.scale, this.scale); this.balls.draw(); this.cross.draw(); ctx.restore(); } }; // ================================= var rad = Math.min(width, height) / 2; var INIT_SCALE = rad / 10; var maxRad = Math.sqrt(width * width + height * height) / 2 / rad * 10; var app; init(); loop(); function init() { app = new App(); } function loop() { ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); app.update(); app.draw(); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/5-loop/46-loop.js ================================================ // -------------------------- var width, height, prevTime; var halfWidth; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; halfWidth = width/2; canvas.width = width; canvas.height = height; var MAX_THETA; var colorArr = ['#16a085', '#27ae60', '#2980b9', '#f39c12', '#c0392b', '#2ecc71', '#d35400', '#8e44ad'] // ================ var Floor = function(id, col, y, height){ _.bindAll(this, 'onRotate2', 'onRotate3', 'onMove', 'onInit', 'init'); this.id = id; this.col = col; this.y = y; this.MAX_THETA = Math.atan2(height / 3, width / 2); MAX_THETA = this.MAX_THETA; this.theta = 0; this.init(); }; Floor.prototype = { count : 7, init : function(){ this.rotate(); }, rotate : function(){ TweenLite.to(this, .5, {theta : this.MAX_THETA, delay: 1, ease: "Power2.easeOut", onComplete: this.onRotate2}) }, onRotate2 : function(){ TweenLite.to(this, .5, {theta : -this.MAX_THETA, delay: 1, ease: "Power2.easeOut", onComplete: this.onRotate3}) }, onRotate3 : function(){ TweenLite.to(this, .5, {theta : 0, delay:1, ease: "Power2.easeOut", onComplete: this.onMove}) }, onMove : function(){ var yPos = this.y - floorHeight; TweenLite.to(this, .5, { y : yPos, delay:.5, ease: "Power2.easeOut", onComplete: this.onInit}) }, onInit : function(){ if(this.id == this.count) this.y += 8 * floorHeight; this.count = (this.count - 1) ; if(this.count < 0) this.count += 8; setTimeout(this.init, 500); }, update : function(){ ctx.save(); ctx.beginPath(); ctx.fillStyle = this.col; ctx.moveTo(0, this.y2 + this.y - floorHeight); ctx.lineTo(width, this.y1 + this.y - floorHeight); ctx.lineTo(width, this.y1 + this.y); ctx.lineTo(0, this.y2 + this.y); ctx.lineTo(0, this.y1 + this.y - floorHeight); ctx.fill(); ctx.closePath(); ctx.restore(); } }; Object.defineProperty(Floor.prototype, 'theta', { get : function(){ return this._theta; }, set : function(value){ this._theta = value; this.y1 = halfWidth * Math.tan(this.theta); this.y2 = -halfWidth * Math.tan(this.theta); } }); // ---------------- var Circle = function(id, x, y){ _.bindAll(this, "onUp", "onMove1", "onUp1", "onMove2", "onMove3", "onInit"); this.id = id; this.x = x; this.y = 0; this.r = 15; this.centerY = y - this.r; this.col = colorArr[this.id]; this.init(); }; Circle.prototype = { count : 0, _xx : 0, init : function(){ this.theta = MAX_THETA; TweenLite.to(this,.5, {xx : halfWidth - this.r, delay: 1.3, ease: "Bounce.easeOut", onComplete: this.onUp}); }, onUp : function(){ TweenLite.to(this,.5, {theta : -MAX_THETA, delay: .7, ease: "Power2.easeOut", onComplete: this.onMove1}); }, onMove1 : function(){ TweenLite.to(this,.5, {xx : this.r - halfWidth, ease: "Bounce.easeOut", onComplete: this.onUp1}); }, onUp1 : function(){ TweenLite.to(this,.5, {theta : 0, delay: .5, ease: "Power2.easeOut", onComplete: this.onMove2}); }, onMove2 : function() { TweenLite.to(this, .5, {xx: 0, ease: "Power2.easeOut", onComplete: this.onMove3}); }, onMove3 : function(){ var nextY = this.centerY + floorHeight; TweenLite.to(this,1, {centerY : nextY, ease: "Bounce.easeOut", onComplete: this.onInit}); }, onInit : function(){ if(this.id == this.count) this.centerY -= 8 * floorHeight; this.count = (this.count + 1) % 8 ; this.init() }, update : function(){ ctx.beginPath(); ctx.fillStyle = this.col; ctx.arc(this.x, this.y + this.centerY, this.r, 0, 2 * Math.PI); ctx.fill(); ctx.closePath(); } }; Object.defineProperty(Circle.prototype, 'xx', { get : function(){ return this._xx; }, set : function(value){ this.x = width/2 + value; this.y = value * Math.tan(this.theta); this._xx = value; } }); Object.defineProperty(Circle.prototype, 'theta', { get : function(){ return this._theta; }, set : function(value){ this.y = (this.x - width/2) * Math.tan(value); this._theta = value; } }); // ================ var floorHeight; var floorNumber = 8; var floorArr = []; var circleArr = []; init(); loop(); function init(){ floorHeight = height / 4; var col, yPos; for(var i = 0;i < floorNumber; i++) { if (i % 2 == 0) col = "#ecf0f1"; else col = "#34495e"; yPos = floorHeight * (5.5 - i); var floor = new Floor(i, col, yPos, floorHeight); floorArr.push(floor); var circle = new Circle(i, width/2, yPos); circleArr.push(circle) } } function loop(){ ctx.clearRect(0, 0, width, height) // updating and drawing the floor. floorArr.forEach(function(element){element.update();}); circleArr.forEach(function(element){element.update();}); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/5-loop/47-loop.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var app; width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // =============== var Circle = function(x, id){ this.x = x; this.y = height/2 + this.sideRad; this.id = id; TweenLite.to(this, 1, { y : - this.sideRad , delay: id/3 +.3, ease:"Power2.easeIn"}); }; Circle.prototype = { type : "rect1", sideRad : 50, update : function(){ switch (this.type){ case "rect2": this.drawRect2(); break; case "rect1": this.drawRect1(); break; } }, drawRect1 : function(){ ctx.save(); ctx.fillStyle = "#fff"; ctx.beginPath(); ctx.arc(this.x, this.y, this.sideRad, 0, 2 * Math.PI, false); ctx.fill(); ctx.closePath(); ctx.restore(); }, drawRect2 : function(){ ctx.save(); ctx.fillStyle = "#000"; ctx.beginPath(); ctx.arc(this.x, this.y, this.sideRad, 0, 2 * Math.PI, false); ctx.fill(); ctx.closePath(); ctx.restore(); }, reset : function(){ if(this.type == "rect1") { this.y = height/2 - this.sideRad*3; this.type = "rect2"; TweenLite.to(this, 1, { y : height + this.sideRad , delay: this.id/3+.5, ease:"Power2.easeOut"}); }else{ this.y = height/2 + this.sideRad; this.type = "rect1"; TweenLite.to(this, 1, { y : - this.sideRad , delay: this.id/3+.5, ease:"Power2.easeOut"}); } } }; var Shape = function(x, id){ //_.bindAll(this, 'tweenOnComplete1'); this.x = x; this.y = height + this.sideRad; this.id = id; TweenLite.to(this, 1, { y : height/2 - this.sideRad , delay: id/3, ease:"Power2.easeOut"}); }; Shape.prototype = { type : "rect1", sideRect : 100, sideRad : 50, update : function(){ switch (this.type){ case "rect2": this.drawRect2(); break; case "rect1": this.drawRect1(); break; } }, drawRect2 : function() { if(this.y > height / 2 - 3 * this.sideRad){ var rectHeight = this.y - height/2 + this.sideRad * 3 ; var rectWidth, theta; var circleHeight, circleWidth; ctx.save(); ctx.fillStyle = "#fff"; ctx.beginPath(); ctx.arc(this.x, this.y, this.sideRad, 0, 2 * Math.PI, false); ctx.closePath(); ctx.fill(); ctx.restore(); ctx.save(); ctx.fillStyle = "#000"; ctx.fillRect(this.x - this.sideRad, this.y + this.sideRad - rectHeight, this.sideRect, rectHeight); ctx.restore(); }else{ ctx.save(); ctx.fillStyle = "#fff"; ctx.beginPath(); ctx.arc(this.x, this.y, this.sideRad, 0, 2 * Math.PI, false); ctx.fill(); ctx.closePath(); ctx.restore(); } }, drawRect1 : function(){ if(this.y < height / 2 + this.sideRad){ var rectHeight = height/2 + this.sideRad - this.y; var rectWidth, theta; var circleHeight, circleWidth; ctx.save(); ctx.fillStyle = "#000"; ctx.beginPath(); ctx.arc(this.x, this.y, this.sideRad, 0, 2 * Math.PI, false); ctx.closePath(); ctx.fill(); ctx.restore(); ctx.save(); ctx.fillStyle = "#fff"; ctx.fillRect(this.x - this.sideRad, this.y - this.sideRad, this.sideRect, rectHeight); ctx.restore(); }else{ ctx.save(); ctx.fillStyle = "#000"; ctx.beginPath(); ctx.arc(this.x, this.y, this.sideRad, 0, 2 * Math.PI, false); ctx.fill(); ctx.closePath(); ctx.restore(); } }, reset : function(){ if(this.type == "rect1") { this.y = -this.sideRad; this.type = "rect2"; }else{ this.y = height + this.sideRad; this.type = "rect1"; } TweenLite.to(this, 1, { y : height/2 - this.sideRad , delay: this.id/3, ease:"Power2.easeOut"}); } }; var Floor = function(){ this.y = height/2; this.height = height/2; }; Floor.prototype = { count : 0, update : function(){ ctx.fillStyle = "#fff"; ctx.save(); ctx.fillRect(0, this.y, width, this.height); ctx.restore(); }, reset : function(){ this.count++; if(this.count % 2 == 0) { this.y = height/2; this.height = height/2;} else { this.y = height/2 - 100; this.height = height/2 + 100;} } }; // ---------------- var App = function(){ _.bindAll(this, 'interval'); this.shapeArrs = []; this.circleArrs = []; this.Floor = new Floor(); //this.shape1 = new Shape1(); var shape = new Shape(width/2, 0); this.shapeArrs.push(shape); var circle = new Circle(width/2, 0); this.circleArrs.push(circle); for(var i = 0; i < Math.round(width / 2 / 100); i++){ var shape01 = new Shape(width/2 - 100 * (i + 1), i+1); var shape02 = new Shape(width/2 + 100 * (i + 1), i+1); this.shapeArrs.push(shape01); this.shapeArrs.push(shape02); // ================= var circle01 = new Circle(width/2 - 100 * (i + 1), i+1); var circle02 = new Circle(width/2 + 100 * (i + 1), i+1); this.circleArrs.push(circle01); this.circleArrs.push(circle02); } this.intervalDuration = (2 +.3 *Math.round(width / 2 / 100))*1000; setTimeout(this.interval, this.intervalDuration); }; App.prototype = { update : function(){ this.Floor.update(); this.circleArrs.forEach(function(element){ element.update(); }); this.shapeArrs.forEach(function(element){ element.update(); }); }, interval : function(){ this.Floor.reset(); this.shapeArrs.forEach(function(element){ element.reset(); }); this.circleArrs.forEach(function(element){ element.reset(); }); setTimeout(this.interval, this.intervalDuration); } }; // ================ init(); loop(); function init(){ app = new App(); prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#000'; ctx.fillRect(0, 0, width, height); app.update(); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/5-loop/51-loop.js ================================================ // -------------------------- var app; var fK; var width, height, prevTime; var halfWidth, halfHeight; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; halfWidth = width / 2; halfHeight = height / 2; canvas.width = width; canvas.height = height; // ================ fK = 0.25; var widthNum = 31; var Point = function(){ }; Point.prototype = { x : null, y : null, vel: 0, mass : 10, setPosY : function(value){ this.y = this.baseYPos = value; } }; var SmallCircle = function(){ }; SmallCircle.prototype = { }; var MainShape = function(){ this.points = []; var gapDistance = (width) / (this.pointNumber - 1); var xPos; var i; for(i = 0; i < this.pointNumber; i++){ xPos = gapDistance * i; var myPt = new Point(); myPt.x = xPos; myPt.setPosY(0); //myPt.y = 0; this.points.push( myPt );i } this.particleSprings = []; for(i = 0; i < this.pointNumber - 1; i++){ var spring = {iLengthY: this.points[i + 1].y - this.points[i].y }; this.particleSprings.push( spring ); } //this.points[this.points.length - 1].y = 200; }; /* this.mcParticles[i].fXPos = this.mcParticles[i]._x; this.mcParticles[i].fYAccel = 0; this.mcParticles[i].fYVel = 0; this.mcParticles[i].fYPos = this.mcParticles[i]._y; this.mcParticles[i].fBaseYPos = this.mcParticles[i]._y; this.mcParticles[i].iMass = 10; */ MainShape.prototype = { pointNumber : widthNum, particleSprings : [], x : 0, y : 0, col : "#fff", update : function(){ // calculation var i; for( i = 0; i < this.points.length; i++){ var fExtensionY = 0; var fForceY = 0; if(i > 0){ fExtensionY = this.points[i - 1].y - this.points[i].y - this.particleSprings[i-1].iLengthY; fForceY += - fK * fExtensionY; } if( i < this.points.length - 1){ fExtensionY = this.points[i].y - this.points[i+1].y - this.particleSprings[i].iLengthY; fForceY += fK * fExtensionY; } fExtensionY = this.points[i].y - this.points[i].baseYPos; fForceY += fK/20 * fExtensionY; this.points[i].acl = - fForceY; this.points[i].vel += this.points[i].acl; this.points[i].y += this.points[i].vel; this.points[i].y += 0.2 * (this.points[i].baseYPos - this.points[i].y); this.points[i].vel /= 1.2; } // ================ ctx.save(); ctx.translate(this.x, this.y); ctx.beginPath(); ctx.lineWidth = 2; /** for( i = 0; i < this.pointNumber; i++){ if(i == 0) ctx.moveTo(this.points[i].x, this.points[i].y); else ctx.lineTo(this.points[i].x, this.points[i].y); }**/ for(i = 0; i < this.pointNumber- 1; i++ ){ var xPos = (this.points[i].x + this.points[i + 1].x)/2; var yPos = (this.points[i].y + this.points[i + 1].y)/2; if(i == 0) ctx.moveTo(xPos, yPos); else ctx.quadraticCurveTo( this.points[i].x, this.points[i].y, xPos, yPos); } //ctx.closePath(); ctx.strokeStyle = this.col; ctx.stroke(); ctx.restore(); }, setCircle : function(xPos, yPos){ for(var i = 0; i < this.points.length; i++){ var dx = xPos - this.x - this.points[i].x; var dy = yPos - this.y - this.points[i].y; var dis = Math.sqrt(dx * dx + dy * dy); if(dis < 60){ this.points[i].y += 40; } } }, addImpulse : function(){ //this.points[parseInt(this.points.length/2)].vel = .1; } }; var App = function(){ var kankakuHeight = 50; var kankakuHeightNum = parseInt(height/kankakuHeight) ; // createCircle // width: widthNum \\ height: kankakuHeightNum for(var i = 0; i < kankakuHeightNum; i++){ var mainShape = new MainShape(); mainShape.y = kankakuHeight * (i + 1); this.mainShapeArr.push(mainShape); } }; App.prototype = { mainShapeArr : [], bgCol : "#333", update : function(){ ctx.fillStyle = this.bgCol; ctx.fillRect(0, 0, width, height); this.mainShapeArr.forEach(function(element){ element.update(); }); }, xPos : 60, yPos : 60, kigo : +1, num : 12, rad : 60, addImpulse : function(){ this.yPos += this.kigo * 50; //= (this.yPos + 50) % height; if(this.yPos > height - this.rad ) { this.yPos = height - this.rad; this.kigo = -1; } if(this.yPos < this.rad) { this.yPos = this.rad; this.kigo = 1; } this.xPos += this.kigo * 50; if(this.xPos > width - this.rad ) { this.xPos = width - this.rad; this.kigo = -1; } if(this.xPos < this.rad) { this.xPos = this.rad; this.kigo = 1; } for(var i = 0; i < this.num; i++){ var xPos = this.rad * Math.cos(2 * Math.PI * i / this.num) + width/2; var yPos = this.rad * Math.sin(2 * Math.PI * i / this.num) + this.yPos; // xPos, yPos for(var jj = 0; jj < this.mainShapeArr.length; jj++){ this.mainShapeArr[jj].setCircle(xPos, yPos); } // var xPos = this.rad * Math.cos(2 * Math.PI * i / this.num) + this.xPos; var yPos = this.rad * Math.sin(2 * Math.PI * i / this.num) + height/2; // xPos, yPos for(var jj = 0; jj < this.mainShapeArr.length; jj++){ this.mainShapeArr[jj].setCircle(xPos, yPos); } } } }; // ================ init(); loop(); function init(){ app = new App(); timer(); } function timer(){ app.addImpulse(); setTimeout(timer, 100); } function loop(){ app.update(); requestAnimationFrame(loop); //setTimeout(loop, 1000); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/6-letters/52-letters.js ================================================ // k var kArr = [ [0.39049999999999996, 0.05], [0.39049999999999996, 0.39549999999999996], [0.39299999999999996, 0.39549999999999996], [0.5670000000000001, 0.05], [0.8165, 0.05], [0.5895, 0.4435], [0.8440000000000001, 0.95], [0.5770000000000001, 0.95], [0.4395, 0.636], [0.39050000000000007, 0.7115], [0.39050000000000007, 0.95], [0.156, 0.95], [0.156, 0.05], [0.39049999999999996, 0.05] ] // e var eArr = [ [0.7609999999999999, 0.05], [0.7609999999999999, 0.2415], [0.462, 0.2415], [0.462, 0.39549999999999996], [0.742, 0.39549999999999996], [0.742, 0.5794999999999999], [0.462, 0.5794999999999999], [0.462, 0.7585], [0.772, 0.7585], [0.772, 0.95], [0.2275, 0.95], [0.2275, 0.05], [0.7609999999999999, 0.05] ]; // n var nArr = [ [0.4445, 0.05], [0.596, 0.6045], [0.5985, 0.6045], [0.5985, 0.05], [0.818, 0.05], [0.818, 0.95], [0.5609999999999999, 0.95], [0.40399999999999997, 0.39399999999999996], [0.40149999999999997, 0.39399999999999996], [0.40149999999999997, 0.95], [0.1825, 0.95], [0.1825, 0.05], [0.4445, 0.05] ] ; // j //var jArr = [ [0.7795000000000001, 0.6595], [0.7065, 0.885, 0.7795000000000001, 0.7665000000000001, 0.755, 0.8415], [0.49050000000000005, 0.95, 0.6575, 0.9285, 0.5855, 0.95], [0.28300000000000003, 0.878, 0.39350000000000007, 0.95, 0.3245, 0.9259999999999999], [0.22100000000000006, 0.6669999999999999, 0.24150000000000005, 0.83, 0.22100000000000006, 0.7595000000000001], [0.22100000000000006, 0.6485], [0.42950000000000005, 0.6485], [0.42950000000000005, 0.6919999999999998], [0.44650000000000006, 0.7765, 0.42950000000000005, 0.7339999999999999, 0.435, 0.7624999999999998], [0.48950000000000005, 0.7974999999999999, 0.4575000000000001, 0.7905, 0.47200000000000003, 0.7974999999999999], [0.5325, 0.7765, 0.507, 0.7974999999999999, 0.521, 0.7904999999999999], [0.5495, 0.6919999999999998, 0.5435, 0.7624999999999998, 0.5495, 0.7344999999999999], [0.5495, 0.05], [0.7805000000000001, 0.05], [0.7805000000000001, 0.6595] ]; var jArr = [ [0.7795000000000001, 0.6595], [0.7795000000000001, 0.7665000000000001, 0.755, 0.8415,0.7065, 0.885], [0.6575, 0.9285, 0.5855, 0.95,0.49050000000000005, 0.95], [0.39350000000000007, 0.95, 0.3245, 0.9259999999999999,0.28300000000000003, 0.878], [0.24150000000000005, 0.83, 0.22100000000000006, 0.7595000000000001,0.22100000000000006, 0.6669999999999999], [0.22100000000000006, 0.6485], [0.42950000000000005, 0.6485], [0.42950000000000005, 0.6919999999999998], [0.42950000000000005, 0.7339999999999999, 0.435, 0.7624999999999998,0.44650000000000006, 0.7765], [0.4575000000000001, 0.7905, 0.47200000000000003, 0.7974999999999999,0.48950000000000005, 0.7974999999999999], [0.507, 0.7974999999999999, 0.521, 0.7904999999999999,0.5325, 0.7765], [0.5435, 0.7624999999999998, 0.5495, 0.7344999999999999,0.5495, 0.6919999999999998], [0.5495, 0.05], [0.7805000000000001, 0.05], [0.7805000000000001, 0.6595] ]; // i var iArr = [ [0.617, 0.05], [0.617, 0.95], [0.38299999999999995, 0.95], [0.38299999999999995, 0.05], [0.617, 0.05] ] ; var kenjiArr = [kArr, eArr, nArr, jArr, iArr]; var size = 400; if(size > window.innerHeight) size = window.innerHeight * .8; var textNumber = 360; var kenjiPtArrs = []; for(var ii = 0; ii < kenjiArr.length; ii++){ kenjiPtArrs[ii] = []; var kankakuDuration = parseInt(textNumber / kenjiArr[ii].length) + 1; var curNumber = textNumber; for(var jj = 0; jj < kenjiArr[ii].length; jj++){ for(var kk = 0; kk < kankakuDuration; kk++){ var ptX, ptY; var rate = kk / kankakuDuration; var curNum = jj; var nextNum = (jj + 1) % kenjiArr[ii].length; if(kenjiArr[ii][nextNum].length == 6){ //ptX = kenjiArr[ii][curNum][0] * size * (1 - rate) + kenjiArr[ii][nextNum][0] * size * rate; //ptY = kenjiArr[ii][curNum][1] * size * (1 - rate) + kenjiArr[ii][nextNum][1] * size * rate; var x1, y1, x2, y2, x3, y3, x4, y4; if(kenjiArr[ii][curNum].length == 2){ x1 = kenjiArr[ii][curNum][0] * size; y1 = kenjiArr[ii][curNum][1] * size; }else if(kenjiArr[ii][curNum].length == 6){ x1 = kenjiArr[ii][curNum][4] * size; y1 = kenjiArr[ii][curNum][5] * size; } x2 = kenjiArr[ii][nextNum][0] * size; y2 = kenjiArr[ii][nextNum][1] * size; x3 = kenjiArr[ii][nextNum][2] * size; y3 = kenjiArr[ii][nextNum][3] * size; x4 = kenjiArr[ii][nextNum][4] * size; y4 = kenjiArr[ii][nextNum][5] * size; ptX = x1 * (1 - rate) * (1 - rate) * (1 - rate) + x2 * 3 * (1-rate) * (1-rate) * rate + x3 * 3 * (1 -rate) * rate * rate + rate * rate * rate * x4; ptY = y1 * (1 - rate) * (1 - rate) * (1 - rate) + y2 * 3 * (1-rate) * (1-rate) * rate + y3 * 3 * (1 -rate) * rate * rate + rate * rate * rate * y4; }else{ if(kenjiArr[ii][curNum].length == 2){ ptX = kenjiArr[ii][curNum][0] * size * (1 - rate) + kenjiArr[ii][nextNum][0] * size * rate; ptY = kenjiArr[ii][curNum][1] * size * (1 - rate) + kenjiArr[ii][nextNum][1] * size * rate; }else if(kenjiArr[ii][curNum].length == 6){ ptX = kenjiArr[ii][curNum][4] * size * (1 - rate) + kenjiArr[ii][nextNum][0] * size * rate; ptY = kenjiArr[ii][curNum][5] * size * (1 - rate) + kenjiArr[ii][nextNum][1] * size * rate; } } var pos = {x: ptX - size/2, y: ptY - size/2}; kenjiPtArrs[ii].push(pos); } curNumber -= kankakuDuration; if(kankakuDuration > curNumber) kankakuDuration = curNumber; } } // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var rot = 0; width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ // ================ var count = 0; var curPtArr = []; var rate; init(); loop(); function init(){ prevTime = +new Date; for(var i = 0; i < kenjiPtArrs[count].length; i++){ var pt = { x: kenjiPtArrs[count][i].x, y : kenjiPtArrs[count][i].y }; curPtArr.push(pt); } setTimeout(timer, 500); } function loop(){ rot += .1; var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.globalCompositeOperation="source-over"; ctx.fillStyle = 'rgba(30, 30, 30, .3)'; ctx.fillRect(0, 0, width, height); for(var n = 0; n < 3; n++){ ctx.save(); ctx.globalCompositeOperation="lighter"; ctx.beginPath(); //ctx.rotate(rot); ctx.translate(width/2, height/2) if(n == 0) ctx.fillStyle = "rgba(200, 0, 0,1)"; if(n == 1) ctx.fillStyle = "rgba(200, 200, 0, 1)"; if(n == 2) ctx.fillStyle = "rgba(0, 0, 200, 1)"; for(var i = 0; i < curPtArr.length; i++){ if(i == 0) ctx.moveTo( curPtArr[i].x + Math.random() * 10, curPtArr[i].y+ Math.random() * 10); else ctx.lineTo( curPtArr[i].x + Math.random() * 10, curPtArr[i].y + Math.random() * 10); } ctx.closePath(); ctx.fill(); ctx.restore(); } requestAnimationFrame(loop); } function timer(){ rate = 0; TweenLite.to(this,.75, {rate: 1, onUpdate: onUpdateTweenHandler, onComplete: onCompleteTwennHandler, ease:Elastic.easeInOut}); setTimeout(timer, 1000); } function onUpdateTweenHandler(){ var nextCount = (count + 1) % kenjiPtArrs.length; for(var i = 0; i < 360; i++){ var xPos = kenjiPtArrs[count][i].x * (1-rate) + kenjiPtArrs[nextCount][i].x * rate; var yPos = kenjiPtArrs[count][i].y * (1-rate) + kenjiPtArrs[nextCount][i].y * rate; curPtArr[i] = {x: xPos, y: yPos}; } } function onCompleteTwennHandler(){ count = (count + 1) % kenjiPtArrs.length; } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/6-letters/53-letters.js ================================================ // k var kArr = [ [0.39049999999999996, 0.05], [0.39049999999999996, 0.39549999999999996], [0.39299999999999996, 0.39549999999999996], [0.5670000000000001, 0.05], [0.8165, 0.05], [0.5895, 0.4435], [0.8440000000000001, 0.95], [0.5770000000000001, 0.95], [0.4395, 0.636], [0.39050000000000007, 0.7115], [0.39050000000000007, 0.95], [0.156, 0.95], [0.156, 0.05], [0.39049999999999996, 0.05] ] // e var eArr = [ [0.7609999999999999, 0.05], [0.7609999999999999, 0.2415], [0.462, 0.2415], [0.462, 0.39549999999999996], [0.742, 0.39549999999999996], [0.742, 0.5794999999999999], [0.462, 0.5794999999999999], [0.462, 0.7585], [0.772, 0.7585], [0.772, 0.95], [0.2275, 0.95], [0.2275, 0.05], [0.7609999999999999, 0.05] ]; // n var nArr = [ [0.4445, 0.05], [0.596, 0.6045], [0.5985, 0.6045], [0.5985, 0.05], [0.818, 0.05], [0.818, 0.95], [0.5609999999999999, 0.95], [0.40399999999999997, 0.39399999999999996], [0.40149999999999997, 0.39399999999999996], [0.40149999999999997, 0.95], [0.1825, 0.95], [0.1825, 0.05], [0.4445, 0.05] ] ; // j //var jArr = [ [0.7795000000000001, 0.6595], [0.7065, 0.885, 0.7795000000000001, 0.7665000000000001, 0.755, 0.8415], [0.49050000000000005, 0.95, 0.6575, 0.9285, 0.5855, 0.95], [0.28300000000000003, 0.878, 0.39350000000000007, 0.95, 0.3245, 0.9259999999999999], [0.22100000000000006, 0.6669999999999999, 0.24150000000000005, 0.83, 0.22100000000000006, 0.7595000000000001], [0.22100000000000006, 0.6485], [0.42950000000000005, 0.6485], [0.42950000000000005, 0.6919999999999998], [0.44650000000000006, 0.7765, 0.42950000000000005, 0.7339999999999999, 0.435, 0.7624999999999998], [0.48950000000000005, 0.7974999999999999, 0.4575000000000001, 0.7905, 0.47200000000000003, 0.7974999999999999], [0.5325, 0.7765, 0.507, 0.7974999999999999, 0.521, 0.7904999999999999], [0.5495, 0.6919999999999998, 0.5435, 0.7624999999999998, 0.5495, 0.7344999999999999], [0.5495, 0.05], [0.7805000000000001, 0.05], [0.7805000000000001, 0.6595] ]; var jArr = [ [0.7795000000000001, 0.6595], [0.7795000000000001, 0.7665000000000001, 0.755, 0.8415,0.7065, 0.885], [0.6575, 0.9285, 0.5855, 0.95,0.49050000000000005, 0.95], [0.39350000000000007, 0.95, 0.3245, 0.9259999999999999,0.28300000000000003, 0.878], [0.24150000000000005, 0.83, 0.22100000000000006, 0.7595000000000001,0.22100000000000006, 0.6669999999999999], [0.22100000000000006, 0.6485], [0.42950000000000005, 0.6485], [0.42950000000000005, 0.6919999999999998], [0.42950000000000005, 0.7339999999999999, 0.435, 0.7624999999999998,0.44650000000000006, 0.7765], [0.4575000000000001, 0.7905, 0.47200000000000003, 0.7974999999999999,0.48950000000000005, 0.7974999999999999], [0.507, 0.7974999999999999, 0.521, 0.7904999999999999,0.5325, 0.7765], [0.5435, 0.7624999999999998, 0.5495, 0.7344999999999999,0.5495, 0.6919999999999998], [0.5495, 0.05], [0.7805000000000001, 0.05], [0.7805000000000001, 0.6595] ]; // i var iArr = [ [0.617, 0.05], [0.617, 0.95], [0.38299999999999995, 0.95], [0.38299999999999995, 0.05], [0.617, 0.05] ] ; var kenjiArr = [kArr, eArr, nArr, jArr, iArr]; var size = 400; if(size > window.innerHeight) size = window.innerHeight * .8; var textNumber = 360; var kenjiPtArrs = []; for(var ii = 0; ii < kenjiArr.length; ii++){ kenjiPtArrs[ii] = []; var kankakuDuration = parseInt(textNumber / kenjiArr[ii].length) + 1; var curNumber = textNumber; for(var jj = 0; jj < kenjiArr[ii].length; jj++){ for(var kk = 0; kk < kankakuDuration; kk++){ var ptX, ptY; var rate = kk / kankakuDuration; var curNum = jj; var nextNum = (jj + 1) % kenjiArr[ii].length; if(kenjiArr[ii][nextNum].length == 6){ //ptX = kenjiArr[ii][curNum][0] * size * (1 - rate) + kenjiArr[ii][nextNum][0] * size * rate; //ptY = kenjiArr[ii][curNum][1] * size * (1 - rate) + kenjiArr[ii][nextNum][1] * size * rate; var x1, y1, x2, y2, x3, y3, x4, y4; if(kenjiArr[ii][curNum].length == 2){ x1 = kenjiArr[ii][curNum][0] * size; y1 = kenjiArr[ii][curNum][1] * size; }else if(kenjiArr[ii][curNum].length == 6){ x1 = kenjiArr[ii][curNum][4] * size; y1 = kenjiArr[ii][curNum][5] * size; } x2 = kenjiArr[ii][nextNum][0] * size; y2 = kenjiArr[ii][nextNum][1] * size; x3 = kenjiArr[ii][nextNum][2] * size; y3 = kenjiArr[ii][nextNum][3] * size; x4 = kenjiArr[ii][nextNum][4] * size; y4 = kenjiArr[ii][nextNum][5] * size; ptX = x1 * (1 - rate) * (1 - rate) * (1 - rate) + x2 * 3 * (1-rate) * (1-rate) * rate + x3 * 3 * (1 -rate) * rate * rate + rate * rate * rate * x4; ptY = y1 * (1 - rate) * (1 - rate) * (1 - rate) + y2 * 3 * (1-rate) * (1-rate) * rate + y3 * 3 * (1 -rate) * rate * rate + rate * rate * rate * y4; }else{ if(kenjiArr[ii][curNum].length == 2){ ptX = kenjiArr[ii][curNum][0] * size * (1 - rate) + kenjiArr[ii][nextNum][0] * size * rate; ptY = kenjiArr[ii][curNum][1] * size * (1 - rate) + kenjiArr[ii][nextNum][1] * size * rate; }else if(kenjiArr[ii][curNum].length == 6){ ptX = kenjiArr[ii][curNum][4] * size * (1 - rate) + kenjiArr[ii][nextNum][0] * size * rate; ptY = kenjiArr[ii][curNum][5] * size * (1 - rate) + kenjiArr[ii][nextNum][1] * size * rate; } } var pos = {x: ptX - size/2, y: ptY - size/2}; kenjiPtArrs[ii].push(pos); } curNumber -= kankakuDuration; if(kankakuDuration > curNumber) kankakuDuration = curNumber; } } // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var rot = 0; width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var Line = function(){ this.x0 = 0; this.x1 = width; this.velY = 2; this.y = 0; }; Line.prototype = { update : function(){ this.y += this.velY; if(this.y > height){ this.y = height; this.velY = -2; } if(this.y < 0){ this.y = 0; this.velY = 2; } }, draw : function(){ ctx.save(); ctx.strokeStyle = "#ffffff"; ctx.moveTo(this.x0, this.y); ctx.lineTo(this.x1, this.y); ctx.stroke(); ctx.restore(); } }; // ================ var count = 0; var curPtArr = []; var rate; var line; init(); loop(); function init(){ line = new Line(); prevTime = +new Date; for(var i = 0; i < kenjiPtArrs[count].length; i++){ var pt = { x: kenjiPtArrs[count][i].x, y : kenjiPtArrs[count][i].y }; curPtArr.push(pt); } //setTimeout(timer, 500); } function loop(){ line.update(); rot += .1; var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.globalCompositeOperation="source-over"; ctx.fillStyle = 'rgba(30, 30, 30, .3)'; ctx.fillRect(0, 0, width, height); for(var n = 0; n < 3; n++){ ctx.save(); ctx.globalCompositeOperation="lighter"; ctx.beginPath(); //ctx.rotate(rot); ctx.translate(width/2, height/2) if(n == 0) ctx.fillStyle = "rgba(200, 0, 0,1)"; if(n == 1) ctx.fillStyle = "rgba(200, 200, 0, 1)"; if(n == 2) ctx.fillStyle = "rgba(0, 0, 200, 1)"; var biv; for(var i = 0; i < curPtArr.length; i++){ if(line.y - height/2 > curPtArr[i].y) biv = 0; else biv = 10; if(i == 0) ctx.moveTo( curPtArr[i].x + Math.random() * biv, curPtArr[i].y+ Math.random() * biv); else ctx.lineTo( curPtArr[i].x + Math.random() * biv, curPtArr[i].y + Math.random() * biv); } ctx.closePath(); ctx.fill(); ctx.restore(); } line.draw(); requestAnimationFrame(loop); } function timer(){ rate = 0; TweenLite.to(this,.75, {rate: 1, onUpdate: onUpdateTweenHandler, onComplete: onCompleteTwennHandler, ease:Elastic.easeInOut}); setTimeout(timer, 1000); } function onUpdateTweenHandler(){ var nextCount = (count + 1) % kenjiPtArrs.length; for(var i = 0; i < 360; i++){ var xPos = kenjiPtArrs[count][i].x * (1-rate) + kenjiPtArrs[nextCount][i].x * rate; var yPos = kenjiPtArrs[count][i].y * (1-rate) + kenjiPtArrs[nextCount][i].y * rate; curPtArr[i] = {x: xPos, y: yPos}; } } function onCompleteTwennHandler(){ count = (count + 1) % kenjiPtArrs.length; } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/6-letters/54-letter.js ================================================ var l1Pt0 = [ [0.6905, 0.534], [0.648, 0.534], [0.638, 0.565], [0.6154999999999999, 0.565], [0.6579999999999999, 0.4445], [0.6809999999999999, 0.4445], [0.7234999999999999, 0.565], [0.701, 0.565], [0.6905, 0.534] ]; var l1Pt1 = [ [0.6695, 0.46549999999999997], [0.6695, 0.46549999999999997, 0.667, 0.4775, 0.6645, 0.484], [0.654, 0.5165], [0.6855000000000001, 0.5165], [0.6750000000000002, 0.484], [0.6725, 0.4775, 0.6695, 0.46549999999999997, 0.6695, 0.46549999999999997], [0.6695, 0.46549999999999997] ]; var l2Pt0 = [ [0.7559999999999999, 0.4445], [0.795, 0.4445], [0.8079999999999999, 0.4445, 0.8140000000000001, 0.44550000000000006, 0.8195, 0.44800000000000006], [0.8315, 0.4535, 0.8390000000000001, 0.4650000000000001, 0.8390000000000001, 0.48100000000000004], [0.8390000000000001, 0.49550000000000005, 0.8315, 0.509, 0.8185000000000001, 0.514], [0.8185000000000001, 0.5145], [0.8185000000000001, 0.5145, 0.8200000000000002, 0.5159999999999999, 0.8225000000000001, 0.5205], [0.8475000000000001, 0.5655], [0.8230000000000001, 0.5655], [0.799, 0.5205], [0.7780000000000001, 0.5205], [0.7780000000000001, 0.5655], [0.7560000000000001, 0.5655], [0.7559999999999999, 0.4445], [0.7559999999999999, 0.4445] ]; var l2Pt1 = [ [0.7975, 0.501], [0.809, 0.501, 0.8165, 0.494, 0.8165, 0.48200000000000004], [0.8165, 0.47050000000000003, 0.8115000000000001, 0.4635, 0.7945, 0.4635], [0.778, 0.4635], [0.778, 0.501], [0.7975, 0.501], [0.7975, 0.501] ]; var l3Pt0 = [ [0.885, 0.4445], [0.9259999999999999, 0.4445], [0.963, 0.4445, 0.9875, 0.4665000000000001, 0.9875, 0.5045000000000001], [0.9875, 0.5425, 0.963, 0.565, 0.9259999999999999, 0.565], [0.885, 0.565], [0.885, 0.4445] ]; var l3Pt1 = [ [0.9245, 0.5465], [0.9490000000000001, 0.5465, 0.9645, 0.5319999999999999, 0.9645, 0.505], [0.9645, 0.478, 0.9485000000000001, 0.4635, 0.9245, 0.4635], [0.9065000000000001, 0.4635], [0.9065000000000001, 0.5465000000000001], [0.9245, 0.5465000000000001] ]; var l4 = [ [1.0265, 0.534], [1.0265, 0.534, 1.0395, 0.5469999999999999, 1.0565, 0.5469999999999999], [1.0655000000000001, 0.5469999999999999, 1.074, 0.5425, 1.074, 0.5325], [1.074, 0.5109999999999999, 1.0170000000000001, 0.5145, 1.0170000000000001, 0.4774999999999999], [1.0170000000000001, 0.4574999999999999, 1.0345, 0.44249999999999995, 1.0575, 0.44249999999999995], [1.0815000000000001, 0.44249999999999995, 1.0935, 0.4554999999999999, 1.0935, 0.4554999999999999], [1.0839999999999999, 0.47349999999999987], [1.0839999999999999, 0.47349999999999987, 1.0724999999999998, 0.4629999999999999, 1.0574999999999999, 0.4629999999999999], [1.0474999999999999, 0.4629999999999999, 1.0394999999999999, 0.4689999999999999, 1.0394999999999999, 0.4774999999999999], [1.0394999999999999, 0.4989999999999999, 1.0964999999999998, 0.49349999999999994, 1.0964999999999998, 0.5325], [1.0964999999999998, 0.5514999999999999, 1.0819999999999999, 0.568, 1.0565, 0.568], [1.0294999999999999, 0.568, 1.015, 0.5514999999999999, 1.015, 0.5514999999999999], [1.0265, 0.534] ]; var l5 = [ [0.4435, 0.4445], [0.4235, 0.528], [0.42200000000000004, 0.535, 0.4215, 0.5405000000000001, 0.4215, 0.5405000000000001], [0.42100000000000004, 0.5405000000000001], [0.42100000000000004, 0.5405000000000001, 0.42050000000000004, 0.5345, 0.419, 0.528], [0.3975, 0.4445], [0.3785, 0.4445], [0.3565, 0.528], [0.3545, 0.535, 0.3545, 0.5405000000000001, 0.3545, 0.5405000000000001], [0.354, 0.5405000000000001], [0.354, 0.5405000000000001, 0.35350000000000004, 0.5345, 0.352, 0.528], [0.33799999999999997, 0.4655], [0.3275, 0.511], [0.341, 0.565], [0.3665, 0.565], [0.385, 0.4935], [0.387, 0.48550000000000004, 0.38799999999999996, 0.4775, 0.38799999999999996, 0.4775], [0.38849999999999996, 0.4775], [0.38849999999999996, 0.4775, 0.38949999999999996, 0.4855, 0.3914999999999999, 0.4935], [0.4099999999999999, 0.565], [0.435, 0.565], [0.466, 0.4445], [0.4435, 0.4445], [0.4435, 0.4445] ]; var l6 = [ [0.5795, 0.4445], [0.5595, 0.528], [0.558, 0.535, 0.5575, 0.5405000000000001, 0.5575, 0.5405000000000001], [0.557, 0.5405000000000001], [0.557, 0.5405000000000001, 0.5565000000000001, 0.5345, 0.555, 0.528], [0.5335, 0.4445], [0.5145000000000001, 0.4445], [0.4925, 0.528], [0.4905, 0.535, 0.4905, 0.5405000000000001, 0.4905, 0.5405000000000001], [0.49, 0.5405000000000001], [0.49, 0.5405000000000001, 0.48950000000000005, 0.5345, 0.488, 0.528], [0.474, 0.465], [0.4635, 0.5105], [0.47700000000000004, 0.565], [0.5025, 0.565], [0.521, 0.4935], [0.523, 0.48550000000000004, 0.524, 0.4775, 0.524, 0.4775], [0.5245, 0.4775], [0.5245, 0.4775, 0.5255, 0.4855, 0.5275, 0.4935], [0.5459999999999999, 0.565], [0.5714999999999999, 0.565], [0.6024999999999999, 0.4445], [0.5795, 0.4445], [0.5795, 0.4445] ]; var l7 = [ [0.13, 0.534], [0.0875, 0.534], [0.0775, 0.565], [0.055, 0.565], [0.0975, 0.4445], [0.12050000000000001, 0.4445], [0.163, 0.565], [0.1405, 0.565], [0.13, 0.534], [0.109, 0.46549999999999997], [0.109, 0.46549999999999997, 0.1065, 0.4775, 0.10400000000000001, 0.484], [0.0935, 0.5165], [0.125, 0.5165], [0.11449999999999999, 0.484], [0.11199999999999999, 0.4775, 0.109, 0.46549999999999997, 0.109, 0.46549999999999997], [0.109, 0.46549999999999997] ]; var l8 = [ [0.2825, 0.528], [0.2845, 0.535, 0.2845, 0.5405, 0.2845, 0.5405], [0.285, 0.5405], [0.285, 0.5405, 0.28550000000000003, 0.5345, 0.287, 0.528], [0.307, 0.44449999999999995], [0.3295, 0.44449999999999995], [0.2985, 0.565], [0.273, 0.565], [0.2545, 0.4935], [0.2525, 0.48550000000000004, 0.2515, 0.4775, 0.2515, 0.4775], [0.251, 0.4775], [0.251, 0.4775, 0.24999999999999997, 0.4855, 0.24799999999999997, 0.4935], [0.22949999999999998, 0.565], [0.204, 0.565], [0.174, 0.4445], [0.19649999999999998, 0.4445], [0.21549999999999997, 0.528], [0.21699999999999997, 0.535, 0.21749999999999997, 0.5405000000000001, 0.21749999999999997, 0.5405000000000001], [0.21799999999999997, 0.5405000000000001], [0.21799999999999997, 0.5405000000000001, 0.21849999999999997, 0.5345, 0.21999999999999997, 0.528], [0.24199999999999997, 0.4445], [0.26099999999999995, 0.4445], [0.2825, 0.528] ]; var kenjiArr = [l1Pt0, l1Pt1, l2Pt0, l2Pt1, l3Pt0, l3Pt1, l4, l5, l6, l7, l8]; var size = 400; if (size > window.innerHeight) size = window.innerHeight * .8; var textNumber = 90; var kenjiPtArrs = []; for (var ii = 0; ii < kenjiArr.length; ii++) { kenjiPtArrs[ii] = []; var kankakuDuration = parseInt(textNumber / kenjiArr[ii].length) + 1; var curNumber = textNumber; for (var jj = 0; jj < kenjiArr[ii].length; jj++) { for (var kk = 0; kk < kankakuDuration; kk++) { var ptX, ptY; var rate = kk / kankakuDuration; var curNum = jj; var nextNum = (jj + 1) % kenjiArr[ii].length; if (kenjiArr[ii][nextNum].length == 6) { //ptX = kenjiArr[ii][curNum][0] * size * (1 - rate) + kenjiArr[ii][nextNum][0] * size * rate; //ptY = kenjiArr[ii][curNum][1] * size * (1 - rate) + kenjiArr[ii][nextNum][1] * size * rate; var x1, y1, x2, y2, x3, y3, x4, y4; if (kenjiArr[ii][curNum].length == 2) { x1 = kenjiArr[ii][curNum][0] * size; y1 = kenjiArr[ii][curNum][1] * size; } else if (kenjiArr[ii][curNum].length == 6) { x1 = kenjiArr[ii][curNum][4] * size; y1 = kenjiArr[ii][curNum][5] * size; } x2 = kenjiArr[ii][nextNum][0] * size; y2 = kenjiArr[ii][nextNum][1] * size; x3 = kenjiArr[ii][nextNum][2] * size; y3 = kenjiArr[ii][nextNum][3] * size; x4 = kenjiArr[ii][nextNum][4] * size; y4 = kenjiArr[ii][nextNum][5] * size; ptX = x1 * (1 - rate) * (1 - rate) * (1 - rate) + x2 * 3 * (1 - rate) * (1 - rate) * rate + x3 * 3 * (1 - rate) * rate * rate + rate * rate * rate * x4; ptY = y1 * (1 - rate) * (1 - rate) * (1 - rate) + y2 * 3 * (1 - rate) * (1 - rate) * rate + y3 * 3 * (1 - rate) * rate * rate + rate * rate * rate * y4; } else { if (kenjiArr[ii][curNum].length == 2) { ptX = kenjiArr[ii][curNum][0] * size * (1 - rate) + kenjiArr[ii][nextNum][0] * size * rate; ptY = kenjiArr[ii][curNum][1] * size * (1 - rate) + kenjiArr[ii][nextNum][1] * size * rate; } else if (kenjiArr[ii][curNum].length == 6) { ptX = kenjiArr[ii][curNum][4] * size * (1 - rate) + kenjiArr[ii][nextNum][0] * size * rate; ptY = kenjiArr[ii][curNum][5] * size * (1 - rate) + kenjiArr[ii][nextNum][1] * size * rate; } } var pos = {x: ptX - size / 2 - 35, y: ptY - size / 2}; kenjiPtArrs[ii].push(pos); } curNumber -= kankakuDuration; if (kankakuDuration > curNumber) kankakuDuration = curNumber; } } // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var rot = 0; width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var Line = function () { this.height = 150; this.width = 500; this.top = (height - this.height)/2; this.bot = this.top + this.height; this.left = (width - this.width)/2; this.x0 = this.left; this.x1 = this.width + this.left; this.velY = 2; this.y = this.top; }; Line.prototype = { update: function () { this.y += this.velY; if (this.y > this.bot) { this.y = this.bot; this.velY = -2; } if (this.y < this.top) { this.y = this.top; this.velY = 2; } }, draw: function () { ctx.save(); ctx.strokeStyle = "#19A598"; ctx.moveTo(this.x0, this.y); ctx.lineTo(this.x1, this.y); ctx.stroke(); ctx.strokeRect(this.left, this.top, this.width, this.height); ctx.restore(); } }; // ================ var rate; var line; init(); loop(); function init() { line = new Line(); prevTime = +new Date; //setTimeout(timer, 500); } function loop() { line.update(); rot += .1; var curTime = +new Date; var duration = (curTime - prevTime) / 1000; prevTime = curTime; ctx.globalCompositeOperation = "source-over"; ctx.fillStyle = 'rgba(30, 30, 30, .3)'; ctx.fillRect(0, 0, width, height); var biv; for(var jj = 0; jj < kenjiPtArrs.length; jj++) { ctx.save(); ctx.beginPath(); ctx.translate(width / 2, height / 2) ctx.strokeStyle = "#19A598"; for (var i = 0; i < kenjiPtArrs[jj].length; i+= 1) { if (line.y - height / 2 > kenjiPtArrs[jj][i].y) biv = 0; else biv = 10; if (i == 0) ctx.moveTo(kenjiPtArrs[jj][i].x + (Math.random() -.5)* biv, kenjiPtArrs[jj][i].y + (Math.random() -.5) * biv); else ctx.lineTo(kenjiPtArrs[jj][i].x + (Math.random() -.5) * biv, kenjiPtArrs[jj][i].y + (Math.random() -.5) * biv); } if (line.y - height / 2 > kenjiPtArrs[jj][0].y) biv = 0; else biv = 10; ctx.moveTo(kenjiPtArrs[jj][0].x + (Math.random() -.5)* biv, kenjiPtArrs[jj][0].y + (Math.random() -.5) * biv); ctx.closePath(); ctx.stroke(); ctx.restore(); } //} line.draw(); requestAnimationFrame(loop); } function timer() { rate = 0; TweenLite.to(this, .75, {rate: 1, onUpdate: onUpdateTweenHandler, onComplete: onCompleteTwennHandler, ease: Elastic.easeInOut}); setTimeout(timer, 1000); } function onUpdateTweenHandler() { var nextCount = (count + 1) % kenjiPtArrs.length; for (var i = 0; i < 360; i++) { var xPos = kenjiPtArrs[count][i].x * (1 - rate) + kenjiPtArrs[nextCount][i].x * rate; var yPos = kenjiPtArrs[count][i].y * (1 - rate) + kenjiPtArrs[nextCount][i].y * rate; curPtArr[i] = {x: xPos, y: yPos}; } } function onCompleteTwennHandler() { count = (count + 1) % kenjiPtArrs.length; } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame ================================================ FILE: app/scripts/99-hobby/26-undefined.js ================================================ // -------------------------- var width, height, prevTime; var pattern; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var RectCollection = function(ctx){ _.bindAll(this, 'onRotation'); this.ctx = ctx; var rectSide = Math.min(width, height); this.x = -width/2; this.y = -height/2; this.rectArr = []; for(var i = 0; i < this.rectNumber; i ++){ var curSide = (.1 + .8 * (this.rectNumber - i) / this.rectNumber) * rectSide; var curRect = new Rect(ctx, curSide); this.rectArr.push(curRect); } _.delay(this.onRotation, 800); } RectCollection.prototype = { rectNumber : 5, rectArr : null, update : function(dt){ this.ctx.save(); this.ctx.fillStyle = pattern; this.ctx.translate(-this.x, -this.y); this.ctx.fillRect(this.x, this.y, width, height); for(var i = 0; i < this.rectNumber; i++){ this.rectArr[i].update(dt); } this.ctx.restore(); }, onRotation : function(){ for(var i = 0; i < this.rectNumber; i++){ this.rectArr[i].onRotation(i /5); } } } var Rect = function(ctx, side){ _.bindAll(this, 'onComplete'); this.ctx = ctx; this.halfSide = side/2; this.pos = - this.halfSide; this.side = side; this.kakusei = this.side; }; Rect.prototype = { theta : 0, sum : 0, kakusei : 0, transx : 0, update : function(dt){ if(this.isTranslate){ this.sum += dt; this.transX = Math.sin(this.sum) *this.side } // ====== // draw this.draw(); }, draw : function(){ this.ctx.save(); this.ctx.fillStyle = pattern; this.ctx.translate(this.transX, 0); this.ctx.rotate(this.theta); this.ctx.fillRect( this.pos, this.pos, this.side, this.side); this.ctx.restore(); }, onRotation : function(delay){ var theta = delay + Math.PI/6; var duration = .4 + delay; TweenLite.to(this, duration, {theta: theta, ease: Power2.easeInOut, onComplete: this.onComplete}); }, onComplete : function(){ this.isTranslate = true; } } var Stripe = function(){ } // ================ var rectCollection; var tempUpdate, tempCanvas, tempCtx, tempSide, tempHalfSide; var sum = 0; init(); loop(); function init(){ // create pattern createPattern(); rectCollection = new RectCollection(ctx); prevTime = +new Date; } function createPattern(){ tempSide = 40; tempHalfSide = tempSide / 2; tempUpdate = 0; tempCanvas = document.createElement('canvas'); tempCanvas.width = tempSide; tempCanvas.height = tempSide; tempCtx = tempCanvas.getContext('2d'); tempCtx.fillStyle = '#fff'; tempCtx.fillRect(0, 0, tempSide/2, tempSide); tempCtx.fillStyle = '#333'; tempCtx.fillRect( tempSide/2, 0, tempSide/2, tempSide); pattern = tempCtx.createPattern(tempCanvas, 'repeat'); } function updatePattern(dt){ sum += dt * 2; var speed = (Math.cos(sum ) + Math.sin(sum) + 2) ; tempUpdate += speed; tempUpdate = tempUpdate % tempSide; var xPos = -1 * tempUpdate; for(var i = 0; i < 4; i++){ var col; if(i % 2 == 0) col = "#ffffff"; else col = '#333'; tempCtx.fillStyle = col; tempCtx.fillRect(xPos, 0, tempHalfSide, tempSide); xPos += tempHalfSide; } pattern = tempCtx.createPattern(tempCanvas, 'repeat'); tempCtx.clearRect(0, 0, tempSide, tempSide); } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; updatePattern(duration); rectCollection.update(duration); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/99-hobby/27-simple-boid.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var Boid = function(ctx){ this.ctx = ctx; this.x = width * Math.random(); this.y = height * Math.random(); this.vx = 0; this.vy = 0; }; Boid.prototype = { rad : 5, col : '#fff', update : function(){ }, draw : function(){ this.ctx.fillStyle = this.col; this.ctx.beginPath(); this.ctx.arc( this.x, this.y, this.rad, 0, 2 * Math.PI, false ); this.ctx.fill(); this.ctx.closePath(); } }; // ================ var boids = []; var randomAclX = []; var randomAclY = []; var isRandom = false; var NUM_BOIDS = 30; var NUM_BOIDS_EXC = NUM_BOIDS - 1; var BOID_SIDE = 40; var MAX_SPEED = 10; var MAX_DIStANCE = 150; init(); loop(); function init(){ for(var i = 0; i < NUM_BOIDS; i++){ var boid = new Boid(ctx); boids.push(boid); } prevTime = +new Date; setTimeout(onRandomChange, 2000); } function onRandomChange(){ isRandom = !isRandom; if(isRandom){ for(var i = 0; i < NUM_BOIDS; i++){ var aclX = 10 * (Math.random() - .5); var aclY = 10 * (Math.random() - .5); randomAclX[i] = aclX; randomAclY[i] = aclY; } setTimeout(onRandomChange, 1000); }else{ setTimeout(onRandomChange, 2000); } } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); for(var i = 0; i < boids.length; i++){ var b = boids[i]; if(!isRandom){ rule1(i); rule2(i); rule3(i); }else{ b.vx += randomAclX[i] b.vy += randomAclY[i]; } var speed = Math.sqrt(b.vx * b.vx + b.vy * b.vy); if(speed >= MAX_SPEED) { var r = MAX_SPEED / speed; b.vx *= r; b.vy *= r; } if(!isRandom){ if(b.x < 0 && b.vx < 0 || b.x > width && b.vx > 0) b.vx *= -1; if(b.y < 0 && b.vy < 0 || b.y > height && b.vy > 0) b.vy *= -1; } b.x += b.vx; b.y += b.vy; if(isRandom){ if(b.x < 0) b.x += width; if(b.x > width) b.x -= width; if(b.y < 0)b.y += height; if(b.y > height)b.y -= height; } } for(var i = 0; i < boids.length; i++){ var boidA = boids[i]; ctx.beginPath(); ctx.fillStyle = 'rgba(255, 255, 255, .3)'; ctx.arc(boidA.x , boidA.y, 2, 0, 2 * Math.PI); ctx.fill(); ctx.closePath(); for(var j = i; j < boids.length; j++){ var boidB = boids[j]; var dx = boidA.x - boidB.x; var dy = boidA.y - boidB.y; var dis = Math.sqrt(dx * dx + dy * dy); if(dis < MAX_DIStANCE){ var alpha = (MAX_DIStANCE - dis) / MAX_DIStANCE; ctx.beginPath(); ctx.strokeStyle = 'rgba(255, 255, 255, ' + alpha + ')'; ctx.moveTo(boidA.x, boidA.y); ctx.lineTo(boidB.x, boidB.y); ctx.stroke(); ctx.closePath(); } } } requestAnimationFrame(loop); } function rule1(index){ var c = {x: 0, y: 0}; for(var i = 0; i < boids.length; i++){ if(i != index){ c.x += boids[i].x; c.y += boids[i].y; } } c.x = c.x / NUM_BOIDS_EXC; c.y = c.y / NUM_BOIDS_EXC; boids[index].vx += (c.x - boids[index].x)/100; boids[index].vy += (c.y - boids[index].y)/100; } function rule2(index){ for( var i = 0; i < boids.length; i++){ var d = getDistance(boids[i], boids[index]); if(d < BOID_SIDE){ boids[index].vx -= boids[i].x - boids[index].x; boids[index].vy -= boids[i].y - boids[index].y; } } } function rule3(index){ var pv = {x: 0, y: 0}; for(var i = 0; i < boids.length; i++){ if(i != index){ pv.x += boids[i].vx; pv.y += boids[i].vy; } } pv.x /= NUM_BOIDS_EXC; pv.y /= NUM_BOIDS_EXC; boids[index].vx += (pv.x - boids[index].vx) / 8; boids[index].vy += (pv.y - boids[index].vy) / 8; } function getDistance(p1, p2){ var dx = p1.x - p2.x; var dy = p1.y -p2.y; return Math.sqrt(dx * dx + dy * dy); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/99-hobby/28-02-combination.js ================================================ window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; // -------------------------- (function () { function Particle(x, y) { this.x = x; this.y = y; this.mix = x; this.miy = y; } var Boid = function(ctx){ this.ctx = ctx; this.x = width * Math.random(); this.y = height * Math.random(); this.vx = 0; this.vy = 0; }; Boid.prototype = { rad : 2, col : '#fff', update : function(){ }, draw : function(){ this.ctx.fillStyle = this.col; this.ctx.beginPath(); this.ctx.arc( this.x, this.y, this.rad, 0, 2 * Math.PI, false ); this.ctx.fill(); this.ctx.closePath(); } }; var boids = []; var NUM_BOIDS = 30; var NUM_BOIDS_EXC = NUM_BOIDS - 1; var BOID_SIDE = 40; var MAX_SPEED = 10; var MAX_DIStANCE = 150; var Circle = function(ctx){ var centerX = 0; var centerY = 0; for(var i = 0;i < NUM_BOIDS; i++){ centerX += boids[i].x; centerY += boids[i].y; } centerX /= NUM_BOIDS; centerY /= NUM_BOIDS; this.x = centerX; this.y = centerY; }; Circle.prototype = { update : function(){ var centerVelX = 0; var centerVelY = 0; for(var i = 0;i < NUM_BOIDS; i++){ centerVelX += boids[i].vx; centerVelY += boids[i].vy; } centerVelX /= NUM_BOIDS; centerVelY /= NUM_BOIDS; this.x += centerVelX; this.y += centerVelY; } } function Particles(particles, context) { this.particles = particles; this.context = context; } Particles.prototype.draw = function () { for (var i = 0; i < this.particles.length; i++) { this.context.beginPath(); this.context.fillStyle = "#fff"; this.context.arc(this.particles[i].x, this.particles[i].y, 3, 0, 2 * Math.PI, false); this.context.fill(); this.context.closePath(); } }; Particles.prototype.lineDraw = function(){ for (var i = 0; i < this.particles.length; i++) { this.context.beginPath(); this.context.strokeStyle = "rgba( 255, 255, 255, .6)"; this.context.moveTo(this.particles[i].mix, this.particles[i].miy); this.context.lineTo(this.particles[i].x, this.particles[i].y); this.context.stroke(); this.context.closePath(); } } function getMousePos(canvas, evt) { var rect = rect = canvas.getBoundingClientRect(); // new Particle( evt.clientX - rect.left, evt.clientY - rect.top); return new Particle(evt.clientX - rect.left, evt.clientY - rect.top); } var mainCanvas, mainContext; var width = window.innerWidth; var height = window.innerHeight; var gridWidNums = 20 + 1; var gridHigNums = 20 + 1; var gripWid = width / (gridWidNums - 1); var gripHig = height / (gridHigNums - 1); var range = gripWid * 3; var particleArray = []; var grids; var circle; var speed = 50; var multiSpeed = 1; var drawCheck = false; mainCanvas = document.getElementById("c"); mainCanvas.width = width; mainCanvas.height = height; mainContext = mainCanvas.getContext("2d"); init(); function init() { for (var _x = 0; _x < gridWidNums; _x++) { for (var _y = 0; _y < gridHigNums; _y++) { var posX = gripWid * _x; var posY = gripHig * _y; var particle = new Particle(posX, posY); particleArray.push(particle); } } grids = new Particles(particleArray, mainContext); grids.draw(); for(var i = 0; i < NUM_BOIDS; i++){ var boid = new Boid(mainContext); boids.push(boid); } circle = new Circle(); } loop() function loop(){ mainContext.fillStyle = "#333"; mainContext.fillRect(0, 0, width, height); for(var i = 0; i < boids.length; i++){ var b = boids[i]; rule1(i); rule2(i); rule3(i); var speed = Math.sqrt(b.vx * b.vx + b.vy * b.vy); var speed = Math.sqrt(b.vx * b.vx + b.vy * b.vy); if(speed >= MAX_SPEED) { var r = MAX_SPEED / speed; b.vx *= r; b.vy *= r; } if(b.x < 0 && b.vx < 0 || b.x > width && b.vx > 0) b.vx *= -1; if(b.y < 0 && b.vy < 0 || b.y > height && b.vy > 0) b.vy *= -1; b.x += b.vx; b.y += b.vy; b.draw(); } circle.update(); var particleNums = grids.particles.length; for (var i = 0; i < particleNums; i++) { var dx, dy, distance; var particle = grids.particles[i]; dx = circle.x - particle.x; dy = circle.y - particle.y; distance = Math.sqrt(dx * dx + dy * dy); particle.x = (particle.x - (dx / distance) * (range / distance) * speed) - ((particle.x - particle.mix) / 2); particle.y = (particle.y - (dy / distance) * (range / distance) * speed) - ((particle.y - particle.miy) / 2); } grids.draw(); requestAnimationFrame(loop); } function rule1(index){ var c = {x: 0, y: 0}; for(var i = 0; i < boids.length; i++){ if(i != index){ c.x += boids[i].x; c.y += boids[i].y; } } c.x = c.x / NUM_BOIDS_EXC; c.y = c.y / NUM_BOIDS_EXC; boids[index].vx += (c.x - boids[index].x)/100; boids[index].vy += (c.y - boids[index].y)/100; } function rule2(index){ for( var i = 0; i < boids.length; i++){ var d = getDistance(boids[i], boids[index]); if(d < BOID_SIDE){ boids[index].vx -= boids[i].x - boids[index].x; boids[index].vy -= boids[i].y - boids[index].y; } } } function rule3(index){ var pv = {x: 0, y: 0}; for(var i = 0; i < boids.length; i++){ if(i != index){ pv.x += boids[i].vx; pv.y += boids[i].vy; } } pv.x /= NUM_BOIDS_EXC; pv.y /= NUM_BOIDS_EXC; boids[index].vx += (pv.x - boids[index].vx) / 8; boids[index].vy += (pv.y - boids[index].vy) / 8; } function getDistance(p1, p2){ var dx = p1.x - p2.x; var dy = p1.y -p2.y; return Math.sqrt(dx * dx + dy * dy); } })(); ================================================ FILE: app/scripts/99-hobby/28-combination.js ================================================ window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; // -------------------------- var Boid = function(ctx){ this.ctx = ctx; this.x = 10 * Math.random() - 5; this.y = 10 * Math.random() - 5; this.vx = 0; this.vy = 0; }; Boid.prototype = { rad : 2, col : '#fff', update : function(){ }, draw : function(){ this.ctx.fillStyle = this.col; this.ctx.beginPath(); this.ctx.arc( this.x, this.y, this.rad, 0, 2 * Math.PI, false ); this.ctx.fill(); this.ctx.closePath(); } }; // -------------------------- var Pt = function(rad, theta){ this.rad = rad; this.theta = theta; }; Pt.prototype = { setTheta : function(val){ this.futureTheta = val; TweenLite.to(this,.5, { theta : val, ease: Elastic.easeInOut}); }, } Object.defineProperty(Pt.prototype, 'theta', { get : function(){ return this._theta; }, set : function(val){ this._theta = val; this.x = this.rad * Math.cos(this._theta); this.y = this.rad * Math.sin(this._theta); } }); var Rect = function(ctx, x, y){ _.bindAll(this, 'rotationComplete'); this.x = this.originX = x; this.y = y; this.transX = 0; this.side = 120; this.halfSide = this.side / 2 * -1; this.ctx = ctx; this.col = '#fff'; this.NUM_BOIDS = 20; this.NUM_BOIDS_EXC = this.NUM_BOIDS - 1; this.BOID_SIDE = 4; this.MAX_SPEED = 5; this.MAX_DIS = 3; this.boids = []; this.rotate = 0; this.thetaArr = [0, Math.PI, Math.PI * 5 / 4, Math.PI * 3 / 2]; this.ptArr =[ new Pt(0, 0), new Pt(this.side, Math.PI), new Pt(this.side * Math.sqrt(2), Math.PI * (5/4)), new Pt(this.side, Math.PI * (3/2)), ]; // initialize the boids for(var i = 0; i < this.NUM_BOIDS; i++){ var boid = new Boid(ctx); this.boids.push(boid); } this.rotation(); }; Rect.prototype = { rotation : function(){ this.rotate = Math.PI/2; for(var i = 0; i < this.ptArr.length; i++){ var pt = this.ptArr[i]; var theta = this.thetaArr[i]; TweenLite.to(pt, 1, { theta : (theta + this.rotate)}); } TweenLite.to(this, 1, { x : (this.originX - 120), onComplete : this.rotationComplete}); }, rotationComplete : function(){ this.ptArr =[ new Pt(0, 0), new Pt(this.side, Math.PI), new Pt(this.side * Math.sqrt(2), Math.PI * (5/4)), new Pt(this.side, Math.PI * (3/2)), ]; this.x = this.originX; this.rotation(); }, update : function(){ var center = { x : this.x + (this.ptArr[0].x + this.ptArr[1].x + this.ptArr[2].x + this.ptArr[3].x)/4 + this.side/2, y : this.y,// - (this.ptArr[0].y + this.ptArr[1].y + this.ptArr[2].y + this.ptArr[3].y)/4 }; for(var i = 0; i < this.NUM_BOIDS; i++){ var b = this.boids[i]; this.rule1(i); this.rule2(i); this.rule3(i); var speed = Math.sqrt(b.vx * b.vx + b.vy * b.vy); if(speed >= this.MAX_SPEED) { var r = this.MAX_SPEED / speed; b.vx *= r; b.vy *= r; } if(b.x < -this.side/2 && b.vx < 0 || b.x > this.side/2 && b.vx > 0) b.vx *= -1; if(b.y < -this.side/2 && b.vy < 0 || b.y > this.side/2 && b.vy > 0) b.vy *= -1; b.x += b.vx; b.y += b.vy; this.ctx.save(); this.ctx.translate( center.x, center.y); b.draw(); this.ctx.restore(); } this.ctx.save(); this.ctx.translate(this.x + this.side /2, this.y + this.side /2); this.ctx.beginPath(); this.ctx.strokeStyle = this.col; this.ctx.moveTo(this.ptArr[0].x, this.ptArr[0].y); for(var i = 0; i < this.ptArr.length; i++ ){ var number = (i + 1) % this.ptArr.length; this.ctx.lineTo(this.ptArr[number].x, this.ptArr[number].y); } this.ctx.stroke(); this.ctx.closePath(); this.ctx.restore(); }, rule1 : function(index){ var c = {x : 0, y: 0}; for(var i = 0; i < this.NUM_BOIDS; i++){ if(i != index){ c.x += this.boids[i].x; c.y += this.boids[i].y; } } c.x /= this.NUM_BOIDS_EXC; c.y /= this.NUM_BOIDS_EXC; this.boids[index].vx += (c.x - this.boids[index].x)/100; this.boids[index].vy += (c.y - this.boids[index].y)/100; }, rule2 : function(index){ for(var i = 0; i < this.NUM_BOIDS; i++){ if(i == index) return; var dis = this.getDistance(this.boids[i], this.boids[index]); if(dis < this.BOID_SIDE){ this.boids[index].vx -= this.boids[i].x - this.boids[index].x; this.boids[index].vy -= this.boids[i].y - this.boids[index].y; } } }, rule3 : function(index){ var pv = {x: 0, y: 0}; for(var i = 0; i < this.NUM_BOIDS; i++){ if(i != index){ pv.x += this.boids[i].vx; pv.y += this.boids[i].vy; } } pv.x /= this.NUM_BOIDS_EXC; pv.y /= this.NUM_BOIDS_EXC; this.boids[index].vx += (pv.x - this.boids[index].vx)/8; this.boids[index].vy += (pv.y - this.boids[index].vy)/8; }, getDistance : function(p1, p2){ var dx = p1.x - p2.x; var dy = p1.y - p2.y; return Math.sqrt(dx * dx + dy * dy); } }; var RectTop1 = function(ctx, x, y, rect){ _.bindAll(this, 'rotationComplete'); this.x = this.originX = x; this.y = y; this.side = 120; this.baseRect = rect; this.ctx = ctx; this.col = '#fff'; this.rotate = 0; this.thetaArr = [0, Math.PI * 3 / 2, Math.PI * 7 / 4, Math.PI * 2]; this.ptArr =[ new Pt(0, 0), new Pt(this.side, Math.PI* (3/2)), new Pt(this.side * Math.sqrt(2), Math.PI * (7/4)), new Pt(this.side, Math.PI * 2), ]; this.rotation(); }; RectTop1.prototype = { rotation : function(){ this.rotate = -Math.PI/2; for(var i = 0; i < this.ptArr.length; i++){ var pt = this.ptArr[i]; var theta = this.thetaArr[i]; TweenLite.to(pt, 1, { theta : (theta + this.rotate)}); } TweenLite.to(this, 1, { x : (this.originX ), onComplete : this.rotationComplete}); }, rotationComplete : function(){ this.ptArr =[ new Pt(0, 0), new Pt(this.side, Math.PI* (3/2)), new Pt(this.side * Math.sqrt(2), Math.PI * (7/4)), new Pt(this.side, Math.PI * 2), ]; this.x = this.originX; this.rotation(); }, update : function(){ this.ctx.save(); //this.ctx.translate(this.x + this.baseRect.ptArr[2].x - this.side/2, this.y + this.baseRect.ptArr[2].y + this.side/2); this.x = this.baseRect.x + this.baseRect.ptArr[2].x + this.side / 2; this.y = this.baseRect.y + this.baseRect.ptArr[2].y + this.side/2; this.ctx.translate( this.x, this.y); this.ctx.beginPath(); this.ctx.strokeStyle = this.col; this.ctx.moveTo(this.ptArr[0].x, this.ptArr[0].y); for(var i = 0; i < this.ptArr.length; i++ ){ var number = (i + 1) % this.ptArr.length; this.ctx.lineTo(this.ptArr[number].x, this.ptArr[number].y); } this.ctx.stroke(); this.ctx.closePath(); this.ctx.restore(); } }; var RectTop2 = function(ctx, x, y, rect){ _.bindAll(this, 'rotationComplete'); this.x = this.originX = x; this.y = y; this.side = 120; this.baseRect = rect; this.ctx = ctx; this.col = '#fff'; this.rotate = 0; this.thetaArr = [0, Math.PI, Math.PI * 5 / 4, Math.PI * 3 / 2]; this.ptArr =[ new Pt(0, 0), new Pt(this.side, Math.PI), new Pt(this.side * Math.sqrt(2), Math.PI * (5/4)), new Pt(this.side, Math.PI * (3/2)), ]; this.rotation(); }; RectTop2.prototype = { rotation : function(){ this.rotate = Math.PI/2; for(var i = 0; i < this.ptArr.length; i++){ var pt = this.ptArr[i]; var theta = this.thetaArr[i]; TweenLite.to(pt, 1, { theta : (theta + this.rotate)}); } TweenLite.to(this, 1, { x : (this.originX ), onComplete : this.rotationComplete}); }, rotationComplete : function(){ this.ptArr =[ new Pt(0, 0), new Pt(this.side, Math.PI), new Pt(this.side * Math.sqrt(2), Math.PI * (5/4)), new Pt(this.side, Math.PI * (3/2)), ]; this.x = this.originX; this.rotation(); }, update : function(){ this.ctx.save(); this.x = this.baseRect.x + this.baseRect.ptArr[2].x; this.y = this.baseRect.y + this.baseRect.ptArr[2].y; this.ctx.translate( this.x, this.y ); this.ctx.beginPath(); this.ctx.strokeStyle = this.col; this.ctx.moveTo(this.ptArr[0].x, this.ptArr[0].y); for(var i = 0; i < this.ptArr.length; i++ ){ var number = (i + 1) % this.ptArr.length; this.ctx.lineTo(this.ptArr[number].x, this.ptArr[number].y); } this.ctx.stroke(); this.ctx.closePath(); this.ctx.restore(); } }; var Road = function(ctx, x, y){ var line; var lineWidth = 20; var lineWidthMargin = 10; this.ctx = ctx; this.width = window.innerWidth; this.x = x; this.y = y; this.lineArr = []; this.mask = {x: - this.num /2 * (lineWidth + lineWidthMargin), width: this.num * (lineWidth + lineWidthMargin)} for(var i = 0; i <= this.num; i++){ line = new Line(this.ctx, (lineWidth + lineWidthMargin) * (i - this.num/2), 0, lineWidth, {minX: this.mask.x, maxX: this.mask.x + this.mask.width}) this.lineArr.push(line); } }; Road.prototype = { num : 20, lineArr : null, update : function(){ this.ctx.save(); this.ctx.translate(this.x, this.y); for(var i = 0; i < this.lineArr.length; i++){ this.lineArr[i].update(); } var grd = this.ctx.createLinearGradient(this.mask.x * 2, 0, this.mask.width, 0); grd.addColorStop(0.25, 'rgba(51, 51, 51, 1)'); grd.addColorStop(0.3, 'rgba(51, 51, 51, 0)'); grd.addColorStop(0.5, 'rgba(51, 51, 51, 0)'); grd.addColorStop(0.7, 'rgba(51, 51, 51, 0)'); grd.addColorStop(0.75, 'rgba(51, 51, 51, 1)'); this.ctx.fillStyle = grd; this.ctx.fillRect(-this.x, -15, this.width, 30); this.ctx.restore(); } }; var Line = function(ctx, x, y, width, range){ this.x = x; this.range = range; this.ctx = ctx; this.col = '#fff'; this.width = width; this.prevTime = + new Date; }; Line.prototype = { update : function(){ this.x -= 1; if(this.x < this.range.minX) this.x = this.range.maxX; this.ctx.strokeStyle = this.col; this.ctx.beginPath(); this.ctx.moveTo(this.x - this.width / 2, 0); this.ctx.lineTo(this.x + this.width / 2, 0); this.ctx.stroke(); this.ctx.closePath(); } }; // -------------------------- var width, height, previousTime; var side1, side2; var rect, rectTop1, rectTop2, side, road; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; side = Math.min(width, height) / 8; canvas.width = width; canvas.height = height; init(); loop(); function init(){ rect = new Rect(ctx, width / 2, height *.9-60); rectTop1 = new RectTop1(ctx, width/2, height*.9-60, rect); rectTop2 = new RectTop2(ctx, width/2, height*.9-60, rectTop1); road = new Road(ctx, width/2, height *.9 + 2); } function loop(){ //ctx.clearRect(0, 0, width, height); ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); rect.update(); rectTop1.update(); rectTop2.update(); road.update(); requestAnimationFrame(loop); } ================================================ FILE: app/scripts/99-hobby/30-mouse-boid.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var Boid = function(ctx, x, y){ this.ctx = ctx; this.x = x; this.y = y; this.vx = 0; this.vy = 0; }; Boid.prototype = { rad : 2, col : '#fff', update : function(){ }, draw : function(){ this.ctx.save(); this.ctx.translate(this.x, this.y); this.ctx.scale(0.05, 0.05); this.ctx.drawImage(image, -imageWid/2, -imageHig/2); this.ctx.restore(); } }; // ================ //init(); //loop(); var boids = []; var BOID_SIDE = 30; var MAX_DIS = 20; var MAX_SPEED = 12; var NUM_BOIDS; var NUM_BOIDS_EXC; var imageWid, imageHig; var image = new Image(); image.src = 'http://www.clipartbest.com/cliparts/dMT/LMo/dMTLMo6ia.png'; image.onload = onLoad; var text = ""; var textCount = 0; var FULL_TEXT = "MOVE MOUSE"; var mouse; var isMouseStatic = false; function onLoad(){ imageWid = image.width; imageHig = image.height; init(); loop(); } function init(){ prevTime = +new Date; showText(); } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#fff'; ctx.fillRect(0, 0, width, height); fillText(); if(boids.length > 0){ var isMouseActive = true; for(var i = 0; i < boids.length; i++){ if(!isMouseStatic){ var b = boids[i]; rule1(i); rule2(i); rule3(i); var speed = Math.sqrt(b.vx * b.vx + b.vy * b.vy); if(speed >= MAX_SPEED) { var r = MAX_SPEED / speed; b.vx *= r; b.vy *= r; } boids[i].x += boids[i].vx; boids[i].y += boids[i].vy; if(b.x < 0 || b.x > width || b.y < 0 || b.y > height) { boids[i].isOut = true; } else { boids[i].isOut = false; } } boids[i].draw(); } for(var i = 0; i < boids.length; i++){ if(!boids[i].isOut) isMouseActive = false; } if(isMouseActive && !isMouseStatic){ isMouseStatic = true; boids = []; showText(); } } requestAnimationFrame(loop); } function showText(){ isMouseStatic = true; textCount = 0; //var boid = new Boid(ctx, 80, 90); //boids.push(boid); loopText(); } function removeText(){ textCount--; text = FULL_TEXT.substring(0, textCount); if(textCount >= 0) setTimeout(removeText, 16); } var mouseCount = 0; var prevMouse = {x: null, y: null}; function loopText(){ textCount++; if(textCount == 1){ var boid = new Boid(ctx, 82, 90); boids.push(boid); }else{ text = FULL_TEXT.substring(0, textCount-1); } if(textCount <= FULL_TEXT.length) setTimeout(loopText, 16); else{ ctx.font="30px Arial"; var textWidth = ctx.measureText(FULL_TEXT).width; var boid = new Boid(ctx, textWidth + 120, 90); boids.push(boid); mouseCount = 0; document.addEventListener('mousemove', onMouseMove); //setTimeout(onIntervalMousePosition, 100); } } function fillText(){ ctx.font = "30px Arial"; ctx.fillStyle = '#333'; ctx.fillText(text, 100, 100); } function onMouseMove(event){ mouse = {x: event.pageX, y: event.pageY}; var boid; if(mouse.x == prevMouse.x && mouse.y == prevMouse.y) return boid = new Boid(ctx, mouse.x, mouse.y); prevMouse = {x: mouse.x, y: mouse.y}; boids.push(boid); mouseCount++; if(mouseCount > 50){ NUM_BOIDS = boids.length; NUM_BOIDS_EXC = NUM_BOIDS - 1; isMouseStatic = false; removeText(); document.removeEventListener('mousemove', onMouseMove); }else{ } mouseCount++; } function rule1(index){ var c = {x: 0, y: 0}; for(var i = 0; i < boids.length; i++){ if(i != index){ c.x += boids[i].x; c.y += boids[i].y; } } c.x = c.x / NUM_BOIDS_EXC; c.y = c.y / NUM_BOIDS_EXC; boids[index].vx += (c.x - boids[index].x)/100; boids[index].vy += (c.y - boids[index].y)/100; } function rule2(index){ for( var i = 0; i < boids.length; i++){ var d = getDistance(boids[i], boids[index]); if(d < BOID_SIDE){ boids[index].vx -= boids[i].x - boids[index].x; boids[index].vy -= boids[i].y - boids[index].y; } } } function rule3(index){ var pv = {x: 0, y: 0}; for(var i = 0; i < boids.length; i++){ if(i != index){ pv.x += boids[i].vx; pv.y += boids[i].vy; } } pv.x /= NUM_BOIDS_EXC; pv.y /= NUM_BOIDS_EXC; boids[index].vx += (pv.x - boids[index].vx) / 8; boids[index].vy += (pv.y - boids[index].vy) / 8; } function getDistance(p1, p2){ var dx = p1.x - p2.x; var dy = p1.y -p2.y; return Math.sqrt(dx * dx + dy * dy); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame ================================================ FILE: app/scripts/99-hobby/32-boid-collection.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; var side = 200 var leftX = width/2 - side/2; var rightX = width/2 + side/2; var topY = height/2 - side/2; var bottomY = height/2 + side/2; // ================ var Boid = function(ctx){ this.ctx = ctx; this.x = width/2 + side * (Math.random() - .5); this.y = height/2 + side * (Math.random() -.5); this.vx = 0; this.vy = 0; }; Boid.prototype = { rad : 2, col : '#fff', update : function(){ }, draw : function(){ this.ctx.fillStyle = this.col; this.ctx.beginPath(); this.ctx.arc( this.x, this.y, this.rad, 0, 2 * Math.PI, false ); this.ctx.fill(); this.ctx.closePath(); } }; // ================ var boidCollection = []; var boids = []; boids[0] = []; boids[1] = []; boids[2] = []; boids[3] = []; var Vars = []; var NUM_BOIDS = 240; var BOID_SIDE; var MAX_SPEED; init(); loop(); function init(){ for(var i = 0; i < 4; i++){ Vars.push({ BOID_SIDE : 2 + 4 * Math.random(), MAX_SPEED : 3 + 3 * Math.random(), rule1 : 10 + 140 * Math.random(), rule3 : 6 + Math.random() * 20 }); } for(var i = 0; i < NUM_BOIDS; i++){ var random = Math.random(); var boid = new Boid(ctx); if(random < 1/4) { boid.col = '#e74c3c'; boids[0].push(boid); } else if(random < 1/2){ boid.col = '#f1c40f'; boids[1].push(boid); } else if(random < 3 /4){ boid.col = '#3498db'; boids[2].push(boid); } else { boid.col = '#1abc9c'; boids[3].push(boid); } boidCollection.push(boid); } prevTime = +new Date; setTimeout(shuffle, 1000 * 4); } function shuffle(){ //var collectionNum = parseInt(Math.random * 4); boids[0] = []; boids[1] = []; boids[2] = []; boids[3] = []; for(var i = 0; i < 4; i++){ Vars[i] = { BOID_SIDE : 2 + 4 * Math.random(), MAX_SPEED : 3 + 3 * Math.random(), rule1 : 10 + 140 * Math.random(), rule3 : 6 + Math.random() * 20 }; } for(var i = 0; i < NUM_BOIDS; i++){ var random = Math.random(); var boid = boidCollection[i]; if(random < 1/4) { boid.col = '#e74c3c'; boids[0].push(boid); } else if(random < 1/2){ boid.col = '#f1c40f'; boids[1].push(boid); } else if(random < 3 /4){ boid.col = '#3498db'; boids[2].push(boid); } else { boid.col = '#1abc9c'; boids[3].push(boid); } } console.log(boidCollection); setTimeout(shuffle, 1000 * 4); } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; side = 300 + 100 * Math.cos(curTime/2000); leftX = width/2 - side/2; rightX = width/2 + side/2; topY = height/2 - side/2; bottomY = height/2 + side/2; ctx.clearRect(0, 0, width, height); ctx.fillStyle = '#333'; ctx.fillRect( leftX, topY, side, side); ctx.beginPath(); ctx.moveTo(0, 0); ctx.lineTo(leftX, topY); ctx.strokeStyle = '#333'; ctx.stroke(); ctx.closePath(); ctx.beginPath(); ctx.moveTo(0, height); ctx.lineTo(leftX, bottomY); ctx.strokeStyle = '#333'; ctx.stroke(); ctx.closePath(); ctx.beginPath(); ctx.moveTo(width, 0); ctx.lineTo(rightX, topY); ctx.strokeStyle = '#333'; ctx.stroke(); ctx.closePath(); ctx.beginPath(); ctx.moveTo(width, height); ctx.lineTo(rightX, bottomY); ctx.strokeStyle = '#333'; ctx.stroke(); ctx.closePath(); for(var i = 0; i < boids.length; i++){ MAX_SPEED = Vars[i].MAX_SPEED; for(var j = 0; j < boids[i].length; j++){ var b = boids[i][j]; b.rad = (side / 400 * .8 + .2) * 3; rule1(i, j); rule2(i, j); rule3(i, j); /** if(b.x < 0) b.x += width; if(b.x > width) b.x -= width; if(b.y < 0) b.y += height; if(b.y > height) b.y -= height;*/ var speed = Math.sqrt(b.vx * b.vx + b.vy * b.vy); if(speed >= MAX_SPEED) { var r = MAX_SPEED / speed; b.vx *= r; b.vy *= r; } if(b.x < leftX && b.vx < 0 || b.x > rightX && b.vx > 0) b.vx *= -.9 if(b.y < topY && b.vy < 0 || b.y > bottomY && b.vy > 0) b.vy *= -.9; b.x += b.vx; b.y += b.vy; b.draw(); } } requestAnimationFrame(loop); } function rule1(index1, index2){ var c = {x: 0, y: 0}; var vel = Vars[index1].rule1; var _boids = boids[index1]; for(var i = 0; i < _boids.length; i++){ if(i != index2){ c.x += _boids[i].x; c.y += _boids[i].y; } } c.x = c.x / (_boids.length-1); c.y = c.y / (_boids.length-1); _boids[index2].vx += (c.x - _boids[index2].x)/vel; _boids[index2].vy += (c.y - _boids[index2].y)/vel; } function rule2(index1, index2){ var _boids = boids[index1]; BOID_SIDE = Vars[index1].BOID_SIDE; for( var i = 0; i < _boids.length; i++){ var d = getDistance(_boids[i], _boids[index2]); if(d < BOID_SIDE){ _boids[index2].vx -= _boids[i].x - _boids[index2].x; _boids[index2].vy -= _boids[i].y - _boids[index2].y; } } } function rule3(index1, index2){ var pv = {x: 0, y: 0}; var _boids = boids[index1]; var vel = Vars[index1].rule3; for(var i = 0; i < _boids.length; i++){ if(i != index2){ pv.x += _boids[i].vx; pv.y += _boids[i].vy; } } pv.x /= (_boids.length - 1); pv.y /= (_boids.length - 1); _boids[index2].vx += (pv.x - _boids[index2].vx) / vel; _boids[index2].vy += (pv.y - _boids[index2].vy) / vel; } function getDistance(p1, p2){ var dx = p1.x - p2.x; var dy = p1.y -p2.y; return Math.sqrt(dx * dx + dy * dy); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/99-hobby/99-01-canvas-letter.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ // ================ init(); loop(); function init(){ ctx.textBaseline="middle"; ctx.font= 60 + "px Arial"; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); var txt="YO!"; ctx.fillStyle = '#fff'; var textWidth = ctx.measureText(txt); var textLeft = (width - textWidth.width)/2; var textTop = height/2; ctx.save(); ctx.translate(textLeft, textTop); ctx.fillText(txt,0,0); ctx.restore(); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/99-hobby/99-02-shader-example.js ================================================ // -------------------------- var scene, camera, renderer; var vertexShaderString, fragmentShaderString; var character = null; var width, height, prevTime; var canvas = document.getElementById('c'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ // ================ var tempCanvas, tempCtx; createCanvas(); init(); loop(); function createCanvas(){ tempCanvas = document.createElement("canvas"); //canvas.width = width; //canvas.height = height; tempCtx = tempCanvas.getContext("2d"); // ---------------- /* ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); var txt="YO!"; ctx.fillStyle = '#fff'; var textWidth = ctx.measureText(txt); var textLeft = (width - textWidth.width)/2; var textTop = height/2; ctx.save(); ctx.translate(textLeft, textTop); ctx.fillText(txt,0,0); ctx.restore(); */ // ---------------- tempCtx.font = "Bold 40px Arial"; tempCtx.fillStyle = "rgba(255,0,0,0.95)"; tempCtx.fillText('YO!', 0, 50); } var texture1; function init(){ scene = new THREE.Scene(); var VIEW_ANGLE= 45; var ASPECT = width / height; var NEAR = 0.2; var FAR = 1000; camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR); scene.add(camera); camera.position.set(0, 0, 5); camera.lookAt(scene.position); // --------------- renderer = new THREE.WebGLRenderer({ canvas : canvas, antialias : true, alpha : true }); //renderer.setSize(width, height); var g = new THREE.PlaneGeometry(1.0, 1.0); var creatureImage = THREE.ImageUtils.loadTexture("/image/texture.png"); texture1 = new THREE.Texture(tempCanvas); texture1.needsUpdate = true; texture1.magFilter = THREE.NearestFilter; creatureImage.magFilter = THREE.NearestFilter; var mat = new THREE.ShaderMaterial({ uniforms : { color : {type: 'f', value: 0.0}, evilCreature : {type: 't', value: texture1} }, vertexShader : [ "varying vec2 vUv;", "void main(){", "vUv = uv;", "gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0 );", "}" ].join("\n"), fragmentShader : [ "precision highp float;", "varying vec2 vUv;", "uniform sampler2D evilCreature;", "void main(void){", "gl_FragColor = texture2D(evilCreature, vUv);", "}" ].join("\n"), transparent: true }); character = new THREE.Mesh(g, mat); scene.add(character); // -------------------------- var light = new THREE.PointLight(0xffffff, 1.0); light.position.set( 0.0, 0.0, 0.1 ); scene.add(light); } function loop(){ loopCanvas(); renderer.render( scene, camera ); requestAnimationFrame(loop); } function loopCanvas(){ tempCtx.clearRect(0, 0, tempCanvas.width, tempCanvas.height); tempCtx.font = "Bold 40px Arial"; tempCtx.fillStyle = "rgba(255,0,0,0.95)"; tempCtx.fillText('YO!', Math.random() * 2 - 1, 50 + Math.random() * 2 - 1); texture1.needsUpdate = true; } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/99-hobby/99-03-circle-drawing.js ================================================ /** * Created by kenji-special on 10/27/14. */ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var extraMarker = { yPos : -1/2*window.innerHeight }; var animationCircle = { start : - Math.PI , end : - Math.PI }; width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var Flag = function(number, theta, rad){ this.setup(number, theta, rad); }; Flag.prototype = { isDraw : false, strokeCol : '#a1a1a1', fillCol : '#999', length : 50, flagHeight : 25, setup : function(number, theta, rad){ this.number = number; this.curTheta = -theta - Math.PI/2; var xPos = rad * Math.cos(this.curTheta); var yPos = rad * Math.sin(this.curTheta); this.startXPos = this.endXPos = this.flagXPos = xPos; this.startYPos = this.endYPos = this.flagYPos = yPos; this.targetXPos = (rad + this.length) * Math.cos(this.curTheta); this.targetYPos = (rad + this.length) * Math.sin(this.curTheta); this.targetX1Pos = (rad + this.flagHeight) * Math.cos(this.curTheta); this.targetY1Pos = (rad + this.flagHeight) * Math.sin(this.curTheta); // --------------------------------------------- this.target1XPos = (rad - 5) * Math.cos(this.curTheta); this.target1YPos = (rad - 5) * Math.sin(this.curTheta); this.flag1XPos = 40 * Math.cos(this.curTheta + Math.PI/2); this.flag1YPos = 40 * Math.sin(this.curTheta + Math.PI/2); this.flagsPos76 }, startAnimation : function(){ this.isDraw = true; TweenLite.to( this, .3, {endXPos: this.targetXPos, endYPos: this.targetYPos, flagXPos: this.targetX1Pos, flagYPos: this.targetY1Pos, ease : 'Power2.easeOut' }); }, update : function(ctx){ if(!this.isDraw) return; ctx.strokeStyle = this.strokeCol; ctx.beginPath(); ctx.moveTo(this.startXPos, this.startYPos); ctx.lineTo(this.endXPos, this.endYPos); ctx.stroke(); ctx.beginPath(); ctx.fillStyle = this.fillCol; ctx.beginPath(); ctx.moveTo(this.endXPos, this.endYPos); ctx.lineTo(this.endXPos + this.flag1XPos, this.endYPos + this.flag1YPos); ctx.lineTo(this.flagXPos + this.flag1XPos, this.flagYPos + this.flag1YPos); ctx.lineTo( this.flagXPos, this.flagYPos); ctx.lineTo(this.endXPos, this.endYPos); ctx.closePath(); ctx.fill(); ctx.save(); ctx.font="18px Open Sans"; ctx.fillStyle = "#fff"; ctx.textAlign="center"; ctx.textBaseline = 'middle'; ctx.translate( (this.endXPos + this.flagXPos + this.flag1XPos)/2, (this.endYPos + this.flagYPos + this.flag1YPos)/2); ctx.rotate(this.curTheta + Math.PI/2); ctx.fillText(this.number, 0, 0); ctx.restore(); /* ctx.beginPath(); ctx.moveTo(this.startXPos, this.startXPos); ctx.lineTo(this.endXPos, this.endXPos); ctx.stroke(); ctx.beginPath(); ctx.moveTo(this.startYPos, this.startYPos); ctx.lineTo(this.endYPos, this.endYPos); ctx.stroke();*/ } }; var sampleWorksNumber = 55; var side = 20; var outlineRad = 200; var inlineRad = 190; var flags = []; // ================ init(); loop(); function init(){ TweenLite.to( extraMarker, 1, { yPos : 0, ease : 'Bounce.easeOut', delay: 1}); TweenLite.to( animationCircle, 1, { start : 0, end : 2 * Math.PI, ease : 'Power2.easeOut', delay: 1});//, onComplete: circleAnimationDone }); for(var i = 0;i < sampleWorksNumber; i+= 10){ var theta = Math.PI * i / sampleWorksNumber * 2; var flag = new Flag(i,theta, outlineRad ); flags.push(flag); } prevTime = +new Date; _.delay(circleAnimationDone, 1500); } function circleAnimationDone(){ for(var i = 0; i < flags.length; i++){ flags[i].startAnimation(); } } function loop(){ ctx.clearRect(0, 0, window.innerWidth, window.innerHeight); ctx.save(); ctx.translate(window.innerWidth/2, window.innerHeight/2); var theta = 0 - Math.PI/2; var theta1 = theta - Math.PI/6; var theta2 = theta + Math.PI/6; var pt1X = Math.cos(theta) * outlineRad; var pt1Y = Math.sin(theta) * outlineRad; var dx1 = side * Math.cos(theta1); var dy1 = side * Math.sin(theta1); var dx2 = side * Math.cos(theta2); var dy2 = side * Math.sin(theta2); ctx.beginPath(); ctx.strokeStyle = '#cccccc'; ctx.arc(0, 0, outlineRad, animationCircle.start, animationCircle.end); ctx.stroke(); ctx.closePath(); ctx.beginPath(); ctx.fillStyle = '#cccccc'; ctx.arc(0, 0, inlineRad, animationCircle.start, animationCircle.end); ctx.fill(); ctx.closePath(); // drawing the flag for(var i = 0; i < flags.length; i++){ flags[i].update(ctx); } ctx.save(); ctx.translate(0, extraMarker.yPos); ctx.beginPath(); ctx.moveTo(pt1X, pt1Y); ctx.lineTo(pt1X + dx1, pt1Y + dy1); ctx.lineTo(pt1X + dx2, pt1Y + dy2); ctx.lineTo(pt1X, pt1Y); ctx.closePath(); ctx.fillStyle = '#3d9ae8'; ctx.fill(); ctx.restore(); ctx.restore(); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/99-hobby/99-04-flag-animation.js ================================================ /** */ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ // ================ init(); loop(); function init(){ prevTime = +new Date; } function loop(){ var curTime = +new Date; var duration = (curTime - prevTime)/1000; prevTime = curTime; ctx.fillStyle = '#333'; ctx.fillRect(0, 0, width, height); requestAnimationFrame(loop); } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/99-hobby/99-05-color-draw.js ================================================ // -------------------------- var width, height, prevTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var sCol = .8, bCol = .8; var colorPaletteArr = []; var isColorSelected; var balls = []; var NUM_BALLS = 130, DAMPING = 0.3, GRAVITY = 1, MOUSE_SIZE = 50, SPEED = 1; var TWO_PI = Math.PI * 2; var count = 0; var colorCircle; var rainbowBall; var isSelectedColor = true; var wall; width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // ================ var Wall = function (left, right, top, bot) { this.left = left; this.right = right; this.top = top; this.bot = bot; }; var Ball = function (x, y, radius, col, wall, isRainbow) { this.x = x; this.y = y; this.px = x; this.py = y; this.fx = 0; this.fy = 0; this.col = col; this.radius = radius; this.isRainbow = isRainbow; }; Ball.prototype.setCanvas = function (_canvas) { this.canvas = _canvas; this.isRainbow = true; } Ball.prototype.apply_force = function (delta) { delta *= delta; this.fy += GRAVITY; this.x += this.fx * delta; this.y += this.fy * delta; this.fx = this.fy = 0; }; Ball.prototype.verlet = function () { var nx = (this.x * 2) - this.px; var ny = (this.y * 2) - this.py; this.px = this.x; this.py = this.y; this.x = nx; this.y = ny; }; Ball.prototype.draw = function (ctx) { if (this.isRainbow) { ctx.save(); ctx.translate(this.x, this.y); ctx.drawImage(this.canvas, -this.radius, -this.radius); ctx.restore(); } else { ctx.beginPath(); ctx.fillStyle = this.col; ctx.arc(this.x, this.y, this.radius, 0, TWO_PI); ctx.fill(); } }; var resolve_collisions = function (ip) { var i = balls.length; while (i--) { var ball_1 = balls[i]; var n = balls.length; while (n--) { if (n == i) continue; var ball_2 = balls[n]; var diff_x = ball_1.x - ball_2.x; var diff_y = ball_1.y - ball_2.y; var length = diff_x * diff_x + diff_y * diff_y; var dist = Math.sqrt(length); var real_dist = dist - (ball_1.radius + ball_2.radius); if (real_dist < 0) { var vel_x1 = ball_1.x - ball_1.px; var vel_y1 = ball_1.y - ball_1.py; var vel_x2 = ball_2.x - ball_2.px; var vel_y2 = ball_2.y - ball_2.py; var depth_x = diff_x * (real_dist / dist); var depth_y = diff_y * (real_dist / dist); ball_1.x -= depth_x * 0.5; ball_1.y -= depth_y * 0.5; ball_2.x += depth_x * 0.5; ball_2.y += depth_y * 0.5; if (ip) { var pr1 = DAMPING * (diff_x * vel_x1 + diff_y * vel_y1) / length, pr2 = DAMPING * (diff_x * vel_x2 + diff_y * vel_y2) / length; vel_x1 += pr2 * diff_x - pr1 * diff_x; vel_x2 += pr1 * diff_x - pr2 * diff_x; vel_y1 += pr2 * diff_y - pr1 * diff_y; vel_y2 += pr1 * diff_y - pr2 * diff_y; ball_1.px = ball_1.x - vel_x1; ball_1.py = ball_1.y - vel_y1; ball_2.px = ball_2.x - vel_x2; ball_2.py = ball_2.y - vel_y2; } } } } }; var check_walls = function (wall) { var i = balls.length; while (i--) { var ball = balls[i]; if (ball.x < wall.left + ball.radius) { var vel_x = ball.px - ball.x; ball.x = wall.left + ball.radius; ball.px = ball.x - vel_x * DAMPING; } else if (ball.x + ball.radius > wall.right) { var vel_x = ball.px - ball.x; ball.x = wall.right - ball.radius; ball.px = ball.x - vel_x * DAMPING; } if (ball.y + ball.radius > wall.bot) { var vel_y = ball.py - ball.y; ball.y = wall.bot - ball.radius; ball.py = ball.y - vel_y * DAMPING; } } }; // ================ function addBall() { isColorSelected = false; var xPos = width / 2; var yPos = height / 2; var rad = 105; var col = "#ffffff"; rainbowBall = new Ball(xPos, yPos, rad, col, wall); rainbowBall.setCanvas(colorCircle.rainbowCircle.canvas); //balls.push(ball); for (var xx = 0; xx < 3; xx++) { var xPos = colorCircle.smallCircles[xx].x + width / 2; var yPos = colorCircle.smallCircles[xx].y + height / 2; var ball = new Ball(xPos, yPos, colorCircle.smallCircles[xx].rad, colorCircle.smallCircles[xx].col, wall); balls.push(ball); } addOnlyBall(); } function addOnlyBall() { for (var num = 0; num < 20; num++) { var xPos = width * (.1 + .8 * Math.random()); var yPos = -height * (.1 + .8 * Math.random()); var rad = 20 + 30 * Math.random(); var randomNum = Math.random() * 3 | 0; var colorStr = colorPaletteArr[randomNum]; balls.push(new Ball(xPos, yPos, rad, colorStr, wall)); } } // ================ var SmallCircle = function () { this.velTheta = .04; this.theta = 0; this.outsideRad = 100; this.isAnimation = true; this.rad = 10; }; SmallCircle.prototype = { update: function () { if (this.isAnimation) this.theta += this.velTheta; if (this.theta < 0) this.theta += Math.PI * 2; this.x = this.outsideRad * Math.cos(this.theta); this.y = this.outsideRad * Math.sin(this.theta); var val = this.theta / (2 * Math.PI); var color = HSVtoRGB(val, sCol, bCol); this.col = "rgb(" + color.r + ", " + color.g + ", " + color.b + ")"; ctx.save(); ctx.fillStyle = this.col; ctx.beginPath(); ctx.arc(this.x, this.y, this.rad, 0, 2 * Math.PI); ctx.fill(); ctx.closePath(); ctx.restore(); }, stop: function () { this.isAnimation = false; } }; var RainbowCircle = function () { this.rad = 100; this.canvas = document.createElement("canvas"); this.canvas.width = 210; this.canvas.height = 210; this.ctx = this.canvas.getContext('2d'); this.ctx.save(); this.ctx.translate(this.canvas.width / 2, this.canvas.height / 2); var xPos, yPos, nextXPos, yPos; for (var ii = 0; ii < 360; ii = ii + 3) { var rate = ii / 360; colorRGB = HSVtoRGB(rate, sCol, bCol); colorString = "rgb(" + colorRGB.r + ", " + colorRGB.g + ", " + colorRGB.b + ")"; xPos = this.rad * Math.cos(ii / 180 * Math.PI); yPos = this.rad * Math.sin(ii / 180 * Math.PI); nextXPos = this.rad * Math.cos((ii + 3) / 180 * Math.PI); nextYPos = this.rad * Math.sin((ii + 3) / 180 * Math.PI); this.ctx.strokeStyle = colorString; this.ctx.beginPath(); this.ctx.moveTo(xPos, yPos); this.ctx.lineTo(nextXPos, nextYPos); this.ctx.stroke(); } this.ctx.restore(); }; var ColorCircle = function (x, y) { this.x = x; this.y = y; this.rad = 100; this.smallCircles = []; var smallCircle = new SmallCircle(); this.smallCircles.push(smallCircle); this.rainbowCircle = new RainbowCircle(); }; ColorCircle.prototype = { isCircle: true, update: function () { var colorRGB, xPos, yPos, nextXPos, nextYPos; var colorString; ctx.lineWidth = 2; ctx.save(); ctx.translate(this.x, this.y); //console.log(this.rainbowCircle.canvas); ctx.drawImage(this.rainbowCircle.canvas, -this.rainbowCircle.canvas.width / 2, -this.rainbowCircle.canvas.height / 2); ctx.save(); for (ii = 0; ii < this.smallCircles.length; ii++) { this.smallCircles[ii].update() } ctx.restore(); ctx.restore(); }, addCircle: function () { if (isSelectedColor) { if (this.smallCircles.length < 2) { this.smallCircles[this.smallCircles.length - 1].stop(); colorPaletteArr.push(this.smallCircles[this.smallCircles.length - 1].col); var smallCircle = new SmallCircle(); smallCircle.theta = this.smallCircles[this.smallCircles.length - 1].theta; this.smallCircles.push(smallCircle); var smallCircle = new SmallCircle(); smallCircle.theta = this.smallCircles[this.smallCircles.length - 1].theta; smallCircle.velTheta = -0.04; this.smallCircles.push(smallCircle); } else if (this.smallCircles.length == 3) { this.smallCircles[this.smallCircles.length - 2].stop(); this.smallCircles[this.smallCircles.length - 1].stop(); colorPaletteArr.push(this.smallCircles[this.smallCircles.length - 2].col); colorPaletteArr.push(this.smallCircles[this.smallCircles.length - 1].col); addBall(); isSelectedColor = false; } } else { addOnlyBall(); } } }; // ================ init(); loop(); function init() { colorCircle = new ColorCircle(width / 2, height / 2); prevTime = +new Date; isColorSelected = true; wall = new Wall(0, width, -height, height); } function loop() { var curTime = +new Date; var duration = (curTime - prevTime) / 1000; prevTime = curTime; ctx.fillStyle = '#000000'; ctx.fillRect(0, 0, width, height); if (isColorSelected) colorCircle.update(); else loopBall(); ctx.save(); var alpha = Math.random() * .1 + .3; ctx.fillStyle = "rgba(255, 255, 255, "+ alpha +")"; ctx.font="22px 'HelveticaNeue-Light','Helvetica Neue Light','Helvetica Neue',sans-serif"; ctx.fillText("CLICK!", width/2 - 35, height/2 +10); ctx.restore(); requestAnimationFrame(loop); } function loopBall() { var iter = 3; var delta = SPEED / iter; while (iter--) { var i = balls.length; while (i--) { balls[i].apply_force(delta); balls[i].verlet(); } rainbowBall.apply_force(delta); rainbowBall.verlet(); resolve_collisions(); check_walls(wall); var i = balls.length; while (i--) balls[i].verlet(); resolve_collisions(1); check_walls(wall); } for (var i = 0; i < balls.length; i++) { balls[i].draw(ctx); } rainbowBall.draw(ctx); } document.addEventListener("click", function (ev) { //alert("click"); colorCircle.addCircle(); }); window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; ================================================ FILE: app/scripts/helpers/boilterplate.js ================================================ function backingScale(context) { if ('devicePixelRatio' in window) { if (window.devicePixelRatio > 1) { return window.devicePixelRatio; } } return 1; } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; var width, height, previousTime; var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var scaleFactor = backingScale(ctx); width = window.innerWidth * scaleFactor; height = window.innerHeight * scaleFactor; canvas.width = width; canvas.height = height; init(); loop(); function init(){ previousTime = +new Date; console.log(previousTime); } function loop(){ requestAnimationFrame(loop); } var Rect = function(x, y, wid, hig){ }; Rect.prototype = { update : function(dt){ } }; ================================================ FILE: app/scripts/helpers/colorConverter.js ================================================ function HSVtoRGB(h, s, v) { var r, g, b, i, f, p, q, t; if (h && s === undefined && v === undefined) { s = h.s, v = h.v, h = h.h; } i = Math.floor(h * 6); f = h * 6 - i; p = v * (1 - s); q = v * (1 - f * s); t = v * (1 - (1 - f) * s); switch (i % 6) { case 0: r = v, g = t, b = p; break; case 1: r = q, g = v, b = p; break; case 2: r = p, g = v, b = t; break; case 3: r = p, g = q, b = v; break; case 4: r = t, g = p, b = v; break; case 5: r = v, g = p, b = q; break; } return { r: Math.floor(r * 255), g: Math.floor(g * 255), b: Math.floor(b * 255) }; } ================================================ FILE: app/scripts/helpers/keyEvents.js ================================================ /** * Created by kenji-special on 12/26/14. */ var cancelRequestAnimFrame = ( function() { return window.cancelAnimationFrame || window.webkitCancelRequestAnimationFrame || window.mozCancelRequestAnimationFrame || window.oCancelRequestAnimationFrame || window.msCancelRequestAnimationFrame || clearTimeout } )(); var requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(/* function */ callback, /* DOMElement */ element){ return window.setTimeout(callback, 1000 / 60); }; })(); var keyEvent = {}; _.extend(keyEvent, Backbone.Events); var KEY_NUMBER = { ESC : 27 }; var ESC_DOWN = "ESCAPE_DOWN"; window.addEventListener("keydown", function(event){ if(KEY_NUMBER.ESC == event.keyCode){ keyEvent.trigger(ESC_DOWN); } }, false); ================================================ FILE: app/scripts/helpers/svg-parse.js ================================================ var l1pt0 = "M138.1,106.8h-8.5l-2,6.2h-4.5l8.5-24.1h4.6l8.5,24.1h-4.5L138.1,106.8z"; var l1pt1 = "M133.9,93.1c0,0-0.5,2.4-1,3.7l-2.1,6.5h6.3l-2.1-6.5C134.5,95.5,133.9,93.1,133.9,93.1L133.9,93.1z"; var l2pt0 = "M151.2,88.9h7.8c2.6,0,3.8,0.2,4.9,0.7c2.4,1.1,3.9,3.4,3.9,6.6c0,2.9-1.5,5.6-4.1,6.6v0.1c0,0,0.3,0.3,0.8,1.2l5,9h-4.9l-4.8-9h-4.2v9h-4.4L151.2,88.9L151.2,88.9z"; var l2pt1 = "M159.5,100.2c2.3,0,3.8-1.4,3.8-3.8c0-2.3-1-3.7-4.4-3.7h-3.3v7.5L159.5,100.2L159.5,100.2z"; var l3pt0 = "M177,88.9h8.2c7.4,0,12.3,4.4,12.3,12c0,7.6-4.9,12.1-12.3,12.1H177V88.9z"; var l3pt1 = "M184.9,109.3c4.9,0,8-2.9,8-8.3c0-5.4-3.2-8.3-8-8.3h-3.6v16.6H184.9z"; var l4 = "M205.3,106.8c0,0,2.6,2.6,6,2.6c1.8,0,3.5-0.9,3.5-2.9c0-4.3-11.4-3.6-11.4-11c0-4,3.5-7,8.1-7c4.8,0,7.2,2.6,7.2,2.6l-1.9,3.6c0,0-2.3-2.1-5.3-2.1c-2,0-3.6,1.2-3.6,2.9c0,4.3,11.4,3.2,11.4,11c0,3.8-2.9,7.1-8,7.1c-5.4,0-8.3-3.3-8.3-3.3L205.3,106.8z"; var l5 = "M88.7,88.9l-4,16.7c-0.3,1.4-0.4,2.5-0.4,2.5h-0.1c0,0-0.1-1.2-0.4-2.5l-4.3-16.7h-3.8l-4.4,16.7c-0.4,1.4-0.4,2.5-0.4,2.5h-0.1c0,0-0.1-1.2-0.4-2.5l-2.8-12.5l-2.1,9.1l2.7,10.8h5.1l3.7-14.3c0.4-1.6,0.6-3.2,0.6-3.2h0.1c0,0,0.2,1.6,0.6,3.2l3.7,14.3H87l6.2-24.1L88.7,88.9L88.7,88.9z"; var l6 = "M115.9,88.9l-4,16.7c-0.3,1.4-0.4,2.5-0.4,2.5h-0.1c0,0-0.1-1.2-0.4-2.5l-4.3-16.7h-3.8l-4.4,16.7c-0.4,1.4-0.4,2.5-0.4,2.5H98c0,0-0.1-1.2-0.4-2.5L94.8,93l-2.1,9.1l2.7,10.9h5.1l3.7-14.3c0.4-1.6,0.6-3.2,0.6-3.2h0.1c0,0,0.2,1.6,0.6,3.2l3.7,14.3h5.1l6.2-24.1H115.9L115.9,88.9z"; var l7 = "M26,106.8h-8.5l-2,6.2H11l8.5-24.1h4.6l8.5,24.1h-4.5L26,106.8z M21.8,93.1c0,0-0.5,2.4-1,3.7l-2.1,6.5h6.3l-2.1-6.5C22.4,95.5,21.8,93.1,21.8,93.1L21.8,93.1z"; var l8 = "M56.5,105.6c0.4,1.4,0.4,2.5,0.4,2.5H57c0,0,0.1-1.2,0.4-2.5l4-16.7h4.5L59.7,113h-5.1l-3.7-14.3c-0.4-1.6-0.6-3.2-0.6-3.2h-0.1c0,0-0.2,1.6-0.6,3.2L45.9,113h-5.1l-6-24.1h4.5l3.8,16.7c0.3,1.4,0.4,2.5,0.4,2.5h0.1c0,0,0.1-1.2,0.4-2.5l4.4-16.7h3.8L56.5,105.6z"; var left = 11; var top = 88; var width = 215; var height = 26; function parsePathData(pathData) { var tokenizer = /([a-z]+)|([+-]?(?:\d+\.?\d*|\.\d+))/gi, match, current, commands = []; tokenizer.lastIndex = 0; while (match = tokenizer.exec(pathData)) { if (match[1]) { if (current) commands.push(current); current = [ match[1] ]; } else { if (!current) current = []; current.push(match[2]); } } if (current) commands.push(current); return commands; } //var pathData = "M78.1,10v69.1h0.5L113.4,10h49.9l-45.4,78.7L168.8,190h-53.4l-27.5-62.8l-9.8,15.1V190H31.2V10H78.1z"; //var pathData = "M152.2,10v38.3H92.4v30.8h56v36.8h-56v35.8h62V190H45.5V10H152.2z"; //var pathData = "M88.9,10l30.3,110.9h0.5V10h43.9v180h-51.4L80.8,78.8h-0.5V190H36.5V10H88.9z"; //var pathData = "M155.9,131.9c0,21.4-4.9,36.4-14.6,45.1c-9.8,8.7-24.2,13-43.2,13c-19.4,0-33.2-4.8-41.5-14.4c-8.3-9.6-12.4-23.7-12.4-42.2v-3.7h41.7v8.7c0,8.4,1.1,14.1,3.4,16.9c2.2,2.8,5.1,4.2,8.6,4.2c3.5,0,6.3-1.4,8.6-4.2c2.2-2.8,3.4-8.4,3.4-16.9V10h46.2V131.9z"; //var pathData = "M123.4,10v180H76.6V10H123.4z"; var commands = parsePathData(l8); var wid = 215; var hig = 26; var pts = []; var pt; var prevPt; for(var i = 0; i < commands.length; i++){ console.log( commands[i]); var text = commands[i][0]; if(pts.length) prevPt = pts[pts.length - 1]; if(/[a-z]/g.test(text)){ if(/[v]/.test(text)){ console.log(prevPt) var pt = {x: prevPt.x, y : Number(commands[i][1]) + prevPt.y}; pts.push(pt); } if(/[h]/g.test(text)){ var pt = {x: Number(commands[i][1]) + prevPt.x, y : prevPt.y}; pts.push(pt); } if(/[l]/g.test(text)){ var pt = {x: Number(commands[i][1]) + prevPt.x, y : Number(commands[i][2]) +prevPt.y }; pts.push(pt); } if(/[c]/g.test(text)){ var pt = {x: Number(commands[i][5]) + prevPt.x, y : Number(commands[i][6]) +prevPt.y, c1X: Number(commands[i][1]) + prevPt.x, c1Y: Number(commands[i][2]) + prevPt.y, c2X: Number(commands[i][3]) + prevPt.x, c2Y: Number(commands[i][4]) + prevPt.y}; pts.push(pt); } if(/[s]/g.test(text)){ var pt = {x: Number(commands[i][3]) + prevPt.x, y : Number(commands[i][4]) +prevPt.y, c1X: Number(commands[i][1]) + prevPt.x, c1Y: Number(commands[i][2]) + prevPt.y}; pts.push(pt); } }else{ if( /[M]/g.test(text) ){ pt = {x: Number(commands[i][1]), y: Number(commands[i][2])}; pts.push(pt); } if(/[V]/.test(text)){ var pt = {x: prevPt.x , y : Number(commands[i][1]) }; pts.push(pt); } if(/[H]/g.test(text)){ var pt = {x: Number(commands[i][1]), y : prevPt.y}; pts.push(pt); } if(/[L]/g.test(text)){ var pt = {x: Number(commands[i][1]), y : Number(commands[i][2])}; pts.push(pt); } if(/[S]/g.test(text)){ //var pt = {x: Number(commands[i][1]) + prevPt.x, y : Number(commands[i][2]) +prevPt.y }; //pts.push(pt); var pt = {x: Number(commands[i][3]), y : Number(commands[i][4]), c1X: Number(commands[i][1]), c1Y: Number(commands[i][2])}; pts.push(pt); } if(/[C]/g.test(text)){ //var pt = {x: Number(commands[i][1]) + prevPt.x, y : Number(commands[i][2]) +prevPt.y }; //pts.push(pt); var pt = {x: Number(commands[i][5]), y : Number(commands[i][6]), c1X: Number(commands[i][1]), c1Y: Number(commands[i][2]), c2X: Number(commands[i][3]), c2Y: Number(commands[i][4])}; pts.push(pt); } } } Object.size = function(obj) { var size = 0, key; for (key in obj) { if (obj.hasOwnProperty(key)) size++; } return size; }; var str = "l" + kk; str += "=[ "; console.log(str); for(var i = 0; i < pts.length; i++){ var number = Object.size(pts[i]); var curStr; if(number == 2){ curStr = "[" + pts[i].x / 200 + ", " + pts[i].y / 40 + "]"; } if(number == 6){ curStr = "[" + pts[i].c1X/200 + ", " + pts[i].c1Y/40 + ", " + pts[i].c2X/200 + ", " + pts[i].c2Y/40 + "," + pts[i].x / 200 + ", " + pts[i].y / 40 +"]"; } if(number == 4){ curStr = "[" + pts[i].c1X/200 + ", " + pts[i].c1Y/40 + "," + pts[i].x / 200 + ", " + pts[i].y / 40 +"]"; } if(i != pts.length - 1) str += curStr + ", "; else str += curStr; } str += " ];"; ================================================ FILE: app/scripts/main.js ================================================ (function(scope) { var app = scope.app || {}; var Rect = app.Rect = function(ctx, x, y){ this.ctx = ctx; this.col = '#fff'; this.x = x; this.y = y; this.side = 30; }; Rect.prototype = { update : function(){ } }; })(window.__scope__ || window); ================================================ FILE: app/scripts/ref/camera.js ================================================ sw = 1000; sh = 1000; var dtr = function(v) {return v * Math.PI/180;} var camera = { focus : 700, self : { x : 0, y : 0, z : 0 }, rotate : { x : 0, y : 0, z : 0 }, up : { x : 0, y : 1, z : 0 }, zoom : 1, display : { x : 700/2, y : 700/2, z : 0 } }; var affine = { world : { size : function(p, size) { return { x : p.x * size.x, y : p.y * size.y, z : p.z * size.z } }, rotate: { x : function(p, rotate) { return { x : p.x, y : p.y*Math.cos(dtr(rotate.x)) - p.z*Math.sin(dtr(rotate.x)), z : p.y*Math.sin(dtr(rotate.x)) + p.z*Math.cos(dtr(rotate.x)) } }, y : function(p, rotate) { return { x : p.x*Math.cos(dtr(rotate.y)) + p.z*Math.sin(dtr(rotate.y)), y : p.y, z : -p.x*Math.sin(dtr(rotate.y)) + p.z*Math.cos(dtr(rotate.y)) } }, z : function(p, rotate) { return { x : p.x*Math.cos(dtr(rotate.z)) - p.y*Math.sin(dtr(rotate.z)), y : p.x*Math.sin(dtr(rotate.z)) + p.y*Math.cos(dtr(rotate.z)), z : p.z } } }, position : function(p, position) { return { x : p.x + position.x, y : p.y + position.y, z : p.z + position.z } }, }, view : { point : function(p) { return { x : p.x - camera.self.x, y : p.y - camera.self.y, z : p.z - camera.self.z } }, x : function(p) { return { x : p.x, y : p.y*Math.cos(dtr(camera.rotate.x)) - p.z*Math.sin(dtr(camera.rotate.x)), z : p.y*Math.sin(dtr(camera.rotate.x)) + p.z*Math.cos(dtr(camera.rotate.x)) } }, y : function(p) { return { x : p.x*Math.cos(dtr(camera.rotate.y)) + p.z*Math.sin(dtr(camera.rotate.y)), y : p.y, z : -p.x*Math.sin(dtr(camera.rotate.y)) + p.z*Math.cos(dtr(camera.rotate.y)) } }, zReversal : function(p) { return { x : p.x, y : p.y, z : -p.z } } }, perspective : function(p) { return { x : p.x * ((camera.focus-camera.self.z) / ((camera.focus-camera.self.z) - p.z)) * camera.zoom, y : p.y * ((camera.focus-camera.self.z) / ((camera.focus-camera.self.z) - p.z)) * camera.zoom, z : p.z * ((camera.focus-camera.self.z) / ((camera.focus-camera.self.z) - p.z)) * camera.zoom, p : ((camera.focus) / ((camera.focus) - p.z)) * camera.zoom } }, display : function(p, display) { return { x : p.x + display.x, y : p.y + display.y, z : p.z + display.z, p : p.p } }, process : function(model, size, rotate, position) { var ret = affine.world.size(model, size); ret = affine.world.rotate.x(ret, rotate); ret = affine.world.rotate.y(ret, rotate); ret = affine.world.rotate.z(ret, rotate); ret = affine.world.position(ret, position); ret = affine.view.point(ret); ret = affine.view.x(ret); ret = affine.view.y(ret); ret = affine.view.zReversal(ret); ret = affine.perspective(ret); ret = affine.display(ret, camera.display); return ret; } } ================================================ FILE: app/styles/main.scss ================================================ // bower:scss // endbower @import "compass/reset"; @import "compass/css3"; body{ background: url("../image/pt4.png"); } canvas{ width: 100%; height: 100%; } $containerWidth: 30px; $containerHeight: 30px; $playStep: $containerHeight / 16; #container { position: absolute; bottom: 30px; left: 30px; width: $containerWidth; height: $containerHeight; text-align: center; } #play, #stop { margin-top: 15px; font-size: 24px; transition: text-shadow 0.2s ease; cursor: pointer; } #play { display: inline-block; } #button, #stop { display: none; } #button:checked ~ { #play { display: none; } #stop { display: inline-block; } #icon { .icon-column { .column-inner { animation-play-state: paused; } } } } ================================================ FILE: app/three-js-shader-sample.html ================================================ 201405 ================================================ FILE: bower.json ================================================ { "name": "201405", "private": true, "dependencies": { "modernizr": "~2.6.2", "jquery": "~1.11.0", "TweenJS": "*", "greensock": "~1.11.7", "underscore": "~1.6.0", "howler.js": "~1.1.25", "threejs": "*", "angular": "~1.2.25", "stats.js": "*", "dat-gui": "~0.5.0", "backbone": "~1.1.2" }, "devDependencies": {} } ================================================ FILE: package.json ================================================ { "name": "201405", "version": "0.0.0", "dependencies": {}, "devDependencies": { "grunt": "~0.4.1", "grunt-contrib-copy": "~0.4.1", "grunt-contrib-concat": "~0.3.0", "grunt-contrib-uglify": "~0.2.0", "grunt-contrib-compass": "~0.7.0", "grunt-contrib-jshint": "~0.7.0", "grunt-contrib-cssmin": "~0.7.0", "grunt-contrib-connect": "~0.5.0", "grunt-contrib-clean": "~0.5.0", "grunt-contrib-htmlmin": "~0.1.3", "grunt-bower-install": "~1.0.0", "grunt-contrib-imagemin": "~0.5.0", "grunt-contrib-watch": "~0.5.2", "grunt-rev": "~0.1.0", "grunt-autoprefixer": "~0.5.0", "grunt-usemin": "~2.0.0", "grunt-mocha": "~0.4.0", "grunt-modernizr": "~0.4.0", "grunt-newer": "~0.6.0", "grunt-svgmin": "~0.2.0", "grunt-concurrent": "~0.4.0", "load-grunt-tasks": "~0.2.0", "time-grunt": "~0.2.0", "jshint-stylish": "~0.1.3" }, "engines": { "node": ">=0.8.0" } } ================================================ FILE: test/index.html ================================================ Mocha Spec Runner
================================================ FILE: test/lib/chai.js ================================================ !function (name, context, definition) { if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') { module.exports = definition(); } else if (typeof define === 'function' && typeof define.amd === 'object') { define(function () { return definition(); }); } else { context[name] = definition(); } }('chai', this, function () { function require(p) { var path = require.resolve(p) , mod = require.modules[path]; if (!mod) throw new Error('failed to require "' + p + '"'); if (!mod.exports) { mod.exports = {}; mod.call(mod.exports, mod, mod.exports, require.relative(path)); } return mod.exports; } require.modules = {}; require.resolve = function (path) { var orig = path , reg = path + '.js' , index = path + '/index.js'; return require.modules[reg] && reg || require.modules[index] && index || orig; }; require.register = function (path, fn) { require.modules[path] = fn; }; require.relative = function (parent) { return function(p){ if ('.' != p.charAt(0)) return require(p); var path = parent.split('/') , segs = p.split('/'); path.pop(); for (var i = 0; i < segs.length; i++) { var seg = segs[i]; if ('..' == seg) path.pop(); else if ('.' != seg) path.push(seg); } return require(path.join('/')); }; }; require.alias = function (from, to) { var fn = require.modules[from]; require.modules[to] = fn; }; require.register("chai.js", function(module, exports, require){ /*! * chai * Copyright(c) 2011-2012 Jake Luer * MIT Licensed */ var used = [] , exports = module.exports = {}; /*! * Chai version */ exports.version = '1.4.2'; /*! * Primary `Assertion` prototype */ exports.Assertion = require('./chai/assertion'); /*! * Assertion Error */ exports.AssertionError = require('./chai/error'); /*! * Utils for plugins (not exported) */ var util = require('./chai/utils'); /** * # .use(function) * * Provides a way to extend the internals of Chai * * @param {Function} * @returns {this} for chaining * @api public */ exports.use = function (fn) { if (!~used.indexOf(fn)) { fn(this, util); used.push(fn); } return this; }; /*! * Core Assertions */ var core = require('./chai/core/assertions'); exports.use(core); /*! * Expect interface */ var expect = require('./chai/interface/expect'); exports.use(expect); /*! * Should interface */ var should = require('./chai/interface/should'); exports.use(should); /*! * Assert interface */ var assert = require('./chai/interface/assert'); exports.use(assert); }); // module: chai.js require.register("chai/assertion.js", function(module, exports, require){ /*! * chai * http://chaijs.com * Copyright(c) 2011-2012 Jake Luer * MIT Licensed */ /*! * Module dependencies. */ var AssertionError = require('./error') , util = require('./utils') , flag = util.flag; /*! * Module export. */ module.exports = Assertion; /*! * Assertion Constructor * * Creates object for chaining. * * @api private */ function Assertion (obj, msg, stack) { flag(this, 'ssfi', stack || arguments.callee); flag(this, 'object', obj); flag(this, 'message', msg); } /*! * ### Assertion.includeStack * * User configurable property, influences whether stack trace * is included in Assertion error message. Default of false * suppresses stack trace in the error message * * Assertion.includeStack = true; // enable stack on error * * @api public */ Assertion.includeStack = false; Assertion.addProperty = function (name, fn) { util.addProperty(this.prototype, name, fn); }; Assertion.addMethod = function (name, fn) { util.addMethod(this.prototype, name, fn); }; Assertion.addChainableMethod = function (name, fn, chainingBehavior) { util.addChainableMethod(this.prototype, name, fn, chainingBehavior); }; Assertion.overwriteProperty = function (name, fn) { util.overwriteProperty(this.prototype, name, fn); }; Assertion.overwriteMethod = function (name, fn) { util.overwriteMethod(this.prototype, name, fn); }; /*! * ### .assert(expression, message, negateMessage, expected, actual) * * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass. * * @name assert * @param {Philosophical} expression to be tested * @param {String} message to display if fails * @param {String} negatedMessage to display if negated expression fails * @param {Mixed} expected value (remember to check for negation) * @param {Mixed} actual (optional) will default to `this.obj` * @api private */ Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) { var ok = util.test(this, arguments); if (true !== showDiff) showDiff = false; if (!ok) { var msg = util.getMessage(this, arguments) , actual = util.getActual(this, arguments); throw new AssertionError({ message: msg , actual: actual , expected: expected , stackStartFunction: (Assertion.includeStack) ? this.assert : flag(this, 'ssfi') , showDiff: showDiff }); } }; /*! * ### ._obj * * Quick reference to stored `actual` value for plugin developers. * * @api private */ Object.defineProperty(Assertion.prototype, '_obj', { get: function () { return flag(this, 'object'); } , set: function (val) { flag(this, 'object', val); } }); }); // module: chai/assertion.js require.register("chai/core/assertions.js", function(module, exports, require){ /*! * chai * http://chaijs.com * Copyright(c) 2011-2012 Jake Luer * MIT Licensed */ module.exports = function (chai, _) { var Assertion = chai.Assertion , toString = Object.prototype.toString , flag = _.flag; /** * ### Language Chains * * The following are provide as chainable getters to * improve the readability of your assertions. They * do not provide an testing capability unless they * have been overwritten by a plugin. * * **Chains** * * - to * - be * - been * - is * - that * - and * - have * - with * - at * - of * * @name language chains * @api public */ [ 'to', 'be', 'been' , 'is', 'and', 'have' , 'with', 'that', 'at' , 'of' ].forEach(function (chain) { Assertion.addProperty(chain, function () { return this; }); }); /** * ### .not * * Negates any of assertions following in the chain. * * expect(foo).to.not.equal('bar'); * expect(goodFn).to.not.throw(Error); * expect({ foo: 'baz' }).to.have.property('foo') * .and.not.equal('bar'); * * @name not * @api public */ Assertion.addProperty('not', function () { flag(this, 'negate', true); }); /** * ### .deep * * Sets the `deep` flag, later used by the `equal` and * `property` assertions. * * expect(foo).to.deep.equal({ bar: 'baz' }); * expect({ foo: { bar: { baz: 'quux' } } }) * .to.have.deep.property('foo.bar.baz', 'quux'); * * @name deep * @api public */ Assertion.addProperty('deep', function () { flag(this, 'deep', true); }); /** * ### .a(type) * * The `a` and `an` assertions are aliases that can be * used either as language chains or to assert a value's * type (as revealed by `Object.prototype.toString`). * * // typeof * expect('test').to.be.a('string'); * expect({ foo: 'bar' }).to.be.an('object'); * expect(null).to.be.a('null'); * expect(undefined).to.be.an('undefined'); * * // language chain * expect(foo).to.be.an.instanceof(Foo); * * @name a * @alias an * @param {String} type * @param {String} message _optional_ * @api public */ function an(type, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object') , klassStart = type.charAt(0).toUpperCase() , klass = klassStart + type.slice(1) , article = ~[ 'A', 'E', 'I', 'O', 'U' ].indexOf(klassStart) ? 'an ' : 'a '; this.assert( '[object ' + klass + ']' === toString.call(obj) , 'expected #{this} to be ' + article + type , 'expected #{this} not to be ' + article + type ); } Assertion.addChainableMethod('an', an); Assertion.addChainableMethod('a', an); /** * ### .include(value) * * The `include` and `contain` assertions can be used as either property * based language chains or as methods to assert the inclusion of an object * in an array or a substring in a string. When used as language chains, * they toggle the `contain` flag for the `keys` assertion. * * expect([1,2,3]).to.include(2); * expect('foobar').to.contain('foo'); * expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo'); * * @name include * @alias contain * @param {Object|String|Number} obj * @param {String} message _optional_ * @api public */ function includeChainingBehavior () { flag(this, 'contains', true); } function include (val, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object') this.assert( ~obj.indexOf(val) , 'expected #{this} to include ' + _.inspect(val) , 'expected #{this} to not include ' + _.inspect(val)); } Assertion.addChainableMethod('include', include, includeChainingBehavior); Assertion.addChainableMethod('contain', include, includeChainingBehavior); /** * ### .ok * * Asserts that the target is truthy. * * expect('everthing').to.be.ok; * expect(1).to.be.ok; * expect(false).to.not.be.ok; * expect(undefined).to.not.be.ok; * expect(null).to.not.be.ok; * * @name ok * @api public */ Assertion.addProperty('ok', function () { this.assert( flag(this, 'object') , 'expected #{this} to be truthy' , 'expected #{this} to be falsy'); }); /** * ### .true * * Asserts that the target is `true`. * * expect(true).to.be.true; * expect(1).to.not.be.true; * * @name true * @api public */ Assertion.addProperty('true', function () { this.assert( true === flag(this, 'object') , 'expected #{this} to be true' , 'expected #{this} to be false' , this.negate ? false : true ); }); /** * ### .false * * Asserts that the target is `false`. * * expect(false).to.be.false; * expect(0).to.not.be.false; * * @name false * @api public */ Assertion.addProperty('false', function () { this.assert( false === flag(this, 'object') , 'expected #{this} to be false' , 'expected #{this} to be true' , this.negate ? true : false ); }); /** * ### .null * * Asserts that the target is `null`. * * expect(null).to.be.null; * expect(undefined).not.to.be.null; * * @name null * @api public */ Assertion.addProperty('null', function () { this.assert( null === flag(this, 'object') , 'expected #{this} to be null' , 'expected #{this} not to be null' ); }); /** * ### .undefined * * Asserts that the target is `undefined`. * * expect(undefined).to.be.undefined; * expect(null).to.not.be.undefined; * * @name undefined * @api public */ Assertion.addProperty('undefined', function () { this.assert( undefined === flag(this, 'object') , 'expected #{this} to be undefined' , 'expected #{this} not to be undefined' ); }); /** * ### .exist * * Asserts that the target is neither `null` nor `undefined`. * * var foo = 'hi' * , bar = null * , baz; * * expect(foo).to.exist; * expect(bar).to.not.exist; * expect(baz).to.not.exist; * * @name exist * @api public */ Assertion.addProperty('exist', function () { this.assert( null != flag(this, 'object') , 'expected #{this} to exist' , 'expected #{this} to not exist' ); }); /** * ### .empty * * Asserts that the target's length is `0`. For arrays, it checks * the `length` property. For objects, it gets the count of * enumerable keys. * * expect([]).to.be.empty; * expect('').to.be.empty; * expect({}).to.be.empty; * * @name empty * @api public */ Assertion.addProperty('empty', function () { var obj = flag(this, 'object') , expected = obj; if (Array.isArray(obj) || 'string' === typeof object) { expected = obj.length; } else if (typeof obj === 'object') { expected = Object.keys(obj).length; } this.assert( !expected , 'expected #{this} to be empty' , 'expected #{this} not to be empty' ); }); /** * ### .arguments * * Asserts that the target is an arguments object. * * function test () { * expect(arguments).to.be.arguments; * } * * @name arguments * @alias Arguments * @api public */ function checkArguments () { var obj = flag(this, 'object') , type = Object.prototype.toString.call(obj); this.assert( '[object Arguments]' === type , 'expected #{this} to be arguments but got ' + type , 'expected #{this} to not be arguments' ); } Assertion.addProperty('arguments', checkArguments); Assertion.addProperty('Arguments', checkArguments); /** * ### .equal(value) * * Asserts that the target is strictly equal (`===`) to `value`. * Alternately, if the `deep` flag is set, asserts that * the target is deeply equal to `value`. * * expect('hello').to.equal('hello'); * expect(42).to.equal(42); * expect(1).to.not.equal(true); * expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' }); * expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' }); * * @name equal * @alias equals * @alias eq * @alias deep.equal * @param {Mixed} value * @param {String} message _optional_ * @api public */ function assertEqual (val, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); if (flag(this, 'deep')) { return this.eql(val); } else { this.assert( val === obj , 'expected #{this} to equal #{exp}' , 'expected #{this} to not equal #{exp}' , val , this._obj , true ); } } Assertion.addMethod('equal', assertEqual); Assertion.addMethod('equals', assertEqual); Assertion.addMethod('eq', assertEqual); /** * ### .eql(value) * * Asserts that the target is deeply equal to `value`. * * expect({ foo: 'bar' }).to.eql({ foo: 'bar' }); * expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]); * * @name eql * @param {Mixed} value * @param {String} message _optional_ * @api public */ Assertion.addMethod('eql', function (obj, msg) { if (msg) flag(this, 'message', msg); this.assert( _.eql(obj, flag(this, 'object')) , 'expected #{this} to deeply equal #{exp}' , 'expected #{this} to not deeply equal #{exp}' , obj , this._obj , true ); }); /** * ### .above(value) * * Asserts that the target is greater than `value`. * * expect(10).to.be.above(5); * * Can also be used in conjunction with `length` to * assert a minimum length. The benefit being a * more informative error message than if the length * was supplied directly. * * expect('foo').to.have.length.above(2); * expect([ 1, 2, 3 ]).to.have.length.above(2); * * @name above * @alias gt * @alias greaterThan * @param {Number} value * @param {String} message _optional_ * @api public */ function assertAbove (n, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); if (flag(this, 'doLength')) { new Assertion(obj, msg).to.have.property('length'); var len = obj.length; this.assert( len > n , 'expected #{this} to have a length above #{exp} but got #{act}' , 'expected #{this} to not have a length above #{exp}' , n , len ); } else { this.assert( obj > n , 'expected #{this} to be above ' + n , 'expected #{this} to be at most ' + n ); } } Assertion.addMethod('above', assertAbove); Assertion.addMethod('gt', assertAbove); Assertion.addMethod('greaterThan', assertAbove); /** * ### .least(value) * * Asserts that the target is greater than or equal to `value`. * * expect(10).to.be.at.least(10); * * Can also be used in conjunction with `length` to * assert a minimum length. The benefit being a * more informative error message than if the length * was supplied directly. * * expect('foo').to.have.length.of.at.least(2); * expect([ 1, 2, 3 ]).to.have.length.of.at.least(3); * * @name least * @alias gte * @param {Number} value * @param {String} message _optional_ * @api public */ function assertLeast (n, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); if (flag(this, 'doLength')) { new Assertion(obj, msg).to.have.property('length'); var len = obj.length; this.assert( len >= n , 'expected #{this} to have a length at least #{exp} but got #{act}' , 'expected #{this} to not have a length below #{exp}' , n , len ); } else { this.assert( obj >= n , 'expected #{this} to be at least ' + n , 'expected #{this} to be below ' + n ); } } Assertion.addMethod('least', assertLeast); Assertion.addMethod('gte', assertLeast); /** * ### .below(value) * * Asserts that the target is less than `value`. * * expect(5).to.be.below(10); * * Can also be used in conjunction with `length` to * assert a maximum length. The benefit being a * more informative error message than if the length * was supplied directly. * * expect('foo').to.have.length.below(4); * expect([ 1, 2, 3 ]).to.have.length.below(4); * * @name below * @alias lt * @alias lessThan * @param {Number} value * @param {String} message _optional_ * @api public */ function assertBelow (n, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); if (flag(this, 'doLength')) { new Assertion(obj, msg).to.have.property('length'); var len = obj.length; this.assert( len < n , 'expected #{this} to have a length below #{exp} but got #{act}' , 'expected #{this} to not have a length below #{exp}' , n , len ); } else { this.assert( obj < n , 'expected #{this} to be below ' + n , 'expected #{this} to be at least ' + n ); } } Assertion.addMethod('below', assertBelow); Assertion.addMethod('lt', assertBelow); Assertion.addMethod('lessThan', assertBelow); /** * ### .most(value) * * Asserts that the target is less than or equal to `value`. * * expect(5).to.be.at.most(5); * * Can also be used in conjunction with `length` to * assert a maximum length. The benefit being a * more informative error message than if the length * was supplied directly. * * expect('foo').to.have.length.of.at.most(4); * expect([ 1, 2, 3 ]).to.have.length.of.at.most(3); * * @name most * @alias lte * @param {Number} value * @param {String} message _optional_ * @api public */ function assertMost (n, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); if (flag(this, 'doLength')) { new Assertion(obj, msg).to.have.property('length'); var len = obj.length; this.assert( len <= n , 'expected #{this} to have a length at most #{exp} but got #{act}' , 'expected #{this} to not have a length above #{exp}' , n , len ); } else { this.assert( obj <= n , 'expected #{this} to be at most ' + n , 'expected #{this} to be above ' + n ); } } Assertion.addMethod('most', assertMost); Assertion.addMethod('lte', assertMost); /** * ### .within(start, finish) * * Asserts that the target is within a range. * * expect(7).to.be.within(5,10); * * Can also be used in conjunction with `length` to * assert a length range. The benefit being a * more informative error message than if the length * was supplied directly. * * expect('foo').to.have.length.within(2,4); * expect([ 1, 2, 3 ]).to.have.length.within(2,4); * * @name within * @param {Number} start lowerbound inclusive * @param {Number} finish upperbound inclusive * @param {String} message _optional_ * @api public */ Assertion.addMethod('within', function (start, finish, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object') , range = start + '..' + finish; if (flag(this, 'doLength')) { new Assertion(obj, msg).to.have.property('length'); var len = obj.length; this.assert( len >= start && len <= finish , 'expected #{this} to have a length within ' + range , 'expected #{this} to not have a length within ' + range ); } else { this.assert( obj >= start && obj <= finish , 'expected #{this} to be within ' + range , 'expected #{this} to not be within ' + range ); } }); /** * ### .instanceof(constructor) * * Asserts that the target is an instance of `constructor`. * * var Tea = function (name) { this.name = name; } * , Chai = new Tea('chai'); * * expect(Chai).to.be.an.instanceof(Tea); * expect([ 1, 2, 3 ]).to.be.instanceof(Array); * * @name instanceof * @param {Constructor} constructor * @param {String} message _optional_ * @alias instanceOf * @api public */ function assertInstanceOf (constructor, msg) { if (msg) flag(this, 'message', msg); var name = _.getName(constructor); this.assert( flag(this, 'object') instanceof constructor , 'expected #{this} to be an instance of ' + name , 'expected #{this} to not be an instance of ' + name ); }; Assertion.addMethod('instanceof', assertInstanceOf); Assertion.addMethod('instanceOf', assertInstanceOf); /** * ### .property(name, [value]) * * Asserts that the target has a property `name`, optionally asserting that * the value of that property is strictly equal to `value`. * If the `deep` flag is set, you can use dot- and bracket-notation for deep * references into objects and arrays. * * // simple referencing * var obj = { foo: 'bar' }; * expect(obj).to.have.property('foo'); * expect(obj).to.have.property('foo', 'bar'); * * // deep referencing * var deepObj = { * green: { tea: 'matcha' } * , teas: [ 'chai', 'matcha', { tea: 'konacha' } ] * }; * expect(deepObj).to.have.deep.property('green.tea', 'matcha'); * expect(deepObj).to.have.deep.property('teas[1]', 'matcha'); * expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha'); * * You can also use an array as the starting point of a `deep.property` * assertion, or traverse nested arrays. * * var arr = [ * [ 'chai', 'matcha', 'konacha' ] * , [ { tea: 'chai' } * , { tea: 'matcha' } * , { tea: 'konacha' } ] * ]; * * expect(arr).to.have.deep.property('[0][1]', 'matcha'); * expect(arr).to.have.deep.property('[1][2].tea', 'konacha'); * * Furthermore, `property` changes the subject of the assertion * to be the value of that property from the original object. This * permits for further chainable assertions on that property. * * expect(obj).to.have.property('foo') * .that.is.a('string'); * expect(deepObj).to.have.property('green') * .that.is.an('object') * .that.deep.equals({ tea: 'matcha' }); * expect(deepObj).to.have.property('teas') * .that.is.an('array') * .with.deep.property('[2]') * .that.deep.equals({ tea: 'konacha' }); * * @name property * @alias deep.property * @param {String} name * @param {Mixed} value (optional) * @param {String} message _optional_ * @returns value of property for chaining * @api public */ Assertion.addMethod('property', function (name, val, msg) { if (msg) flag(this, 'message', msg); var descriptor = flag(this, 'deep') ? 'deep property ' : 'property ' , negate = flag(this, 'negate') , obj = flag(this, 'object') , value = flag(this, 'deep') ? _.getPathValue(name, obj) : obj[name]; if (negate && undefined !== val) { if (undefined === value) { msg = (msg != null) ? msg + ': ' : ''; throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name)); } } else { this.assert( undefined !== value , 'expected #{this} to have a ' + descriptor + _.inspect(name) , 'expected #{this} to not have ' + descriptor + _.inspect(name)); } if (undefined !== val) { this.assert( val === value , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}' , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}' , val , value ); } flag(this, 'object', value); }); /** * ### .ownProperty(name) * * Asserts that the target has an own property `name`. * * expect('test').to.have.ownProperty('length'); * * @name ownProperty * @alias haveOwnProperty * @param {String} name * @param {String} message _optional_ * @api public */ function assertOwnProperty (name, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); this.assert( obj.hasOwnProperty(name) , 'expected #{this} to have own property ' + _.inspect(name) , 'expected #{this} to not have own property ' + _.inspect(name) ); } Assertion.addMethod('ownProperty', assertOwnProperty); Assertion.addMethod('haveOwnProperty', assertOwnProperty); /** * ### .length(value) * * Asserts that the target's `length` property has * the expected value. * * expect([ 1, 2, 3]).to.have.length(3); * expect('foobar').to.have.length(6); * * Can also be used as a chain precursor to a value * comparison for the length property. * * expect('foo').to.have.length.above(2); * expect([ 1, 2, 3 ]).to.have.length.above(2); * expect('foo').to.have.length.below(4); * expect([ 1, 2, 3 ]).to.have.length.below(4); * expect('foo').to.have.length.within(2,4); * expect([ 1, 2, 3 ]).to.have.length.within(2,4); * * @name length * @alias lengthOf * @param {Number} length * @param {String} message _optional_ * @api public */ function assertLengthChain () { flag(this, 'doLength', true); } function assertLength (n, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); new Assertion(obj, msg).to.have.property('length'); var len = obj.length; this.assert( len == n , 'expected #{this} to have a length of #{exp} but got #{act}' , 'expected #{this} to not have a length of #{act}' , n , len ); } Assertion.addChainableMethod('length', assertLength, assertLengthChain); Assertion.addMethod('lengthOf', assertLength, assertLengthChain); /** * ### .match(regexp) * * Asserts that the target matches a regular expression. * * expect('foobar').to.match(/^foo/); * * @name match * @param {RegExp} RegularExpression * @param {String} message _optional_ * @api public */ Assertion.addMethod('match', function (re, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); this.assert( re.exec(obj) , 'expected #{this} to match ' + re , 'expected #{this} not to match ' + re ); }); /** * ### .string(string) * * Asserts that the string target contains another string. * * expect('foobar').to.have.string('bar'); * * @name string * @param {String} string * @param {String} message _optional_ * @api public */ Assertion.addMethod('string', function (str, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); new Assertion(obj, msg).is.a('string'); this.assert( ~obj.indexOf(str) , 'expected #{this} to contain ' + _.inspect(str) , 'expected #{this} to not contain ' + _.inspect(str) ); }); /** * ### .keys(key1, [key2], [...]) * * Asserts that the target has exactly the given keys, or * asserts the inclusion of some keys when using the * `include` or `contain` modifiers. * * expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']); * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar'); * * @name keys * @alias key * @param {String...|Array} keys * @api public */ function assertKeys (keys) { var obj = flag(this, 'object') , str , ok = true; keys = keys instanceof Array ? keys : Array.prototype.slice.call(arguments); if (!keys.length) throw new Error('keys required'); var actual = Object.keys(obj) , len = keys.length; // Inclusion ok = keys.every(function(key){ return ~actual.indexOf(key); }); // Strict if (!flag(this, 'negate') && !flag(this, 'contains')) { ok = ok && keys.length == actual.length; } // Key string if (len > 1) { keys = keys.map(function(key){ return _.inspect(key); }); var last = keys.pop(); str = keys.join(', ') + ', and ' + last; } else { str = _.inspect(keys[0]); } // Form str = (len > 1 ? 'keys ' : 'key ') + str; // Have / include str = (flag(this, 'contains') ? 'contain ' : 'have ') + str; // Assertion this.assert( ok , 'expected #{this} to ' + str , 'expected #{this} to not ' + str ); } Assertion.addMethod('keys', assertKeys); Assertion.addMethod('key', assertKeys); /** * ### .throw(constructor) * * Asserts that the function target will throw a specific error, or specific type of error * (as determined using `instanceof`), optionally with a RegExp or string inclusion test * for the error's message. * * var err = new ReferenceError('This is a bad function.'); * var fn = function () { throw err; } * expect(fn).to.throw(ReferenceError); * expect(fn).to.throw(Error); * expect(fn).to.throw(/bad function/); * expect(fn).to.not.throw('good function'); * expect(fn).to.throw(ReferenceError, /bad function/); * expect(fn).to.throw(err); * expect(fn).to.not.throw(new RangeError('Out of range.')); * * Please note that when a throw expectation is negated, it will check each * parameter independently, starting with error constructor type. The appropriate way * to check for the existence of a type of error but for a message that does not match * is to use `and`. * * expect(fn).to.throw(ReferenceError) * .and.not.throw(/good function/); * * @name throw * @alias throws * @alias Throw * @param {ErrorConstructor} constructor * @param {String|RegExp} expected error message * @param {String} message _optional_ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types * @api public */ function assertThrows (constructor, errMsg, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); new Assertion(obj, msg).is.a('function'); var thrown = false , desiredError = null , name = null , thrownError = null; if (arguments.length === 0) { errMsg = null; constructor = null; } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) { errMsg = constructor; constructor = null; } else if (constructor && constructor instanceof Error) { desiredError = constructor; constructor = null; errMsg = null; } else if (typeof constructor === 'function') { name = (new constructor()).name; } else { constructor = null; } try { obj(); } catch (err) { // first, check desired error if (desiredError) { this.assert( err === desiredError , 'expected #{this} to throw ' + _.inspect(desiredError) + ' but ' + _.inspect(err) + ' was thrown' , 'expected #{this} to not throw ' + _.inspect(desiredError) ); return this; } // next, check constructor if (constructor) { this.assert( err instanceof constructor , 'expected #{this} to throw ' + name + ' but ' + _.inspect(err) + ' was thrown' , 'expected #{this} to not throw ' + name + ' but ' + _.inspect(err) + ' was thrown'); if (!errMsg) return this; } // next, check message if (err.message && errMsg && errMsg instanceof RegExp) { this.assert( errMsg.exec(err.message) , 'expected #{this} to throw error matching ' + errMsg + ' but got ' + _.inspect(err.message) , 'expected #{this} to throw error not matching ' + errMsg ); return this; } else if (err.message && errMsg && 'string' === typeof errMsg) { this.assert( ~err.message.indexOf(errMsg) , 'expected #{this} to throw error including #{exp} but got #{act}' , 'expected #{this} to throw error not including #{act}' , errMsg , err.message ); return this; } else { thrown = true; thrownError = err; } } var expectedThrown = name ? name : desiredError ? _.inspect(desiredError) : 'an error'; var actuallyGot = '' if (thrown) { actuallyGot = ' but ' + _.inspect(thrownError) + ' was thrown' } this.assert( thrown === true , 'expected #{this} to throw ' + expectedThrown + actuallyGot , 'expected #{this} to not throw ' + expectedThrown + actuallyGot ); }; Assertion.addMethod('throw', assertThrows); Assertion.addMethod('throws', assertThrows); Assertion.addMethod('Throw', assertThrows); /** * ### .respondTo(method) * * Asserts that the object or class target will respond to a method. * * Klass.prototype.bar = function(){}; * expect(Klass).to.respondTo('bar'); * expect(obj).to.respondTo('bar'); * * To check if a constructor will respond to a static function, * set the `itself` flag. * * Klass.baz = function(){}; * expect(Klass).itself.to.respondTo('baz'); * * @name respondTo * @param {String} method * @param {String} message _optional_ * @api public */ Assertion.addMethod('respondTo', function (method, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object') , itself = flag(this, 'itself') , context = ('function' === typeof obj && !itself) ? obj.prototype[method] : obj[method]; this.assert( 'function' === typeof context , 'expected #{this} to respond to ' + _.inspect(method) , 'expected #{this} to not respond to ' + _.inspect(method) ); }); /** * ### .itself * * Sets the `itself` flag, later used by the `respondTo` assertion. * * function Foo() {} * Foo.bar = function() {} * Foo.prototype.baz = function() {} * * expect(Foo).itself.to.respondTo('bar'); * expect(Foo).itself.not.to.respondTo('baz'); * * @name itself * @api public */ Assertion.addProperty('itself', function () { flag(this, 'itself', true); }); /** * ### .satisfy(method) * * Asserts that the target passes a given truth test. * * expect(1).to.satisfy(function(num) { return num > 0; }); * * @name satisfy * @param {Function} matcher * @param {String} message _optional_ * @api public */ Assertion.addMethod('satisfy', function (matcher, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); this.assert( matcher(obj) , 'expected #{this} to satisfy ' + _.inspect(matcher) , 'expected #{this} to not satisfy' + _.inspect(matcher) , this.negate ? false : true , matcher(obj) ); }); /** * ### .closeTo(expected, delta) * * Asserts that the target is equal `expected`, to within a +/- `delta` range. * * expect(1.5).to.be.closeTo(1, 0.5); * * @name closeTo * @param {Number} expected * @param {Number} delta * @param {String} message _optional_ * @api public */ Assertion.addMethod('closeTo', function (expected, delta, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); this.assert( Math.abs(obj - expected) <= delta , 'expected #{this} to be close to ' + expected + ' +/- ' + delta , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta ); }); }; }); // module: chai/core/assertions.js require.register("chai/error.js", function(module, exports, require){ /*! * chai * Copyright(c) 2011-2012 Jake Luer * MIT Licensed */ /*! * Main export */ module.exports = AssertionError; /** * # AssertionError (constructor) * * Create a new assertion error based on the Javascript * `Error` prototype. * * **Options** * - message * - actual * - expected * - operator * - startStackFunction * * @param {Object} options * @api public */ function AssertionError (options) { options = options || {}; this.message = options.message; this.actual = options.actual; this.expected = options.expected; this.operator = options.operator; this.showDiff = options.showDiff; if (options.stackStartFunction && Error.captureStackTrace) { var stackStartFunction = options.stackStartFunction; Error.captureStackTrace(this, stackStartFunction); } } /*! * Inherit from Error */ AssertionError.prototype = Object.create(Error.prototype); AssertionError.prototype.name = 'AssertionError'; AssertionError.prototype.constructor = AssertionError; /** * # toString() * * Override default to string method */ AssertionError.prototype.toString = function() { return this.message; }; }); // module: chai/error.js require.register("chai/interface/assert.js", function(module, exports, require){ /*! * chai * Copyright(c) 2011-2012 Jake Luer * MIT Licensed */ module.exports = function (chai, util) { /*! * Chai dependencies. */ var Assertion = chai.Assertion , flag = util.flag; /*! * Module export. */ /** * ### assert(expression, message) * * Write your own test expressions. * * assert('foo' !== 'bar', 'foo is not bar'); * assert(Array.isArray([]), 'empty arrays are arrays'); * * @param {Mixed} expression to test for truthiness * @param {String} message to display on error * @name assert * @api public */ var assert = chai.assert = function (express, errmsg) { var test = new Assertion(null); test.assert( express , errmsg , '[ negation message unavailable ]' ); }; /** * ### .fail(actual, expected, [message], [operator]) * * Throw a failure. Node.js `assert` module-compatible. * * @name fail * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @param {String} operator * @api public */ assert.fail = function (actual, expected, message, operator) { throw new chai.AssertionError({ actual: actual , expected: expected , message: message , operator: operator , stackStartFunction: assert.fail }); }; /** * ### .ok(object, [message]) * * Asserts that `object` is truthy. * * assert.ok('everything', 'everything is ok'); * assert.ok(false, 'this will fail'); * * @name ok * @param {Mixed} object to test * @param {String} message * @api public */ assert.ok = function (val, msg) { new Assertion(val, msg).is.ok; }; /** * ### .equal(actual, expected, [message]) * * Asserts non-strict equality (`==`) of `actual` and `expected`. * * assert.equal(3, '3', '== coerces values to strings'); * * @name equal * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @api public */ assert.equal = function (act, exp, msg) { var test = new Assertion(act, msg); test.assert( exp == flag(test, 'object') , 'expected #{this} to equal #{exp}' , 'expected #{this} to not equal #{act}' , exp , act ); }; /** * ### .notEqual(actual, expected, [message]) * * Asserts non-strict inequality (`!=`) of `actual` and `expected`. * * assert.notEqual(3, 4, 'these numbers are not equal'); * * @name notEqual * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @api public */ assert.notEqual = function (act, exp, msg) { var test = new Assertion(act, msg); test.assert( exp != flag(test, 'object') , 'expected #{this} to not equal #{exp}' , 'expected #{this} to equal #{act}' , exp , act ); }; /** * ### .strictEqual(actual, expected, [message]) * * Asserts strict equality (`===`) of `actual` and `expected`. * * assert.strictEqual(true, true, 'these booleans are strictly equal'); * * @name strictEqual * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @api public */ assert.strictEqual = function (act, exp, msg) { new Assertion(act, msg).to.equal(exp); }; /** * ### .notStrictEqual(actual, expected, [message]) * * Asserts strict inequality (`!==`) of `actual` and `expected`. * * assert.notStrictEqual(3, '3', 'no coercion for strict equality'); * * @name notStrictEqual * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @api public */ assert.notStrictEqual = function (act, exp, msg) { new Assertion(act, msg).to.not.equal(exp); }; /** * ### .deepEqual(actual, expected, [message]) * * Asserts that `actual` is deeply equal to `expected`. * * assert.deepEqual({ tea: 'green' }, { tea: 'green' }); * * @name deepEqual * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @api public */ assert.deepEqual = function (act, exp, msg) { new Assertion(act, msg).to.eql(exp); }; /** * ### .notDeepEqual(actual, expected, [message]) * * Assert that `actual` is not deeply equal to `expected`. * * assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' }); * * @name notDeepEqual * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @api public */ assert.notDeepEqual = function (act, exp, msg) { new Assertion(act, msg).to.not.eql(exp); }; /** * ### .isTrue(value, [message]) * * Asserts that `value` is true. * * var teaServed = true; * assert.isTrue(teaServed, 'the tea has been served'); * * @name isTrue * @param {Mixed} value * @param {String} message * @api public */ assert.isTrue = function (val, msg) { new Assertion(val, msg).is['true']; }; /** * ### .isFalse(value, [message]) * * Asserts that `value` is false. * * var teaServed = false; * assert.isFalse(teaServed, 'no tea yet? hmm...'); * * @name isFalse * @param {Mixed} value * @param {String} message * @api public */ assert.isFalse = function (val, msg) { new Assertion(val, msg).is['false']; }; /** * ### .isNull(value, [message]) * * Asserts that `value` is null. * * assert.isNull(err, 'there was no error'); * * @name isNull * @param {Mixed} value * @param {String} message * @api public */ assert.isNull = function (val, msg) { new Assertion(val, msg).to.equal(null); }; /** * ### .isNotNull(value, [message]) * * Asserts that `value` is not null. * * var tea = 'tasty chai'; * assert.isNotNull(tea, 'great, time for tea!'); * * @name isNotNull * @param {Mixed} value * @param {String} message * @api public */ assert.isNotNull = function (val, msg) { new Assertion(val, msg).to.not.equal(null); }; /** * ### .isUndefined(value, [message]) * * Asserts that `value` is `undefined`. * * var tea; * assert.isUndefined(tea, 'no tea defined'); * * @name isUndefined * @param {Mixed} value * @param {String} message * @api public */ assert.isUndefined = function (val, msg) { new Assertion(val, msg).to.equal(undefined); }; /** * ### .isDefined(value, [message]) * * Asserts that `value` is not `undefined`. * * var tea = 'cup of chai'; * assert.isDefined(tea, 'tea has been defined'); * * @name isUndefined * @param {Mixed} value * @param {String} message * @api public */ assert.isDefined = function (val, msg) { new Assertion(val, msg).to.not.equal(undefined); }; /** * ### .isFunction(value, [message]) * * Asserts that `value` is a function. * * function serveTea() { return 'cup of tea'; }; * assert.isFunction(serveTea, 'great, we can have tea now'); * * @name isFunction * @param {Mixed} value * @param {String} message * @api public */ assert.isFunction = function (val, msg) { new Assertion(val, msg).to.be.a('function'); }; /** * ### .isNotFunction(value, [message]) * * Asserts that `value` is _not_ a function. * * var serveTea = [ 'heat', 'pour', 'sip' ]; * assert.isNotFunction(serveTea, 'great, we have listed the steps'); * * @name isNotFunction * @param {Mixed} value * @param {String} message * @api public */ assert.isNotFunction = function (val, msg) { new Assertion(val, msg).to.not.be.a('function'); }; /** * ### .isObject(value, [message]) * * Asserts that `value` is an object (as revealed by * `Object.prototype.toString`). * * var selection = { name: 'Chai', serve: 'with spices' }; * assert.isObject(selection, 'tea selection is an object'); * * @name isObject * @param {Mixed} value * @param {String} message * @api public */ assert.isObject = function (val, msg) { new Assertion(val, msg).to.be.a('object'); }; /** * ### .isNotObject(value, [message]) * * Asserts that `value` is _not_ an object. * * var selection = 'chai' * assert.isObject(selection, 'tea selection is not an object'); * assert.isObject(null, 'null is not an object'); * * @name isNotObject * @param {Mixed} value * @param {String} message * @api public */ assert.isNotObject = function (val, msg) { new Assertion(val, msg).to.not.be.a('object'); }; /** * ### .isArray(value, [message]) * * Asserts that `value` is an array. * * var menu = [ 'green', 'chai', 'oolong' ]; * assert.isArray(menu, 'what kind of tea do we want?'); * * @name isArray * @param {Mixed} value * @param {String} message * @api public */ assert.isArray = function (val, msg) { new Assertion(val, msg).to.be.an('array'); }; /** * ### .isNotArray(value, [message]) * * Asserts that `value` is _not_ an array. * * var menu = 'green|chai|oolong'; * assert.isNotArray(menu, 'what kind of tea do we want?'); * * @name isNotArray * @param {Mixed} value * @param {String} message * @api public */ assert.isNotArray = function (val, msg) { new Assertion(val, msg).to.not.be.an('array'); }; /** * ### .isString(value, [message]) * * Asserts that `value` is a string. * * var teaOrder = 'chai'; * assert.isString(teaOrder, 'order placed'); * * @name isString * @param {Mixed} value * @param {String} message * @api public */ assert.isString = function (val, msg) { new Assertion(val, msg).to.be.a('string'); }; /** * ### .isNotString(value, [message]) * * Asserts that `value` is _not_ a string. * * var teaOrder = 4; * assert.isNotString(teaOrder, 'order placed'); * * @name isNotString * @param {Mixed} value * @param {String} message * @api public */ assert.isNotString = function (val, msg) { new Assertion(val, msg).to.not.be.a('string'); }; /** * ### .isNumber(value, [message]) * * Asserts that `value` is a number. * * var cups = 2; * assert.isNumber(cups, 'how many cups'); * * @name isNumber * @param {Number} value * @param {String} message * @api public */ assert.isNumber = function (val, msg) { new Assertion(val, msg).to.be.a('number'); }; /** * ### .isNotNumber(value, [message]) * * Asserts that `value` is _not_ a number. * * var cups = '2 cups please'; * assert.isNotNumber(cups, 'how many cups'); * * @name isNotNumber * @param {Mixed} value * @param {String} message * @api public */ assert.isNotNumber = function (val, msg) { new Assertion(val, msg).to.not.be.a('number'); }; /** * ### .isBoolean(value, [message]) * * Asserts that `value` is a boolean. * * var teaReady = true * , teaServed = false; * * assert.isBoolean(teaReady, 'is the tea ready'); * assert.isBoolean(teaServed, 'has tea been served'); * * @name isBoolean * @param {Mixed} value * @param {String} message * @api public */ assert.isBoolean = function (val, msg) { new Assertion(val, msg).to.be.a('boolean'); }; /** * ### .isNotBoolean(value, [message]) * * Asserts that `value` is _not_ a boolean. * * var teaReady = 'yep' * , teaServed = 'nope'; * * assert.isNotBoolean(teaReady, 'is the tea ready'); * assert.isNotBoolean(teaServed, 'has tea been served'); * * @name isNotBoolean * @param {Mixed} value * @param {String} message * @api public */ assert.isNotBoolean = function (val, msg) { new Assertion(val, msg).to.not.be.a('boolean'); }; /** * ### .typeOf(value, name, [message]) * * Asserts that `value`'s type is `name`, as determined by * `Object.prototype.toString`. * * assert.typeOf({ tea: 'chai' }, 'object', 'we have an object'); * assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array'); * assert.typeOf('tea', 'string', 'we have a string'); * assert.typeOf(/tea/, 'regexp', 'we have a regular expression'); * assert.typeOf(null, 'null', 'we have a null'); * assert.typeOf(undefined, 'undefined', 'we have an undefined'); * * @name typeOf * @param {Mixed} value * @param {String} name * @param {String} message * @api public */ assert.typeOf = function (val, type, msg) { new Assertion(val, msg).to.be.a(type); }; /** * ### .notTypeOf(value, name, [message]) * * Asserts that `value`'s type is _not_ `name`, as determined by * `Object.prototype.toString`. * * assert.notTypeOf('tea', 'number', 'strings are not numbers'); * * @name notTypeOf * @param {Mixed} value * @param {String} typeof name * @param {String} message * @api public */ assert.notTypeOf = function (val, type, msg) { new Assertion(val, msg).to.not.be.a(type); }; /** * ### .instanceOf(object, constructor, [message]) * * Asserts that `value` is an instance of `constructor`. * * var Tea = function (name) { this.name = name; } * , chai = new Tea('chai'); * * assert.instanceOf(chai, Tea, 'chai is an instance of tea'); * * @name instanceOf * @param {Object} object * @param {Constructor} constructor * @param {String} message * @api public */ assert.instanceOf = function (val, type, msg) { new Assertion(val, msg).to.be.instanceOf(type); }; /** * ### .notInstanceOf(object, constructor, [message]) * * Asserts `value` is not an instance of `constructor`. * * var Tea = function (name) { this.name = name; } * , chai = new String('chai'); * * assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea'); * * @name notInstanceOf * @param {Object} object * @param {Constructor} constructor * @param {String} message * @api public */ assert.notInstanceOf = function (val, type, msg) { new Assertion(val, msg).to.not.be.instanceOf(type); }; /** * ### .include(haystack, needle, [message]) * * Asserts that `haystack` includes `needle`. Works * for strings and arrays. * * assert.include('foobar', 'bar', 'foobar contains string "bar"'); * assert.include([ 1, 2, 3 ], 3, 'array contains value'); * * @name include * @param {Array|String} haystack * @param {Mixed} needle * @param {String} message * @api public */ assert.include = function (exp, inc, msg) { var obj = new Assertion(exp, msg); if (Array.isArray(exp)) { obj.to.include(inc); } else if ('string' === typeof exp) { obj.to.contain.string(inc); } }; /** * ### .match(value, regexp, [message]) * * Asserts that `value` matches the regular expression `regexp`. * * assert.match('foobar', /^foo/, 'regexp matches'); * * @name match * @param {Mixed} value * @param {RegExp} regexp * @param {String} message * @api public */ assert.match = function (exp, re, msg) { new Assertion(exp, msg).to.match(re); }; /** * ### .notMatch(value, regexp, [message]) * * Asserts that `value` does not match the regular expression `regexp`. * * assert.notMatch('foobar', /^foo/, 'regexp does not match'); * * @name notMatch * @param {Mixed} value * @param {RegExp} regexp * @param {String} message * @api public */ assert.notMatch = function (exp, re, msg) { new Assertion(exp, msg).to.not.match(re); }; /** * ### .property(object, property, [message]) * * Asserts that `object` has a property named by `property`. * * assert.property({ tea: { green: 'matcha' }}, 'tea'); * * @name property * @param {Object} object * @param {String} property * @param {String} message * @api public */ assert.property = function (obj, prop, msg) { new Assertion(obj, msg).to.have.property(prop); }; /** * ### .notProperty(object, property, [message]) * * Asserts that `object` does _not_ have a property named by `property`. * * assert.notProperty({ tea: { green: 'matcha' }}, 'coffee'); * * @name notProperty * @param {Object} object * @param {String} property * @param {String} message * @api public */ assert.notProperty = function (obj, prop, msg) { new Assertion(obj, msg).to.not.have.property(prop); }; /** * ### .deepProperty(object, property, [message]) * * Asserts that `object` has a property named by `property`, which can be a * string using dot- and bracket-notation for deep reference. * * assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green'); * * @name deepProperty * @param {Object} object * @param {String} property * @param {String} message * @api public */ assert.deepProperty = function (obj, prop, msg) { new Assertion(obj, msg).to.have.deep.property(prop); }; /** * ### .notDeepProperty(object, property, [message]) * * Asserts that `object` does _not_ have a property named by `property`, which * can be a string using dot- and bracket-notation for deep reference. * * assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong'); * * @name notDeepProperty * @param {Object} object * @param {String} property * @param {String} message * @api public */ assert.notDeepProperty = function (obj, prop, msg) { new Assertion(obj, msg).to.not.have.deep.property(prop); }; /** * ### .propertyVal(object, property, value, [message]) * * Asserts that `object` has a property named by `property` with value given * by `value`. * * assert.propertyVal({ tea: 'is good' }, 'tea', 'is good'); * * @name propertyVal * @param {Object} object * @param {String} property * @param {Mixed} value * @param {String} message * @api public */ assert.propertyVal = function (obj, prop, val, msg) { new Assertion(obj, msg).to.have.property(prop, val); }; /** * ### .propertyNotVal(object, property, value, [message]) * * Asserts that `object` has a property named by `property`, but with a value * different from that given by `value`. * * assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad'); * * @name propertyNotVal * @param {Object} object * @param {String} property * @param {Mixed} value * @param {String} message * @api public */ assert.propertyNotVal = function (obj, prop, val, msg) { new Assertion(obj, msg).to.not.have.property(prop, val); }; /** * ### .deepPropertyVal(object, property, value, [message]) * * Asserts that `object` has a property named by `property` with value given * by `value`. `property` can use dot- and bracket-notation for deep * reference. * * assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha'); * * @name deepPropertyVal * @param {Object} object * @param {String} property * @param {Mixed} value * @param {String} message * @api public */ assert.deepPropertyVal = function (obj, prop, val, msg) { new Assertion(obj, msg).to.have.deep.property(prop, val); }; /** * ### .deepPropertyNotVal(object, property, value, [message]) * * Asserts that `object` has a property named by `property`, but with a value * different from that given by `value`. `property` can use dot- and * bracket-notation for deep reference. * * assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha'); * * @name deepPropertyNotVal * @param {Object} object * @param {String} property * @param {Mixed} value * @param {String} message * @api public */ assert.deepPropertyNotVal = function (obj, prop, val, msg) { new Assertion(obj, msg).to.not.have.deep.property(prop, val); }; /** * ### .lengthOf(object, length, [message]) * * Asserts that `object` has a `length` property with the expected value. * * assert.lengthOf([1,2,3], 3, 'array has length of 3'); * assert.lengthOf('foobar', 5, 'string has length of 6'); * * @name lengthOf * @param {Mixed} object * @param {Number} length * @param {String} message * @api public */ assert.lengthOf = function (exp, len, msg) { new Assertion(exp, msg).to.have.length(len); }; /** * ### .throws(function, [constructor/string/regexp], [string/regexp], [message]) * * Asserts that `function` will throw an error that is an instance of * `constructor`, or alternately that it will throw an error with message * matching `regexp`. * * assert.throw(fn, 'function throws a reference error'); * assert.throw(fn, /function throws a reference error/); * assert.throw(fn, ReferenceError); * assert.throw(fn, ReferenceError, 'function throws a reference error'); * assert.throw(fn, ReferenceError, /function throws a reference error/); * * @name throws * @alias throw * @alias Throw * @param {Function} function * @param {ErrorConstructor} constructor * @param {RegExp} regexp * @param {String} message * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types * @api public */ assert.Throw = function (fn, errt, errs, msg) { if ('string' === typeof errt || errt instanceof RegExp) { errs = errt; errt = null; } new Assertion(fn, msg).to.Throw(errt, errs); }; /** * ### .doesNotThrow(function, [constructor/regexp], [message]) * * Asserts that `function` will _not_ throw an error that is an instance of * `constructor`, or alternately that it will not throw an error with message * matching `regexp`. * * assert.doesNotThrow(fn, Error, 'function does not throw'); * * @name doesNotThrow * @param {Function} function * @param {ErrorConstructor} constructor * @param {RegExp} regexp * @param {String} message * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types * @api public */ assert.doesNotThrow = function (fn, type, msg) { if ('string' === typeof type) { msg = type; type = null; } new Assertion(fn, msg).to.not.Throw(type); }; /** * ### .operator(val1, operator, val2, [message]) * * Compares two values using `operator`. * * assert.operator(1, '<', 2, 'everything is ok'); * assert.operator(1, '>', 2, 'this will fail'); * * @name operator * @param {Mixed} val1 * @param {String} operator * @param {Mixed} val2 * @param {String} message * @api public */ assert.operator = function (val, operator, val2, msg) { if (!~['==', '===', '>', '>=', '<', '<=', '!=', '!=='].indexOf(operator)) { throw new Error('Invalid operator "' + operator + '"'); } var test = new Assertion(eval(val + operator + val2), msg); test.assert( true === flag(test, 'object') , 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2) , 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) ); }; /** * ### .closeTo(actual, expected, delta, [message]) * * Asserts that the target is equal `expected`, to within a +/- `delta` range. * * assert.closeTo(1.5, 1, 0.5, 'numbers are close'); * * @name closeTo * @param {Number} actual * @param {Number} expected * @param {Number} delta * @param {String} message * @api public */ assert.closeTo = function (act, exp, delta, msg) { new Assertion(act, msg).to.be.closeTo(exp, delta); }; /*! * Undocumented / untested */ assert.ifError = function (val, msg) { new Assertion(val, msg).to.not.be.ok; }; /*! * Aliases. */ (function alias(name, as){ assert[as] = assert[name]; return alias; }) ('Throw', 'throw') ('Throw', 'throws'); }; }); // module: chai/interface/assert.js require.register("chai/interface/expect.js", function(module, exports, require){ /*! * chai * Copyright(c) 2011-2012 Jake Luer * MIT Licensed */ module.exports = function (chai, util) { chai.expect = function (val, message) { return new chai.Assertion(val, message); }; }; }); // module: chai/interface/expect.js require.register("chai/interface/should.js", function(module, exports, require){ /*! * chai * Copyright(c) 2011-2012 Jake Luer * MIT Licensed */ module.exports = function (chai, util) { var Assertion = chai.Assertion; function loadShould () { // modify Object.prototype to have `should` Object.defineProperty(Object.prototype, 'should', { set: function (value) { // See https://github.com/chaijs/chai/issues/86: this makes // `whatever.should = someValue` actually set `someValue`, which is // especially useful for `global.should = require('chai').should()`. // // Note that we have to use [[DefineProperty]] instead of [[Put]] // since otherwise we would trigger this very setter! Object.defineProperty(this, 'should', { value: value, enumerable: true, configurable: true, writable: true }); } , get: function(){ if (this instanceof String || this instanceof Number) { return new Assertion(this.constructor(this)); } else if (this instanceof Boolean) { return new Assertion(this == true); } return new Assertion(this); } , configurable: true }); var should = {}; should.equal = function (val1, val2, msg) { new Assertion(val1, msg).to.equal(val2); }; should.Throw = function (fn, errt, errs, msg) { new Assertion(fn, msg).to.Throw(errt, errs); }; should.exist = function (val, msg) { new Assertion(val, msg).to.exist; } // negation should.not = {} should.not.equal = function (val1, val2, msg) { new Assertion(val1, msg).to.not.equal(val2); }; should.not.Throw = function (fn, errt, errs, msg) { new Assertion(fn, msg).to.not.Throw(errt, errs); }; should.not.exist = function (val, msg) { new Assertion(val, msg).to.not.exist; } should['throw'] = should['Throw']; should.not['throw'] = should.not['Throw']; return should; }; chai.should = loadShould; chai.Should = loadShould; }; }); // module: chai/interface/should.js require.register("chai/utils/addChainableMethod.js", function(module, exports, require){ /*! * Chai - addChainingMethod utility * Copyright(c) 2012 Jake Luer * MIT Licensed */ /*! * Module dependencies */ var transferFlags = require('./transferFlags'); /** * ### addChainableMethod (ctx, name, method, chainingBehavior) * * Adds a method to an object, such that the method can also be chained. * * utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) { * var obj = utils.flag(this, 'object'); * new chai.Assertion(obj).to.be.equal(str); * }); * * Can also be accessed directly from `chai.Assertion`. * * chai.Assertion.addChainableMethod('foo', fn, chainingBehavior); * * The result can then be used as both a method assertion, executing both `method` and * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`. * * expect(fooStr).to.be.foo('bar'); * expect(fooStr).to.be.foo.equal('foo'); * * @param {Object} ctx object to which the method is added * @param {String} name of method to add * @param {Function} method function to be used for `name`, when called * @param {Function} chainingBehavior function to be called every time the property is accessed * @name addChainableMethod * @api public */ module.exports = function (ctx, name, method, chainingBehavior) { if (typeof chainingBehavior !== 'function') chainingBehavior = function () { }; Object.defineProperty(ctx, name, { get: function () { chainingBehavior.call(this); var assert = function () { var result = method.apply(this, arguments); return result === undefined ? this : result; }; // Re-enumerate every time to better accomodate plugins. var asserterNames = Object.getOwnPropertyNames(ctx); asserterNames.forEach(function (asserterName) { var pd = Object.getOwnPropertyDescriptor(ctx, asserterName) , functionProtoPD = Object.getOwnPropertyDescriptor(Function.prototype, asserterName); // Avoid trying to overwrite things that we can't, like `length` and `arguments`. if (functionProtoPD && !functionProtoPD.configurable) return; if (asserterName === 'arguments') return; // @see chaijs/chai/issues/69 Object.defineProperty(assert, asserterName, pd); }); transferFlags(this, assert); return assert; } , configurable: true }); }; }); // module: chai/utils/addChainableMethod.js require.register("chai/utils/addMethod.js", function(module, exports, require){ /*! * Chai - addMethod utility * Copyright(c) 2012 Jake Luer * MIT Licensed */ /** * ### .addMethod (ctx, name, method) * * Adds a method to the prototype of an object. * * utils.addMethod(chai.Assertion.prototype, 'foo', function (str) { * var obj = utils.flag(this, 'object'); * new chai.Assertion(obj).to.be.equal(str); * }); * * Can also be accessed directly from `chai.Assertion`. * * chai.Assertion.addMethod('foo', fn); * * Then can be used as any other assertion. * * expect(fooStr).to.be.foo('bar'); * * @param {Object} ctx object to which the method is added * @param {String} name of method to add * @param {Function} method function to be used for name * @name addMethod * @api public */ module.exports = function (ctx, name, method) { ctx[name] = function () { var result = method.apply(this, arguments); return result === undefined ? this : result; }; }; }); // module: chai/utils/addMethod.js require.register("chai/utils/addProperty.js", function(module, exports, require){ /*! * Chai - addProperty utility * Copyright(c) 2012 Jake Luer * MIT Licensed */ /** * ### addProperty (ctx, name, getter) * * Adds a property to the prototype of an object. * * utils.addProperty(chai.Assertion.prototype, 'foo', function () { * var obj = utils.flag(this, 'object'); * new chai.Assertion(obj).to.be.instanceof(Foo); * }); * * Can also be accessed directly from `chai.Assertion`. * * chai.Assertion.addProperty('foo', fn); * * Then can be used as any other assertion. * * expect(myFoo).to.be.foo; * * @param {Object} ctx object to which the property is added * @param {String} name of property to add * @param {Function} getter function to be used for name * @name addProperty * @api public */ module.exports = function (ctx, name, getter) { Object.defineProperty(ctx, name, { get: function () { var result = getter.call(this); return result === undefined ? this : result; } , configurable: true }); }; }); // module: chai/utils/addProperty.js require.register("chai/utils/eql.js", function(module, exports, require){ // This is (almost) directly from Node.js assert // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/assert.js module.exports = _deepEqual; // for the browser var Buffer; try { Buffer = require('buffer').Buffer; } catch (ex) { Buffer = { isBuffer: function () { return false; } }; } function _deepEqual(actual, expected, memos) { // 7.1. All identical values are equivalent, as determined by ===. if (actual === expected) { return true; } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) { if (actual.length != expected.length) return false; for (var i = 0; i < actual.length; i++) { if (actual[i] !== expected[i]) return false; } return true; // 7.2. If the expected value is a Date object, the actual value is // equivalent if it is also a Date object that refers to the same time. } else if (actual instanceof Date && expected instanceof Date) { return actual.getTime() === expected.getTime(); // 7.3. Other pairs that do not both pass typeof value == 'object', // equivalence is determined by ==. } else if (typeof actual != 'object' && typeof expected != 'object') { return actual === expected; // 7.4. For all other Object pairs, including Array objects, equivalence is // determined by having the same number of owned properties (as verified // with Object.prototype.hasOwnProperty.call), the same set of keys // (although not necessarily the same order), equivalent values for every // corresponding key, and an identical 'prototype' property. Note: this // accounts for both named and indexed properties on Arrays. } else { return objEquiv(actual, expected, memos); } } function isUndefinedOrNull(value) { return value === null || value === undefined; } function isArguments(object) { return Object.prototype.toString.call(object) == '[object Arguments]'; } function objEquiv(a, b, memos) { if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) return false; // an identical 'prototype' property. if (a.prototype !== b.prototype) return false; // check if we have already compared a and b var i; if (memos) { for(i = 0; i < memos.length; i++) { if ((memos[i][0] === a && memos[i][1] === b) || (memos[i][0] === b && memos[i][1] === a)) return true; } } else { memos = []; } //~~~I've managed to break Object.keys through screwy arguments passing. // Converting to array solves the problem. if (isArguments(a)) { if (!isArguments(b)) { return false; } a = pSlice.call(a); b = pSlice.call(b); return _deepEqual(a, b, memos); } try { var ka = Object.keys(a), kb = Object.keys(b), key; } catch (e) {//happens when one is a string literal and the other isn't return false; } // having the same number of owned properties (keys incorporates // hasOwnProperty) if (ka.length != kb.length) return false; //the same set of keys (although not necessarily the same order), ka.sort(); kb.sort(); //~~~cheap key test for (i = ka.length - 1; i >= 0; i--) { if (ka[i] != kb[i]) return false; } // remember objects we have compared to guard against circular references memos.push([ a, b ]); //equivalent values for every corresponding key, and //~~~possibly expensive deep test for (i = ka.length - 1; i >= 0; i--) { key = ka[i]; if (!_deepEqual(a[key], b[key], memos)) return false; } return true; } }); // module: chai/utils/eql.js require.register("chai/utils/flag.js", function(module, exports, require){ /*! * Chai - flag utility * Copyright(c) 2012 Jake Luer * MIT Licensed */ /** * ### flag(object ,key, [value]) * * Get or set a flag value on an object. If a * value is provided it will be set, else it will * return the currently set value or `undefined` if * the value is not set. * * utils.flag(this, 'foo', 'bar'); // setter * utils.flag(this, 'foo'); // getter, returns `bar` * * @param {Object} object (constructed Assertion * @param {String} key * @param {Mixed} value (optional) * @name flag * @api private */ module.exports = function (obj, key, value) { var flags = obj.__flags || (obj.__flags = Object.create(null)); if (arguments.length === 3) { flags[key] = value; } else { return flags[key]; } }; }); // module: chai/utils/flag.js require.register("chai/utils/getActual.js", function(module, exports, require){ /*! * Chai - getActual utility * Copyright(c) 2012 Jake Luer * MIT Licensed */ /** * # getActual(object, [actual]) * * Returns the `actual` value for an Assertion * * @param {Object} object (constructed Assertion) * @param {Arguments} chai.Assertion.prototype.assert arguments */ module.exports = function (obj, args) { var actual = args[4]; return 'undefined' !== typeof actual ? actual : obj._obj; }; }); // module: chai/utils/getActual.js require.register("chai/utils/getMessage.js", function(module, exports, require){ /*! * Chai - message composition utility * Copyright(c) 2012 Jake Luer * MIT Licensed */ /*! * Module dependancies */ var flag = require('./flag') , getActual = require('./getActual') , inspect = require('./inspect') , objDisplay = require('./objDisplay'); /** * ### .getMessage(object, message, negateMessage) * * Construct the error message based on flags * and template tags. Template tags will return * a stringified inspection of the object referenced. * * Messsage template tags: * - `#{this}` current asserted object * - `#{act}` actual value * - `#{exp}` expected value * * @param {Object} object (constructed Assertion) * @param {Arguments} chai.Assertion.prototype.assert arguments * @name getMessage * @api public */ module.exports = function (obj, args) { var negate = flag(obj, 'negate') , val = flag(obj, 'object') , expected = args[3] , actual = getActual(obj, args) , msg = negate ? args[2] : args[1] , flagMsg = flag(obj, 'message'); msg = msg || ''; msg = msg .replace(/#{this}/g, objDisplay(val)) .replace(/#{act}/g, objDisplay(actual)) .replace(/#{exp}/g, objDisplay(expected)); return flagMsg ? flagMsg + ': ' + msg : msg; }; }); // module: chai/utils/getMessage.js require.register("chai/utils/getName.js", function(module, exports, require){ /*! * Chai - getName utility * Copyright(c) 2012 Jake Luer * MIT Licensed */ /** * # getName(func) * * Gets the name of a function, in a cross-browser way. * * @param {Function} a function (usually a constructor) */ module.exports = function (func) { if (func.name) return func.name; var match = /^\s?function ([^(]*)\(/.exec(func); return match && match[1] ? match[1] : ""; }; }); // module: chai/utils/getName.js require.register("chai/utils/getPathValue.js", function(module, exports, require){ /*! * Chai - getPathValue utility * Copyright(c) 2012 Jake Luer * @see https://github.com/logicalparadox/filtr * MIT Licensed */ /** * ### .getPathValue(path, object) * * This allows the retrieval of values in an * object given a string path. * * var obj = { * prop1: { * arr: ['a', 'b', 'c'] * , str: 'Hello' * } * , prop2: { * arr: [ { nested: 'Universe' } ] * , str: 'Hello again!' * } * } * * The following would be the results. * * getPathValue('prop1.str', obj); // Hello * getPathValue('prop1.att[2]', obj); // b * getPathValue('prop2.arr[0].nested', obj); // Universe * * @param {String} path * @param {Object} object * @returns {Object} value or `undefined` * @name getPathValue * @api public */ var getPathValue = module.exports = function (path, obj) { var parsed = parsePath(path); return _getPathValue(parsed, obj); }; /*! * ## parsePath(path) * * Helper function used to parse string object * paths. Use in conjunction with `_getPathValue`. * * var parsed = parsePath('myobject.property.subprop'); * * ### Paths: * * * Can be as near infinitely deep and nested * * Arrays are also valid using the formal `myobject.document[3].property`. * * @param {String} path * @returns {Object} parsed * @api private */ function parsePath (path) { var str = path.replace(/\[/g, '.[') , parts = str.match(/(\\\.|[^.]+?)+/g); return parts.map(function (value) { var re = /\[(\d+)\]$/ , mArr = re.exec(value) if (mArr) return { i: parseFloat(mArr[1]) }; else return { p: value }; }); }; /*! * ## _getPathValue(parsed, obj) * * Helper companion function for `.parsePath` that returns * the value located at the parsed address. * * var value = getPathValue(parsed, obj); * * @param {Object} parsed definition from `parsePath`. * @param {Object} object to search against * @returns {Object|Undefined} value * @api private */ function _getPathValue (parsed, obj) { var tmp = obj , res; for (var i = 0, l = parsed.length; i < l; i++) { var part = parsed[i]; if (tmp) { if ('undefined' !== typeof part.p) tmp = tmp[part.p]; else if ('undefined' !== typeof part.i) tmp = tmp[part.i]; if (i == (l - 1)) res = tmp; } else { res = undefined; } } return res; }; }); // module: chai/utils/getPathValue.js require.register("chai/utils/index.js", function(module, exports, require){ /*! * chai * Copyright(c) 2011 Jake Luer * MIT Licensed */ /*! * Main exports */ var exports = module.exports = {}; /*! * test utility */ exports.test = require('./test'); /*! * message utility */ exports.getMessage = require('./getMessage'); /*! * actual utility */ exports.getActual = require('./getActual'); /*! * Inspect util */ exports.inspect = require('./inspect'); /*! * Object Display util */ exports.objDisplay = require('./objDisplay'); /*! * Flag utility */ exports.flag = require('./flag'); /*! * Flag transferring utility */ exports.transferFlags = require('./transferFlags'); /*! * Deep equal utility */ exports.eql = require('./eql'); /*! * Deep path value */ exports.getPathValue = require('./getPathValue'); /*! * Function name */ exports.getName = require('./getName'); /*! * add Property */ exports.addProperty = require('./addProperty'); /*! * add Method */ exports.addMethod = require('./addMethod'); /*! * overwrite Property */ exports.overwriteProperty = require('./overwriteProperty'); /*! * overwrite Method */ exports.overwriteMethod = require('./overwriteMethod'); /*! * Add a chainable method */ exports.addChainableMethod = require('./addChainableMethod'); }); // module: chai/utils/index.js require.register("chai/utils/inspect.js", function(module, exports, require){ // This is (almost) directly from Node.js utils // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js var getName = require('./getName'); module.exports = inspect; /** * Echos the value of a value. Trys to print the value out * in the best way possible given the different types. * * @param {Object} obj The object to print out. * @param {Boolean} showHidden Flag that shows hidden (not enumerable) * properties of objects. * @param {Number} depth Depth in which to descend in object. Default is 2. * @param {Boolean} colors Flag to turn on ANSI escape codes to color the * output. Default is false (no coloring). */ function inspect(obj, showHidden, depth, colors) { var ctx = { showHidden: showHidden, seen: [], stylize: function (str) { return str; } }; return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth)); } // https://gist.github.com/1044128/ var getOuterHTML = function(element) { if ('outerHTML' in element) return element.outerHTML; var ns = "http://www.w3.org/1999/xhtml"; var container = document.createElementNS(ns, '_'); var elemProto = (window.HTMLElement || window.Element).prototype; var xmlSerializer = new XMLSerializer(); var html; if (document.xmlVersion) { return xmlSerializer.serializeToString(element); } else { container.appendChild(element.cloneNode(false)); html = container.innerHTML.replace('><', '>' + element.innerHTML + '<'); container.innerHTML = ''; return html; } }; // Returns true if object is a DOM element. var isDOMElement = function (object) { if (typeof HTMLElement === 'object') { return object instanceof HTMLElement; } else { return object && typeof object === 'object' && object.nodeType === 1 && typeof object.nodeName === 'string'; } }; function formatValue(ctx, value, recurseTimes) { // Provide a hook for user-specified inspect functions. // Check that value is an object with an inspect function on it if (value && typeof value.inspect === 'function' && // Filter out the util module, it's inspect function is special value.inspect !== exports.inspect && // Also filter out any prototype objects using the circular check. !(value.constructor && value.constructor.prototype === value)) { return value.inspect(recurseTimes); } // Primitive types cannot have properties var primitive = formatPrimitive(ctx, value); if (primitive) { return primitive; } // If it's DOM elem, get outer HTML. if (isDOMElement(value)) { return getOuterHTML(value); } // Look up the keys of the object. var visibleKeys = Object.keys(value); var keys = ctx.showHidden ? Object.getOwnPropertyNames(value) : visibleKeys; // Some type of object without properties can be shortcutted. // In IE, errors have a single `stack` property, or if they are vanilla `Error`, // a `stack` plus `description` property; ignore those for consistency. if (keys.length === 0 || (isError(value) && ( (keys.length === 1 && keys[0] === 'stack') || (keys.length === 2 && keys[0] === 'description' && keys[1] === 'stack') ))) { if (typeof value === 'function') { var name = getName(value); var nameSuffix = name ? ': ' + name : ''; return ctx.stylize('[Function' + nameSuffix + ']', 'special'); } if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } if (isDate(value)) { return ctx.stylize(Date.prototype.toUTCString.call(value), 'date'); } if (isError(value)) { return formatError(value); } } var base = '', array = false, braces = ['{', '}']; // Make Array say that they are Array if (isArray(value)) { array = true; braces = ['[', ']']; } // Make functions say that they are functions if (typeof value === 'function') { var name = getName(value); var nameSuffix = name ? ': ' + name : ''; base = ' [Function' + nameSuffix + ']'; } // Make RegExps say that they are RegExps if (isRegExp(value)) { base = ' ' + RegExp.prototype.toString.call(value); } // Make dates with properties first say the date if (isDate(value)) { base = ' ' + Date.prototype.toUTCString.call(value); } // Make error with message first say the error if (isError(value)) { return formatError(value); } if (keys.length === 0 && (!array || value.length == 0)) { return braces[0] + base + braces[1]; } if (recurseTimes < 0) { if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } else { return ctx.stylize('[Object]', 'special'); } } ctx.seen.push(value); var output; if (array) { output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); } else { output = keys.map(function(key) { return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); }); } ctx.seen.pop(); return reduceToSingleString(output, base, braces); } function formatPrimitive(ctx, value) { switch (typeof value) { case 'undefined': return ctx.stylize('undefined', 'undefined'); case 'string': var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') .replace(/'/g, "\\'") .replace(/\\"/g, '"') + '\''; return ctx.stylize(simple, 'string'); case 'number': return ctx.stylize('' + value, 'number'); case 'boolean': return ctx.stylize('' + value, 'boolean'); } // For some reason typeof null is "object", so special case here. if (value === null) { return ctx.stylize('null', 'null'); } } function formatError(value) { return '[' + Error.prototype.toString.call(value) + ']'; } function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { var output = []; for (var i = 0, l = value.length; i < l; ++i) { if (Object.prototype.hasOwnProperty.call(value, String(i))) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, String(i), true)); } else { output.push(''); } } keys.forEach(function(key) { if (!key.match(/^\d+$/)) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, key, true)); } }); return output; } function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { var name, str; if (value.__lookupGetter__) { if (value.__lookupGetter__(key)) { if (value.__lookupSetter__(key)) { str = ctx.stylize('[Getter/Setter]', 'special'); } else { str = ctx.stylize('[Getter]', 'special'); } } else { if (value.__lookupSetter__(key)) { str = ctx.stylize('[Setter]', 'special'); } } } if (visibleKeys.indexOf(key) < 0) { name = '[' + key + ']'; } if (!str) { if (ctx.seen.indexOf(value[key]) < 0) { if (recurseTimes === null) { str = formatValue(ctx, value[key], null); } else { str = formatValue(ctx, value[key], recurseTimes - 1); } if (str.indexOf('\n') > -1) { if (array) { str = str.split('\n').map(function(line) { return ' ' + line; }).join('\n').substr(2); } else { str = '\n' + str.split('\n').map(function(line) { return ' ' + line; }).join('\n'); } } } else { str = ctx.stylize('[Circular]', 'special'); } } if (typeof name === 'undefined') { if (array && key.match(/^\d+$/)) { return str; } name = JSON.stringify('' + key); if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { name = name.substr(1, name.length - 2); name = ctx.stylize(name, 'name'); } else { name = name.replace(/'/g, "\\'") .replace(/\\"/g, '"') .replace(/(^"|"$)/g, "'"); name = ctx.stylize(name, 'string'); } } return name + ': ' + str; } function reduceToSingleString(output, base, braces) { var numLinesEst = 0; var length = output.reduce(function(prev, cur) { numLinesEst++; if (cur.indexOf('\n') >= 0) numLinesEst++; return prev + cur.length + 1; }, 0); if (length > 60) { return braces[0] + (base === '' ? '' : base + '\n ') + ' ' + output.join(',\n ') + ' ' + braces[1]; } return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; } function isArray(ar) { return Array.isArray(ar) || (typeof ar === 'object' && objectToString(ar) === '[object Array]'); } function isRegExp(re) { return typeof re === 'object' && objectToString(re) === '[object RegExp]'; } function isDate(d) { return typeof d === 'object' && objectToString(d) === '[object Date]'; } function isError(e) { return typeof e === 'object' && objectToString(e) === '[object Error]'; } function objectToString(o) { return Object.prototype.toString.call(o); } }); // module: chai/utils/inspect.js require.register("chai/utils/objDisplay.js", function(module, exports, require){ /*! * Chai - flag utility * Copyright(c) 2012 Jake Luer * MIT Licensed */ /*! * Module dependancies */ var inspect = require('./inspect'); /** * ### .objDisplay (object) * * Determines if an object or an array matches * criteria to be inspected in-line for error * messages or should be truncated. * * @param {Mixed} javascript object to inspect * @name objDisplay * @api public */ module.exports = function (obj) { var str = inspect(obj) , type = Object.prototype.toString.call(obj); if (str.length >= 40) { if (type === '[object Array]') { return '[ Array(' + obj.length + ') ]'; } else if (type === '[object Object]') { var keys = Object.keys(obj) , kstr = keys.length > 2 ? keys.splice(0, 2).join(', ') + ', ...' : keys.join(', '); return '{ Object (' + kstr + ') }'; } else { return str; } } else { return str; } }; }); // module: chai/utils/objDisplay.js require.register("chai/utils/overwriteMethod.js", function(module, exports, require){ /*! * Chai - overwriteMethod utility * Copyright(c) 2012 Jake Luer * MIT Licensed */ /** * ### overwriteMethod (ctx, name, fn) * * Overwites an already existing method and provides * access to previous function. Must return function * to be used for name. * * utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) { * return function (str) { * var obj = utils.flag(this, 'object'); * if (obj instanceof Foo) { * new chai.Assertion(obj.value).to.equal(str); * } else { * _super.apply(this, arguments); * } * } * }); * * Can also be accessed directly from `chai.Assertion`. * * chai.Assertion.overwriteMethod('foo', fn); * * Then can be used as any other assertion. * * expect(myFoo).to.equal('bar'); * * @param {Object} ctx object whose method is to be overwritten * @param {String} name of method to overwrite * @param {Function} method function that returns a function to be used for name * @name overwriteMethod * @api public */ module.exports = function (ctx, name, method) { var _method = ctx[name] , _super = function () { return this; }; if (_method && 'function' === typeof _method) _super = _method; ctx[name] = function () { var result = method(_super).apply(this, arguments); return result === undefined ? this : result; } }; }); // module: chai/utils/overwriteMethod.js require.register("chai/utils/overwriteProperty.js", function(module, exports, require){ /*! * Chai - overwriteProperty utility * Copyright(c) 2012 Jake Luer * MIT Licensed */ /** * ### overwriteProperty (ctx, name, fn) * * Overwites an already existing property getter and provides * access to previous value. Must return function to use as getter. * * utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) { * return function () { * var obj = utils.flag(this, 'object'); * if (obj instanceof Foo) { * new chai.Assertion(obj.name).to.equal('bar'); * } else { * _super.call(this); * } * } * }); * * * Can also be accessed directly from `chai.Assertion`. * * chai.Assertion.overwriteProperty('foo', fn); * * Then can be used as any other assertion. * * expect(myFoo).to.be.ok; * * @param {Object} ctx object whose property is to be overwritten * @param {String} name of property to overwrite * @param {Function} getter function that returns a getter function to be used for name * @name overwriteProperty * @api public */ module.exports = function (ctx, name, getter) { var _get = Object.getOwnPropertyDescriptor(ctx, name) , _super = function () {}; if (_get && 'function' === typeof _get.get) _super = _get.get Object.defineProperty(ctx, name, { get: function () { var result = getter(_super).call(this); return result === undefined ? this : result; } , configurable: true }); }; }); // module: chai/utils/overwriteProperty.js require.register("chai/utils/test.js", function(module, exports, require){ /*! * Chai - test utility * Copyright(c) 2012 Jake Luer * MIT Licensed */ /*! * Module dependancies */ var flag = require('./flag'); /** * # test(object, expression) * * Test and object for expression. * * @param {Object} object (constructed Assertion) * @param {Arguments} chai.Assertion.prototype.assert arguments */ module.exports = function (obj, args) { var negate = flag(obj, 'negate') , expr = args[0]; return negate ? !expr : expr; }; }); // module: chai/utils/test.js require.register("chai/utils/transferFlags.js", function(module, exports, require){ /*! * Chai - transferFlags utility * Copyright(c) 2012 Jake Luer * MIT Licensed */ /** * ### transferFlags(assertion, object, includeAll = true) * * Transfer all the flags for `assertion` to `object`. If * `includeAll` is set to `false`, then the base Chai * assertion flags (namely `object`, `ssfi`, and `message`) * will not be transferred. * * * var newAssertion = new Assertion(); * utils.transferFlags(assertion, newAssertion); * * var anotherAsseriton = new Assertion(myObj); * utils.transferFlags(assertion, anotherAssertion, false); * * @param {Assertion} assertion the assertion to transfer the flags from * @param {Object} object the object to transfer the flags too; usually a new assertion * @param {Boolean} includeAll * @name getAllFlags * @api private */ module.exports = function (assertion, object, includeAll) { var flags = assertion.__flags || (assertion.__flags = Object.create(null)); if (!object.__flags) { object.__flags = Object.create(null); } includeAll = arguments.length === 3 ? includeAll : true; for (var flag in flags) { if (includeAll || (flag !== 'object' && flag !== 'ssfi' && flag != 'message')) { object.__flags[flag] = flags[flag]; } } }; }); // module: chai/utils/transferFlags.js require.alias("./chai.js", "chai"); return require('chai'); }); ================================================ FILE: test/lib/expect.js ================================================ /*! * chai * Copyright(c) 2011-2012 Jake Luer * MIT Licensed */ module.exports = function (chai, util) { chai.expect = function (val, message) { return new chai.Assertion(val, message); }; }; ================================================ FILE: test/lib/mocha/mocha.css ================================================ @charset "utf-8"; body { font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; padding: 60px 50px; } #mocha ul, #mocha li { margin: 0; padding: 0; } #mocha ul { list-style: none; } #mocha h1, #mocha h2 { margin: 0; } #mocha h1 { margin-top: 15px; font-size: 1em; font-weight: 200; } #mocha h1 a { text-decoration: none; color: inherit; } #mocha h1 a:hover { text-decoration: underline; } #mocha .suite .suite h1 { margin-top: 0; font-size: .8em; } .hidden { display: none; } #mocha h2 { font-size: 12px; font-weight: normal; cursor: pointer; } #mocha .suite { margin-left: 15px; } #mocha .test { margin-left: 15px; overflow: hidden; } #mocha .test.pending:hover h2::after { content: '(pending)'; font-family: arial; } #mocha .test.pass.medium .duration { background: #C09853; } #mocha .test.pass.slow .duration { background: #B94A48; } #mocha .test.pass::before { content: '✓'; font-size: 12px; display: block; float: left; margin-right: 5px; color: #00d6b2; } #mocha .test.pass .duration { font-size: 9px; margin-left: 5px; padding: 2px 5px; color: white; -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); box-shadow: inset 0 1px 1px rgba(0,0,0,.2); -webkit-border-radius: 5px; -moz-border-radius: 5px; -ms-border-radius: 5px; -o-border-radius: 5px; border-radius: 5px; } #mocha .test.pass.fast .duration { display: none; } #mocha .test.pending { color: #0b97c4; } #mocha .test.pending::before { content: '◦'; color: #0b97c4; } #mocha .test.fail { color: #c00; } #mocha .test.fail pre { color: black; } #mocha .test.fail::before { content: '✖'; font-size: 12px; display: block; float: left; margin-right: 5px; color: #c00; } #mocha .test pre.error { color: #c00; max-height: 300px; overflow: auto; } #mocha .test pre { display: block; float: left; clear: left; font: 12px/1.5 monaco, monospace; margin: 5px; padding: 15px; border: 1px solid #eee; border-bottom-color: #ddd; -webkit-border-radius: 3px; -webkit-box-shadow: 0 1px 3px #eee; -moz-border-radius: 3px; -moz-box-shadow: 0 1px 3px #eee; } #mocha .test h2 { position: relative; } #mocha .test a.replay { position: absolute; top: 3px; right: 0; text-decoration: none; vertical-align: middle; display: block; width: 15px; height: 15px; line-height: 15px; text-align: center; background: #eee; font-size: 15px; -moz-border-radius: 15px; border-radius: 15px; -webkit-transition: opacity 200ms; -moz-transition: opacity 200ms; transition: opacity 200ms; opacity: 0.3; color: #888; } #mocha .test:hover a.replay { opacity: 1; } #mocha-report.pass .test.fail { display: none; } #mocha-report.fail .test.pass { display: none; } #mocha-error { color: #c00; font-size: 1.5 em; font-weight: 100; letter-spacing: 1px; } #mocha-stats { position: fixed; top: 15px; right: 10px; font-size: 12px; margin: 0; color: #888; } #mocha-stats .progress { float: right; padding-top: 0; } #mocha-stats em { color: black; } #mocha-stats a { text-decoration: none; color: inherit; } #mocha-stats a:hover { border-bottom: 1px solid #eee; } #mocha-stats li { display: inline-block; margin: 0 5px; list-style: none; padding-top: 11px; } code .comment { color: #ddd } code .init { color: #2F6FAD } code .string { color: #5890AD } code .keyword { color: #8A6343 } code .number { color: #2F6FAD } ================================================ FILE: test/lib/mocha/mocha.js ================================================ ;(function(){ // CommonJS require() function require(p){ var path = require.resolve(p) , mod = require.modules[path]; if (!mod) throw new Error('failed to require "' + p + '"'); if (!mod.exports) { mod.exports = {}; mod.call(mod.exports, mod, mod.exports, require.relative(path)); } return mod.exports; } require.modules = {}; require.resolve = function (path){ var orig = path , reg = path + '.js' , index = path + '/index.js'; return require.modules[reg] && reg || require.modules[index] && index || orig; }; require.register = function (path, fn){ require.modules[path] = fn; }; require.relative = function (parent) { return function(p){ if ('.' != p.charAt(0)) return require(p); var path = parent.split('/') , segs = p.split('/'); path.pop(); for (var i = 0; i < segs.length; i++) { var seg = segs[i]; if ('..' == seg) path.pop(); else if ('.' != seg) path.push(seg); } return require(path.join('/')); }; }; require.register("browser/debug.js", function(module, exports, require){ module.exports = function(type){ return function(){ } }; }); // module: browser/debug.js require.register("browser/diff.js", function(module, exports, require){ /* See license.txt for terms of usage */ /* * Text diff implementation. * * This library supports the following APIS: * JsDiff.diffChars: Character by character diff * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace * JsDiff.diffLines: Line based diff * * JsDiff.diffCss: Diff targeted at CSS content * * These methods are based on the implementation proposed in * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986). * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927 */ var JsDiff = (function() { function clonePath(path) { return { newPos: path.newPos, components: path.components.slice(0) }; } function removeEmpty(array) { var ret = []; for (var i = 0; i < array.length; i++) { if (array[i]) { ret.push(array[i]); } } return ret; } function escapeHTML(s) { var n = s; n = n.replace(/&/g, "&"); n = n.replace(//g, ">"); n = n.replace(/"/g, """); return n; } var fbDiff = function(ignoreWhitespace) { this.ignoreWhitespace = ignoreWhitespace; }; fbDiff.prototype = { diff: function(oldString, newString) { // Handle the identity case (this is due to unrolling editLength == 0 if (newString == oldString) { return [{ value: newString }]; } if (!newString) { return [{ value: oldString, removed: true }]; } if (!oldString) { return [{ value: newString, added: true }]; } newString = this.tokenize(newString); oldString = this.tokenize(oldString); var newLen = newString.length, oldLen = oldString.length; var maxEditLength = newLen + oldLen; var bestPath = [{ newPos: -1, components: [] }]; // Seed editLength = 0 var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0); if (bestPath[0].newPos+1 >= newLen && oldPos+1 >= oldLen) { return bestPath[0].components; } for (var editLength = 1; editLength <= maxEditLength; editLength++) { for (var diagonalPath = -1*editLength; diagonalPath <= editLength; diagonalPath+=2) { var basePath; var addPath = bestPath[diagonalPath-1], removePath = bestPath[diagonalPath+1]; oldPos = (removePath ? removePath.newPos : 0) - diagonalPath; if (addPath) { // No one else is going to attempt to use this value, clear it bestPath[diagonalPath-1] = undefined; } var canAdd = addPath && addPath.newPos+1 < newLen; var canRemove = removePath && 0 <= oldPos && oldPos < oldLen; if (!canAdd && !canRemove) { bestPath[diagonalPath] = undefined; continue; } // Select the diagonal that we want to branch from. We select the prior // path whose position in the new string is the farthest from the origin // and does not pass the bounds of the diff graph if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) { basePath = clonePath(removePath); this.pushComponent(basePath.components, oldString[oldPos], undefined, true); } else { basePath = clonePath(addPath); basePath.newPos++; this.pushComponent(basePath.components, newString[basePath.newPos], true, undefined); } var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath); if (basePath.newPos+1 >= newLen && oldPos+1 >= oldLen) { return basePath.components; } else { bestPath[diagonalPath] = basePath; } } } }, pushComponent: function(components, value, added, removed) { var last = components[components.length-1]; if (last && last.added === added && last.removed === removed) { // We need to clone here as the component clone operation is just // as shallow array clone components[components.length-1] = {value: this.join(last.value, value), added: added, removed: removed }; } else { components.push({value: value, added: added, removed: removed }); } }, extractCommon: function(basePath, newString, oldString, diagonalPath) { var newLen = newString.length, oldLen = oldString.length, newPos = basePath.newPos, oldPos = newPos - diagonalPath; while (newPos+1 < newLen && oldPos+1 < oldLen && this.equals(newString[newPos+1], oldString[oldPos+1])) { newPos++; oldPos++; this.pushComponent(basePath.components, newString[newPos], undefined, undefined); } basePath.newPos = newPos; return oldPos; }, equals: function(left, right) { var reWhitespace = /\S/; if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) { return true; } else { return left == right; } }, join: function(left, right) { return left + right; }, tokenize: function(value) { return value; } }; var CharDiff = new fbDiff(); var WordDiff = new fbDiff(true); WordDiff.tokenize = function(value) { return removeEmpty(value.split(/(\s+|\b)/)); }; var CssDiff = new fbDiff(true); CssDiff.tokenize = function(value) { return removeEmpty(value.split(/([{}:;,]|\s+)/)); }; var LineDiff = new fbDiff(); LineDiff.tokenize = function(value) { return value.split(/^/m); }; return { diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); }, diffWords: function(oldStr, newStr) { return WordDiff.diff(oldStr, newStr); }, diffLines: function(oldStr, newStr) { return LineDiff.diff(oldStr, newStr); }, diffCss: function(oldStr, newStr) { return CssDiff.diff(oldStr, newStr); }, createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) { var ret = []; ret.push("Index: " + fileName); ret.push("==================================================================="); ret.push("--- " + fileName + (typeof oldHeader === "undefined" ? "" : "\t" + oldHeader)); ret.push("+++ " + fileName + (typeof newHeader === "undefined" ? "" : "\t" + newHeader)); var diff = LineDiff.diff(oldStr, newStr); if (!diff[diff.length-1].value) { diff.pop(); // Remove trailing newline add } diff.push({value: "", lines: []}); // Append an empty value to make cleanup easier function contextLines(lines) { return lines.map(function(entry) { return ' ' + entry; }); } function eofNL(curRange, i, current) { var last = diff[diff.length-2], isLast = i === diff.length-2, isLastOfType = i === diff.length-3 && (current.added === !last.added || current.removed === !last.removed); // Figure out if this is the last line for the given file and missing NL if (!/\n$/.test(current.value) && (isLast || isLastOfType)) { curRange.push('\\ No newline at end of file'); } } var oldRangeStart = 0, newRangeStart = 0, curRange = [], oldLine = 1, newLine = 1; for (var i = 0; i < diff.length; i++) { var current = diff[i], lines = current.lines || current.value.replace(/\n$/, "").split("\n"); current.lines = lines; if (current.added || current.removed) { if (!oldRangeStart) { var prev = diff[i-1]; oldRangeStart = oldLine; newRangeStart = newLine; if (prev) { curRange = contextLines(prev.lines.slice(-4)); oldRangeStart -= curRange.length; newRangeStart -= curRange.length; } } curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?"+":"-") + entry; })); eofNL(curRange, i, current); if (current.added) { newLine += lines.length; } else { oldLine += lines.length; } } else { if (oldRangeStart) { // Close out any changes that have been output (or join overlapping) if (lines.length <= 8 && i < diff.length-2) { // Overlapping curRange.push.apply(curRange, contextLines(lines)); } else { // end the range and output var contextSize = Math.min(lines.length, 4); ret.push( "@@ -" + oldRangeStart + "," + (oldLine-oldRangeStart+contextSize) + " +" + newRangeStart + "," + (newLine-newRangeStart+contextSize) + " @@"); ret.push.apply(ret, curRange); ret.push.apply(ret, contextLines(lines.slice(0, contextSize))); if (lines.length <= 4) { eofNL(ret, i, current); } oldRangeStart = 0; newRangeStart = 0; curRange = []; } } oldLine += lines.length; newLine += lines.length; } } return ret.join('\n') + '\n'; }, convertChangesToXML: function(changes){ var ret = []; for ( var i = 0; i < changes.length; i++) { var change = changes[i]; if (change.added) { ret.push(""); } else if (change.removed) { ret.push(""); } ret.push(escapeHTML(change.value)); if (change.added) { ret.push(""); } else if (change.removed) { ret.push(""); } } return ret.join(""); } }; })(); if (typeof module !== "undefined") { module.exports = JsDiff; } }); // module: browser/diff.js require.register("browser/events.js", function(module, exports, require){ /** * Module exports. */ exports.EventEmitter = EventEmitter; /** * Check if `obj` is an array. */ function isArray(obj) { return '[object Array]' == {}.toString.call(obj); } /** * Event emitter constructor. * * @api public */ function EventEmitter(){}; /** * Adds a listener. * * @api public */ EventEmitter.prototype.on = function (name, fn) { if (!this.$events) { this.$events = {}; } if (!this.$events[name]) { this.$events[name] = fn; } else if (isArray(this.$events[name])) { this.$events[name].push(fn); } else { this.$events[name] = [this.$events[name], fn]; } return this; }; EventEmitter.prototype.addListener = EventEmitter.prototype.on; /** * Adds a volatile listener. * * @api public */ EventEmitter.prototype.once = function (name, fn) { var self = this; function on () { self.removeListener(name, on); fn.apply(this, arguments); }; on.listener = fn; this.on(name, on); return this; }; /** * Removes a listener. * * @api public */ EventEmitter.prototype.removeListener = function (name, fn) { if (this.$events && this.$events[name]) { var list = this.$events[name]; if (isArray(list)) { var pos = -1; for (var i = 0, l = list.length; i < l; i++) { if (list[i] === fn || (list[i].listener && list[i].listener === fn)) { pos = i; break; } } if (pos < 0) { return this; } list.splice(pos, 1); if (!list.length) { delete this.$events[name]; } } else if (list === fn || (list.listener && list.listener === fn)) { delete this.$events[name]; } } return this; }; /** * Removes all listeners for an event. * * @api public */ EventEmitter.prototype.removeAllListeners = function (name) { if (name === undefined) { this.$events = {}; return this; } if (this.$events && this.$events[name]) { this.$events[name] = null; } return this; }; /** * Gets all listeners for a certain event. * * @api public */ EventEmitter.prototype.listeners = function (name) { if (!this.$events) { this.$events = {}; } if (!this.$events[name]) { this.$events[name] = []; } if (!isArray(this.$events[name])) { this.$events[name] = [this.$events[name]]; } return this.$events[name]; }; /** * Emits an event. * * @api public */ EventEmitter.prototype.emit = function (name) { if (!this.$events) { return false; } var handler = this.$events[name]; if (!handler) { return false; } var args = [].slice.call(arguments, 1); if ('function' == typeof handler) { handler.apply(this, args); } else if (isArray(handler)) { var listeners = handler.slice(); for (var i = 0, l = listeners.length; i < l; i++) { listeners[i].apply(this, args); } } else { return false; } return true; }; }); // module: browser/events.js require.register("browser/fs.js", function(module, exports, require){ }); // module: browser/fs.js require.register("browser/path.js", function(module, exports, require){ }); // module: browser/path.js require.register("browser/progress.js", function(module, exports, require){ /** * Expose `Progress`. */ module.exports = Progress; /** * Initialize a new `Progress` indicator. */ function Progress() { this.percent = 0; this.size(0); this.fontSize(11); this.font('helvetica, arial, sans-serif'); } /** * Set progress size to `n`. * * @param {Number} n * @return {Progress} for chaining * @api public */ Progress.prototype.size = function(n){ this._size = n; return this; }; /** * Set text to `str`. * * @param {String} str * @return {Progress} for chaining * @api public */ Progress.prototype.text = function(str){ this._text = str; return this; }; /** * Set font size to `n`. * * @param {Number} n * @return {Progress} for chaining * @api public */ Progress.prototype.fontSize = function(n){ this._fontSize = n; return this; }; /** * Set font `family`. * * @param {String} family * @return {Progress} for chaining */ Progress.prototype.font = function(family){ this._font = family; return this; }; /** * Update percentage to `n`. * * @param {Number} n * @return {Progress} for chaining */ Progress.prototype.update = function(n){ this.percent = n; return this; }; /** * Draw on `ctx`. * * @param {CanvasRenderingContext2d} ctx * @return {Progress} for chaining */ Progress.prototype.draw = function(ctx){ var percent = Math.min(this.percent, 100) , size = this._size , half = size / 2 , x = half , y = half , rad = half - 1 , fontSize = this._fontSize; ctx.font = fontSize + 'px ' + this._font; var angle = Math.PI * 2 * (percent / 100); ctx.clearRect(0, 0, size, size); // outer circle ctx.strokeStyle = '#9f9f9f'; ctx.beginPath(); ctx.arc(x, y, rad, 0, angle, false); ctx.stroke(); // inner circle ctx.strokeStyle = '#eee'; ctx.beginPath(); ctx.arc(x, y, rad - 1, 0, angle, true); ctx.stroke(); // text var text = this._text || (percent | 0) + '%' , w = ctx.measureText(text).width; ctx.fillText( text , x - w / 2 + 1 , y + fontSize / 2 - 1); return this; }; }); // module: browser/progress.js require.register("browser/tty.js", function(module, exports, require){ exports.isatty = function(){ return true; }; exports.getWindowSize = function(){ return [window.innerHeight, window.innerWidth]; }; }); // module: browser/tty.js require.register("context.js", function(module, exports, require){ /** * Expose `Context`. */ module.exports = Context; /** * Initialize a new `Context`. * * @api private */ function Context(){} /** * Set or get the context `Runnable` to `runnable`. * * @param {Runnable} runnable * @return {Context} * @api private */ Context.prototype.runnable = function(runnable){ if (0 == arguments.length) return this._runnable; this.test = this._runnable = runnable; return this; }; /** * Set test timeout `ms`. * * @param {Number} ms * @return {Context} self * @api private */ Context.prototype.timeout = function(ms){ this.runnable().timeout(ms); return this; }; /** * Set test slowness threshold `ms`. * * @param {Number} ms * @return {Context} self * @api private */ Context.prototype.slow = function(ms){ this.runnable().slow(ms); return this; }; /** * Inspect the context void of `._runnable`. * * @return {String} * @api private */ Context.prototype.inspect = function(){ return JSON.stringify(this, function(key, val){ if ('_runnable' == key) return; if ('test' == key) return; return val; }, 2); }; }); // module: context.js require.register("hook.js", function(module, exports, require){ /** * Module dependencies. */ var Runnable = require('./runnable'); /** * Expose `Hook`. */ module.exports = Hook; /** * Initialize a new `Hook` with the given `title` and callback `fn`. * * @param {String} title * @param {Function} fn * @api private */ function Hook(title, fn) { Runnable.call(this, title, fn); this.type = 'hook'; } /** * Inherit from `Runnable.prototype`. */ function F(){}; F.prototype = Runnable.prototype; Hook.prototype = new F; Hook.prototype.constructor = Hook; /** * Get or set the test `err`. * * @param {Error} err * @return {Error} * @api public */ Hook.prototype.error = function(err){ if (0 == arguments.length) { var err = this._error; this._error = null; return err; } this._error = err; }; }); // module: hook.js require.register("interfaces/bdd.js", function(module, exports, require){ /** * Module dependencies. */ var Suite = require('../suite') , Test = require('../test'); /** * BDD-style interface: * * describe('Array', function(){ * describe('#indexOf()', function(){ * it('should return -1 when not present', function(){ * * }); * * it('should return the index when present', function(){ * * }); * }); * }); * */ module.exports = function(suite){ var suites = [suite]; suite.on('pre-require', function(context, file, mocha){ /** * Execute before running tests. */ context.before = function(fn){ suites[0].beforeAll(fn); }; /** * Execute after running tests. */ context.after = function(fn){ suites[0].afterAll(fn); }; /** * Execute before each test case. */ context.beforeEach = function(fn){ suites[0].beforeEach(fn); }; /** * Execute after each test case. */ context.afterEach = function(fn){ suites[0].afterEach(fn); }; /** * Describe a "suite" with the given `title` * and callback `fn` containing nested suites * and/or tests. */ context.describe = context.context = function(title, fn){ var suite = Suite.create(suites[0], title); suites.unshift(suite); fn.call(suite); suites.shift(); return suite; }; /** * Pending describe. */ context.xdescribe = context.xcontext = context.describe.skip = function(title, fn){ var suite = Suite.create(suites[0], title); suite.pending = true; suites.unshift(suite); fn.call(suite); suites.shift(); }; /** * Exclusive suite. */ context.describe.only = function(title, fn){ var suite = context.describe(title, fn); mocha.grep(suite.fullTitle()); }; /** * Describe a specification or test-case * with the given `title` and callback `fn` * acting as a thunk. */ context.it = context.specify = function(title, fn){ var suite = suites[0]; if (suite.pending) var fn = null; var test = new Test(title, fn); suite.addTest(test); return test; }; /** * Exclusive test-case. */ context.it.only = function(title, fn){ var test = context.it(title, fn); mocha.grep(test.fullTitle()); }; /** * Pending test case. */ context.xit = context.xspecify = context.it.skip = function(title){ context.it(title); }; }); }; }); // module: interfaces/bdd.js require.register("interfaces/exports.js", function(module, exports, require){ /** * Module dependencies. */ var Suite = require('../suite') , Test = require('../test'); /** * TDD-style interface: * * exports.Array = { * '#indexOf()': { * 'should return -1 when the value is not present': function(){ * * }, * * 'should return the correct index when the value is present': function(){ * * } * } * }; * */ module.exports = function(suite){ var suites = [suite]; suite.on('require', visit); function visit(obj) { var suite; for (var key in obj) { if ('function' == typeof obj[key]) { var fn = obj[key]; switch (key) { case 'before': suites[0].beforeAll(fn); break; case 'after': suites[0].afterAll(fn); break; case 'beforeEach': suites[0].beforeEach(fn); break; case 'afterEach': suites[0].afterEach(fn); break; default: suites[0].addTest(new Test(key, fn)); } } else { var suite = Suite.create(suites[0], key); suites.unshift(suite); visit(obj[key]); suites.shift(); } } } }; }); // module: interfaces/exports.js require.register("interfaces/index.js", function(module, exports, require){ exports.bdd = require('./bdd'); exports.tdd = require('./tdd'); exports.qunit = require('./qunit'); exports.exports = require('./exports'); }); // module: interfaces/index.js require.register("interfaces/qunit.js", function(module, exports, require){ /** * Module dependencies. */ var Suite = require('../suite') , Test = require('../test'); /** * QUnit-style interface: * * suite('Array'); * * test('#length', function(){ * var arr = [1,2,3]; * ok(arr.length == 3); * }); * * test('#indexOf()', function(){ * var arr = [1,2,3]; * ok(arr.indexOf(1) == 0); * ok(arr.indexOf(2) == 1); * ok(arr.indexOf(3) == 2); * }); * * suite('String'); * * test('#length', function(){ * ok('foo'.length == 3); * }); * */ module.exports = function(suite){ var suites = [suite]; suite.on('pre-require', function(context){ /** * Execute before running tests. */ context.before = function(fn){ suites[0].beforeAll(fn); }; /** * Execute after running tests. */ context.after = function(fn){ suites[0].afterAll(fn); }; /** * Execute before each test case. */ context.beforeEach = function(fn){ suites[0].beforeEach(fn); }; /** * Execute after each test case. */ context.afterEach = function(fn){ suites[0].afterEach(fn); }; /** * Describe a "suite" with the given `title`. */ context.suite = function(title){ if (suites.length > 1) suites.shift(); var suite = Suite.create(suites[0], title); suites.unshift(suite); }; /** * Describe a specification or test-case * with the given `title` and callback `fn` * acting as a thunk. */ context.test = function(title, fn){ suites[0].addTest(new Test(title, fn)); }; }); }; }); // module: interfaces/qunit.js require.register("interfaces/tdd.js", function(module, exports, require){ /** * Module dependencies. */ var Suite = require('../suite') , Test = require('../test'); /** * TDD-style interface: * * suite('Array', function(){ * suite('#indexOf()', function(){ * suiteSetup(function(){ * * }); * * test('should return -1 when not present', function(){ * * }); * * test('should return the index when present', function(){ * * }); * * suiteTeardown(function(){ * * }); * }); * }); * */ module.exports = function(suite){ var suites = [suite]; suite.on('pre-require', function(context, file, mocha){ /** * Execute before each test case. */ context.setup = function(fn){ suites[0].beforeEach(fn); }; /** * Execute after each test case. */ context.teardown = function(fn){ suites[0].afterEach(fn); }; /** * Execute before the suite. */ context.suiteSetup = function(fn){ suites[0].beforeAll(fn); }; /** * Execute after the suite. */ context.suiteTeardown = function(fn){ suites[0].afterAll(fn); }; /** * Describe a "suite" with the given `title` * and callback `fn` containing nested suites * and/or tests. */ context.suite = function(title, fn){ var suite = Suite.create(suites[0], title); suites.unshift(suite); fn.call(suite); suites.shift(); return suite; }; /** * Exclusive test-case. */ context.suite.only = function(title, fn){ var suite = context.suite(title, fn); mocha.grep(suite.fullTitle()); }; /** * Describe a specification or test-case * with the given `title` and callback `fn` * acting as a thunk. */ context.test = function(title, fn){ var test = new Test(title, fn); suites[0].addTest(test); return test; }; /** * Exclusive test-case. */ context.test.only = function(title, fn){ var test = context.test(title, fn); mocha.grep(test.fullTitle()); }; /** * Pending test case. */ context.test.skip = function(title){ context.test(title); }; }); }; }); // module: interfaces/tdd.js require.register("mocha.js", function(module, exports, require){ /*! * mocha * Copyright(c) 2011 TJ Holowaychuk * MIT Licensed */ /** * Module dependencies. */ var path = require('browser/path') , utils = require('./utils'); /** * Expose `Mocha`. */ exports = module.exports = Mocha; /** * Expose internals. */ exports.utils = utils; exports.interfaces = require('./interfaces'); exports.reporters = require('./reporters'); exports.Runnable = require('./runnable'); exports.Context = require('./context'); exports.Runner = require('./runner'); exports.Suite = require('./suite'); exports.Hook = require('./hook'); exports.Test = require('./test'); /** * Return image `name` path. * * @param {String} name * @return {String} * @api private */ function image(name) { return __dirname + '/../images/' + name + '.png'; } /** * Setup mocha with `options`. * * Options: * * - `ui` name "bdd", "tdd", "exports" etc * - `reporter` reporter instance, defaults to `mocha.reporters.Dot` * - `globals` array of accepted globals * - `timeout` timeout in milliseconds * - `bail` bail on the first test failure * - `slow` milliseconds to wait before considering a test slow * - `ignoreLeaks` ignore global leaks * - `grep` string or regexp to filter tests with * * @param {Object} options * @api public */ function Mocha(options) { options = options || {}; this.files = []; this.options = options; this.grep(options.grep); this.suite = new exports.Suite('', new exports.Context); this.ui(options.ui); this.bail(options.bail); this.reporter(options.reporter); if (options.timeout) this.timeout(options.timeout); if (options.slow) this.slow(options.slow); } /** * Enable or disable bailing on the first failure. * * @param {Boolean} [bail] * @api public */ Mocha.prototype.bail = function(bail){ if (null == bail) bail = true; this.suite.bail(bail); return this; }; /** * Add test `file`. * * @param {String} file * @api public */ Mocha.prototype.addFile = function(file){ this.files.push(file); return this; }; /** * Set reporter to `reporter`, defaults to "dot". * * @param {String|Function} reporter name or constructor * @api public */ Mocha.prototype.reporter = function(reporter){ if ('function' == typeof reporter) { this._reporter = reporter; } else { reporter = reporter || 'dot'; try { this._reporter = require('./reporters/' + reporter); } catch (err) { this._reporter = require(reporter); } if (!this._reporter) throw new Error('invalid reporter "' + reporter + '"'); } return this; }; /** * Set test UI `name`, defaults to "bdd". * * @param {String} bdd * @api public */ Mocha.prototype.ui = function(name){ name = name || 'bdd'; this._ui = exports.interfaces[name]; if (!this._ui) throw new Error('invalid interface "' + name + '"'); this._ui = this._ui(this.suite); return this; }; /** * Load registered files. * * @api private */ Mocha.prototype.loadFiles = function(fn){ var self = this; var suite = this.suite; var pending = this.files.length; this.files.forEach(function(file){ file = path.resolve(file); suite.emit('pre-require', global, file, self); suite.emit('require', require(file), file, self); suite.emit('post-require', global, file, self); --pending || (fn && fn()); }); }; /** * Enable growl support. * * @api private */ Mocha.prototype._growl = function(runner, reporter) { var notify = require('growl'); runner.on('end', function(){ var stats = reporter.stats; if (stats.failures) { var msg = stats.failures + ' of ' + runner.total + ' tests failed'; notify(msg, { name: 'mocha', title: 'Failed', image: image('error') }); } else { notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', { name: 'mocha' , title: 'Passed' , image: image('ok') }); } }); }; /** * Add regexp to grep, if `re` is a string it is escaped. * * @param {RegExp|String} re * @return {Mocha} * @api public */ Mocha.prototype.grep = function(re){ this.options.grep = 'string' == typeof re ? new RegExp(utils.escapeRegexp(re)) : re; return this; }; /** * Invert `.grep()` matches. * * @return {Mocha} * @api public */ Mocha.prototype.invert = function(){ this.options.invert = true; return this; }; /** * Ignore global leaks. * * @return {Mocha} * @api public */ Mocha.prototype.ignoreLeaks = function(){ this.options.ignoreLeaks = true; return this; }; /** * Enable global leak checking. * * @return {Mocha} * @api public */ Mocha.prototype.checkLeaks = function(){ this.options.ignoreLeaks = false; return this; }; /** * Enable growl support. * * @return {Mocha} * @api public */ Mocha.prototype.growl = function(){ this.options.growl = true; return this; }; /** * Ignore `globals` array or string. * * @param {Array|String} globals * @return {Mocha} * @api public */ Mocha.prototype.globals = function(globals){ this.options.globals = (this.options.globals || []).concat(globals); return this; }; /** * Set the timeout in milliseconds. * * @param {Number} timeout * @return {Mocha} * @api public */ Mocha.prototype.timeout = function(timeout){ this.suite.timeout(timeout); return this; }; /** * Set slowness threshold in milliseconds. * * @param {Number} slow * @return {Mocha} * @api public */ Mocha.prototype.slow = function(slow){ this.suite.slow(slow); return this; }; /** * Makes all tests async (accepting a callback) * * @return {Mocha} * @api public */ Mocha.prototype.asyncOnly = function(){ this.options.asyncOnly = true; return this; }; /** * Run tests and invoke `fn()` when complete. * * @param {Function} fn * @return {Runner} * @api public */ Mocha.prototype.run = function(fn){ if (this.files.length) this.loadFiles(); var suite = this.suite; var options = this.options; var runner = new exports.Runner(suite); var reporter = new this._reporter(runner); runner.ignoreLeaks = options.ignoreLeaks; runner.asyncOnly = options.asyncOnly; if (options.grep) runner.grep(options.grep, options.invert); if (options.globals) runner.globals(options.globals); if (options.growl) this._growl(runner, reporter); return runner.run(fn); }; }); // module: mocha.js require.register("ms.js", function(module, exports, require){ /** * Helpers. */ var s = 1000; var m = s * 60; var h = m * 60; var d = h * 24; /** * Parse or format the given `val`. * * @param {String|Number} val * @return {String|Number} * @api public */ module.exports = function(val){ if ('string' == typeof val) return parse(val); return format(val); } /** * Parse the given `str` and return milliseconds. * * @param {String} str * @return {Number} * @api private */ function parse(str) { var m = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str); if (!m) return; var n = parseFloat(m[1]); var type = (m[2] || 'ms').toLowerCase(); switch (type) { case 'years': case 'year': case 'y': return n * 31557600000; case 'days': case 'day': case 'd': return n * 86400000; case 'hours': case 'hour': case 'h': return n * 3600000; case 'minutes': case 'minute': case 'm': return n * 60000; case 'seconds': case 'second': case 's': return n * 1000; case 'ms': return n; } } /** * Format the given `ms`. * * @param {Number} ms * @return {String} * @api public */ function format(ms) { if (ms == d) return Math.round(ms / d) + ' day'; if (ms > d) return Math.round(ms / d) + ' days'; if (ms == h) return Math.round(ms / h) + ' hour'; if (ms > h) return Math.round(ms / h) + ' hours'; if (ms == m) return Math.round(ms / m) + ' minute'; if (ms > m) return Math.round(ms / m) + ' minutes'; if (ms == s) return Math.round(ms / s) + ' second'; if (ms > s) return Math.round(ms / s) + ' seconds'; return ms + ' ms'; } }); // module: ms.js require.register("reporters/base.js", function(module, exports, require){ /** * Module dependencies. */ var tty = require('browser/tty') , diff = require('browser/diff') , ms = require('../ms'); /** * Save timer references to avoid Sinon interfering (see GH-237). */ var Date = global.Date , setTimeout = global.setTimeout , setInterval = global.setInterval , clearTimeout = global.clearTimeout , clearInterval = global.clearInterval; /** * Check if both stdio streams are associated with a tty. */ var isatty = tty.isatty(1) && tty.isatty(2); /** * Expose `Base`. */ exports = module.exports = Base; /** * Enable coloring by default. */ exports.useColors = isatty; /** * Default color map. */ exports.colors = { 'pass': 90 , 'fail': 31 , 'bright pass': 92 , 'bright fail': 91 , 'bright yellow': 93 , 'pending': 36 , 'suite': 0 , 'error title': 0 , 'error message': 31 , 'error stack': 90 , 'checkmark': 32 , 'fast': 90 , 'medium': 33 , 'slow': 31 , 'green': 32 , 'light': 90 , 'diff gutter': 90 , 'diff added': 42 , 'diff removed': 41 }; /** * Default symbol map. */ exports.symbols = { ok: '✓', err: '✖', dot: '․' }; // With node.js on Windows: use symbols available in terminal default fonts if ('win32' == process.platform) { exports.symbols.ok = '\u221A'; exports.symbols.err = '\u00D7'; exports.symbols.dot = '.'; } /** * Color `str` with the given `type`, * allowing colors to be disabled, * as well as user-defined color * schemes. * * @param {String} type * @param {String} str * @return {String} * @api private */ var color = exports.color = function(type, str) { if (!exports.useColors) return str; return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m'; }; /** * Expose term window size, with some * defaults for when stderr is not a tty. */ exports.window = { width: isatty ? process.stdout.getWindowSize ? process.stdout.getWindowSize(1)[0] : tty.getWindowSize()[1] : 75 }; /** * Expose some basic cursor interactions * that are common among reporters. */ exports.cursor = { hide: function(){ process.stdout.write('\u001b[?25l'); }, show: function(){ process.stdout.write('\u001b[?25h'); }, deleteLine: function(){ process.stdout.write('\u001b[2K'); }, beginningOfLine: function(){ process.stdout.write('\u001b[0G'); }, CR: function(){ exports.cursor.deleteLine(); exports.cursor.beginningOfLine(); } }; /** * Outut the given `failures` as a list. * * @param {Array} failures * @api public */ exports.list = function(failures){ console.error(); failures.forEach(function(test, i){ // format var fmt = color('error title', ' %s) %s:\n') + color('error message', ' %s') + color('error stack', '\n%s\n'); // msg var err = test.err , message = err.message || '' , stack = err.stack || message , index = stack.indexOf(message) + message.length , msg = stack.slice(0, index) , actual = err.actual , expected = err.expected , escape = true; // explicitly show diff if (err.showDiff) { escape = false; err.actual = actual = JSON.stringify(actual, null, 2); err.expected = expected = JSON.stringify(expected, null, 2); } // actual / expected diff if ('string' == typeof actual && 'string' == typeof expected) { var len = Math.max(actual.length, expected.length); if (len < 20) msg = errorDiff(err, 'Chars', escape); else msg = errorDiff(err, 'Words', escape); // linenos var lines = msg.split('\n'); if (lines.length > 4) { var width = String(lines.length).length; msg = lines.map(function(str, i){ return pad(++i, width) + ' |' + ' ' + str; }).join('\n'); } // legend msg = '\n' + color('diff removed', 'actual') + ' ' + color('diff added', 'expected') + '\n\n' + msg + '\n'; // indent msg = msg.replace(/^/gm, ' '); fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n'); } // indent stack trace without msg stack = stack.slice(index ? index + 1 : index) .replace(/^/gm, ' '); console.error(fmt, (i + 1), test.fullTitle(), msg, stack); }); }; /** * Initialize a new `Base` reporter. * * All other reporters generally * inherit from this reporter, providing * stats such as test duration, number * of tests passed / failed etc. * * @param {Runner} runner * @api public */ function Base(runner) { var self = this , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 } , failures = this.failures = []; if (!runner) return; this.runner = runner; runner.stats = stats; runner.on('start', function(){ stats.start = new Date; }); runner.on('suite', function(suite){ stats.suites = stats.suites || 0; suite.root || stats.suites++; }); runner.on('test end', function(test){ stats.tests = stats.tests || 0; stats.tests++; }); runner.on('pass', function(test){ stats.passes = stats.passes || 0; var medium = test.slow() / 2; test.speed = test.duration > test.slow() ? 'slow' : test.duration > medium ? 'medium' : 'fast'; stats.passes++; }); runner.on('fail', function(test, err){ stats.failures = stats.failures || 0; stats.failures++; test.err = err; failures.push(test); }); runner.on('end', function(){ stats.end = new Date; stats.duration = new Date - stats.start; }); runner.on('pending', function(){ stats.pending++; }); } /** * Output common epilogue used by many of * the bundled reporters. * * @api public */ Base.prototype.epilogue = function(){ var stats = this.stats , fmt , tests; console.log(); function pluralize(n) { return 1 == n ? 'test' : 'tests'; } // failure if (stats.failures) { fmt = color('bright fail', ' ' + exports.symbols.err) + color('fail', ' %d of %d %s failed') + color('light', ':') console.error(fmt, stats.failures, this.runner.total, pluralize(this.runner.total)); Base.list(this.failures); console.error(); return; } // pass fmt = color('bright pass', ' ') + color('green', ' %d %s complete') + color('light', ' (%s)'); console.log(fmt, stats.tests || 0, pluralize(stats.tests), ms(stats.duration)); // pending if (stats.pending) { fmt = color('pending', ' ') + color('pending', ' %d %s pending'); console.log(fmt, stats.pending, pluralize(stats.pending)); } console.log(); }; /** * Pad the given `str` to `len`. * * @param {String} str * @param {String} len * @return {String} * @api private */ function pad(str, len) { str = String(str); return Array(len - str.length + 1).join(' ') + str; } /** * Return a character diff for `err`. * * @param {Error} err * @return {String} * @api private */ function errorDiff(err, type, escape) { return diff['diff' + type](err.actual, err.expected).map(function(str){ if (escape) { str.value = str.value .replace(/\t/g, '') .replace(/\r/g, '') .replace(/\n/g, '\n'); } if (str.added) return colorLines('diff added', str.value); if (str.removed) return colorLines('diff removed', str.value); return str.value; }).join(''); } /** * Color lines for `str`, using the color `name`. * * @param {String} name * @param {String} str * @return {String} * @api private */ function colorLines(name, str) { return str.split('\n').map(function(str){ return color(name, str); }).join('\n'); } }); // module: reporters/base.js require.register("reporters/doc.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , utils = require('../utils'); /** * Expose `Doc`. */ exports = module.exports = Doc; /** * Initialize a new `Doc` reporter. * * @param {Runner} runner * @api public */ function Doc(runner) { Base.call(this, runner); var self = this , stats = this.stats , total = runner.total , indents = 2; function indent() { return Array(indents).join(' '); } runner.on('suite', function(suite){ if (suite.root) return; ++indents; console.log('%s
', indent()); ++indents; console.log('%s

%s

', indent(), utils.escape(suite.title)); console.log('%s
', indent()); }); runner.on('suite end', function(suite){ if (suite.root) return; console.log('%s
', indent()); --indents; console.log('%s
', indent()); --indents; }); runner.on('pass', function(test){ console.log('%s
%s
', indent(), utils.escape(test.title)); var code = utils.escape(utils.clean(test.fn.toString())); console.log('%s
%s
', indent(), code); }); } }); // module: reporters/doc.js require.register("reporters/dot.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , color = Base.color; /** * Expose `Dot`. */ exports = module.exports = Dot; /** * Initialize a new `Dot` matrix test reporter. * * @param {Runner} runner * @api public */ function Dot(runner) { Base.call(this, runner); var self = this , stats = this.stats , width = Base.window.width * .75 | 0 , n = 0; runner.on('start', function(){ process.stdout.write('\n '); }); runner.on('pending', function(test){ process.stdout.write(color('pending', Base.symbols.dot)); }); runner.on('pass', function(test){ if (++n % width == 0) process.stdout.write('\n '); if ('slow' == test.speed) { process.stdout.write(color('bright yellow', Base.symbols.dot)); } else { process.stdout.write(color(test.speed, Base.symbols.dot)); } }); runner.on('fail', function(test, err){ if (++n % width == 0) process.stdout.write('\n '); process.stdout.write(color('fail', Base.symbols.dot)); }); runner.on('end', function(){ console.log(); self.epilogue(); }); } /** * Inherit from `Base.prototype`. */ function F(){}; F.prototype = Base.prototype; Dot.prototype = new F; Dot.prototype.constructor = Dot; }); // module: reporters/dot.js require.register("reporters/html-cov.js", function(module, exports, require){ /** * Module dependencies. */ var JSONCov = require('./json-cov') , fs = require('browser/fs'); /** * Expose `HTMLCov`. */ exports = module.exports = HTMLCov; /** * Initialize a new `JsCoverage` reporter. * * @param {Runner} runner * @api public */ function HTMLCov(runner) { var jade = require('jade') , file = __dirname + '/templates/coverage.jade' , str = fs.readFileSync(file, 'utf8') , fn = jade.compile(str, { filename: file }) , self = this; JSONCov.call(this, runner, false); runner.on('end', function(){ process.stdout.write(fn({ cov: self.cov , coverageClass: coverageClass })); }); } /** * Return coverage class for `n`. * * @return {String} * @api private */ function coverageClass(n) { if (n >= 75) return 'high'; if (n >= 50) return 'medium'; if (n >= 25) return 'low'; return 'terrible'; } }); // module: reporters/html-cov.js require.register("reporters/html.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , utils = require('../utils') , Progress = require('../browser/progress') , escape = utils.escape; /** * Save timer references to avoid Sinon interfering (see GH-237). */ var Date = global.Date , setTimeout = global.setTimeout , setInterval = global.setInterval , clearTimeout = global.clearTimeout , clearInterval = global.clearInterval; /** * Expose `Doc`. */ exports = module.exports = HTML; /** * Stats template. */ var statsTemplate = ''; /** * Initialize a new `Doc` reporter. * * @param {Runner} runner * @api public */ function HTML(runner, root) { Base.call(this, runner); var self = this , stats = this.stats , total = runner.total , stat = fragment(statsTemplate) , items = stat.getElementsByTagName('li') , passes = items[1].getElementsByTagName('em')[0] , passesLink = items[1].getElementsByTagName('a')[0] , failures = items[2].getElementsByTagName('em')[0] , failuresLink = items[2].getElementsByTagName('a')[0] , duration = items[3].getElementsByTagName('em')[0] , canvas = stat.getElementsByTagName('canvas')[0] , report = fragment('
    ') , stack = [report] , progress , ctx root = root || document.getElementById('mocha'); if (canvas.getContext) { var ratio = window.devicePixelRatio || 1; canvas.style.width = canvas.width; canvas.style.height = canvas.height; canvas.width *= ratio; canvas.height *= ratio; ctx = canvas.getContext('2d'); ctx.scale(ratio, ratio); progress = new Progress; } if (!root) return error('#mocha div missing, add it to your document'); // pass toggle on(passesLink, 'click', function(){ unhide(); var name = /pass/.test(report.className) ? '' : ' pass'; report.className = report.className.replace(/fail|pass/g, '') + name; if (report.className.trim()) hideSuitesWithout('test pass'); }); // failure toggle on(failuresLink, 'click', function(){ unhide(); var name = /fail/.test(report.className) ? '' : ' fail'; report.className = report.className.replace(/fail|pass/g, '') + name; if (report.className.trim()) hideSuitesWithout('test fail'); }); root.appendChild(stat); root.appendChild(report); if (progress) progress.size(40); runner.on('suite', function(suite){ if (suite.root) return; // suite var url = '?grep=' + encodeURIComponent(suite.fullTitle()); var el = fragment('
  • %s

  • ', url, escape(suite.title)); // container stack[0].appendChild(el); stack.unshift(document.createElement('ul')); el.appendChild(stack[0]); }); runner.on('suite end', function(suite){ if (suite.root) return; stack.shift(); }); runner.on('fail', function(test, err){ if ('hook' == test.type) runner.emit('test end', test); }); runner.on('test end', function(test){ window.scrollTo(0, document.body.scrollHeight); // TODO: add to stats var percent = stats.tests / this.total * 100 | 0; if (progress) progress.update(percent).draw(ctx); // update stats var ms = new Date - stats.start; text(passes, stats.passes); text(failures, stats.failures); text(duration, (ms / 1000).toFixed(2)); // test if ('passed' == test.state) { var el = fragment('
  • %e%ems

  • ', test.speed, test.title, test.duration, encodeURIComponent(test.fullTitle())); } else if (test.pending) { var el = fragment('
  • %e

  • ', test.title); } else { var el = fragment('
  • %e

  • ', test.title, encodeURIComponent(test.fullTitle())); var str = test.err.stack || test.err.toString(); // FF / Opera do not add the message if (!~str.indexOf(test.err.message)) { str = test.err.message + '\n' + str; } // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we // check for the result of the stringifying. if ('[object Error]' == str) str = test.err.message; // Safari doesn't give you a stack. Let's at least provide a source line. if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) { str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")"; } el.appendChild(fragment('
    %e
    ', str)); } // toggle code // TODO: defer if (!test.pending) { var h2 = el.getElementsByTagName('h2')[0]; on(h2, 'click', function(){ pre.style.display = 'none' == pre.style.display ? 'block' : 'none'; }); var pre = fragment('
    %e
    ', utils.clean(test.fn.toString())); el.appendChild(pre); pre.style.display = 'none'; } // Don't call .appendChild if #mocha-report was already .shift()'ed off the stack. if (stack[0]) stack[0].appendChild(el); }); } /** * Display error `msg`. */ function error(msg) { document.body.appendChild(fragment('
    %s
    ', msg)); } /** * Return a DOM fragment from `html`. */ function fragment(html) { var args = arguments , div = document.createElement('div') , i = 1; div.innerHTML = html.replace(/%([se])/g, function(_, type){ switch (type) { case 's': return String(args[i++]); case 'e': return escape(args[i++]); } }); return div.firstChild; } /** * Check for suites that do not have elements * with `classname`, and hide them. */ function hideSuitesWithout(classname) { var suites = document.getElementsByClassName('suite'); for (var i = 0; i < suites.length; i++) { var els = suites[i].getElementsByClassName(classname); if (0 == els.length) suites[i].className += ' hidden'; } } /** * Unhide .hidden suites. */ function unhide() { var els = document.getElementsByClassName('suite hidden'); for (var i = 0; i < els.length; ++i) { els[i].className = els[i].className.replace('suite hidden', 'suite'); } } /** * Set `el` text to `str`. */ function text(el, str) { if (el.textContent) { el.textContent = str; } else { el.innerText = str; } } /** * Listen on `event` with callback `fn`. */ function on(el, event, fn) { if (el.addEventListener) { el.addEventListener(event, fn, false); } else { el.attachEvent('on' + event, fn); } } }); // module: reporters/html.js require.register("reporters/index.js", function(module, exports, require){ exports.Base = require('./base'); exports.Dot = require('./dot'); exports.Doc = require('./doc'); exports.TAP = require('./tap'); exports.JSON = require('./json'); exports.HTML = require('./html'); exports.List = require('./list'); exports.Min = require('./min'); exports.Spec = require('./spec'); exports.Nyan = require('./nyan'); exports.XUnit = require('./xunit'); exports.Markdown = require('./markdown'); exports.Progress = require('./progress'); exports.Landing = require('./landing'); exports.JSONCov = require('./json-cov'); exports.HTMLCov = require('./html-cov'); exports.JSONStream = require('./json-stream'); exports.Teamcity = require('./teamcity'); }); // module: reporters/index.js require.register("reporters/json-cov.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base'); /** * Expose `JSONCov`. */ exports = module.exports = JSONCov; /** * Initialize a new `JsCoverage` reporter. * * @param {Runner} runner * @param {Boolean} output * @api public */ function JSONCov(runner, output) { var self = this , output = 1 == arguments.length ? true : output; Base.call(this, runner); var tests = [] , failures = [] , passes = []; runner.on('test end', function(test){ tests.push(test); }); runner.on('pass', function(test){ passes.push(test); }); runner.on('fail', function(test){ failures.push(test); }); runner.on('end', function(){ var cov = global._$jscoverage || {}; var result = self.cov = map(cov); result.stats = self.stats; result.tests = tests.map(clean); result.failures = failures.map(clean); result.passes = passes.map(clean); if (!output) return; process.stdout.write(JSON.stringify(result, null, 2 )); }); } /** * Map jscoverage data to a JSON structure * suitable for reporting. * * @param {Object} cov * @return {Object} * @api private */ function map(cov) { var ret = { instrumentation: 'node-jscoverage' , sloc: 0 , hits: 0 , misses: 0 , coverage: 0 , files: [] }; for (var filename in cov) { var data = coverage(filename, cov[filename]); ret.files.push(data); ret.hits += data.hits; ret.misses += data.misses; ret.sloc += data.sloc; } ret.files.sort(function(a, b) { return a.filename.localeCompare(b.filename); }); if (ret.sloc > 0) { ret.coverage = (ret.hits / ret.sloc) * 100; } return ret; }; /** * Map jscoverage data for a single source file * to a JSON structure suitable for reporting. * * @param {String} filename name of the source file * @param {Object} data jscoverage coverage data * @return {Object} * @api private */ function coverage(filename, data) { var ret = { filename: filename, coverage: 0, hits: 0, misses: 0, sloc: 0, source: {} }; data.source.forEach(function(line, num){ num++; if (data[num] === 0) { ret.misses++; ret.sloc++; } else if (data[num] !== undefined) { ret.hits++; ret.sloc++; } ret.source[num] = { source: line , coverage: data[num] === undefined ? '' : data[num] }; }); ret.coverage = ret.hits / ret.sloc * 100; return ret; } /** * Return a plain-object representation of `test` * free of cyclic properties etc. * * @param {Object} test * @return {Object} * @api private */ function clean(test) { return { title: test.title , fullTitle: test.fullTitle() , duration: test.duration } } }); // module: reporters/json-cov.js require.register("reporters/json-stream.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , color = Base.color; /** * Expose `List`. */ exports = module.exports = List; /** * Initialize a new `List` test reporter. * * @param {Runner} runner * @api public */ function List(runner) { Base.call(this, runner); var self = this , stats = this.stats , total = runner.total; runner.on('start', function(){ console.log(JSON.stringify(['start', { total: total }])); }); runner.on('pass', function(test){ console.log(JSON.stringify(['pass', clean(test)])); }); runner.on('fail', function(test, err){ console.log(JSON.stringify(['fail', clean(test)])); }); runner.on('end', function(){ process.stdout.write(JSON.stringify(['end', self.stats])); }); } /** * Return a plain-object representation of `test` * free of cyclic properties etc. * * @param {Object} test * @return {Object} * @api private */ function clean(test) { return { title: test.title , fullTitle: test.fullTitle() , duration: test.duration } } }); // module: reporters/json-stream.js require.register("reporters/json.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `JSON`. */ exports = module.exports = JSONReporter; /** * Initialize a new `JSON` reporter. * * @param {Runner} runner * @api public */ function JSONReporter(runner) { var self = this; Base.call(this, runner); var tests = [] , failures = [] , passes = []; runner.on('test end', function(test){ tests.push(test); }); runner.on('pass', function(test){ passes.push(test); }); runner.on('fail', function(test){ failures.push(test); }); runner.on('end', function(){ var obj = { stats: self.stats , tests: tests.map(clean) , failures: failures.map(clean) , passes: passes.map(clean) }; process.stdout.write(JSON.stringify(obj, null, 2)); }); } /** * Return a plain-object representation of `test` * free of cyclic properties etc. * * @param {Object} test * @return {Object} * @api private */ function clean(test) { return { title: test.title , fullTitle: test.fullTitle() , duration: test.duration } } }); // module: reporters/json.js require.register("reporters/landing.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `Landing`. */ exports = module.exports = Landing; /** * Airplane color. */ Base.colors.plane = 0; /** * Airplane crash color. */ Base.colors['plane crash'] = 31; /** * Runway color. */ Base.colors.runway = 90; /** * Initialize a new `Landing` reporter. * * @param {Runner} runner * @api public */ function Landing(runner) { Base.call(this, runner); var self = this , stats = this.stats , width = Base.window.width * .75 | 0 , total = runner.total , stream = process.stdout , plane = color('plane', '✈') , crashed = -1 , n = 0; function runway() { var buf = Array(width).join('-'); return ' ' + color('runway', buf); } runner.on('start', function(){ stream.write('\n '); cursor.hide(); }); runner.on('test end', function(test){ // check if the plane crashed var col = -1 == crashed ? width * ++n / total | 0 : crashed; // show the crash if ('failed' == test.state) { plane = color('plane crash', '✈'); crashed = col; } // render landing strip stream.write('\u001b[4F\n\n'); stream.write(runway()); stream.write('\n '); stream.write(color('runway', Array(col).join('⋅'))); stream.write(plane) stream.write(color('runway', Array(width - col).join('⋅') + '\n')); stream.write(runway()); stream.write('\u001b[0m'); }); runner.on('end', function(){ cursor.show(); console.log(); self.epilogue(); }); } /** * Inherit from `Base.prototype`. */ function F(){}; F.prototype = Base.prototype; Landing.prototype = new F; Landing.prototype.constructor = Landing; }); // module: reporters/landing.js require.register("reporters/list.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `List`. */ exports = module.exports = List; /** * Initialize a new `List` test reporter. * * @param {Runner} runner * @api public */ function List(runner) { Base.call(this, runner); var self = this , stats = this.stats , n = 0; runner.on('start', function(){ console.log(); }); runner.on('test', function(test){ process.stdout.write(color('pass', ' ' + test.fullTitle() + ': ')); }); runner.on('pending', function(test){ var fmt = color('checkmark', ' -') + color('pending', ' %s'); console.log(fmt, test.fullTitle()); }); runner.on('pass', function(test){ var fmt = color('checkmark', ' '+Base.symbols.dot) + color('pass', ' %s: ') + color(test.speed, '%dms'); cursor.CR(); console.log(fmt, test.fullTitle(), test.duration); }); runner.on('fail', function(test, err){ cursor.CR(); console.log(color('fail', ' %d) %s'), ++n, test.fullTitle()); }); runner.on('end', self.epilogue.bind(self)); } /** * Inherit from `Base.prototype`. */ function F(){}; F.prototype = Base.prototype; List.prototype = new F; List.prototype.constructor = List; }); // module: reporters/list.js require.register("reporters/markdown.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , utils = require('../utils'); /** * Expose `Markdown`. */ exports = module.exports = Markdown; /** * Initialize a new `Markdown` reporter. * * @param {Runner} runner * @api public */ function Markdown(runner) { Base.call(this, runner); var self = this , stats = this.stats , level = 0 , buf = ''; function title(str) { return Array(level).join('#') + ' ' + str; } function indent() { return Array(level).join(' '); } function mapTOC(suite, obj) { var ret = obj; obj = obj[suite.title] = obj[suite.title] || { suite: suite }; suite.suites.forEach(function(suite){ mapTOC(suite, obj); }); return ret; } function stringifyTOC(obj, level) { ++level; var buf = ''; var link; for (var key in obj) { if ('suite' == key) continue; if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n'; if (key) buf += Array(level).join(' ') + link; buf += stringifyTOC(obj[key], level); } --level; return buf; } function generateTOC(suite) { var obj = mapTOC(suite, {}); return stringifyTOC(obj, 0); } generateTOC(runner.suite); runner.on('suite', function(suite){ ++level; var slug = utils.slug(suite.fullTitle()); buf += '' + '\n'; buf += title(suite.title) + '\n'; }); runner.on('suite end', function(suite){ --level; }); runner.on('pass', function(test){ var code = utils.clean(test.fn.toString()); buf += test.title + '.\n'; buf += '\n```js\n'; buf += code + '\n'; buf += '```\n\n'; }); runner.on('end', function(){ process.stdout.write('# TOC\n'); process.stdout.write(generateTOC(runner.suite)); process.stdout.write(buf); }); } }); // module: reporters/markdown.js require.register("reporters/min.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base'); /** * Expose `Min`. */ exports = module.exports = Min; /** * Initialize a new `Min` minimal test reporter (best used with --watch). * * @param {Runner} runner * @api public */ function Min(runner) { Base.call(this, runner); runner.on('start', function(){ // clear screen process.stdout.write('\u001b[2J'); // set cursor position process.stdout.write('\u001b[1;3H'); }); runner.on('end', this.epilogue.bind(this)); } /** * Inherit from `Base.prototype`. */ function F(){}; F.prototype = Base.prototype; Min.prototype = new F; Min.prototype.constructor = Min; }); // module: reporters/min.js require.register("reporters/nyan.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , color = Base.color; /** * Expose `Dot`. */ exports = module.exports = NyanCat; /** * Initialize a new `Dot` matrix test reporter. * * @param {Runner} runner * @api public */ function NyanCat(runner) { Base.call(this, runner); var self = this , stats = this.stats , width = Base.window.width * .75 | 0 , rainbowColors = this.rainbowColors = self.generateColors() , colorIndex = this.colorIndex = 0 , numerOfLines = this.numberOfLines = 4 , trajectories = this.trajectories = [[], [], [], []] , nyanCatWidth = this.nyanCatWidth = 11 , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth) , scoreboardWidth = this.scoreboardWidth = 5 , tick = this.tick = 0 , n = 0; runner.on('start', function(){ Base.cursor.hide(); self.draw('start'); }); runner.on('pending', function(test){ self.draw('pending'); }); runner.on('pass', function(test){ self.draw('pass'); }); runner.on('fail', function(test, err){ self.draw('fail'); }); runner.on('end', function(){ Base.cursor.show(); for (var i = 0; i < self.numberOfLines; i++) write('\n'); self.epilogue(); }); } /** * Draw the nyan cat with runner `status`. * * @param {String} status * @api private */ NyanCat.prototype.draw = function(status){ this.appendRainbow(); this.drawScoreboard(); this.drawRainbow(); this.drawNyanCat(status); this.tick = !this.tick; }; /** * Draw the "scoreboard" showing the number * of passes, failures and pending tests. * * @api private */ NyanCat.prototype.drawScoreboard = function(){ var stats = this.stats; var colors = Base.colors; function draw(color, n) { write(' '); write('\u001b[' + color + 'm' + n + '\u001b[0m'); write('\n'); } draw(colors.green, stats.passes); draw(colors.fail, stats.failures); draw(colors.pending, stats.pending); write('\n'); this.cursorUp(this.numberOfLines); }; /** * Append the rainbow. * * @api private */ NyanCat.prototype.appendRainbow = function(){ var segment = this.tick ? '_' : '-'; var rainbowified = this.rainbowify(segment); for (var index = 0; index < this.numberOfLines; index++) { var trajectory = this.trajectories[index]; if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift(); trajectory.push(rainbowified); } }; /** * Draw the rainbow. * * @api private */ NyanCat.prototype.drawRainbow = function(){ var self = this; this.trajectories.forEach(function(line, index) { write('\u001b[' + self.scoreboardWidth + 'C'); write(line.join('')); write('\n'); }); this.cursorUp(this.numberOfLines); }; /** * Draw the nyan cat with `status`. * * @param {String} status * @api private */ NyanCat.prototype.drawNyanCat = function(status) { var self = this; var startWidth = this.scoreboardWidth + this.trajectories[0].length; [0, 1, 2, 3].forEach(function(index) { write('\u001b[' + startWidth + 'C'); switch (index) { case 0: write('_,------,'); write('\n'); break; case 1: var padding = self.tick ? ' ' : ' '; write('_|' + padding + '/\\_/\\ '); write('\n'); break; case 2: var padding = self.tick ? '_' : '__'; var tail = self.tick ? '~' : '^'; var face; switch (status) { case 'pass': face = '( ^ .^)'; break; case 'fail': face = '( o .o)'; break; default: face = '( - .-)'; } write(tail + '|' + padding + face + ' '); write('\n'); break; case 3: var padding = self.tick ? ' ' : ' '; write(padding + '"" "" '); write('\n'); break; } }); this.cursorUp(this.numberOfLines); }; /** * Move cursor up `n`. * * @param {Number} n * @api private */ NyanCat.prototype.cursorUp = function(n) { write('\u001b[' + n + 'A'); }; /** * Move cursor down `n`. * * @param {Number} n * @api private */ NyanCat.prototype.cursorDown = function(n) { write('\u001b[' + n + 'B'); }; /** * Generate rainbow colors. * * @return {Array} * @api private */ NyanCat.prototype.generateColors = function(){ var colors = []; for (var i = 0; i < (6 * 7); i++) { var pi3 = Math.floor(Math.PI / 3); var n = (i * (1.0 / 6)); var r = Math.floor(3 * Math.sin(n) + 3); var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3); var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3); colors.push(36 * r + 6 * g + b + 16); } return colors; }; /** * Apply rainbow to the given `str`. * * @param {String} str * @return {String} * @api private */ NyanCat.prototype.rainbowify = function(str){ var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length]; this.colorIndex += 1; return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m'; }; /** * Stdout helper. */ function write(string) { process.stdout.write(string); } /** * Inherit from `Base.prototype`. */ function F(){}; F.prototype = Base.prototype; NyanCat.prototype = new F; NyanCat.prototype.constructor = NyanCat; }); // module: reporters/nyan.js require.register("reporters/progress.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `Progress`. */ exports = module.exports = Progress; /** * General progress bar color. */ Base.colors.progress = 90; /** * Initialize a new `Progress` bar test reporter. * * @param {Runner} runner * @param {Object} options * @api public */ function Progress(runner, options) { Base.call(this, runner); var self = this , options = options || {} , stats = this.stats , width = Base.window.width * .50 | 0 , total = runner.total , complete = 0 , max = Math.max; // default chars options.open = options.open || '['; options.complete = options.complete || '▬'; options.incomplete = options.incomplete || Base.symbols.dot; options.close = options.close || ']'; options.verbose = false; // tests started runner.on('start', function(){ console.log(); cursor.hide(); }); // tests complete runner.on('test end', function(){ complete++; var incomplete = total - complete , percent = complete / total , n = width * percent | 0 , i = width - n; cursor.CR(); process.stdout.write('\u001b[J'); process.stdout.write(color('progress', ' ' + options.open)); process.stdout.write(Array(n).join(options.complete)); process.stdout.write(Array(i).join(options.incomplete)); process.stdout.write(color('progress', options.close)); if (options.verbose) { process.stdout.write(color('progress', ' ' + complete + ' of ' + total)); } }); // tests are complete, output some stats // and the failures if any runner.on('end', function(){ cursor.show(); console.log(); self.epilogue(); }); } /** * Inherit from `Base.prototype`. */ function F(){}; F.prototype = Base.prototype; Progress.prototype = new F; Progress.prototype.constructor = Progress; }); // module: reporters/progress.js require.register("reporters/spec.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `Spec`. */ exports = module.exports = Spec; /** * Initialize a new `Spec` test reporter. * * @param {Runner} runner * @api public */ function Spec(runner) { Base.call(this, runner); var self = this , stats = this.stats , indents = 0 , n = 0; function indent() { return Array(indents).join(' ') } runner.on('start', function(){ console.log(); }); runner.on('suite', function(suite){ ++indents; console.log(color('suite', '%s%s'), indent(), suite.title); }); runner.on('suite end', function(suite){ --indents; if (1 == indents) console.log(); }); runner.on('test', function(test){ process.stdout.write(indent() + color('pass', ' ◦ ' + test.title + ': ')); }); runner.on('pending', function(test){ var fmt = indent() + color('pending', ' - %s'); console.log(fmt, test.title); }); runner.on('pass', function(test){ if ('fast' == test.speed) { var fmt = indent() + color('checkmark', ' ' + Base.symbols.ok) + color('pass', ' %s '); cursor.CR(); console.log(fmt, test.title); } else { var fmt = indent() + color('checkmark', ' ' + Base.symbols.ok) + color('pass', ' %s ') + color(test.speed, '(%dms)'); cursor.CR(); console.log(fmt, test.title, test.duration); } }); runner.on('fail', function(test, err){ cursor.CR(); console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); }); runner.on('end', self.epilogue.bind(self)); } /** * Inherit from `Base.prototype`. */ function F(){}; F.prototype = Base.prototype; Spec.prototype = new F; Spec.prototype.constructor = Spec; }); // module: reporters/spec.js require.register("reporters/tap.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `TAP`. */ exports = module.exports = TAP; /** * Initialize a new `TAP` reporter. * * @param {Runner} runner * @api public */ function TAP(runner) { Base.call(this, runner); var self = this , stats = this.stats , n = 1 , passes = 0 , failures = 0; runner.on('start', function(){ var total = runner.grepTotal(runner.suite); console.log('%d..%d', 1, total); }); runner.on('test end', function(){ ++n; }); runner.on('pending', function(test){ console.log('ok %d %s # SKIP -', n, title(test)); }); runner.on('pass', function(test){ passes++; console.log('ok %d %s', n, title(test)); }); runner.on('fail', function(test, err){ failures++; console.log('not ok %d %s', n, title(test)); if (err.stack) console.log(err.stack.replace(/^/gm, ' ')); }); runner.on('end', function(){ console.log('# tests ' + (passes + failures)); console.log('# pass ' + passes); console.log('# fail ' + failures); }); } /** * Return a TAP-safe title of `test` * * @param {Object} test * @return {String} * @api private */ function title(test) { return test.fullTitle().replace(/#/g, ''); } }); // module: reporters/tap.js require.register("reporters/teamcity.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base'); /** * Expose `Teamcity`. */ exports = module.exports = Teamcity; /** * Initialize a new `Teamcity` reporter. * * @param {Runner} runner * @api public */ function Teamcity(runner) { Base.call(this, runner); var stats = this.stats; runner.on('start', function() { console.log("##teamcity[testSuiteStarted name='mocha.suite']"); }); runner.on('test', function(test) { console.log("##teamcity[testStarted name='" + escape(test.fullTitle()) + "']"); }); runner.on('fail', function(test, err) { console.log("##teamcity[testFailed name='" + escape(test.fullTitle()) + "' message='" + escape(err.message) + "']"); }); runner.on('pending', function(test) { console.log("##teamcity[testIgnored name='" + escape(test.fullTitle()) + "' message='pending']"); }); runner.on('test end', function(test) { console.log("##teamcity[testFinished name='" + escape(test.fullTitle()) + "' duration='" + test.duration + "']"); }); runner.on('end', function() { console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='" + stats.duration + "']"); }); } /** * Escape the given `str`. */ function escape(str) { return str .replace(/\|/g, "||") .replace(/\n/g, "|n") .replace(/\r/g, "|r") .replace(/\[/g, "|[") .replace(/\]/g, "|]") .replace(/\u0085/g, "|x") .replace(/\u2028/g, "|l") .replace(/\u2029/g, "|p") .replace(/'/g, "|'"); } }); // module: reporters/teamcity.js require.register("reporters/xunit.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , utils = require('../utils') , escape = utils.escape; /** * Save timer references to avoid Sinon interfering (see GH-237). */ var Date = global.Date , setTimeout = global.setTimeout , setInterval = global.setInterval , clearTimeout = global.clearTimeout , clearInterval = global.clearInterval; /** * Expose `XUnit`. */ exports = module.exports = XUnit; /** * Initialize a new `XUnit` reporter. * * @param {Runner} runner * @api public */ function XUnit(runner) { Base.call(this, runner); var stats = this.stats , tests = [] , self = this; runner.on('pass', function(test){ tests.push(test); }); runner.on('fail', function(test){ tests.push(test); }); runner.on('end', function(){ console.log(tag('testsuite', { name: 'Mocha Tests' , tests: stats.tests , failures: stats.failures , errors: stats.failures , skip: stats.tests - stats.failures - stats.passes , timestamp: (new Date).toUTCString() , time: stats.duration / 1000 }, false)); tests.forEach(test); console.log(''); }); } /** * Inherit from `Base.prototype`. */ function F(){}; F.prototype = Base.prototype; XUnit.prototype = new F; XUnit.prototype.constructor = XUnit; /** * Output tag for the given `test.` */ function test(test) { var attrs = { classname: test.parent.fullTitle() , name: test.title , time: test.duration / 1000 }; if ('failed' == test.state) { var err = test.err; attrs.message = escape(err.message); console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack)))); } else if (test.pending) { console.log(tag('testcase', attrs, false, tag('skipped', {}, true))); } else { console.log(tag('testcase', attrs, true) ); } } /** * HTML tag helper. */ function tag(name, attrs, close, content) { var end = close ? '/>' : '>' , pairs = [] , tag; for (var key in attrs) { pairs.push(key + '="' + escape(attrs[key]) + '"'); } tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end; if (content) tag += content + ''; } }); // module: reporters/xunit.js require.register("runnable.js", function(module, exports, require){ /** * Module dependencies. */ var EventEmitter = require('browser/events').EventEmitter , debug = require('browser/debug')('mocha:runnable') , milliseconds = require('./ms'); /** * Save timer references to avoid Sinon interfering (see GH-237). */ var Date = global.Date , setTimeout = global.setTimeout , setInterval = global.setInterval , clearTimeout = global.clearTimeout , clearInterval = global.clearInterval; /** * Object#toString(). */ var toString = Object.prototype.toString; /** * Expose `Runnable`. */ module.exports = Runnable; /** * Initialize a new `Runnable` with the given `title` and callback `fn`. * * @param {String} title * @param {Function} fn * @api private */ function Runnable(title, fn) { this.title = title; this.fn = fn; this.async = fn && fn.length; this.sync = ! this.async; this._timeout = 2000; this._slow = 75; this.timedOut = false; } /** * Inherit from `EventEmitter.prototype`. */ function F(){}; F.prototype = EventEmitter.prototype; Runnable.prototype = new F; Runnable.prototype.constructor = Runnable; /** * Set & get timeout `ms`. * * @param {Number|String} ms * @return {Runnable|Number} ms or self * @api private */ Runnable.prototype.timeout = function(ms){ if (0 == arguments.length) return this._timeout; if ('string' == typeof ms) ms = milliseconds(ms); debug('timeout %d', ms); this._timeout = ms; if (this.timer) this.resetTimeout(); return this; }; /** * Set & get slow `ms`. * * @param {Number|String} ms * @return {Runnable|Number} ms or self * @api private */ Runnable.prototype.slow = function(ms){ if (0 === arguments.length) return this._slow; if ('string' == typeof ms) ms = milliseconds(ms); debug('timeout %d', ms); this._slow = ms; return this; }; /** * Return the full title generated by recursively * concatenating the parent's full title. * * @return {String} * @api public */ Runnable.prototype.fullTitle = function(){ return this.parent.fullTitle() + ' ' + this.title; }; /** * Clear the timeout. * * @api private */ Runnable.prototype.clearTimeout = function(){ clearTimeout(this.timer); }; /** * Inspect the runnable void of private properties. * * @return {String} * @api private */ Runnable.prototype.inspect = function(){ return JSON.stringify(this, function(key, val){ if ('_' == key[0]) return; if ('parent' == key) return '#'; if ('ctx' == key) return '#'; return val; }, 2); }; /** * Reset the timeout. * * @api private */ Runnable.prototype.resetTimeout = function(){ var self = this , ms = this.timeout(); this.clearTimeout(); if (ms) { this.timer = setTimeout(function(){ self.callback(new Error('timeout of ' + ms + 'ms exceeded')); self.timedOut = true; }, ms); } }; /** * Run the test and invoke `fn(err)`. * * @param {Function} fn * @api private */ Runnable.prototype.run = function(fn){ var self = this , ms = this.timeout() , start = new Date , ctx = this.ctx , finished , emitted; if (ctx) ctx.runnable(this); // timeout if (this.async) { if (ms) { this.timer = setTimeout(function(){ done(new Error('timeout of ' + ms + 'ms exceeded')); self.timedOut = true; }, ms); } } // called multiple times function multiple(err) { if (emitted) return; emitted = true; self.emit('error', err || new Error('done() called multiple times')); } // finished function done(err) { if (self.timedOut) return; if (finished) return multiple(err); self.clearTimeout(); self.duration = new Date - start; finished = true; fn(err); } // for .resetTimeout() this.callback = done; // async if (this.async) { try { this.fn.call(ctx, function(err){ if (err instanceof Error || toString.call(err) === "[object Error]") return done(err); if (null != err) return done(new Error('done() invoked with non-Error: ' + err)); done(); }); } catch (err) { done(err); } return; } if (this.asyncOnly) { return done(new Error('--async-only option in use without declaring `done()`')); } // sync try { if (!this.pending) this.fn.call(ctx); this.duration = new Date - start; fn(); } catch (err) { fn(err); } }; }); // module: runnable.js require.register("runner.js", function(module, exports, require){ /** * Module dependencies. */ var EventEmitter = require('browser/events').EventEmitter , debug = require('browser/debug')('mocha:runner') , Test = require('./test') , utils = require('./utils') , filter = utils.filter , keys = utils.keys , noop = function(){}; /** * Non-enumerable globals. */ var globals = [ 'setTimeout', 'clearTimeout', 'setInterval', 'clearInterval', 'XMLHttpRequest', 'Date' ]; /** * Expose `Runner`. */ module.exports = Runner; /** * Initialize a `Runner` for the given `suite`. * * Events: * * - `start` execution started * - `end` execution complete * - `suite` (suite) test suite execution started * - `suite end` (suite) all tests (and sub-suites) have finished * - `test` (test) test execution started * - `test end` (test) test completed * - `hook` (hook) hook execution started * - `hook end` (hook) hook complete * - `pass` (test) test passed * - `fail` (test, err) test failed * * @api public */ function Runner(suite) { var self = this; this._globals = []; this.suite = suite; this.total = suite.total(); this.failures = 0; this.on('test end', function(test){ self.checkGlobals(test); }); this.on('hook end', function(hook){ self.checkGlobals(hook); }); this.grep(/.*/); this.globals(this.globalProps().concat(['errno'])); } /** * Inherit from `EventEmitter.prototype`. */ function F(){}; F.prototype = EventEmitter.prototype; Runner.prototype = new F; Runner.prototype.constructor = Runner; /** * Run tests with full titles matching `re`. Updates runner.total * with number of tests matched. * * @param {RegExp} re * @param {Boolean} invert * @return {Runner} for chaining * @api public */ Runner.prototype.grep = function(re, invert){ debug('grep %s', re); this._grep = re; this._invert = invert; this.total = this.grepTotal(this.suite); return this; }; /** * Returns the number of tests matching the grep search for the * given suite. * * @param {Suite} suite * @return {Number} * @api public */ Runner.prototype.grepTotal = function(suite) { var self = this; var total = 0; suite.eachTest(function(test){ var match = self._grep.test(test.fullTitle()); if (self._invert) match = !match; if (match) total++; }); return total; }; /** * Return a list of global properties. * * @return {Array} * @api private */ Runner.prototype.globalProps = function() { var props = utils.keys(global); // non-enumerables for (var i = 0; i < globals.length; ++i) { if (~utils.indexOf(props, globals[i])) continue; props.push(globals[i]); } return props; }; /** * Allow the given `arr` of globals. * * @param {Array} arr * @return {Runner} for chaining * @api public */ Runner.prototype.globals = function(arr){ if (0 == arguments.length) return this._globals; debug('globals %j', arr); utils.forEach(arr, function(arr){ this._globals.push(arr); }, this); return this; }; /** * Check for global variable leaks. * * @api private */ Runner.prototype.checkGlobals = function(test){ if (this.ignoreLeaks) return; var ok = this._globals; var globals = this.globalProps(); var isNode = process.kill; var leaks; // check length - 2 ('errno' and 'location' globals) if (isNode && 1 == ok.length - globals.length) return else if (2 == ok.length - globals.length) return; leaks = filterLeaks(ok, globals); this._globals = this._globals.concat(leaks); if (leaks.length > 1) { this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + '')); } else if (leaks.length) { this.fail(test, new Error('global leak detected: ' + leaks[0])); } }; /** * Fail the given `test`. * * @param {Test} test * @param {Error} err * @api private */ Runner.prototype.fail = function(test, err){ ++this.failures; test.state = 'failed'; if ('string' == typeof err) { err = new Error('the string "' + err + '" was thrown, throw an Error :)'); } this.emit('fail', test, err); }; /** * Fail the given `hook` with `err`. * * Hook failures (currently) hard-end due * to that fact that a failing hook will * surely cause subsequent tests to fail, * causing jumbled reporting. * * @param {Hook} hook * @param {Error} err * @api private */ Runner.prototype.failHook = function(hook, err){ this.fail(hook, err); this.emit('end'); }; /** * Run hook `name` callbacks and then invoke `fn()`. * * @param {String} name * @param {Function} function * @api private */ Runner.prototype.hook = function(name, fn){ var suite = this.suite , hooks = suite['_' + name] , self = this , timer; function next(i) { var hook = hooks[i]; if (!hook) return fn(); self.currentRunnable = hook; self.emit('hook', hook); hook.on('error', function(err){ self.failHook(hook, err); }); hook.run(function(err){ hook.removeAllListeners('error'); var testError = hook.error(); if (testError) self.fail(self.test, testError); if (err) return self.failHook(hook, err); self.emit('hook end', hook); next(++i); }); } process.nextTick(function(){ next(0); }); }; /** * Run hook `name` for the given array of `suites` * in order, and callback `fn(err)`. * * @param {String} name * @param {Array} suites * @param {Function} fn * @api private */ Runner.prototype.hooks = function(name, suites, fn){ var self = this , orig = this.suite; function next(suite) { self.suite = suite; if (!suite) { self.suite = orig; return fn(); } self.hook(name, function(err){ if (err) { self.suite = orig; return fn(err); } next(suites.pop()); }); } next(suites.pop()); }; /** * Run hooks from the top level down. * * @param {String} name * @param {Function} fn * @api private */ Runner.prototype.hookUp = function(name, fn){ var suites = [this.suite].concat(this.parents()).reverse(); this.hooks(name, suites, fn); }; /** * Run hooks from the bottom up. * * @param {String} name * @param {Function} fn * @api private */ Runner.prototype.hookDown = function(name, fn){ var suites = [this.suite].concat(this.parents()); this.hooks(name, suites, fn); }; /** * Return an array of parent Suites from * closest to furthest. * * @return {Array} * @api private */ Runner.prototype.parents = function(){ var suite = this.suite , suites = []; while (suite = suite.parent) suites.push(suite); return suites; }; /** * Run the current test and callback `fn(err)`. * * @param {Function} fn * @api private */ Runner.prototype.runTest = function(fn){ var test = this.test , self = this; if (this.asyncOnly) test.asyncOnly = true; try { test.on('error', function(err){ self.fail(test, err); }); test.run(fn); } catch (err) { fn(err); } }; /** * Run tests in the given `suite` and invoke * the callback `fn()` when complete. * * @param {Suite} suite * @param {Function} fn * @api private */ Runner.prototype.runTests = function(suite, fn){ var self = this , tests = suite.tests.slice() , test; function next(err) { // if we bail after first err if (self.failures && suite._bail) return fn(); // next test test = tests.shift(); // all done if (!test) return fn(); // grep var match = self._grep.test(test.fullTitle()); if (self._invert) match = !match; if (!match) return next(); // pending if (test.pending) { self.emit('pending', test); self.emit('test end', test); return next(); } // execute test and hook(s) self.emit('test', self.test = test); self.hookDown('beforeEach', function(){ self.currentRunnable = self.test; self.runTest(function(err){ test = self.test; if (err) { self.fail(test, err); self.emit('test end', test); return self.hookUp('afterEach', next); } test.state = 'passed'; self.emit('pass', test); self.emit('test end', test); self.hookUp('afterEach', next); }); }); } this.next = next; next(); }; /** * Run the given `suite` and invoke the * callback `fn()` when complete. * * @param {Suite} suite * @param {Function} fn * @api private */ Runner.prototype.runSuite = function(suite, fn){ var total = this.grepTotal(suite) , self = this , i = 0; debug('run suite %s', suite.fullTitle()); if (!total) return fn(); this.emit('suite', this.suite = suite); function next() { var curr = suite.suites[i++]; if (!curr) return done(); self.runSuite(curr, next); } function done() { self.suite = suite; self.hook('afterAll', function(){ self.emit('suite end', suite); fn(); }); } this.hook('beforeAll', function(){ self.runTests(suite, next); }); }; /** * Handle uncaught exceptions. * * @param {Error} err * @api private */ Runner.prototype.uncaught = function(err){ debug('uncaught exception %s', err.message); var runnable = this.currentRunnable; if (!runnable || 'failed' == runnable.state) return; runnable.clearTimeout(); err.uncaught = true; this.fail(runnable, err); // recover from test if ('test' == runnable.type) { this.emit('test end', runnable); this.hookUp('afterEach', this.next); return; } // bail on hooks this.emit('end'); }; /** * Run the root suite and invoke `fn(failures)` * on completion. * * @param {Function} fn * @return {Runner} for chaining * @api public */ Runner.prototype.run = function(fn){ var self = this , fn = fn || function(){}; debug('start'); // callback this.on('end', function(){ debug('end'); process.removeListener('uncaughtException', function(err){ self.uncaught(err); }); fn(self.failures); }); // run suites this.emit('start'); this.runSuite(this.suite, function(){ debug('finished running'); self.emit('end'); }); // uncaught exception process.on('uncaughtException', function(err){ self.uncaught(err); }); return this; }; /** * Filter leaks with the given globals flagged as `ok`. * * @param {Array} ok * @param {Array} globals * @return {Array} * @api private */ function filterLeaks(ok, globals) { return filter(globals, function(key){ var matched = filter(ok, function(ok){ if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]); // Opera and IE expose global variables for HTML element IDs (issue #243) if (/^mocha-/.test(key)) return true; return key == ok; }); return matched.length == 0 && (!global.navigator || 'onerror' !== key); }); } }); // module: runner.js require.register("suite.js", function(module, exports, require){ /** * Module dependencies. */ var EventEmitter = require('browser/events').EventEmitter , debug = require('browser/debug')('mocha:suite') , milliseconds = require('./ms') , utils = require('./utils') , Hook = require('./hook'); /** * Expose `Suite`. */ exports = module.exports = Suite; /** * Create a new `Suite` with the given `title` * and parent `Suite`. When a suite with the * same title is already present, that suite * is returned to provide nicer reporter * and more flexible meta-testing. * * @param {Suite} parent * @param {String} title * @return {Suite} * @api public */ exports.create = function(parent, title){ var suite = new Suite(title, parent.ctx); suite.parent = parent; if (parent.pending) suite.pending = true; title = suite.fullTitle(); parent.addSuite(suite); return suite; }; /** * Initialize a new `Suite` with the given * `title` and `ctx`. * * @param {String} title * @param {Context} ctx * @api private */ function Suite(title, ctx) { this.title = title; this.ctx = ctx; this.suites = []; this.tests = []; this.pending = false; this._beforeEach = []; this._beforeAll = []; this._afterEach = []; this._afterAll = []; this.root = !title; this._timeout = 2000; this._slow = 75; this._bail = false; } /** * Inherit from `EventEmitter.prototype`. */ function F(){}; F.prototype = EventEmitter.prototype; Suite.prototype = new F; Suite.prototype.constructor = Suite; /** * Return a clone of this `Suite`. * * @return {Suite} * @api private */ Suite.prototype.clone = function(){ var suite = new Suite(this.title); debug('clone'); suite.ctx = this.ctx; suite.timeout(this.timeout()); suite.slow(this.slow()); suite.bail(this.bail()); return suite; }; /** * Set timeout `ms` or short-hand such as "2s". * * @param {Number|String} ms * @return {Suite|Number} for chaining * @api private */ Suite.prototype.timeout = function(ms){ if (0 == arguments.length) return this._timeout; if ('string' == typeof ms) ms = milliseconds(ms); debug('timeout %d', ms); this._timeout = parseInt(ms, 10); return this; }; /** * Set slow `ms` or short-hand such as "2s". * * @param {Number|String} ms * @return {Suite|Number} for chaining * @api private */ Suite.prototype.slow = function(ms){ if (0 === arguments.length) return this._slow; if ('string' == typeof ms) ms = milliseconds(ms); debug('slow %d', ms); this._slow = ms; return this; }; /** * Sets whether to bail after first error. * * @parma {Boolean} bail * @return {Suite|Number} for chaining * @api private */ Suite.prototype.bail = function(bail){ if (0 == arguments.length) return this._bail; debug('bail %s', bail); this._bail = bail; return this; }; /** * Run `fn(test[, done])` before running tests. * * @param {Function} fn * @return {Suite} for chaining * @api private */ Suite.prototype.beforeAll = function(fn){ if (this.pending) return this; var hook = new Hook('"before all" hook', fn); hook.parent = this; hook.timeout(this.timeout()); hook.slow(this.slow()); hook.ctx = this.ctx; this._beforeAll.push(hook); this.emit('beforeAll', hook); return this; }; /** * Run `fn(test[, done])` after running tests. * * @param {Function} fn * @return {Suite} for chaining * @api private */ Suite.prototype.afterAll = function(fn){ if (this.pending) return this; var hook = new Hook('"after all" hook', fn); hook.parent = this; hook.timeout(this.timeout()); hook.slow(this.slow()); hook.ctx = this.ctx; this._afterAll.push(hook); this.emit('afterAll', hook); return this; }; /** * Run `fn(test[, done])` before each test case. * * @param {Function} fn * @return {Suite} for chaining * @api private */ Suite.prototype.beforeEach = function(fn){ if (this.pending) return this; var hook = new Hook('"before each" hook', fn); hook.parent = this; hook.timeout(this.timeout()); hook.slow(this.slow()); hook.ctx = this.ctx; this._beforeEach.push(hook); this.emit('beforeEach', hook); return this; }; /** * Run `fn(test[, done])` after each test case. * * @param {Function} fn * @return {Suite} for chaining * @api private */ Suite.prototype.afterEach = function(fn){ if (this.pending) return this; var hook = new Hook('"after each" hook', fn); hook.parent = this; hook.timeout(this.timeout()); hook.slow(this.slow()); hook.ctx = this.ctx; this._afterEach.push(hook); this.emit('afterEach', hook); return this; }; /** * Add a test `suite`. * * @param {Suite} suite * @return {Suite} for chaining * @api private */ Suite.prototype.addSuite = function(suite){ suite.parent = this; suite.timeout(this.timeout()); suite.slow(this.slow()); suite.bail(this.bail()); this.suites.push(suite); this.emit('suite', suite); return this; }; /** * Add a `test` to this suite. * * @param {Test} test * @return {Suite} for chaining * @api private */ Suite.prototype.addTest = function(test){ test.parent = this; test.timeout(this.timeout()); test.slow(this.slow()); test.ctx = this.ctx; this.tests.push(test); this.emit('test', test); return this; }; /** * Return the full title generated by recursively * concatenating the parent's full title. * * @return {String} * @api public */ Suite.prototype.fullTitle = function(){ if (this.parent) { var full = this.parent.fullTitle(); if (full) return full + ' ' + this.title; } return this.title; }; /** * Return the total number of tests. * * @return {Number} * @api public */ Suite.prototype.total = function(){ return utils.reduce(this.suites, function(sum, suite){ return sum + suite.total(); }, 0) + this.tests.length; }; /** * Iterates through each suite recursively to find * all tests. Applies a function in the format * `fn(test)`. * * @param {Function} fn * @return {Suite} * @api private */ Suite.prototype.eachTest = function(fn){ utils.forEach(this.tests, fn); utils.forEach(this.suites, function(suite){ suite.eachTest(fn); }); return this; }; }); // module: suite.js require.register("test.js", function(module, exports, require){ /** * Module dependencies. */ var Runnable = require('./runnable'); /** * Expose `Test`. */ module.exports = Test; /** * Initialize a new `Test` with the given `title` and callback `fn`. * * @param {String} title * @param {Function} fn * @api private */ function Test(title, fn) { Runnable.call(this, title, fn); this.pending = !fn; this.type = 'test'; } /** * Inherit from `Runnable.prototype`. */ function F(){}; F.prototype = Runnable.prototype; Test.prototype = new F; Test.prototype.constructor = Test; }); // module: test.js require.register("utils.js", function(module, exports, require){ /** * Module dependencies. */ var fs = require('browser/fs') , path = require('browser/path') , join = path.join , debug = require('browser/debug')('mocha:watch'); /** * Ignored directories. */ var ignore = ['node_modules', '.git']; /** * Escape special characters in the given string of html. * * @param {String} html * @return {String} * @api private */ exports.escape = function(html){ return String(html) .replace(/&/g, '&') .replace(/"/g, '"') .replace(//g, '>'); }; /** * Array#forEach (<=IE8) * * @param {Array} array * @param {Function} fn * @param {Object} scope * @api private */ exports.forEach = function(arr, fn, scope){ for (var i = 0, l = arr.length; i < l; i++) fn.call(scope, arr[i], i); }; /** * Array#indexOf (<=IE8) * * @parma {Array} arr * @param {Object} obj to find index of * @param {Number} start * @api private */ exports.indexOf = function(arr, obj, start){ for (var i = start || 0, l = arr.length; i < l; i++) { if (arr[i] === obj) return i; } return -1; }; /** * Array#reduce (<=IE8) * * @param {Array} array * @param {Function} fn * @param {Object} initial value * @api private */ exports.reduce = function(arr, fn, val){ var rval = val; for (var i = 0, l = arr.length; i < l; i++) { rval = fn(rval, arr[i], i, arr); } return rval; }; /** * Array#filter (<=IE8) * * @param {Array} array * @param {Function} fn * @api private */ exports.filter = function(arr, fn){ var ret = []; for (var i = 0, l = arr.length; i < l; i++) { var val = arr[i]; if (fn(val, i, arr)) ret.push(val); } return ret; }; /** * Object.keys (<=IE8) * * @param {Object} obj * @return {Array} keys * @api private */ exports.keys = Object.keys || function(obj) { var keys = [] , has = Object.prototype.hasOwnProperty // for `window` on <=IE8 for (var key in obj) { if (has.call(obj, key)) { keys.push(key); } } return keys; }; /** * Watch the given `files` for changes * and invoke `fn(file)` on modification. * * @param {Array} files * @param {Function} fn * @api private */ exports.watch = function(files, fn){ var options = { interval: 100 }; files.forEach(function(file){ debug('file %s', file); fs.watchFile(file, options, function(curr, prev){ if (prev.mtime < curr.mtime) fn(file); }); }); }; /** * Ignored files. */ function ignored(path){ return !~ignore.indexOf(path); } /** * Lookup files in the given `dir`. * * @return {Array} * @api private */ exports.files = function(dir, ret){ ret = ret || []; fs.readdirSync(dir) .filter(ignored) .forEach(function(path){ path = join(dir, path); if (fs.statSync(path).isDirectory()) { exports.files(path, ret); } else if (path.match(/\.(js|coffee)$/)) { ret.push(path); } }); return ret; }; /** * Compute a slug from the given `str`. * * @param {String} str * @return {String} * @api private */ exports.slug = function(str){ return str .toLowerCase() .replace(/ +/g, '-') .replace(/[^-\w]/g, ''); }; /** * Strip the function definition from `str`, * and re-indent for pre whitespace. */ exports.clean = function(str) { str = str .replace(/^function *\(.*\) *{/, '') .replace(/\s+\}$/, ''); var spaces = str.match(/^\n?( *)/)[1].length , re = new RegExp('^ {' + spaces + '}', 'gm'); str = str.replace(re, ''); return exports.trim(str); }; /** * Escape regular expression characters in `str`. * * @param {String} str * @return {String} * @api private */ exports.escapeRegexp = function(str){ return str.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&"); }; /** * Trim the given `str`. * * @param {String} str * @return {String} * @api private */ exports.trim = function(str){ return str.replace(/^\s+|\s+$/g, ''); }; /** * Parse the given `qs`. * * @param {String} qs * @return {Object} * @api private */ exports.parseQuery = function(qs){ return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){ var i = pair.indexOf('=') , key = pair.slice(0, i) , val = pair.slice(++i); obj[key] = decodeURIComponent(val); return obj; }, {}); }; /** * Highlight the given string of `js`. * * @param {String} js * @return {String} * @api private */ function highlight(js) { return js .replace(//g, '>') .replace(/\/\/(.*)/gm, '//$1') .replace(/('.*?')/gm, '$1') .replace(/(\d+\.\d+)/gm, '$1') .replace(/(\d+)/gm, '$1') .replace(/\bnew *(\w+)/gm, 'new $1') .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '$1') } /** * Highlight the contents of tag `name`. * * @param {String} name * @api private */ exports.highlightTags = function(name) { var code = document.getElementsByTagName(name); for (var i = 0, len = code.length; i < len; ++i) { code[i].innerHTML = highlight(code[i].innerHTML); } }; }); // module: utils.js /** * Node shims. * * These are meant only to allow * mocha.js to run untouched, not * to allow running node code in * the browser. */ process = {}; process.exit = function(status){}; process.stdout = {}; global = window; /** * next tick implementation. */ process.nextTick = (function(){ // postMessage behaves badly on IE8 if (window.ActiveXObject || !window.postMessage) { return function(fn){ fn() }; } // based on setZeroTimeout by David Baron // - http://dbaron.org/log/20100309-faster-timeouts var timeouts = [] , name = 'mocha-zero-timeout' window.addEventListener('message', function(e){ if (e.source == window && e.data == name) { if (e.stopPropagation) e.stopPropagation(); if (timeouts.length) timeouts.shift()(); } }, true); return function(fn){ timeouts.push(fn); window.postMessage(name, '*'); } })(); /** * Remove uncaughtException listener. */ process.removeListener = function(e){ if ('uncaughtException' == e) { window.onerror = null; } }; /** * Implements uncaughtException listener. */ process.on = function(e, fn){ if ('uncaughtException' == e) { window.onerror = function(err, url, line){ fn(new Error(err + ' (' + url + ':' + line + ')')); }; } }; // boot ;(function(){ /** * Expose mocha. */ var Mocha = window.Mocha = require('mocha'), mocha = window.mocha = new Mocha({ reporter: 'html' }); /** * Override ui to ensure that the ui functions are initialized. * Normally this would happen in Mocha.prototype.loadFiles. */ mocha.ui = function(ui){ Mocha.prototype.ui.call(this, ui); this.suite.emit('pre-require', window, null, this); return this; }; /** * Setup mocha with the given setting options. */ mocha.setup = function(opts){ if ('string' == typeof opts) opts = { ui: opts }; for (var opt in opts) this[opt](opts[opt]); return this; }; /** * Run mocha, returning the Runner. */ mocha.run = function(fn){ var options = mocha.options; mocha.globals('location'); var query = Mocha.utils.parseQuery(window.location.search || ''); if (query.grep) mocha.grep(query.grep); if (query.invert) mocha.invert(); return Mocha.prototype.run.call(mocha, function(){ Mocha.utils.highlightTags('code'); if (fn) fn(); }); }; })(); })(); ================================================ FILE: test/spec/test.js ================================================ /*global describe, it */ 'use strict'; (function () { describe('Give it some context', function () { describe('maybe a bit more context here', function () { it('should run here few assertions', function () { }); }); }); })();