I am trying to recreate something like this.
This is what I have tried
// 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>
As you can see that it is not creating the desired effect at all. I can't seem to understand why is that. I know in creating a gooey effect the background color
must be contrasting which I believe is the case above.
Can someone please help me point me to the correct direction as to what am I doing wrong here? Also, I need to admit that I don't understand the math behind the svg filter
used here. Does that need to be manipulated to achieve the desired effect?
The filter must affect both shapes at the same time so that they are part of the same "SourceGraphic". To do so, you can use a <g>
element and add the filter on it:
// 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>