Skip to content

Instantly share code, notes, and snippets.

@OliverLeighC
Last active April 30, 2021 16:09
Show Gist options
  • Select an option

  • Save OliverLeighC/1ff2b801a45257af97aa3ed11022a319 to your computer and use it in GitHub Desktop.

Select an option

Save OliverLeighC/1ff2b801a45257af97aa3ed11022a319 to your computer and use it in GitHub Desktop.
React-PDF Svg Chart Options
Display the source blob
Display the rendered blob
Raw
<svg xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" class="highcharts-root" style="font-family:Helvetica;font-size:12px;" xmlns="http://www.w3.org/2000/svg" width="600" height="600" viewBox="0 0 600 600"><desc>Created with Highcharts 9.0.1</desc><defs><clipPath id="highcharts-o1kbh0z-313-"><rect x="0" y="0" width="449" height="495" fill="none"></rect></clipPath></defs><rect fill="#ffffff" class="highcharts-background" x="0" y="0" width="600" height="600" rx="0" ry="0"></rect><rect fill="none" class="highcharts-plot-background" x="95" y="60" width="495" height="449"></rect><g class="highcharts-grid highcharts-xaxis-grid" data-z-index="1"><path fill="none" data-z-index="1" class="highcharts-grid-line" d="M 95 285.5 L 590 285.5" opacity="1"></path><path fill="none" data-z-index="1" class="highcharts-grid-line" d="M 95 509.5 L 590 509.5" opacity="1"></path><path fill="none" data-z-index="1" class="highcharts-grid-line" d="M 95 60.5 L 590 60.5" opacity="1"></path></g><g class="highcharts-grid highcharts-yaxis-grid" data-z-index="1"><path fill="none" stroke="#e6e6e6" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 94.5 60 L 94.5 509" opacity="1"></path><path fill="none" stroke="#e6e6e6" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 149.5 60 L 149.5 509" opacity="1"></path><path fill="none" stroke="#e6e6e6" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 204.5 60 L 204.5 509" opacity="1"></path><path fill="none" stroke="#e6e6e6" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 259.5 60 L 259.5 509" opacity="1"></path><path fill="none" stroke="#e6e6e6" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 314.5 60 L 314.5 509" opacity="1"></path><path fill="none" stroke="#e6e6e6" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 369.5 60 L 369.5 509" opacity="1"></path><path fill="none" stroke="#e6e6e6" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 424.5 60 L 424.5 509" opacity="1"></path><path fill="none" stroke="#e6e6e6" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 479.5 60 L 479.5 509" opacity="1"></path><path fill="none" stroke="#e6e6e6" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 534.5 60 L 534.5 509" opacity="1"></path><path fill="none" stroke="#e6e6e6" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 590.5 60 L 590.5 509" opacity="1"></path></g><rect fill="none" class="highcharts-plot-border" data-z-index="1" x="95" y="60" width="495" height="449"></rect><g class="highcharts-axis highcharts-xaxis" data-z-index="2"><path fill="none" class="highcharts-axis-line" stroke="#ccd6eb" stroke-width="1" data-z-index="7" d="M 94.5 60 L 94.5 509"></path></g><g class="highcharts-axis highcharts-yaxis" data-z-index="2"><text x="590" data-z-index="7" text-anchor="end" transform="translate(0,0)" class="highcharts-axis-title" style="color:#666666;fill:#666666;" y="546.5">Weight (%)</text><path fill="none" class="highcharts-axis-line" data-z-index="7" d="M 95 509 L 590 509"></path></g><g class="highcharts-series-group" data-z-index="3"><g class="highcharts-series highcharts-series-0 highcharts-bar-series highcharts-color-0" data-z-index="0.1" opacity="1" transform="translate(590,509) rotate(90) scale(-1,1) scale(1 1)" clip-path="url(#highcharts-o1kbh0z-313-)"><rect x="344.5" y="291.5" width="50" height="204" fill="#A9DACC" stroke="#ffffff" stroke-width="1" opacity="1" class="highcharts-point highcharts-color-0"></rect><rect x="120.5" y="51.5" width="50" height="444" fill="#A9DACC" stroke="#ffffff" stroke-width="1" opacity="1" class="highcharts-point highcharts-color-0"></rect></g><g class="highcharts-markers highcharts-series-0 highcharts-bar-series highcharts-color-0" data-z-index="0.1" opacity="1" transform="translate(590,509) rotate(90) scale(-1,1) scale(1 1)" clip-path="none"></g><g class="highcharts-series highcharts-series-1 highcharts-bar-series highcharts-color-1" data-z-index="0.1" opacity="1" transform="translate(590,509) rotate(90) scale(-1,1) scale(1 1)" clip-path="url(#highcharts-o1kbh0z-313-)"><rect x="277.5" y="262.5" width="50" height="233" fill="#75C6D1" stroke="#ffffff" stroke-width="1" opacity="1" class="highcharts-point highcharts-color-1"></rect><rect x="53.5" y="140.5" width="50" height="355" fill="#75C6D1" stroke="#ffffff" stroke-width="1" opacity="1" class="highcharts-point highcharts-color-1"></rect></g><g class="highcharts-markers highcharts-series-1 highcharts-bar-series highcharts-color-1" data-z-index="0.1" opacity="1" transform="translate(590,509) rotate(90) scale(-1,1) scale(1 1)" clip-path="none"></g></g><text x="300" text-anchor="middle" class="highcharts-title" data-z-index="4" style="color:#333333;font-size:18px;fill:#333333;" y="24">Regional Exposure</text><text x="300" text-anchor="middle" class="highcharts-subtitle" data-z-index="4" style="color:#666666;fill:#666666;" y="45">As Of 2021-Apr</text><text x="10" text-anchor="start" class="highcharts-caption" data-z-index="4" style="color:#666666;fill:#666666;" y="597"></text><g class="highcharts-data-labels highcharts-series-0 highcharts-bar-series highcharts-color-0" data-z-index="6" opacity="1" transform="translate(95,60) scale(1 1)"><g class="highcharts-label highcharts-data-label highcharts-data-label-color-0" data-z-index="1" transform="translate(204,68)"><text x="5" data-z-index="1" y="16" style="color:#000000;font-size:11px;font-weight:bold;fill:#000000;"><tspan class="highcharts-text-outline" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="2px" stroke-linejoin="round" style="">18.54<tspan x="5" y="16">​</tspan></tspan>18.54</text></g><g class="highcharts-label highcharts-data-label highcharts-data-label-color-0" data-z-index="1" transform="translate(326,292)"><text x="5" data-z-index="1" y="16" style="color:#000000;font-size:11px;font-weight:bold;fill:#000000;"><tspan class="highcharts-text-outline" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="2px" stroke-linejoin="round" style="">40.367999999999995<tspan x="5" y="16">​</tspan></tspan>40.367999999999995</text></g></g><g class="highcharts-data-labels highcharts-series-1 highcharts-bar-series highcharts-color-1" data-z-index="6" opacity="1" transform="translate(95,60) scale(1 1)"><g class="highcharts-label highcharts-data-label highcharts-data-label-color-1" data-z-index="1" transform="translate(233,135)"><text x="5" data-z-index="1" y="16" style="color:#000000;font-size:11px;font-weight:bold;fill:#000000;"><tspan class="highcharts-text-outline" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="2px" stroke-linejoin="round" style="">21.224<tspan x="5" y="16">​</tspan></tspan>21.224</text></g><g class="highcharts-label highcharts-data-label highcharts-data-label-color-1" data-z-index="1" transform="translate(355,359)"><text x="5" data-z-index="1" y="16" style="color:#000000;font-size:11px;font-weight:bold;fill:#000000;"><tspan class="highcharts-text-outline" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="2px" stroke-linejoin="round">32.267999999999994<tspan x="5" y="16">​</tspan></tspan>32.267999999999994</text></g></g><g class="highcharts-legend" data-z-index="7" transform="translate(153,560)"><rect fill="none" class="highcharts-legend-box" rx="0" ry="0" x="0" y="0" width="293" height="25" visibility="visible"></rect><g data-z-index="1"><g><g class="highcharts-legend-item highcharts-bar-series highcharts-color-0 highcharts-series-0" data-z-index="1" transform="translate(8,3)"><text x="21" style="color:#333333;cursor:pointer;font-size:12px;font-weight:bold;fill:#333333;" text-anchor="start" data-z-index="2" y="15">some cool fund</text><rect x="2" y="4" width="12" height="12" fill="#A9DACC" rx="6" ry="6" class="highcharts-point" data-z-index="3"></rect></g><g class="highcharts-legend-item highcharts-bar-series highcharts-color-1 highcharts-series-1" data-z-index="1" transform="translate(137.671875,3)"><text x="21" y="15" style="color:#333333;cursor:pointer;font-size:12px;font-weight:bold;fill:#333333;" text-anchor="start" data-z-index="2">some cool benchmark</text><rect x="2" y="4" width="12" height="12" fill="#75C6D1" rx="6" ry="6" class="highcharts-point" data-z-index="3"></rect></g></g></g></g><g class="highcharts-axis-labels highcharts-xaxis-labels" data-z-index="7"><text x="80" style="color:#666666;cursor:default;font-size:11px;fill:#666666;" text-anchor="end" transform="translate(0,0)" y="177" opacity="1">Europe</text><text x="80" style="color:#666666;cursor:default;font-size:11px;fill:#666666;" text-anchor="end" transform="translate(0,0)" y="402" opacity="1">North America</text></g><g class="highcharts-axis-labels highcharts-yaxis-labels" data-z-index="7"><text x="95" style="color:#666666;cursor:default;font-size:11px;fill:#666666;" text-anchor="middle" transform="translate(0,0)" y="528" opacity="1">0</text><text x="150" style="color:#666666;cursor:default;font-size:11px;fill:#666666;" text-anchor="middle" transform="translate(0,0)" y="528" opacity="1">5</text><text x="205" style="color:#666666;cursor:default;font-size:11px;fill:#666666;" text-anchor="middle" transform="translate(0,0)" y="528" opacity="1">10</text><text x="260" style="color:#666666;cursor:default;font-size:11px;fill:#666666;" text-anchor="middle" transform="translate(0,0)" y="528" opacity="1">15</text><text x="315" style="color:#666666;cursor:default;font-size:11px;fill:#666666;" text-anchor="middle" transform="translate(0,0)" y="528" opacity="1">20</text><text x="370" style="color:#666666;cursor:default;font-size:11px;fill:#666666;" text-anchor="middle" transform="translate(0,0)" y="528" opacity="1">25</text><text x="425" style="color:#666666;cursor:default;font-size:11px;fill:#666666;" text-anchor="middle" transform="translate(0,0)" y="528" opacity="1">30</text><text x="480" style="color:#666666;cursor:default;font-size:11px;fill:#666666;" text-anchor="middle" transform="translate(0,0)" y="528" opacity="1">35</text><text x="535" style="color:#666666;cursor:default;font-size:11px;fill:#666666;" text-anchor="middle" transform="translate(0,0)" y="528" opacity="1">40</text><text x="583.875" style="color:#666666;cursor:default;font-size:11px;fill:#666666;" text-anchor="middle" transform="translate(0,0)" y="528" opacity="1">45</text></g><text x="590" class="highcharts-credits" text-anchor="end" data-z-index="8" style="cursor:pointer;color:#999999;font-size:9px;fill:#999999;" y="595">Highcharts.com</text></svg>
<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" class=\"highcharts-root\" style=\"font-family:Helvetica;font-size:20px;\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1000\" height=\"800\" viewBox=\"0 0 1000 800\"><desc>Created with Highcharts 9.0.1</desc><defs><clipPath id=\"highcharts-hn7jjeq-91-\"><rect x=\"0\" y=\"0\" width=\"980\" height=\"737\" fill=\"none\"></rect></clipPath></defs><rect fill=\"#ffffff\" class=\"highcharts-background\" x=\"0\" y=\"0\" width=\"1000\" height=\"800\" rx=\"0\" ry=\"0\"></rect><rect fill=\"none\" class=\"highcharts-plot-background\" x=\"10\" y=\"48\" width=\"980\" height=\"737\"></rect><rect fill=\"none\" class=\"highcharts-plot-border\" data-z-index=\"1\" x=\"10\" y=\"48\" width=\"980\" height=\"737\"></rect><g class=\"highcharts-series-group\" data-z-index=\"3\"><g class=\"highcharts-series highcharts-series-0 highcharts-pie-series\" data-z-index=\"0.1\" opacity=\"1\" transform=\"translate(10,48) scale(1 1)\"><path fill=\"none\" d=\"M 490 10 A 358.5 358.5 0 1 1 489.64150005974983 10.00017924998508 M 490 368.5 A 0 0 0 1 0 490 368.5\" class=\"highcharts-empty-series\" stroke=\"#cccccc\" stroke-width=\"1\"></path></g><g class=\"highcharts-markers highcharts-series-0 highcharts-pie-series\" data-z-index=\"0.1\" opacity=\"1\" transform=\"translate(10,48) scale(1 1)\"></g></g><text x=\"500\" text-anchor=\"middle\" class=\"highcharts-title\" data-z-index=\"4\" style=\"color:#333333;font-size:18px;fill:#333333;\" y=\"24\"></text><text x=\"500\" text-anchor=\"middle\" class=\"highcharts-subtitle\" data-z-index=\"4\" style=\"color:#666666;font-size:20px;fill:#666666;\" y=\"30\">As Of Apr-2021</text><text x=\"10\" text-anchor=\"start\" class=\"highcharts-caption\" data-z-index=\"4\" style=\"color:#666666;fill:#666666;\" y=\"803\"></text><g class=\"highcharts-data-labels highcharts-series-0 highcharts-pie-series\" data-z-index=\"6\" opacity=\"1\" transform=\"translate(10,48) scale(1 1)\"></g><g class=\"highcharts-legend\" data-z-index=\"7\"><rect fill=\"none\" class=\"highcharts-legend-box\" rx=\"0\" ry=\"0\" x=\"0\" y=\"0\" width=\"8\" height=\"8\" visibility=\"hidden\"></rect><g data-z-index=\"1\"><g></g></g></g></svg>
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
/* eslint-disable no-console */
import { useMemo, createElement } from "react";
import { parse, TextNode, ElementNode, RootNode } from "svg-parser";
const supportedStyleProps = [
"color",
"dominantBaseline",
"fill",
"fillOpacity",
"fillRule",
"opacity",
"stroke",
"strokeWidth",
"strokeOpacity",
"strokeLinecap",
"strokeDasharray",
"transform",
"textAnchor",
"visibility"
]
function isElementNode(node: TextNode | ElementNode): node is ElementNode {
return node.type === 'element'
}
function removeLineBreaks(text?: string | number | boolean) {
if (typeof text === 'string') {
return text.replace(/(\r\n|\n|\r)/gm, "")
}
return text;
}
// https://dev.to/qausim/convert-html-inline-styles-to-a-style-object-for-react-components-2cbi
const formatStringToCamelCase = (str: string) => {
const splitted = str.split("-");
if (splitted.length === 1) return splitted[0];
return (
splitted[0] +
splitted
.slice(1)
.map((word) => word[0].toUpperCase() + word.slice(1))
.join("")
);
};
export const getStyleObjectFromString = (str: string | null) => {
const style: any = {};
if (!str) return {};
str.split(";").forEach((el) => {
const [property, value] = el.split(":");
if (!property) return;
if (property === "cursor") return;
const formattedProperty = formatStringToCamelCase(property.trim());
if (supportedStyleProps.includes(formattedProperty)) {
style[formattedProperty] = value.trim();
}
});
return style;
};
function handleRelativePositioning(currentPosition: string | number, parentPosition?: number) {
let position = Number(currentPosition) ?? 0;
if (parentPosition) {
position += parentPosition
}
return position;
}
function getParentPosition(pos: number | string | undefined) {
if (!pos) return 0;
if (typeof pos === 'string') return Number(pos);
return pos;
}
function svgToJSXWithRelPositioning(
node: TextNode | ElementNode | string, parentX?: number, parentY?: number
): any {
if (typeof node === 'string') {
return removeLineBreaks(node);
}
if (!isElementNode(node)) {
return removeLineBreaks(node.value);
}
const elementName = node.tagName;
if (!elementName) {
console.log('NO TAG NAME: ', node);
return null;
}
let componentProps;
if (node.tagName === 'desc' || node.tagName === 'defs') return null;
if (node.properties !== undefined) {
if (node.tagName === "text" || node.tagName === "tspan") {
componentProps = {
x: handleRelativePositioning(node.properties.x, parentX),
y: handleRelativePositioning(node.properties.y, parentY),
textAnchor: node.properties['text-anchor']
}
} else {
componentProps = {
x: handleRelativePositioning(node.properties.x, parentX),
y: handleRelativePositioning(node.properties.y, parentY),
...node.properties
}
}
if (node.properties.style) {
componentProps = {
...componentProps,
style: getStyleObjectFromString(node.properties.style as string)
}
}
}
let children;
if (node.children && node.children.length > 0) {
children = node.children.map(
(childNode) =>
svgToJSXWithRelPositioning(
childNode, getParentPosition(node.properties?.x), getParentPosition(node.properties?.y)
)
)
}
return createElement(elementName.toUpperCase(), componentProps, children);
}
export const createSvgComponent = (svgXml: string) => {
if (!svgXml || svgXml === "") return null;
const svg = svgXml.replaceAll("px", "pt");
const svgElement = useMemo(() => {
const parsed: RootNode = parse(svg);
return svgToJSXWithRelPositioning(parsed.children[0], 0);
}, [svgXml]);
return svgElement;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment