<div class="canvas-wrapper">
<svg class="canvas" viewBox="0 0 1920 1080" preserveAspectRatio="xMaxYMid slice"></svg>
</div>
<div class="controls">
<p>* Export is disabled for mobile devices</p>
<button class="download">Скопировать код</button>
<button class="regenerate">Варианты</button>
</div>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-smoothing: antialiased;
osx-font-smoothing: grayscale;
}
body {
min-height: 100vh;
display: grid;
place-items: center;
padding: 1rem;
font-family: system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
color: hsl(0, 0%, 10%);
background: hsl(0, 0%, 100%);
}
.canvas-wrapper {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.canvas {
width: 100vw;
height: 100vh;
}
.controls {
position: relative;
display: grid;
grid-gap: 1rem;
grid-template-columns: 1fr;
width: 100%;
max-width: 24rem;
padding: 1rem;
background: hsla(0, 0%, 100%, 0.25);
z-index: 1;
backdrop-filter: blur(12px);
backdrop-filter: blur(12px);
border-radius: 0.5rem;
border: 1px solid hsla(0, 0%, 100%, 0.25);
opacity: 0;
}
.controls p {
grid-column: -1 / 1;
font-style: italic;
text-align: center;
font-size: 0.75rem;
}
button {
width: 100%;
height: 2.25rem;
border: 0;
font-weight: 500;
font-family: inherit;
border-radius: 0.5rem;
font-size: 0.875rem;
line-height: 2.25rem;
background: hsla(0, 0%, 100%, 0.25);
cursor: pointer;
}
button:nth-of-type(1) {
backdrop-filter: blur(12px);
backdrop-filter: blur(12px);
display: none;
}
button:nth-of-type(2) {
background: linear-gradient(to bottom, #287cfe, #0466ff);
color: #fff;
}
@media only screen and (min-width: 640px) {
.controls {
grid-template-columns: 1fr 1fr;
}
.controls p {
display: none;
}
.controls button:nth-of-type(1) {
display: block;
}
}
console.clear();
import { SVG } from "https://cdn.skypack.dev/@svgdotjs/svg.js";
import {
random,
map,
spline,
pointsInPath
} from "https://cdn.skypack.dev/@georgedoescode/generative-utils@1.0.0";
import tinycolor from "https://cdn.skypack.dev/tinycolor2@1.4.2";
import "https://cdn.skypack.dev/@svgdotjs/svg.filter.js";
import copy from "https://cdn.skypack.dev/copy-to-clipboard@3.3.1";
import { gsap } from "https://cdn.skypack.dev/gsap@3.6.0";
const svg = SVG(".canvas");
const { width, height } = svg.viewbox();
const regenerateBtn = document.querySelector(".regenerate");
const downloadBtn = document.querySelector(".download");
function wave(start, end, gradient) {
const numSteps = random(4, 8, true);
const step = 1 / numSteps;
const randomRange = random(32, 64);
const points = [];
let pointPosition = 0;
for (let i = 0; i <= numSteps; i++) {
const step = map(i, 0, numSteps, 0, 1);
let x = lerp(start.x, end.x, step);
let y = lerp(start.y, end.y, step);
if (i !== 0 && i !== numSteps) {
x += random(-randomRange, randomRange);
y += random(-randomRange, randomRange);
}
points.push({ x, y });
}
const pathData =
spline(points, 1, false) + `L ${end.x} ${height} L ${start.x} ${height} Z`;
const path = svg.path(pathData).attr("fill", gradient);
}
function lerp(v0, v1, t) {
return v0 * (1 - t) + v1 * t;
}
function generate() {
const numWaves = 7;
const base = tinycolor(`hsl(${random(0, 360)}, 65%, 55%)`);
const colors = base.analogous(6);
svg.rect(width, height).fill(random(colors).clone().darken(40).toString());
for (let i = 0; i < numWaves; i++) {
const randomOffset = random(-50, 50);
const originY = map(i, 0, numWaves, -height / 2, height / 3) + randomOffset;
const endY = map(i, 0, numWaves, 0, 1000) + randomOffset;
const color = random(colors).clone();
if (i < 3) {
color.darken(50).desaturate(10);
}
const gradientOffset = map(i, 0, numWaves, 0.1, 1);
let gradient = svg.gradient("linear", function (add) {
add.stop(0, color.clone().lighten(30).toHexString());
add.stop(gradientOffset, color.clone().spin(60).toHexString());
});
gradient.from(0.5, 0).to(0, 1);
wave({ x: 0, y: originY }, { x: width, y: endY }, gradient);
}
}
generate();
regenerateBtn.addEventListener("click", () => {
svg.clear();
generate();
});
downloadBtn.addEventListener("click", () => {
copy(svg.node.outerHTML);
downloadBtn.innerHTML = "Код скопирован";
setTimeout(() => {
downloadBtn.innerHTML = "Теперь вставь на сайт";
}, 1500);
});
gsap.fromTo(
".controls",
{
opacity: 0,
y: 24
},
{
opacity: 1,
y: 0,
ease: "back.out(1.7)",
delay: 0.175
}
);
gsap.fromTo(
"button",
{
opacity: 0,
y: 12
},
{
opacity: 1,
y: 0,
stagger: 0.125,
delay: 0.175,
ease: "back.out(1.7)"
}
);
gsap.fromTo(
"p",
{
opacity: 0,
y: 12
},
{
opacity: 1,
y: 0,
ease: "back.out(1.7)",
delay: 0.175
}
);
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.