<svg id="svg" viewBox="0 0 1000 1000">
<path id="path1"></path>
<path id="path2"></path>
<path id="path3"></path>
<g id="dot-container"></g>
</svg>
#svg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#path1 {
fill: #ffcf4e; // yellow
mix-blend-mode: multiply;
}
#path2 {
fill: #FF00FF; // red
mix-blend-mode: multiply;
}
#path3 {
fill: #0ebeff; // blue
mix-blend-mode: multiply;
}
.controls {
position: fixed;
top: 0;
left: 0;
padding: 15px;
}
.dot {
fill: #1a237e;
fill-opacity: 0.3;
stroke: #1a237e;
stroke-width: 1;
vector-effect: non-scaling-stroke;
}
View Compiled
var blob1 = createBlob({
element: document.querySelector("#path1"),
numPoints: 10,
centerX: 480,
centerY: 480,
minRadius: 300,
maxRadius: 350,
minDuration: 1,
maxDuration: 2
});
var blob2 = createBlob({
element: document.querySelector("#path2"),
numPoints: 10,
centerX: 500,
centerY: 500,
minRadius: 280,
maxRadius: 350,
minDuration: 2,
maxDuration: 3
});
var blob3 = createBlob({
element: document.querySelector("#path3"),
numPoints: 10,
centerX: 520,
centerY: 520,
minRadius: 300,
maxRadius: 350,
minDuration: 1.5,
maxDuration: 2.5
});
function createBlob(options) {
var points = [];
var path = options.element;
var slice = (Math.PI * 2) / options.numPoints;
var startAngle = random(Math.PI * 2);
var tl = new TimelineMax({
onUpdate: update
});
for (var i = 0; i < options.numPoints; i++) {
var angle = startAngle + i * slice;
var duration = random(options.minDuration, options.maxDuration);
var point = {
x: options.centerX + Math.cos(angle) * options.minRadius,
y: options.centerY + Math.sin(angle) * options.minRadius
};
var tween = TweenMax.to(point, duration, {
x: options.centerX + Math.cos(angle) * options.maxRadius,
y: options.centerY + Math.sin(angle) * options.maxRadius,
repeat: -1,
yoyo: true,
ease: Sine.easeInOut
});
tl.add(tween, -random(duration));
points.push(point);
}
options.tl = tl;
options.points = points;
function update() {
path.setAttribute("d", cardinal(points, true, 1));
}
return options;
}
// Cardinal spline - a uniform Catmull-Rom spline with a tension option
function cardinal(data, closed, tension) {
if (data.length < 1) return "M0 0";
if (tension == null) tension = 1;
var size = data.length - (closed ? 0 : 1);
var path = "M" + data[0].x + " " + data[0].y + " C";
for (var i = 0; i < size; i++) {
var p0, p1, p2, p3;
if (closed) {
p0 = data[(i - 1 + size) % size];
p1 = data[i];
p2 = data[(i + 1) % size];
p3 = data[(i + 2) % size];
} else {
p0 = i == 0 ? data[0] : data[i - 1];
p1 = data[i];
p2 = data[i + 1];
p3 = i == size - 1 ? p2 : data[i + 2];
}
var x1 = p1.x + (p2.x - p0.x) / 6 * tension;
var y1 = p1.y + (p2.y - p0.y) / 6 * tension;
var x2 = p2.x - (p3.x - p1.x) / 6 * tension;
var y2 = p2.y - (p3.y - p1.y) / 6 * tension;
path += " " + x1 + " " + y1 + " " + x2 + " " + y2 + " " + p2.x + " " + p2.y;
}
return closed ? path + "z" : path;
}
function random(min, max) {
if (max == null) { max = min; min = 0; }
if (min > max) { var tmp = min; min = max; max = tmp; }
return min + (max - min) * Math.random();
}
This Pen doesn't use any external CSS resources.