Skip to content

Instantly share code, notes, and snippets.

@mcshaz
Last active June 28, 2019 08:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mcshaz/394876e099d7efc1d1d509bb62fd5b66 to your computer and use it in GitHub Desktop.
Save mcshaz/394876e099d7efc1d1d509bb62fd5b66 to your computer and use it in GitHub Desktop.
cut and paste a section of svg markup, enter x & y translated, and all vectors will be offset (not bulletproof, but works for my markup)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>svg markup offset</title>
</head>
<body>
<form>
<label>
add to x
<input id="moveX" value="0" type="number" step="any">
</label>
<label>
add to y
<input id="moveY" value="0" type="number" step="any">
</label>
<textarea id="in"></textarea>
<input type="submit" value="transform">
<pre><code id="out"></code></pre>
</form>
<script>
document.getElementsByTagName('form')[0].addEventListener('submit', submit);
function submit(evt) {
evt.preventDefault();
const input = document.getElementById('in');
const moveX = Number(document.getElementById('moveX').value);
const moveY = Number(document.getElementById('moveY').value);
let moved = parse(input.value, moveX, moveY);
document.getElementById('out').innerHTML = moved.replace(/&/g,'&amp;').replace(/</g,'&lt;');
}
function parse(domStr, moveX, moveY) {
const colonPlace = '_colon_';
if (typeof domStr !== 'string') {
throw new TypeError('domStr must be a string');
}
const oParser = new DOMParser();
const isWrappedSvg = /^[\s\r\n]*<\s*svg/.test(domStr)
if (!isWrappedSvg) {
domStr = '<svg>' + domStr.replace(/:/g,colonPlace) + '</svg>';
}
const oDOM = oParser.parseFromString(domStr, "application/xml");
const modifyAllAtt = (a, delegate) => {
const xpath = `//*[@${a}]`;
const nodesSnapshot = oDOM.evaluate(xpath, oDOM, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for (let i=0; i < nodesSnapshot.snapshotLength; i++ ) {
const thisNode = nodesSnapshot.snapshotItem(i);
const val = thisNode.getAttribute(a);
thisNode.setAttribute(a, delegate(val));
}
}
const addValToAtt = (a, addVal) => {
modifyAllAtt(a, (v) => parseFloat(v) + addVal);
}
const xs = ['x', 'cx', 'x1', 'x2'];
for (const a of xs) {
addValToAtt(a, moveX);
addValToAtt(a.replace('x', 'y'), moveY);
}
modifyAllAtt('d', (a) => {
if (a[0] === 'm') {
return a.replace(/^m *([\d\-][\d.]*)([, ]+)([\d\-][\d.]*)/, (m, x, sep, y) => 'm ' + (parseFloat(x) + moveX) + sep + (parseFloat(y) + moveY));
}
if (a[0] === 'M') {
return a.replace(/([vVhH]|[\d\-][\d.]*)([, ]*)([\d\-][\d.]*)/g, (m, x, sep, y) => {
const xVal = parseFloat(x);
if (isNaN(xVal)) {
if (x === 'V') {
return 'V' + sep + (parseFloat(y) + moveY);
}
if (x === 'H') {
return 'H' + sep + (parseFloat(y) + moveX);
}
} else {
return (xVal + moveX) + sep + (parseFloat(y) + moveY);
}
return m;
});
}
console.log(`unknown d attribute='${a}'`);
});
return (isWrappedSvg
? oDOM.documentElement.outerHTML
: oDOM.documentElement.innerHTML).replace(new RegExp(colonPlace, 'g'), ':');
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment