javascriptとsvgで波のアニメーションを作成しました
2022年1月9日
javascriptとsvgで波のアニメーションを作成しました。
ただ、SVGのpathのanimateに、適当な数字のパラメータのベジェ曲線を作って入れるだけです(語彙力)。
波といえるのか微妙ですが、以下です。
<svg width="100%" height="400" version="1.1" xmlns="http://www.w3.org/2000/svg" id="wave_svg">
<linearGradient id="wave_grad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#00B4DB" />
<stop offset="100%" stop-color="#224488" />
</linearGradient>
</svg>
<script>
"use strict";
let WaveAni = function (svg_id, debug_flg) {
let svg = document.getElementById(svg_id);
/*
points:[
[(起点)y, (ベジェ曲線のハンドル)x1, y1, x2, y2, (終点)y], [...],[...]
]
*/
let draw = function(points) {
let rect = svg.getBoundingClientRect(),
width = rect.width,
height = rect.height,
h = Math.floor(height) * 0.1,
w = Math.floor(width) * 0.1,
y_center = h * 5,
v = "";
let path = document.createElementNS('http://www.w3.org/2000/svg','path');
path.setAttribute('d', '');
path.setAttribute('fill','url(#wave_grad)');
path.setAttribute('style','opacity:0.8;');
if (debug_flg) {
// console.log(h);
// console.log(w);
debug_grid(svg, h, w);
}
let cnt = points.length;
let i, v_tmp, v_start_y, v_x1, v_y1, v_x2, v_y2, v_end_y, colors = ["red","blue","green","yellow","purple"];
for (i = 0; i < cnt; i++){
// (起点)y, (ベジェ曲線のハンドル)x1, y1, x2, y2, (終点)y
v_start_y = y_center + (h * points[i][0]);
v_x1 = w * points[i][1];
v_y1 = y_center + (h * points[i][2]);
v_x2 = w * points[i][3];
v_y2 = y_center + (h * points[i][4]);
v_end_y = y_center + (h * points[i][5]);
v_tmp = "M 0 " + v_start_y + " C " + v_x1 + "," + v_y1 + " " + v_x2 + "," + v_y2 + " " + width + "," + v_end_y + " V " + height + " H 0 Z;";
if (debug_flg) {
debug_path(svg, v_tmp, colors[i]);
debug_line(svg, 0, v_start_y, v_x1, v_y1, "red");
debug_line(svg, v_x2, v_y2, width, v_end_y, "red");
}
if (i > 0) v += " ";
v += v_tmp;
}
let animate = document.createElementNS("http://www.w3.org/2000/svg","animate");
animate.setAttribute('attributeName', 'd');
animate.setAttribute('dur', '15s');
animate.setAttribute('repeatCount', 'indefinite');
animate.setAttribute('values', v);
path.appendChild(animate);
svg.appendChild(path);
//animate.beginElement();
};
let debug_grid = function(svg, h, w) {
let path = document.createElementNS('http://www.w3.org/2000/svg','path');
let d = "", i;
for (i = 0; i <= 10; i++) {
d += "M 0 " + h * i + " H " + w * 10 + " " +
"M " + w * i + " 0 V " + h * 10 + " ";
}
path.setAttribute('d', d);
path.setAttribute('stroke', 'black');
path.setAttribute('fill','transparent');
path.setAttribute('stroke-dasharray','2');
path.setAttribute('style','opacity:0.5;');
svg.appendChild(path);
};
let debug_path = function(svg, d, color) {
let path = document.createElementNS('http://www.w3.org/2000/svg','path');
path.setAttribute('d', d);
path.setAttribute('stroke', color);
path.setAttribute('fill','transparent');
//path.setAttribute('stroke-dasharray','10');
path.setAttribute('style','opacity:0.75;');
svg.appendChild(path);
};
let debug_line = function(svg, x1, y1, x2, y2, color) {
let line = document.createElementNS('http://www.w3.org/2000/svg','line');
line.setAttribute('x1', x1);
line.setAttribute('y1', y1);
line.setAttribute('x2', x2);
line.setAttribute('y2', y2);
line.setAttribute('stroke', color);
line.setAttribute('stroke-dasharray','2');
line.setAttribute('style','opacity:0.75;');
svg.appendChild(line);
};
return {
draw: function(points) {
draw(points);
}
};
}
let wave = WaveAni('wave_svg', 0);
wave.draw([[1, 3, 1, 6, -2, -0.5],
[0, 4, -2.5, 6, 0.5, 1],
[-1, 4, 2, 7, -1, -1.5],
[1, 3, 1, 6, -2, -0.5]]);
wave.draw([[0, 4, -2.5, 6, 0.5, 1],
[-1, 4, 2, 7, -1, -1.5],
[1, 3, 1, 6, -2, -0.5],
[0, 4, -2.5, 6, 0.5, 1]]);
</script>