Preface
Goal: Generating SVG in DOM using Native Javascript.
Preview
The looks from the preview below is nice, but the animation is horrible, as we can see the video later.
SetInterval
I’m using SetInterval
method to run javascript.
I learnt it from w3schools
.
I do not know if javascript animation is not a good idea. Or maybe just my script that is bad.
But we need this example,
so we can compare with @keyframes
method counterpart.
Disclaimer
We are still discussing about, generating SVG in DOM using javascript.
This article is intended to be sort.
You can skip this entire section.
And click right away to @keyframes
method.
Alter D Attribute on the Fly
The HTML document is remain the same. But the javascript has many enhancement.
HTML: Head
<head>
<title>Bezier Curves</title>
<link rel="stylesheet"
href="24-bezier.css"/>
<link rel="stylesheet"
href="24-style.css"/>
<script src="28-bezier.js"></script>
</head>
HTML: Body
Also prepare the HTML body.
<body>
<div id="svg_container">
<svg xmlns="http://www.w3.org/2000/svg"
id="svg_root" viewbox="0 0 200 160">
</svg>
</div>
<div id="sitedesc_image"></div>
<p style="text-align: center;">
Paragraph Test on SVG Background</p>
</body>
Javascript: Skeleton
While the HTML code is remain the same, the javascript would slightly different, with variant for each animation.
function createPaths(svg_root, range) {...}
function getBezierParams(index, variant) {...}
function modifyPaths(svg_root, range) {
...
function frame() {...}
}
document.addEventListener(
"DOMContentLoaded", function(event) {...});
Notice the variant argument.
And frame
function inside modifyPaths
.
Javascript: Create Path
Exactly the same as previous function.
function createPaths(svg_root, range) {
const xmlns = 'http://www.w3.org/2000/svg';
const blueScale = [ '#E3F2FD',
'#BBDEFB', '#90CAF9', '#64B5F6',
'#42A5F5', '#2196F3', '#1E88E5',
'#1976D2', '#1565C0', '#0D47A1'
];
range.forEach((_, i) => {
area = document.createElementNS(xmlns,"path");
area.setAttribute("class", "area");
area.setAttribute("id", `svg_area_${i}`);
area.setAttribute("fill", blueScale[i]);
svg_root.appendChild(area)
});
}
We haven’t set any d
property yet.
No points initialized.
Javascript: Get Bezier Params
Be functional.
The idea is, to have the point result by index. And calculate without any loop.
function getBezierParams(index, variant) {
const i = index + 1;
// Initialize with destructuring style
let [mx, my] = [0, 190];
let [c1x, c2x, c3x] = [-10, 70, 120];
let c1y, c2y, c3y;
let [s1x, s1y, s2x, s2y] = [170, 230, 200, 220];
my -= 20*i;
c1x += 10*i;
[c1y, c2y, c3y] = [my-10, my-10, my+10]
s1y -= 20*i;
s2y -= 20*i;
c1x += variant;
c1y += variant;
c3x -= variant;
c3y += variant;
s1x -= variant;
s1y += variant;
return {
mx: mx, my: my,
c1x: c1x, c1y: c1y, c2x: c2x, c2y: c2y,
c3x: c3x, c3y: c3y,
s1x: s1x, s1y: s1y, s2x: s2x, s2y: s2y
};
}
The only different with our previous script is, we have this variant argument.
function getBezierParams(index, variant) {
...
c1x += variant;
c1y += variant;
c3x -= variant;
c3y += variant;
s1x -= variant;
s1y += variant;
...
}
Again. You can be as creative as you want. This code above is just an example.
Javascript: Modify Path
This is also a loop, with each has different interval.
function modifyPaths(svg_root, range) {
range.forEach((_, i) => {
let id = null;
clearInterval(id);
id = setInterval(frame, 100+10*i);
let variant = 0;
const area = document
.getElementById(`svg_area_${i}`);
function frame() {...}
});
}
Javascript: Frame
For each loop, we destructure our bezier params first.
Then set the d
attribute property.
function frame() {
if (variant == 20) {
variant = 0;
} else {
variant++;
const {
mx, my,
c1x, c1y, c2x, c2y, c3x, c3y,
s1x, s1y, s2x, s2y
} = getBezierParams(i, variant);
area.setAttribute("d",
`M ${mx} ${my}
C ${c1x} ${c1y}, ${c2x} ${c2y}, ${c3x} ${c3y}
S ${s1x} ${s1y}, ${s2x} ${s2y}
L 200, 0 L 0, 0
Z ${mx} ${my}`);
}
}
Javascript: Main Entry Point
The program entry point in web development, could be DOM Ready or DOM Content Loaded.
document.addEventListener(
"DOMContentLoaded", function(event) {
const svg_root = document
.getElementById("svg_root");
const range = [...Array(10)];
createPaths(svg_root, range);
modifyPaths(svg_root, range);
});
That is all.
Preview
The result is similar as below:
It does not feel smooth. And I do not know about high CPU usage.
What is Next ?
Instead of javascript,
we can smooth the animation,
using @keyframes
in stylesheet.
Consider continue reading [ Bezier SVG - Keyframe Animation ].
Thank you for reading.