Skip to content

Instantly share code, notes, and snippets.

@CodeMyUI
Created April 20, 2018 05:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save CodeMyUI/e07d57ec9ad5e5d58fbb53878cbfc16d to your computer and use it in GitHub Desktop.
Save CodeMyUI/e07d57ec9ad5e5d58fbb53878cbfc16d to your computer and use it in GitHub Desktop.
Spilled Paint v2
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script>
$(document).ready(function(){
var slider = new gooSlider('body');
var l1,l2;
$('body').click(function(){
var c = 'hsla('+ (Math.floor(Math.random()*7) * 50) +',56%,68%,1)';
if(c != l1 && c != l2){
slider.wave(c, function(){});
l2 = l1;
l1 = c;
} else {
$('body').click();
}
});
var count = 5,
cur = 0;
function start(){
slider.wave('hsla('+ (Math.floor(Math.random()*7) * 50) +',82%,64%,1)', function(){});
cur++;
if(cur<count){
setTimeout(function(){
start();
}, 1500)
}
}
start();
});
</script>
<div id="info">Click to spill more paint!</div>
window.requestFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
var gooSlider = function(parent, id){
var size = {
x: $(parent).width(),
y: $(parent).height()
};
var canvas = $('<canvas/>').attr({width: size.x, height: size.y, id: id}).appendTo(parent),
context = canvas.get(0).getContext("2d");
var startTime = new Date().getTime(); // timing stuff
var currentTime = 0; // more timing, it just makes it so it always falls at the same rate
var dripDist = 100; // distance between each "drip"
var dripsAmount = Math.floor(size.x / dripDist) + 2; // amount of drips that will go across screen
waves = []; // this will contain the information for each wave (color, drip positions, etc...)
this.waves = waves; // making the waves variable available to the outside world
noise.seed(Math.random());
this.wave = function(settings, call){ // this creates the wave object. You pass through the color of the "wave" and the callback for when the wave covers the screen.
if(typeof call != 'function') { call = function(){} }
var it = {
drips: [],
callback: call,
defaults: {
color: '#99db81',
minSpeed: 1,
maxSpeed: 3
},
settings: {}
};
if(typeof settings == 'object'){
it.settings = $.extend(true, it.defaults, settings);
} else {
it.settings = $.extend(true, it.defaults, {color: settings});
}
for(var i = 0; i < dripsAmount; i++){
it.drips.push(0);
}
waves.push(it); // add the object to the waves array so it's animated.
}
function loop(){
var now = new Date().getTime();
currentTime = (now - startTime) / 10000; // more timing..
//context.clearRect(0,0,size.x,size.y);
for(var i = 0; i <= waves.length; i++){ // for each wave
if(waves[i] != undefined){ // make sure it's still getting animated
var done = true; // this tells me if we're on the last animation frame for this wave or not
var points = []; // this will contain the points for the wave
for(var c = 0; c < waves[i].drips.length; c++){ // for each drip in the wave
waves[i].drips[c] += waves[i].settings.minSpeed + ((noise.simplex2((i*dripsAmount)+c,currentTime) + 1) * waves[i].settings.maxSpeed); // add the "speed" of that drop to the y position
points.push({ // add this point to be animated
x: dripDist*c,
y: waves[i].drips[c]
});
if(waves[i].drips[c] < size.y){ // if this point is not to the bottom of the screen yet, set done to false. Once all points are below the screen, done will be set to true and the animation for this wave will end and the callback will be... called.
done = false; // ^^
}
}
if(done == true){ // The continuation of the comment above
waves[i].callback(); // callback
waves[i].callback = function(){}; // callback
waves[i-1] = undefined; // stop the waves before this ones animation.
// The reason why I do that ^ instead of setting this one to undefined, is to fix an issue where the previous wave will be undrawn before the current wave reaches the bottom. Which results in random colors flashing at the bottom which is no good.
} else {
context.beginPath(); // this is the animation
context.strokeStyle = waves[i].settings.color; // set the color of the wave
context.fillStyle = waves[i].settings.color; // ^^
context.moveTo(0, 0); // move to the top left
context.lineTo(points[0].x, points[0].y); // draw to the first point
var p = 0;
for (p = 1; p < points.length - 2; p ++){ // loop through almost all of the points, but leave the last 2 alone and we'll code that in by hand
var xc = (points[p].x + points[p + 1].x) / 2; // math for x offset
var yc = ((points[p].y + points[p + 1].y) / 2); // ^^ but for y
context.quadraticCurveTo(points[p].x, points[p].y, xc, yc); // draw the curve to this new point, using the x and y offsets
}
// curve through the last two points
context.quadraticCurveTo(points[p].x, points[p].y, points[p+1].x,points[p+1].y); // draw the last two by hand
context.lineTo(size.x, 0); // draw a line to the top right so the fill works properly
context.stroke();
context.fill();
}
}
}
requestFrame(loop);
}
this.clear = function(){ // this will come in handy for practical uses
waves = [];
context.clearRect(0,0,size.x,size.y);
}
loop(); // start the animation
}
<script src="https://codepen.io/darrylhuffman/pen/zogYQW.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
html, body {
height: 100%;
width: 100%;
padding: 0px;
margin: 0px;
overflow: hidden;
display: flex;
}
#info {
margin: auto;
position: relative;
z-index: 2;
color: #ffffff;
font-family: sans-serif;
pointer-events: none;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none
}
canvas {
z-index: 1;
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment