| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- /**
- * @see https://stackoverflow.com/a/28226736
- * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas
- * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL
- *
- * @created 25.09.2023
- * @author smiley <smiley@chillerlan.net>
- * @copyright 2023 smiley
- * @license MIT
- */
- export default class SVGConvert{
- /**
- * Converts the SVG image from the source element into a raster image with the given size and format
- * and inserts the resulting data URI into the src attribute of the given destination image element.
- *
- * @param {SVGElement|HTMLImageElement} source
- * @param {HTMLImageElement} destination
- * @param {Number<int>} width
- * @param {Number<int>} height
- * @param {String} format
- * @return {void}
- */
- static toDataURI(source, destination, width, height, format){
- // format is whatever the fuck the specification allows:
- // @see https://html.spec.whatwg.org/multipage/canvas.html#dom-canvas-todataurl-dev
- format = (format || 'image/png');
- if(!destination instanceof HTMLImageElement){
- throw new Error('destination is not an instance of HTMLImageElement');
- }
- if(source instanceof HTMLImageElement){
- source = SVGConvert.base64Decode(source);
- }
- SVGConvert.toCanvas(source, width, height)
- .then(canvas => destination.src = canvas.toDataURL(format))
- .catch(error => console.log('(╯°□°)╯彡┻━┻ ', error));
- }
- /**
- * Draws the given SVG source on a canvas of the given size and returns the canvas element
- *
- * @param {SVGElement} source
- * @param {Number<int>} width
- * @param {Number<int>} height
- * @return {Promise<HTMLCanvasElement>}
- */
- static toCanvas(source, width, height){
- return new Promise((resolve, reject) => {
- if(!source instanceof SVGElement){
- throw new Error('source is not an instance of SVGElement');
- }
- // the source SVG element needs to be visible
- source.style.display = 'inline-block';
- source.style.visibility = 'visible';
- // add/fix the width/height of the SVG element
- // @see https://bugzilla.mozilla.org/show_bug.cgi?id=700533#c39
- source.width.baseVal.valueAsString = width;
- source.height.baseVal.valueAsString = height;
- try{
- // stringify the SVG element and create an object URL for it
- let svgString = new XMLSerializer().serializeToString(source);
- let svgBlob = new Blob([svgString], {type: 'image/svg+xml;charset=utf-8'});
- let tempUrl = URL.createObjectURL(svgBlob);
- // create a temporary image
- let tempImg = new Image(width, height);
- // trigger the onLoad event with the temporary blob URL
- tempImg.src = tempUrl;
- // process the conversion in the onLoad event
- tempImg.onload = function(){
- // create a canvas element to draw the SVG on
- let canvas = document.createElement('canvas');
- canvas.width = width;
- canvas.height = height;
- canvas.getContext('2d').drawImage(tempImg, 0, 0);
- // revoke the temporary blob
- URL.revokeObjectURL(tempUrl);
- // return the PNG image as data URI
- resolve(canvas);
- };
- }
- catch(error){
- reject(error.message);
- }
- });
- }
- /**
- * Converts the given SVG base64 data URI into a DOM element
- *
- * @param {HTMLImageElement} image
- * @return {SVGElement}
- */
- static base64Decode(image){
- if(!image instanceof HTMLImageElement){
- throw new Error('image is not an instance of HTMLImageElement');
- }
- if(!image.src || !image.src.includes('base64,')){
- throw new Error('invalid image source');
- }
- return new DOMParser().parseFromString(atob(image.src.split(',')[1]), 'image/svg+xml').firstChild;
- }
- }
|