Skip to content

Instantly share code, notes, and snippets.

@jgoday
Last active July 2, 2019 12:24
Show Gist options
  • Save jgoday/d1cf29ad83df8d55995d668c43e6d6ad to your computer and use it in GitHub Desktop.
Save jgoday/d1cf29ad83df8d55995d668c43e6d6ad to your computer and use it in GitHub Desktop.
import * as React from 'react';
import './App.css';
export interface IProps {
}
async function srcToDataUrl(url: string) {
return new Promise<string>(async (resolve, _) => {
const resp = await fetch(url);
const data = await resp.blob();
resolve(await readBlobAsDataUrl(data));
});
}
async function readBlobAsDataUrl(blob: Blob) {
return new Promise<string>((resolve, _) => {
const fr = new FileReader();
fr.onload = (e: any) => {
resolve(e.target.result);
};
fr.readAsDataURL(blob);
});
}
export default function App(props: IProps) {
const canvasRef = React.useRef<HTMLCanvasElement>();
const transformNodes = async (node: ChildNode) => {
const newNode = node.cloneNode(false) as HTMLElement;
if (newNode.nodeName == 'CANVAS') {
return [];
}
else if (newNode.nodeName == 'IMG') {
newNode.setAttribute('src', await srcToDataUrl(newNode.getAttribute('src')));
const autocloseTag = document.createElement('span');
autocloseTag.setAttribute("class", "close-image");
return [newNode, autocloseTag];
}
for (const ch of node.childNodes) {
const childs = await transformNodes(ch);
for (const newChild of childs) {
newNode.appendChild(newChild);
}
}
return [newNode];
}
const share = async (nodeId: string) => {
const nodes = await transformNodes(document.getElementById(nodeId));
const node = nodes[0] as HTMLElement;
const WIDTH = window.innerWidth;
const HEIGHT = window.innerHeight;
const canvas = canvasRef.current;
const isExplorer = window.navigator.userAgent.indexOf('MSIE') >= 0
|| window.navigator.userAgent.indexOf('Trident') >= 0;
const svgNs = isExplorer
? ''
: 'xmlns="http://www.w3.org/2000/svg"';
const htmlNs = isExplorer
? ''
: 'xmlns="http://www.w3.org/1999/xhtml"';
const data = `<svg ${svgNs} width='${WIDTH}px' height='${HEIGHT}px'>
<foreignObject width='100%' height='100%' >
<body ${htmlNs}>
${node.innerHTML.replace('><span class="close-image"></span>', ' externalResourcesRequired="true" />')}
</body>
</foreignObject>
</svg>`;
const img = new Image();
const svg = new Blob([data], {type: "image/svg+xml;charset=utf8"});
const url = await readBlobAsDataUrl(svg);
img.addEventListener('load', () => {
const ctx = canvas.getContext("2d");
ctx.canvas.width = WIDTH;
ctx.canvas.height= HEIGHT;
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, WIDTH, HEIGHT);
// URL.revokeObjectURL(url);
ctx.drawImage(img, 0, 0);
// const link = document.createElement('a');
// document.body.appendChild(link);
// link.setAttribute('download', 'image.png');
// canvas.toBlob(console.log);
const d = canvas.toDataURL("image/png");
const img2 = new Image();
img2.src = d;
document.body.appendChild(img2);
// console.log(d);
// link.setAttribute('href', d);
// link.click();
});
if (!isExplorer || true) {
document.body.appendChild(img);
}
img.src = url;
}
return (<div>
<ul>
<li>First</li>
<li>Second</li>
</ul>
<img src="https://avatars0.githubusercontent.com/u/32933512?s=200&v=4" />
<button
onClick={() => share('root')}>
Share
</button>
<canvas style={{display: 'none', width: '100%', height: '100%'}}
ref={canvasRef}>
</canvas>
</div>);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment