JSFiddle - React, Tailwind, and code Playground
HTML
<body>
This fiddle shows just one SVG path, but I'm dealing with several.
<div>
<button id="trigger">
Click me to raise the tail
</button>
</div>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="300px" height="4000px" viewBox="0 0 300 4000" enable-background="new 0 0 300 4000">
<g>
<path opacity="0.5" fill="#000000" d="M0,342.9c63.2,0,84.4-12.9,121.5-92.6 C152,184.6,155,25,300,25v154c-64.4-81.6-113.2,6.6-178.7,124C112.5,318.9,77,370.7,0,370.7">
<animate begin="indefinite" attributeName="d" dur="1000ms" fill="freeze"/> <!-- "to" attribute gets injected from JS -->
</path>
<!-- More paths are here -->
</g>
</svg>
</body>
JavaScript
document.getElementById("trigger").addEventListener("click",function() {offsetSVG(50)});
// please don't hate me if this is a crappy regex (-:
var path0regex = /^[^,]*,(-?[\d\.]+)[\s\S]*[Cc][^,]+,(-?[\d\.]+)[^Vv]+[Vv][^,]+,[^,]+,[^,]+,[^,]+,(-?[\d\.]+),[^,]+,(-?[\d\.]+)[^,]+,(-?[\d\.]+),[^,]+,(-?[\d\.]+),[^,]+,(-?[\d\.]+).*/
function offsetSVG(offset) {
var paths = document.getElementsByTagName("path");
for (var i=0; i<paths.length; i++) {
var path = paths[i];
var regex = eval("path" + i + "regex");
captureCount = regex.toString().split("(").length - 1;
var newPosition = svgCoordinates(path,offset,regex,captureCount);
path.setAttribute("d",newPosition);
}
}
function svgCoordinates(path,offset,regex,captureCount) {
var d = path.getAttribute("d").replace(/-/g,',-'); // implementation detail left out of question
var dMatch = d.match(regex);
var dValuesAltered = [];
for (i=1; i<dMatch.length; i++) {
dValuesAltered.push(d.replace(regex, (parseInt(dMatch[i])-offset).toString()));
}
// please don't hate me if this is crappily done (-:
var reverseRE = regex.toString()
.replace(/\(/g,"@)@")
.replace(/([^@]+)\)/g,"$1(")
.replace(/@\)@/g,")")
.replace(/^\//,"(")
.replace(/\/$/,")")
reverseRE = new RegExp(reverseRE);
var newD;
// I'm trying to avoid the kind of code that's here.
if (captureCount == 5) {
newD = d.replace(reverseRE, "$1" + dValuesAltered[0] + "$2" + dValuesAltered[1] + "$3" + dValuesAltered[2] + "$4" + dValuesAltered[3] + "$5" + dValuesAltered[4] + "$6");
} else if (captureCount == 7) {
newD = d.replace(reverseRE, "$1" + dValuesAltered[0] + "$2" + dValuesAltered[1] + "$3" + dValuesAltered[2] + "$4" + dValuesAltered[3] + "$5" + dValuesAltered[4] + "$6" + dValuesAltered[5] + "$7" + dValuesAltered[6] + "$8");
} else { // 4
newD = d.replace(reverseRE, "$1" + dValuesAltered[0] + "$2" + dValuesAltered[1] + "$3" + dValuesAltered[2] + "$4" + dValuesAltered[3] + "$5");
...