├── .gitignore ├── .travis.yml ├── Aquarelle.js ├── AquarellePass.js ├── LICENSE ├── README.md ├── Screenshots └── web__transition__effect_ramotion.gif ├── bower.json ├── deploy-to-gh-pages.sh ├── examples ├── bower.json ├── example_scroll.html ├── img │ ├── bg.png │ ├── icon01.png │ ├── icon02.png │ ├── icon03.png │ ├── jobs.jpg │ ├── logo.png │ ├── mask.png │ ├── mouse.svg │ ├── splash.png │ ├── title.png │ └── top_menu.png └── index.html └── header.png /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .DS_Store 3 | examples/bower_components/ 4 | examples/.git -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | before_script: 3 | - npm install -g bower 4 | script: 5 | - bash ./deploy-to-gh-pages.sh 6 | env: 7 | global: 8 | - GITHUB_REPO: "Ramotion/aquarelle" 9 | - secure: "jbYrk4ft6krPuSanHopdtgUAUknFVS1m0+fokfS9FJWhsuOqmfP59EKF4mQpPk2ywLIu25NxPF6PuK26sk+8JVmiI4a+ycQIgjjbo/SStzJBy6mCTuXDjU1jJN8W3z20yf3+ltFtJuPmrE6nTZ+FAhmRk/Fp/A2TjjQsmz+ZlnCjTWjuiLEEkXY9nkqrceftUBt4BvHRcqn3vWp8ipDAiP52MJ9lArk4nHe6URcAvURk4QEuQ6bu8hRyysI8/ukSnVFHD4vYvn1T2ed5U3KgJqiayVJD32epSyYFixx+aLpwmJyMTrRpOkjCoxNwn6yDN4sKHuox5pUyWP2wzdSCvJCTrwHc2N+End5/n9YTOTM2UX75mtaMRTsg+lrngg3rQvCjdxGMXD4uM6u1r1KLvocYjOSM4P1sttV7g3Tu/Gmp5BCYC++snoG3SDlbfu2shtf8gARO7MnM5lpo8+NnkBT2NtUh9/g5RAbUkXbNLqs4pFhdg7wN/ieRLPqRIWK5d/zJZfGsUpLtqLrqfXZOU4nrxF6quGfTKJ1zdFj6GQIKvbfr7YQSVa79121Khmfb2xDX8/SLb/D5qVbF4pxXX3lpzVT9qXFVqLlBLCoBpH7XPvM1ys6v06VvZN8ML2TyMVSe43oTvQoFip6t2ss+RTN+4+Y2oHgaTk2gw9uo9gU=" -------------------------------------------------------------------------------- /Aquarelle.js: -------------------------------------------------------------------------------- 1 | var THREE = window.THREE || {}; 2 | 3 | (function() { 4 | var stack = []; 5 | var lastTime = Date.now(); 6 | 7 | // Thanks https://github.com/d3 for the plugin 8 | function contour(grid) { 9 | var s = []; 10 | var c = []; 11 | var x = s ? s[0] : 0; 12 | var y = s ? s[1] : 0; 13 | var dx = 0; 14 | var dy = 0; 15 | var pdx = NaN; 16 | var pdy = NaN; 17 | var i = 0; 18 | 19 | while(true) { 20 | if(grid(x, y)) { 21 | s = [x, y]; 22 | break; 23 | } 24 | if(x) { 25 | x = x - 1; 26 | y = y + 1; 27 | } else { 28 | x = y + 1; 29 | y = 0; 30 | } 31 | } 32 | 33 | do { 34 | i = 0; 35 | 36 | if(grid(x - 1, y - 1)) { 37 | i += 1; 38 | } 39 | if(grid(x, y - 1)) { 40 | i += 2; 41 | } 42 | if(grid(x - 1, y)) { 43 | i += 4; 44 | } 45 | if(grid(x, y)) { 46 | i += 8; 47 | } 48 | 49 | if(i === 6) { 50 | dx = pdy === -1 ? -1 : 1; 51 | dy = 0; 52 | } else 53 | if(i === 9) { 54 | dx = 0; 55 | dy = pdx === 1 ? -1 : 1; 56 | } else { 57 | dx = [1, 0, 1, 1, -1, 0, -1, 1, 0, 0, 0, 0, -1, 0, -1, NaN][i]; 58 | dy = [0, -1, 0, 0, 0, -1, 0, 0, 1, -1, 1, 1, 0, -1, 0, NaN][i]; 59 | } 60 | 61 | if(dx != pdx && dy != pdy) { 62 | c.push([x, y]); 63 | pdx = dx; 64 | pdy = dy; 65 | } 66 | 67 | x += dx; 68 | y += dy; 69 | } while(s[0] != x || s[1] != y); 70 | 71 | return c; 72 | } 73 | 74 | function Aquarelle(texture, mask, options) { 75 | var self = this; 76 | 77 | self.setOptions(Aquarelle.defaultOptions); 78 | self.setOptions(options); 79 | 80 | self.mask = {}; 81 | 82 | self.mask.canvas = document.createElement('canvas'); 83 | self.mask.ctx = self.mask.canvas.getContext('2d'); 84 | 85 | if(typeof mask === 'string') { 86 | self.mask.img = new Image; 87 | self.mask.img.onload = function() { 88 | self.drawMaskImage(); 89 | }; 90 | self.mask.crossOrigin = 'Anonymous'; 91 | self.mask.img.src = mask; 92 | } else 93 | if(mask.nodeName && mask.src) { 94 | self.mask.img = mask; 95 | self.drawMaskImage(); 96 | } 97 | 98 | THREE.ImageUtils.crossOrigin = ''; 99 | new THREE.TextureLoader().load(texture && (typeof texture === 'string' ? texture : texture.nodeName && texture.src) || '', function(texture) { 100 | self.texture = texture; 101 | texture.minFilter = THREE.LinearFilter; 102 | 103 | var composer = self.getComposer(); 104 | 105 | composer.addPass(new THREE.ClearPass); 106 | 107 | var mask = new THREE.Texture(self.mask.canvas); 108 | mask.needsUpdate = true; 109 | mask.minFilter = THREE.LinearFilter; 110 | 111 | var turbulentPass = self.turbulentPass = new THREE.AquarellePass(texture, mask); 112 | composer.addPass(turbulentPass); 113 | 114 | var outputPass = new THREE.ShaderPass(THREE.CopyShader); 115 | outputPass.renderToScreen = true; 116 | composer.addPass(outputPass); 117 | 118 | self.dispatchEvent(self.getEventObject('created')); 119 | 120 | if(self.options.autoplay) { 121 | self.start(); 122 | } 123 | 124 | self.reset(); 125 | 126 | self.isInitialized = true; 127 | }); 128 | 129 | stack.push(self); 130 | } 131 | 132 | Object.assign(Aquarelle.prototype, THREE.EventDispatcher.prototype); 133 | 134 | Aquarelle.prototype.getRenderer = function() { 135 | if(!this.renderer) { 136 | var renderer = this.renderer = new THREE.WebGLRenderer({ 137 | alpha: true 138 | }); 139 | renderer.setClearColor(0x000000, 0); 140 | renderer.setSize(this.texture.image.width, this.texture.image.height); 141 | renderer.autoClear = false; 142 | } 143 | 144 | return this.renderer; 145 | }; 146 | Aquarelle.prototype.getCanvas = function() { 147 | return this.getRenderer().domElement; 148 | }; 149 | Aquarelle.prototype.getComposer = function() { 150 | if(!this.composer) { 151 | this.composer = new THREE.EffectComposer(this.getRenderer(), new THREE.WebGLRenderTarget(this.texture.image.width, this.texture.image.height)); 152 | } 153 | 154 | return this.composer; 155 | }; 156 | 157 | Aquarelle.prototype.drawMaskImage = function() { 158 | var mask = this.mask || {}; 159 | 160 | if(mask.img) { 161 | mask.canvas.width = mask.img.width; 162 | mask.canvas.height = mask.img.height; 163 | 164 | mask.ctx.drawImage(mask.img, 0, 0); 165 | 166 | var data = mask.ctx.getImageData(0, 0, mask.img.width, mask.img.height).data; 167 | mask.points = contour(function(x, y) { 168 | return data[(y * mask.img.width + x) * 4 + 3] > 0; 169 | }); 170 | } 171 | }; 172 | Aquarelle.prototype.renderMask = function() { 173 | var mask = this.mask || {}; 174 | 175 | if(!mask.points) { 176 | return; 177 | } 178 | 179 | mask.ctx.clearRect(0, 0, mask.canvas.width, mask.canvas.height); 180 | 181 | mask.ctx.lineJoin = 'round'; 182 | mask.ctx.lineWidth = Math.abs(mask.offset) * 2; 183 | 184 | if(mask.offset) { 185 | mask.ctx.globalCompositeOperation = 'source-' + (mask.offset < 0 ? 'out' : 'over'); 186 | 187 | this.pathPoints(); 188 | mask.ctx.stroke(); 189 | } 190 | 191 | this.pathPoints(); 192 | mask.ctx.fill(); 193 | }; 194 | Aquarelle.prototype.pathPoints = function() { 195 | var mask = this.mask || {}; 196 | 197 | mask.ctx.beginPath(); 198 | mask.points.forEach(function(point, index) { 199 | mask.ctx[index ? 'lineTo' : 'moveTo'](point[0], point[1]); 200 | }); 201 | mask.ctx.closePath(); 202 | }; 203 | 204 | Aquarelle.prototype.direction = 1; 205 | Aquarelle.prototype.progress = 1; 206 | Aquarelle.prototype.isPaused = true; 207 | 208 | Aquarelle.prototype.render = function(delta) { 209 | if(!this.turbulentPass || !this.composer) { 210 | return; 211 | } 212 | 213 | var lastProgress = this.progress; 214 | var progress = this.clampedProgress(lastProgress + this.direction * delta / (this.options.duration / 1000)); 215 | 216 | if(!this.isPaused && lastProgress !== progress) { 217 | this.progress = progress; 218 | this.reset(); 219 | } 220 | 221 | this.renderMask(); 222 | this.getRenderer().clear(); 223 | this.getComposer().render(delta); 224 | }; 225 | 226 | Aquarelle.prototype.transitionForProgressInRange = function(progress, startValue, endValue) { 227 | return startValue + (endValue - startValue) * progress; 228 | }; 229 | Aquarelle.prototype.progressForValueInRange = function(value, startValue, endValue) { 230 | return (value - startValue) / (endValue - startValue); 231 | }; 232 | Aquarelle.prototype.clampedProgress = function(progress) { 233 | return Math.max(0, Math.min(progress, 1)); 234 | }; 235 | 236 | Aquarelle.prototype.transitionInRange = function(startValue, endValue, startTime, endTime) { 237 | return this.transitionForProgressInRange(this.clampedProgress(this.progressForValueInRange(this.progress, (startTime || 0) / this.options.duration, (endTime || this.options.duration) / this.options.duration)), startValue, endValue); 238 | }; 239 | 240 | Aquarelle.prototype.isComplete = function() { 241 | return this.direction > 0 ? this.progress === 1 : this.direction < 0 && !this.progress; 242 | }; 243 | 244 | Aquarelle.prototype.pause = function() { 245 | if(this.isPaused) { 246 | return; 247 | } 248 | 249 | this.isPaused = true; 250 | 251 | if(this.isInitialized) { 252 | this.dispatchEvent(this.getEventObject('paused')); 253 | } 254 | }; 255 | Aquarelle.prototype.play = function() { 256 | if(!this.isPaused) { 257 | return; 258 | } 259 | 260 | this.isPaused = false; 261 | 262 | this.dispatchEvent(this.getEventObject('played')); 263 | }; 264 | Aquarelle.prototype.stop = function() { 265 | if(this.progress === +(this.direction >= 0) && this.isPaused) { 266 | return; 267 | } 268 | 269 | this.progress = +(this.direction >= 0); 270 | 271 | this.pause(); 272 | 273 | if(this.isInitialized) { 274 | this.dispatchEvent(this.getEventObject('stopped')); 275 | } 276 | }; 277 | Aquarelle.prototype.start = function() { 278 | if(this.progress === +(this.direction < 0) && !this.isPaused) { 279 | return; 280 | } 281 | 282 | this.progress = +(this.direction < 0); 283 | 284 | this.dispatchEvent(this.getEventObject('started')); 285 | 286 | this.play(); 287 | }; 288 | 289 | Aquarelle.prototype.reverse = function() { 290 | this.direction = this.direction < 0 ? 1 : -1; 291 | }; 292 | Aquarelle.prototype.reset = function() { 293 | if(!this.turbulentPass) { 294 | return; 295 | } 296 | 297 | this.turbulentPass.uniforms.Amplitude.value = this.transitionInRange(this.options.fromAmplitude, this.options.toAmplitude); 298 | this.turbulentPass.uniforms.Frequency.value = this.transitionInRange(this.options.fromFrequency, this.options.toFrequency); 299 | this.mask.offset = this.transitionInRange(this.options.fromOffset, this.options.toOffset); 300 | 301 | this.turbulentPass.uniforms.Mask.value.needsUpdate = true; 302 | 303 | this.dispatchEvent(this.getEventObject('changed')); 304 | 305 | if(this.isComplete()) { 306 | this.dispatchEvent(this.getEventObject('completed')); 307 | 308 | var isPaused = this.isPaused; 309 | this.stop(); 310 | } 311 | if(this.isComplete() && this.options.loop && !isPaused) { 312 | this.start(); 313 | } 314 | }; 315 | 316 | Aquarelle.prototype.getEventObject = function(type) { 317 | return { 318 | type: type, 319 | timeStamp: Date.now(), 320 | direction: this.direction, 321 | progress: this.progress, 322 | isComplete: this.isComplete() 323 | }; 324 | }; 325 | 326 | Aquarelle.prototype.setOptions = function(options) { 327 | if(typeof options === 'object' && options !== null) { 328 | this.options = Object.assign(this.options || {}, options); 329 | } 330 | }; 331 | 332 | Aquarelle.defaultOptions = { 333 | fromAmplitude: 50, 334 | toAmplitude: 0, 335 | 336 | fromFrequency: 8, 337 | toFrequency: 7, 338 | 339 | fromOffset: -30, 340 | toOffset: 28, 341 | 342 | autoplay: false, 343 | loop: false, 344 | duration: 8000 345 | }; 346 | 347 | function frame() { 348 | var time = Date.now(); 349 | var deltaTime = time - lastTime; 350 | 351 | lastTime = time; 352 | 353 | stack.forEach(function(item) { 354 | item.render(deltaTime / 1000); 355 | }); 356 | 357 | requestAnimationFrame(frame); 358 | } 359 | frame(); 360 | 361 | window.Aquarelle = Aquarelle; 362 | }()); -------------------------------------------------------------------------------- /AquarellePass.js: -------------------------------------------------------------------------------- 1 | var THREE = window.THREE || {}; 2 | 3 | THREE.AquarellePass = function(texture, mask) { 4 | THREE.Pass.call(this); 5 | 6 | this.uniforms = { 7 | Texture: { 8 | type: 't', 9 | value: texture 10 | }, 11 | Mask: { 12 | type: 't', 13 | value: mask 14 | }, 15 | Amplitude: { 16 | type: 'f', 17 | value: 50 18 | }, 19 | Frequency: { 20 | type: 'f', 21 | value: 10 22 | } 23 | }; 24 | 25 | this.material = new THREE.ShaderMaterial({ 26 | uniforms: this.uniforms, 27 | vertexShader: [ 28 | 'varying vec2 vUv;', 29 | 30 | 'void main() {', 31 | 'vUv = uv;', 32 | 'gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1);', 33 | '}' 34 | ].join('\n'), 35 | fragmentShader: [ 36 | '// Uniform variables.', 37 | 'uniform sampler2D Texture;', 38 | 'uniform sampler2D Mask;', 39 | 40 | 'uniform float Amplitude;', 41 | 'uniform float Frequency;', 42 | 43 | 44 | '// Varying variables.', 45 | 'varying vec2 vUv;', 46 | 47 | 48 | '// Description : Array and textureless GLSL 3D simplex noise function.', 49 | '// Author : Ian McEwan, Ashima Arts.', 50 | '// Maintainer : ijm', 51 | '// Lastmod : 20110822 (ijm)', 52 | '// License : Copyright (C) 2011 Ashima Arts. All rights reserved.', 53 | '// Distributed under the MIT License. See LICENSE file.', 54 | '// https://github.com/ashima/webgl-noise', 55 | 'vec3 mod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }', 56 | 'vec4 mod289(vec4 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }', 57 | 'vec4 permute(vec4 x) { return mod289(((x*34.0)+1.0)*x); }', 58 | 'vec4 taylorInvSqrt(vec4 r) { return 1.79284291400159 - 0.85373472095314 * r; }', 59 | 'float snoise(vec3 v)', 60 | '{', 61 | 'const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;', 62 | 'const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);', 63 | 64 | '// First corner', 65 | 'vec3 i = floor(v + dot(v, C.yyy) );', 66 | 'vec3 x0 = v - i + dot(i, C.xxx) ;', 67 | 68 | '// Other corners', 69 | 'vec3 g = step(x0.yzx, x0.xyz);', 70 | 'vec3 l = 1.0 - g;', 71 | 'vec3 i1 = min( g.xyz, l.zxy );', 72 | 'vec3 i2 = max( g.xyz, l.zxy );', 73 | 74 | '// x0 = x0 - 0.0 + 0.0 * C.xxx;', 75 | '// x1 = x0 - i1 + 1.0 * C.xxx;', 76 | '// x2 = x0 - i2 + 2.0 * C.xxx;', 77 | '// x3 = x0 - 1.0 + 3.0 * C.xxx;', 78 | 'vec3 x1 = x0 - i1 + C.xxx;', 79 | 'vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y', 80 | 'vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y', 81 | 82 | '// Permutations', 83 | 'i = mod289(i);', 84 | 'vec4 p = permute( permute( permute(', 85 | 'i.z + vec4(0.0, i1.z, i2.z, 1.0 ))', 86 | '+ i.y + vec4(0.0, i1.y, i2.y, 1.0 ))', 87 | '+ i.x + vec4(0.0, i1.x, i2.x, 1.0 ));', 88 | 89 | '// Gradients: 7x7 points over a square, mapped onto an octahedron.', 90 | '// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)', 91 | 'float n_ = 0.142857142857; // 1.0/7.0', 92 | 'vec3 ns = n_ * D.wyz - D.xzx;', 93 | 94 | 'vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)', 95 | 96 | 'vec4 x_ = floor(j * ns.z);', 97 | 'vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)', 98 | 99 | 'vec4 x = x_ *ns.x + ns.yyyy;', 100 | 'vec4 y = y_ *ns.x + ns.yyyy;', 101 | 'vec4 h = 1.0 - abs(x) - abs(y);', 102 | 103 | 'vec4 b0 = vec4( x.xy, y.xy );', 104 | 'vec4 b1 = vec4( x.zw, y.zw );', 105 | 106 | '//vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;', 107 | '//vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;', 108 | 'vec4 s0 = floor(b0)*2.0 + 1.0;', 109 | 'vec4 s1 = floor(b1)*2.0 + 1.0;', 110 | 'vec4 sh = -step(h, vec4(0.0));', 111 | 112 | 'vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;', 113 | 'vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;', 114 | 115 | 'vec3 p0 = vec3(a0.xy,h.x);', 116 | 'vec3 p1 = vec3(a0.zw,h.y);', 117 | 'vec3 p2 = vec3(a1.xy,h.z);', 118 | 'vec3 p3 = vec3(a1.zw,h.w);', 119 | 120 | '//Normalise gradients', 121 | 'vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));', 122 | 'p0 *= norm.x;', 123 | 'p1 *= norm.y;', 124 | 'p2 *= norm.z;', 125 | 'p3 *= norm.w;', 126 | 127 | '// Mix final noise value', 128 | 'vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);', 129 | 'm = m * m;', 130 | 'return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3) ) );', 131 | '}', 132 | 133 | 134 | 'void main() {', 135 | 'vec2 offset;', 136 | 137 | 'float noise = snoise(vec3(vUv * Frequency, 0)) * 3.14;', 138 | 'offset = vec2(cos(noise), sin(noise)) * Amplitude * .001;', 139 | 140 | 'vec4 texture = texture2D(Texture, vUv + offset);', 141 | 142 | 143 | 'vec2 shift = vUv;', 144 | 145 | 'float largeNoise = snoise(vec3(vUv * 20.0, 0));', 146 | 'shift += vec2(cos(largeNoise), sin(largeNoise)) * .07;', 147 | 148 | 'float smallNoise = snoise(vec3(vUv * 70.0, 0));', 149 | 'shift += vec2(cos(smallNoise), sin(smallNoise)) * .02;', 150 | 151 | 'vec4 mask = texture2D(Mask, shift);', 152 | 153 | 154 | 'gl_FragColor = vec4(texture.r, texture.g, texture.b, mask.a);', 155 | '}' 156 | ].join('\n'), 157 | transparent: true 158 | }); 159 | 160 | this.needsSwap = false; 161 | 162 | this.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1); 163 | this.scene = new THREE.Scene; 164 | 165 | this.quad = new THREE.Mesh(new THREE.PlaneBufferGeometry(2, 2)); 166 | this.scene.add(this.quad); 167 | }; 168 | 169 | THREE.AquarellePass.prototype = Object.assign(Object.create(THREE.Pass.prototype), { 170 | constructor: THREE.AquarellePass, 171 | 172 | render: function(renderer, writeBuffer, readBuffer) { 173 | this.quad.material = this.material; 174 | 175 | renderer.render(this.scene, this.camera, readBuffer, this.clear); 176 | } 177 | }); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Ramotion 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Header](./header.png)](https://www.ramotion.com/agency/app-development?utm_source=gthb&utm_medium=special&utm_campaign=aquarelle) 2 | [![preview](./Screenshots/web__transition__effect_ramotion.gif)](https://ramotion.github.io/aquarelle/) 3 | 4 | # Aquarelle 5 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/a2d54fa890b84f538be1bc9349dc5121)](https://www.codacy.com/app/juri-v/aquarelle?utm_source=github.com&utm_medium=referral&utm_content=Ramotion/aquarelle&utm_campaign=Badge_Grade) 6 | [![Bower](https://img.shields.io/bower/v/aquarelle.svg)]() 7 | [![Twitter](https://img.shields.io/badge/Twitter-@Ramotion-blue.svg?style=flat)](http://twitter.com/Ramotion) 8 | [![Travis](https://img.shields.io/travis/Ramotion/aquarelle.svg)](https://travis-ci.org/Ramotion/aquarelle) 9 | [![Donate](https://img.shields.io/badge/Donate-PayPal-blue.svg)](https://paypal.me/Ramotion) 10 | 11 | 12 | ## About 13 | This project is maintained by Ramotion, Inc.
14 | We specialize in the designing and coding of custom UI for Mobile Apps and Websites.
15 | 16 | **Looking for developers for your project?**
17 | This project is maintained by Ramotion, Inc. We specialize in the designing and coding of custom UI for Mobile Apps and Websites. 18 | 19 | 20 |
21 | 22 | ## Browser support 23 | 24 | * Chrome 25 | * Safari 26 | * Opera 27 | * Firefox 28 | * IE 11 29 | 30 | ## Installation 31 | 32 | `bower install aquarelle` 33 | 34 | Then insert in your html: 35 | 36 | ```html 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | ``` 48 | 49 | 50 | ## API 51 | 52 | ### Constructor 53 | 54 | `new Aquarelle(textureImage, maskImage[, options]);` 55 | 56 | | Names | Required | Type | Description 57 | | --- | --- | --- | --- 58 | | textureImage | `true` | `string`, `Image` or `` | background image 59 | | maskImage | `true` | `string`, `Image` or `` | background image mask 60 | | options | `false` | `object` | initial options 61 | 62 | ### Options 63 | 64 | | Names | Defaults | Description 65 | | --- | --- | --- 66 | | fromAmplitude | `50` | initial noise amplitude value 67 | | toAmplitude | `0` | final noise amplitude value 68 | | fromFrequency | `8` | initial noise frequiency 69 | | toFrequency | `7` | final noise frequiency 70 | | fromOffset | `-30` | initial mask size 71 | | autoplay | `false` | `true` - start animation before first frame is being rendered 72 | | loop | `false` | `true` - repeat animation in loop 73 | | duration | `8000` | animation duration 74 | 75 | ### Events 76 | 77 | | Names | Description 78 | | --- | --- 79 | | created | triggered before first frame is rendered 80 | | changed | triggered before rendering of a frame 81 | | completed | triggered before latest frame is rendered 82 | | started | triggered before animation is started 83 | | played | triggered after animation is started 84 | | paused | triggered before pause of animation 85 | | stopped | triggered before reset of animation 86 | 87 | ### Methods 88 | 89 | | Names | Description 90 | | --- | --- 91 | | `pause()` | pause animation 92 | | `play()` | start animation 93 | | `stop()` | stop and reset animation 94 | | `start()` | start animation over 95 | | `reverse()` | reverse animation 96 | | `reset()` | re-render frame 97 | | `setOptions([object])` | set animation options 98 | | `transitionInRange(startValue, endValue[, startTimeMS[, endTimeMS]])` | return value between `startValue`..`endValue` in range `startTimeMS`..`endTimeMS` 99 | | `addEventListener(type, listener)` | add listener (`listener`) of event (`type`) 100 | | `removeEventListener(type, listener)` | remove (`listener`) of event (`type`) 101 | 102 | 103 | ## Usage 104 | 105 | ≈ 106 | 107 | ```javascript 108 | var aquarelle = new Aquarelle(textureImage, maskImage[, options]); 109 | ``` 110 | 111 | ##### Listeners 112 | 113 | ```javascript 114 | function listener(event) {} 115 | 116 | aquarelle.addEventListener('created', listener); 117 | 118 | aquarelle.removeEventListener('created', listener); 119 | ``` 120 | ##### Demos 121 | 122 | [Static demo](http://ramotion.github.io/aquarelle) 123 | 124 | [Dynamic demo](https://ramotion.github.io/aquarelle/example_scroll.html) 125 | 126 | ## Licence 127 | 128 | Aquarelle is released under the MIT license. 129 | See [LICENSE](./LICENSE) for details. 130 | 131 | # Get the Showroom App for iOS to give it a try 132 | Try our UI components in our iOS app. Contact us if interested. 133 | 134 | 135 | 136 | 137 | 138 |
139 |
140 | Follow us for the latest updates 141 |
142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /Screenshots/web__transition__effect_ramotion.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/aquarelle/aef4c7cd9fc4ab482559f49447822a1df169216d/Screenshots/web__transition__effect_ramotion.gif -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aquarelle", 3 | "main": "aquarelle.js", 4 | "homepage": "https://ramotion.com", 5 | "authors": [ 6 | "juri.v@ramotion.com" 7 | ], 8 | "description": "watercolor animation", 9 | "moduleType": [ 10 | "amd" 11 | ], 12 | "keywords": [ 13 | "aquarelle", 14 | "watercolor", 15 | "animation", 16 | "transition" 17 | ], 18 | "license": "MIT", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "test", 24 | "tests" 25 | ], 26 | "dependencies": { 27 | "three.js": "threejs#*" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /deploy-to-gh-pages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit 3 | 4 | # config 5 | git config --global user.email "nobody@nobody.org" 6 | git config --global user.name "Travis CI" 7 | 8 | # deploy 9 | cd examples 10 | bower install 11 | rm -rf .git 12 | git init 13 | git add . 14 | git commit -m "Deploy to Github Pages" 15 | git push --force --quiet "https://${GITHUB_TOKEN}@github.com/${GITHUB_REPO}.git" master:gh-pages -------------------------------------------------------------------------------- /examples/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "examples", 3 | "homepage": "https://github.com/Ramotion/aquarelle", 4 | "authors": [ 5 | "yury " 6 | ], 7 | "license": "MIT", 8 | "dependencies": { 9 | "aquarelle": "*" 10 | }, 11 | "ignore": [ 12 | "**/.*", 13 | "bower_components" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /examples/example_scroll.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 60 | 61 |
62 | 63 | 64 | 65 | 66 | 67 | 68 | Scroll down 69 |
70 | 71 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /examples/img/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/aquarelle/aef4c7cd9fc4ab482559f49447822a1df169216d/examples/img/bg.png -------------------------------------------------------------------------------- /examples/img/icon01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/aquarelle/aef4c7cd9fc4ab482559f49447822a1df169216d/examples/img/icon01.png -------------------------------------------------------------------------------- /examples/img/icon02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/aquarelle/aef4c7cd9fc4ab482559f49447822a1df169216d/examples/img/icon02.png -------------------------------------------------------------------------------- /examples/img/icon03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/aquarelle/aef4c7cd9fc4ab482559f49447822a1df169216d/examples/img/icon03.png -------------------------------------------------------------------------------- /examples/img/jobs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/aquarelle/aef4c7cd9fc4ab482559f49447822a1df169216d/examples/img/jobs.jpg -------------------------------------------------------------------------------- /examples/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/aquarelle/aef4c7cd9fc4ab482559f49447822a1df169216d/examples/img/logo.png -------------------------------------------------------------------------------- /examples/img/mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/aquarelle/aef4c7cd9fc4ab482559f49447822a1df169216d/examples/img/mask.png -------------------------------------------------------------------------------- /examples/img/mouse.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 10 | 12 | 13 | -------------------------------------------------------------------------------- /examples/img/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/aquarelle/aef4c7cd9fc4ab482559f49447822a1df169216d/examples/img/splash.png -------------------------------------------------------------------------------- /examples/img/title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/aquarelle/aef4c7cd9fc4ab482559f49447822a1df169216d/examples/img/title.png -------------------------------------------------------------------------------- /examples/img/top_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/aquarelle/aef4c7cd9fc4ab482559f49447822a1df169216d/examples/img/top_menu.png -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 113 | 114 |
115 | 116 |
117 | 118 | 119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 | 128 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/aquarelle/aef4c7cd9fc4ab482559f49447822a1df169216d/header.png --------------------------------------------------------------------------------