Add 'Export SVG' button.

pull/9/head
Atul Varma 2021-02-17 08:46:30 -05:00
rodzic 9d47ddf1b2
commit 68f5339e5f
1 zmienionych plików z 50 dodań i 13 usunięć

Wyświetl plik

@ -237,15 +237,38 @@ function randomlyReplaceParts(rng: Random, creature: JSX.Element): JSX.Element {
}); });
} }
function getSvgMarkup(el: SVGSVGElement): string {
return [
`<?xml version="1.0" encoding="utf-8"?>`,
"<!-- Generator: https://github.com/toolness/mystic-symbolic -->",
'<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">',
el.outerHTML,
].join("\n");
}
function exportSvg(filename: string, svgEl: SVGSVGElement) {
const dataURL = `data:image/svg+xml;utf8,${encodeURIComponent(
getSvgMarkup(svgEl)
)}`;
const anchor = document.createElement("a");
anchor.href = dataURL;
anchor.download = filename;
document.body.append(anchor);
anchor.click();
document.body.removeChild(anchor);
}
const AutoSizingSvg: React.FC<{ const AutoSizingSvg: React.FC<{
padding: number; padding: number;
children: JSX.Element | JSX.Element[]; children: JSX.Element | JSX.Element[];
}> = (props) => { downloadFilename?: string;
}> = ({ downloadFilename, ...props }) => {
const ref = useRef<SVGSVGElement>(null); const ref = useRef<SVGSVGElement>(null);
const [x, setX] = useState(0); const [x, setX] = useState(0);
const [y, setY] = useState(0); const [y, setY] = useState(0);
const [width, setWidth] = useState(1); const [width, setWidth] = useState(1);
const [height, setHeight] = useState(1); const [height, setHeight] = useState(1);
const svgEl = ref.current;
useEffect(() => { useEffect(() => {
if (ref.current) { if (ref.current) {
@ -258,7 +281,10 @@ const AutoSizingSvg: React.FC<{
}); });
return ( return (
<>
<svg <svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
width={`${width}px`} width={`${width}px`}
height={`${height}px`} height={`${height}px`}
viewBox={`${x} ${y} ${width} ${height}`} viewBox={`${x} ${y} ${width} ${height}`}
@ -266,6 +292,14 @@ const AutoSizingSvg: React.FC<{
> >
{props.children} {props.children}
</svg> </svg>
{downloadFilename && svgEl && (
<p>
<button onClick={() => exportSvg(downloadFilename, svgEl)}>
Export SVG
</button>
</p>
)}
</>
); );
}; };
@ -282,6 +316,11 @@ export const CreaturePage: React.FC<{}> = () => {
randomSeed === null randomSeed === null
? EYE_CREATURE ? EYE_CREATURE
: randomlyReplaceParts(new Random(randomSeed), EYE_CREATURE); : randomlyReplaceParts(new Random(randomSeed), EYE_CREATURE);
let downloadBasename = "mystic-symbolic-creature";
if (randomSeed !== null) {
downloadBasename += `-${randomSeed}`;
}
return ( return (
<> <>
@ -292,10 +331,8 @@ export const CreaturePage: React.FC<{}> = () => {
<button onClick={() => window.location.reload()}>Reset</button> <button onClick={() => window.location.reload()}>Reset</button>
</p> </p>
<CreatureContext.Provider value={ctx}> <CreatureContext.Provider value={ctx}>
<AutoSizingSvg padding={5}> <AutoSizingSvg padding={5} downloadFilename={`${downloadBasename}.svg`}>
<g transform-origin="50% 50%" transform="scale(0.5 0.5)"> <g transform="scale(0.5 0.5)">{creature}</g>
{creature}
</g>
</AutoSizingSvg> </AutoSizingSvg>
</CreatureContext.Provider> </CreatureContext.Provider>
</> </>