- Open Reddit's avatar editor
- Edit your avatar (include Premium parts)
- Run this code at browser's console.
Change the variable "scale" to get different size image.
| (async () => { | |
| let scale = 2; | |
| let width = 1185; | |
| let height = 1875; | |
| let root = document.querySelector('[data-testid="avatar"]'); | |
| if (root === null) { | |
| alert('Avatar editor is not open.'); | |
| return; | |
| } | |
| let layersDiv = root.querySelectorAll('[data-testid*="avatar:layer"]'); | |
| let variables = {}; | |
| Array.from(document.body.style) | |
| .filter((prop) => prop.startsWith('--')) | |
| .forEach(prop => { | |
| variables[prop] = document.body.style.getPropertyValue(prop); | |
| }); | |
| let layersImg = await Promise.all(Array.from(layersDiv).map(elm => { | |
| let svgSrc = elm.shadowRoot.querySelector('svg').outerHTML; | |
| Object.entries(variables).forEach(([ key, value ]) => { | |
| svgSrc = svgSrc.replaceAll(new RegExp(`var\\(${key}, var\\(--backup-fill\\)\\)`, 'g'), value); | |
| }); | |
| let blob = new Blob([ svgSrc ], { type: 'image/svg+xml' }); | |
| let url = URL.createObjectURL(blob); | |
| return loadImg(url); | |
| })); | |
| let cvs = new OffscreenCanvas(width * scale, height * scale); | |
| let ctx = cvs.getContext('2d'); | |
| layersImg.forEach((img) => { | |
| ctx.drawImage(img, 0, 0, cvs.width, cvs.height); | |
| }); | |
| let anchor = document.createElement('a'); | |
| anchor.download = "avatar.png"; | |
| anchor.href = URL.createObjectURL(await cvs.convertToBlob()) | |
| anchor.click(); | |
| function loadImg(src) { | |
| return new Promise((resolve, reject) => { | |
| let img = new Image(); | |
| img.addEventListener('load', () => { | |
| resolve(img); | |
| }); | |
| img.addEventListener('error', (e) => { | |
| reject(e); | |
| }); | |
| img.src = src; | |
| }); | |
| } | |
| })() |
CSS in SVGs doesn't work when convert to
<img>using blob or dataurl, so I have to replace css variables with their values.The CSS actually looks like this
fill: var(--color-hair, var(--backup-fill)). So when--color-hairis not defined, the value of--backup-fillwill be used. However, the value of--backup-fillis different based on classnames, it's difficult to replace it. For now, I just ignore it.