- 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-hair
is not defined, the value of--backup-fill
will be used. However, the value of--backup-fill
is different based on classnames, it's difficult to replace it. For now, I just ignore it.