일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 쇼핑몰
- 해피씨지아이
- #업종별
- 게시판
- 홈페이지제작
- 사이트제작
- 해피CGI
- #CSS
- 홈페이지
- #해피CGI
- jquery
- #cgimall
- #홈페이지제작
- #image
- happycgi
- #솔루션
- CGIMALL
- #이미지
- 솔루션
- #동영상
- #웹솔루션
- javascript
- php
- 웹솔루션
- #jQuery
- #홈페이지
- #뉴스
- #쇼핑몰
- CSS
- #happycgi
- Today
- Total
웹솔루션개발 22년 노하우! 해피CGI의 모든것
[해피CGI][cgimall] SVG를 이용한 백그라운드 애니메이션 Generative Morphing Soft Gradients [Experiment, SVG] 본문
[해피CGI][cgimall] SVG를 이용한 백그라운드 애니메이션 Generative Morphing Soft Gradients [Experiment, SVG]
해피CGI윤실장 2024. 7. 1. 09:06
SVG를 이용한 백그라운드 애니메이션입니다.
CSS 소스
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
svg {
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: -1;
transform: translate3d(0px, 0px, 0px);
}
JS 소스
import tinycolor from "https://cdn.skypack.dev/tinycolor2@1.4.2";
import SimplexNoise from "https://cdn.skypack.dev/simplex-noise@2.4.0";
const simplex = new SimplexNoise(Math.random);
console.clear();
class GradientBG {
constructor(width = 1920, height = 1080, target = document.body) {
this.width = width;
this.height = height;
this.target = target;
this.svgns = "http://www.w3.org/2000/svg";
this.SVGElement = this._createSVGElement();
this.id = Math.random();
}
generate() {
this.SVGElement.innerHTML = "";
this.defs = this._createDefs();
this.backgroundGradient = this._createBackgroundGradient();
this.blurFilter = this._createBlurFilter();
let baseColor = tinycolor(
`hsl(${~~this._random(0, 360)}, ${this._random(75, 100)}, ${this._random(
80,
92
)}%)`
);
let combinations = baseColor.splitcomplement();
let secondaryColor = combinations[~~this._random(1, combinations.length)];
let secondaryCombinations = secondaryColor.splitcomplement();
const stopOffset1 = this._random(0, 25);
const stopOffset2 = 100 - this._random(0, 25);
this.backgroundGradient.stop1.setAttribute(
"stop-color",
baseColor.toHslString()
);
this.backgroundGradient.stop2.setAttribute(
"stop-color",
secondaryColor.toHslString()
);
this.backgroundGradient.stop1.setAttribute("offset", `${stopOffset1}%`);
this.backgroundGradient.stop2.setAttribute("offset", `${stopOffset2}%`);
const maxBlobSize = Math.min(this.width, this.height);
this._blob({
x: `${this._random(0, this.width / 4)}`,
y: `${this._random(0, this.height / 4)}`,
r: `${this._random(maxBlobSize / 2, maxBlobSize)}`,
fill: combinations[~~this._random(0, combinations.length)]
});
this._blob({
x: `${this._random(this.width - this.width / 4, this.width)}`,
y: `${this._random(0, this.height / 4)}`,
r: `${this._random(maxBlobSize / 2, maxBlobSize)}`,
fill: combinations[~~this._random(0, combinations.length)]
});
this._blob({
x: `${this._random(0, this.width / 4)}`,
y: `${this._random(this.height - this.height / 4, this.height)}`,
r: `${this._random(maxBlobSize / 2, maxBlobSize)}`,
fill:
secondaryCombinations[~~this._random(0, secondaryCombinations.length)]
});
this._blob({
x: `${this._random(this.width - this.width / 4, this.width)}`,
y: `${this._random(this.height - this.height / 4, this.height)}`,
r: `${this._random(maxBlobSize / 2, maxBlobSize)}`,
fill:
secondaryCombinations[~~this._random(0, secondaryCombinations.length)]
});
}
_createSVGElement() {
const el = document.createElementNS(this.svgns, "svg");
el.setAttribute("viewBox", `0 0 ${this.width} ${this.height}`);
el.setAttribute("preserveAspectRatio", "xMidYMid slice");
this.target.appendChild(el);
return el;
}
_createDefs() {
const el = document.createElementNS(this.svgns, "defs");
this.SVGElement.appendChild(el);
return el;
}
_createBackgroundGradient() {
const el = document.createElementNS(this.svgns, "linearGradient");
el.id = "bgGradient" + this.id;
el.setAttribute("gradientTransform", "rotate(90)");
const stop1 = document.createElementNS(this.svgns, "stop");
stop1.setAttribute("offset", `${~~this._random(0, 25)}%`);
const stop2 = document.createElementNS(this.svgns, "stop");
stop2.setAttribute("offset", `${~~this._random(75, 100)}%`);
el.appendChild(stop1);
el.appendChild(stop2);
this.defs.appendChild(el);
const rect = document.createElementNS(this.svgns, "rect");
rect.setAttribute("x", "0");
rect.setAttribute("y", "0");
rect.setAttribute("width", "100%");
rect.setAttribute("height", "100%");
rect.setAttribute("fill", `url(#bgGradient${this.id})`);
this.SVGElement.appendChild(rect);
return {
rect: rect,
stop1: stop1,
stop2: stop2
};
}
_createBlurFilter() {
const el = document.createElementNS(this.svgns, "filter");
el.id = "blur" + this.id;
el.setAttribute("x", "-100%");
el.setAttribute("y", "-100%");
el.setAttribute("width", "300%");
el.setAttribute("height", "300%");
const gaussianBlur = document.createElementNS(this.svgns, "feGaussianBlur");
gaussianBlur.setAttribute("in", "SourceGraphic");
gaussianBlur.setAttribute("stdDeviation", this._random(100, 110));
el.appendChild(gaussianBlur);
this.defs.appendChild(el);
return el;
}
_blob({ x, y, r, fill, filter = `url(#blur${this.id})` }) {
const circle = document.createElementNS(this.svgns, "circle");
circle.setAttribute("cx", x);
circle.setAttribute("cy", y);
circle.setAttribute("r", r);
circle.setAttribute("fill", fill);
circle.setAttribute("filter", filter);
this.SVGElement.appendChild(circle);
return circle;
}
_random(min, max) {
return Math.random() * (max - min) + min;
}
}
const gradient = new GradientBG();
gradient.generate();
const circles = [];
document.querySelectorAll("circle").forEach((el) => {
circles.push({
el,
x: ~~el.getAttribute("cx"),
y: ~~el.getAttribute("cy"),
originX: ~~el.getAttribute("cx"),
originY: ~~el.getAttribute("cy"),
xOff: Math.random(),
yOff: Math.random()
});
});
function map(n, start1, end1, start2, end2) {
return ((n - start1) / (end1 - start1)) * (end2 - start2) + start2;
}
(function animate() {
circles.forEach((c) => {
const noiseX = simplex.noise2D(c.xOff, c.xOff);
const noiseY = simplex.noise2D(c.yOff, c.yOff);
const x = map(noiseX, 0, 1, 0, 1920);
const y = map(noiseY, 0, 1, 0, 1080);
c.el.setAttribute("cx", x);
c.el.setAttribute("cy", y);
c.xOff += 0.002;
c.yOff += 0.002;
});
requestAnimationFrame(animate);
})();
첨부파일을 다운로드 받거나 해당 사이트로 이동해서 전체 소스를 확인하실 수 있습니다.
'웹프로그램밍 자료실 > HTML 자료' 카테고리의 다른 글
[해피CGI][cgimall] Radios With Sliding Focus 라디오 버튼 슬라이딩 포커스 (0) | 2024.07.03 |
---|---|
[해피CGI][cgimall] GSAP를 이용한 무한 이미지 슬라이드 (0) | 2024.07.02 |
[해피CGI][cgimall] 간단한 버튼, 로딩바, input 효과 CSS (0) | 2024.06.28 |
[해피CGI][cgimall] Customize your CSS Border (0) | 2024.06.27 |
[해피CGI][cgimall] Responsive GSAP Slider with Button Wave Effect (0) | 2024.06.26 |