Skip to content

Instantly share code, notes, and snippets.

@nigjo
Created November 4, 2023 16:13
Show Gist options
  • Save nigjo/4faca926fa714d715734e94bae1c2201 to your computer and use it in GitHub Desktop.
Save nigjo/4faca926fa714d715734e94bae1c2201 to your computer and use it in GitHub Desktop.
A single function to convert JSON Data to a SVG Element
/**
* Convert a JSON data structure to a svg element with content.
*
* Some special keys are treated as tag name ("<"), text content ("_"),
* style-attribute ("~") or child elements (">"). All other
* keys are used as attribute names to the svg element.
*
* Text content or attribute values may be a single string or an array of
* strings (joined together for output).
*
* "styles" may be defined as a "normal" attribute or via the "~" key as an
* object of CSS key-value-pairs.
*
* This function does no validation to the json or svg data.
*
* @argument {object} data svg image (part) as json structure
*
* @returns {Element} A SVG Element
*/
function jsonToSvg(data) {
const SVGNS = 'http://www.w3.org/2000/svg';
if (data['<'] === '!') {
if (typeof (data['_']) === 'object') {
return document.createComment(data['_'].join(''));
} else {
return document.createComment(data['_']);
}
}
let e = document.createElementNS(SVGNS, data['<']);
for (let k of Object.keys(data)) {
switch (k) {
case '<':
//ignore tag name here
break;
case '_':
if (typeof (data[k]) === 'object') {
e.textContent = data[k].join('');
} else {
e.textContent = data[k];
}
break;
case '~':
//styles
let styles = "";
for (const [n, v] of Object.entries(data[k])) {
styles += `${n}:${v};`;
}
e.setAttribute('style', styles);
break;
case '>':
//children
for (let c of data[k]) {
e.append(jsonToSvg(c));
}
break;
default:
if (typeof (data[k]) === 'object') {
e.setAttribute(k, data[k].join(''));
} else {
e.setAttribute(k, data[k]);
}
break;
}
}
return e;
}
<!doctype html>
<html>
<head>
<title>json2svg Sample</title>
<script src="json2svg.js"></script>
<script>
fetch('sample.json').then(r => r.json()).then(j => {
j.width = j.height = 512;
j['>'].unshift({
"<": "style",
"_": [
"path{",
"fill:red;",
"stroke:none;",
"}"
]
});
document.body.append(jsonToSvg(j));
});
</script>
</head>
<body>
</body>
</html>
{
"<": "svg",
"viewBox": "0 0 100 100",
">": [
{
"<": "!",
"_": "from https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path"
},
{
"<": "path",
"d": [
"M 10,30\n",
"A 20,20 0,0,1 50,30\n",
"A 20,20 0,0,1 90,30\n",
"Q 90,60 50,90\n",
"Q 10,60 10,30 z"
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment