如何创建 SVG Gooey 效果
How to create SVG Gooey effect
我正在尝试重新创建类似 this 的内容。
这是我试过的
// targeting the svg itself
const svg = document.querySelector("svg");
// variable for the namespace
const svgns = "http://www.w3.org/2000/svg"
//vboxDim
var vboxW = 200;
var vboxH = 200;
//assigning svg element attribute
svg.setAttribute('class', 'layer1');
svg.setAttribute('xmlns', svgns);
svg.setAttribute('viewBox', `0 0 ${vboxW} ${vboxH}`);
//make background
var fill1 = 'black';
let bg = document.createElementNS(svgns, 'rect');
bg.setAttribute('class', 'bg');
bg.setAttribute('id', 'bg');
bg.setAttribute("width", `${vboxW}`);
bg.setAttribute("height", `${vboxH}`);
bg.setAttribute("fill", fill1);
svg.appendChild(bg);
var color = ['white', 'white']
var r = 20;
var cx = (vboxH / 2);
var cy = (vboxW / 2) - 20;
for (var i = 0; i < 2; i++) {
let circ = document.createElementNS(svgns, 'circle');
circ.setAttribute('class', 'crcl' + i);
circ.setAttribute('id', 'crcl' + i);
circ.setAttribute("cx", `${cx}`);
circ.setAttribute("cy", `${cy}`);
circ.setAttribute("r", r);
circ.setAttribute("fill", color[i]);
svg.appendChild(circ);
r = r - 12;
cy = cy + .5;
}
.crcl0 {
filter: url(#goo);
}
.crcl1 {
filter: url(#goo);
animation: move 5s linear infinite alternate forwards;
}
@keyframes move {
0% {
transform: translate(-80px, 0);
}
100% {
transform: translate(+80px, 0);
}
<!DOCTYPE html>
<html>
<body>
<link rel="stylesheet" href="style.css"></link>
<svg>
<defs>
<filter id="goo">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10" result="goo" />
<feBlend in="SourceGraphic" in2="goo" />
</filter>
</defs>
<script href="index.js"></script>
</svg>
</body>
</html>
如您所见,它根本没有产生预期的效果。我似乎无法理解为什么会这样。我知道在创造粘稠效果时,background color
必须形成对比,我相信上面就是这种情况。
有人可以帮我指出正确的方向吗?我在这里做错了什么?另外,我需要承认我不理解这里使用的 svg filter
背后的数学原理。是否需要对其进行操作才能达到预期效果?
过滤器必须同时影响两个形状,以便它们属于同一个“SourceGraphic”。为此,您可以使用 <g>
元素并在其上添加过滤器:
// targeting the svg itself
const svg = document.querySelector("svg");
// variable for the namespace
const svgns = "http://www.w3.org/2000/svg"
//vboxDim
var vboxW = 200;
var vboxH = 200;
//assigning svg element attribute
svg.setAttribute('class', 'layer1');
svg.setAttribute('xmlns', svgns);
svg.setAttribute('viewBox', `0 0 ${vboxW} ${vboxH}`);
//make background
var fill1 = 'black';
let bg = document.createElementNS(svgns, 'rect');
bg.setAttribute('class', 'bg');
bg.setAttribute('id', 'bg');
bg.setAttribute("width", `${vboxW}`);
bg.setAttribute("height", `${vboxH}`);
bg.setAttribute("fill", fill1);
svg.appendChild(bg);
var group = document.createElementNS(svgns, "g");
group.classList.add("gooey");
svg.appendChild(group);
var color = ['white', 'white']
var r = 20;
var cx = (vboxH / 2);
var cy = (vboxW / 2) - 20;
for (var i = 0; i < 2; i++) {
let circ = document.createElementNS(svgns, 'circle');
circ.setAttribute('class', 'crcl' + i);
circ.setAttribute('id', 'crcl' + i);
circ.setAttribute("cx", `${cx}`);
circ.setAttribute("cy", `${cy}`);
circ.setAttribute("r", r);
circ.setAttribute("fill", color[i]);
group.appendChild(circ);
r = r - 12;
cy = cy + .5;
}
.gooey {
filter: url(#goo);
}
.crcl1 {
animation: move 5s linear infinite alternate forwards;
}
@keyframes move {
0% {
transform: translate(-80px, 0);
}
100% {
transform: translate(+80px, 0);
}
}
<!DOCTYPE html>
<html>
<body>
<link rel="stylesheet" href="style.css"></link>
<svg>
<defs>
<filter id="goo">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10" result="goo" />
<feBlend in="SourceGraphic" in2="goo" />
</filter>
</defs>
<script href="index.js"></script>
</svg>
</body>
</html>
我正在尝试重新创建类似 this 的内容。
这是我试过的
// targeting the svg itself
const svg = document.querySelector("svg");
// variable for the namespace
const svgns = "http://www.w3.org/2000/svg"
//vboxDim
var vboxW = 200;
var vboxH = 200;
//assigning svg element attribute
svg.setAttribute('class', 'layer1');
svg.setAttribute('xmlns', svgns);
svg.setAttribute('viewBox', `0 0 ${vboxW} ${vboxH}`);
//make background
var fill1 = 'black';
let bg = document.createElementNS(svgns, 'rect');
bg.setAttribute('class', 'bg');
bg.setAttribute('id', 'bg');
bg.setAttribute("width", `${vboxW}`);
bg.setAttribute("height", `${vboxH}`);
bg.setAttribute("fill", fill1);
svg.appendChild(bg);
var color = ['white', 'white']
var r = 20;
var cx = (vboxH / 2);
var cy = (vboxW / 2) - 20;
for (var i = 0; i < 2; i++) {
let circ = document.createElementNS(svgns, 'circle');
circ.setAttribute('class', 'crcl' + i);
circ.setAttribute('id', 'crcl' + i);
circ.setAttribute("cx", `${cx}`);
circ.setAttribute("cy", `${cy}`);
circ.setAttribute("r", r);
circ.setAttribute("fill", color[i]);
svg.appendChild(circ);
r = r - 12;
cy = cy + .5;
}
.crcl0 {
filter: url(#goo);
}
.crcl1 {
filter: url(#goo);
animation: move 5s linear infinite alternate forwards;
}
@keyframes move {
0% {
transform: translate(-80px, 0);
}
100% {
transform: translate(+80px, 0);
}
<!DOCTYPE html>
<html>
<body>
<link rel="stylesheet" href="style.css"></link>
<svg>
<defs>
<filter id="goo">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10" result="goo" />
<feBlend in="SourceGraphic" in2="goo" />
</filter>
</defs>
<script href="index.js"></script>
</svg>
</body>
</html>
如您所见,它根本没有产生预期的效果。我似乎无法理解为什么会这样。我知道在创造粘稠效果时,background color
必须形成对比,我相信上面就是这种情况。
有人可以帮我指出正确的方向吗?我在这里做错了什么?另外,我需要承认我不理解这里使用的 svg filter
背后的数学原理。是否需要对其进行操作才能达到预期效果?
过滤器必须同时影响两个形状,以便它们属于同一个“SourceGraphic”。为此,您可以使用 <g>
元素并在其上添加过滤器:
// targeting the svg itself
const svg = document.querySelector("svg");
// variable for the namespace
const svgns = "http://www.w3.org/2000/svg"
//vboxDim
var vboxW = 200;
var vboxH = 200;
//assigning svg element attribute
svg.setAttribute('class', 'layer1');
svg.setAttribute('xmlns', svgns);
svg.setAttribute('viewBox', `0 0 ${vboxW} ${vboxH}`);
//make background
var fill1 = 'black';
let bg = document.createElementNS(svgns, 'rect');
bg.setAttribute('class', 'bg');
bg.setAttribute('id', 'bg');
bg.setAttribute("width", `${vboxW}`);
bg.setAttribute("height", `${vboxH}`);
bg.setAttribute("fill", fill1);
svg.appendChild(bg);
var group = document.createElementNS(svgns, "g");
group.classList.add("gooey");
svg.appendChild(group);
var color = ['white', 'white']
var r = 20;
var cx = (vboxH / 2);
var cy = (vboxW / 2) - 20;
for (var i = 0; i < 2; i++) {
let circ = document.createElementNS(svgns, 'circle');
circ.setAttribute('class', 'crcl' + i);
circ.setAttribute('id', 'crcl' + i);
circ.setAttribute("cx", `${cx}`);
circ.setAttribute("cy", `${cy}`);
circ.setAttribute("r", r);
circ.setAttribute("fill", color[i]);
group.appendChild(circ);
r = r - 12;
cy = cy + .5;
}
.gooey {
filter: url(#goo);
}
.crcl1 {
animation: move 5s linear infinite alternate forwards;
}
@keyframes move {
0% {
transform: translate(-80px, 0);
}
100% {
transform: translate(+80px, 0);
}
}
<!DOCTYPE html>
<html>
<body>
<link rel="stylesheet" href="style.css"></link>
<svg>
<defs>
<filter id="goo">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10" result="goo" />
<feBlend in="SourceGraphic" in2="goo" />
</filter>
</defs>
<script href="index.js"></script>
</svg>
</body>
</html>