Skip to content

Instantly share code, notes, and snippets.

@sarsamurmu
Last active December 31, 2023 16:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sarsamurmu/fd6d48b98c5b530417d4a80e1f10e796 to your computer and use it in GitHub Desktop.
Save sarsamurmu/fd6d48b98c5b530417d4a80e1f10e796 to your computer and use it in GitHub Desktop.
Image Occlusion Enhanced One by One
<script>
var mask = document.querySelector('#io-overlay > img');
var svg = null
var nFill = '#FFF'
var qFill = '#FF7E7E'
var maskGroup = null
var occs = null
var currOccIdx = 0
async function swapToSvg() {
const parser = new DOMParser()
const imgName = parser.parseFromString(`{{Question Mask}}`, 'text/html').querySelector('img').getAttribute('src')
const imgLink = mask.src.replace(mask.getAttribute('src'), imgName)
const text = await (await fetch(imgLink)).text()
svg = parser.parseFromString(text, 'text/html').body.childNodes[0]
mask.style.display = 'none'
const h = svg.getAttribute('height')
const w = svg.getAttribute('width')
svg.setAttribute('viewBox', `0 0 ${w} ${h}`);
['height', 'width'].forEach(x => svg.removeAttribute(x))
const parent = document.querySelector('#io-overlay')
const prevSvg = parent.querySelector('svg')
prevSvg && prevSvg.remove()
parent.append(svg)
resizeSvg()
setTimeout(() => resizeSvg(), 100)
maskGroup = [...svg.querySelectorAll('title')].find(t => t.innerHTML === 'Masks').closest('g')
try { qFill = maskGroup.querySelector('rect.qshape').getAttribute('fill') } catch (e) { }
try { nFill = maskGroup.querySelector('rect:not(.qshape)').getAttribute('fill') } catch (e) { }
occs = [...maskGroup.children].filter(c => c.tagName !== 'title')
if (occs.length === 1 && occs[0].tagName === 'g') {
occs = [...occs[0].children]
}
occs.forEach(occ => {
occ.addEventListener('click', () => occ.style.display = 'none')
})
}
function markCurrent(el, isQ = true) {
if (el.tagName === 'rect') {
el.setAttribute('fill', isQ ? qFill : nFill)
} else {
el.querySelectorAll('rect').forEach(a => markCurrent(a, isQ))
}
}
async function revealNext() {
if (!svg) {
await swapToSvg();
}
if (currOccIdx > 0) {
occs[currOccIdx-1].style.display = 'none'
while (currOccIdx < occs.length && occs[currOccIdx].style.display === 'none') {
// console.log('Hidden', occs[currOccIdx])
currOccIdx++
}
}
if (currOccIdx < occs.length) {
markCurrent(maskGroup, false)
markCurrent(occs[currOccIdx])
if (document.documentElement.classList.contains('mobile')) {
const currOcc = occs[currOccIdx];
setTimeout(() => currOcc.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' }), 1000);
}
currOccIdx++
}
}
function reloadOccs() {
svg = null
currOccIdx = 0
revealNext()
}
function resizeSvg() {
const parent = document.querySelector('#io-wrapper')
const svg = parent.querySelector('svg')
const img = parent.querySelector('#io-original img')
;['width', 'height'].forEach(x => svg.setAttribute(x, img[x]))
}
// Prevent original image from loading before mask
aFade = 50, qFade = 0;
function loaded() {
const original = document.querySelector('#io-original')
original.style.visibility = 'visible'
}
if (mask === null || mask.complete) {
loaded()
} else {
mask.addEventListener('load', loaded)
}
// Toggle answer mask on clicking the image
function toggle() {
const style = document.querySelector('#io-overlay').style
style.display = style.display === 'block' || style.display === ''
? 'none'
: 'block'
}
// Key
if (window.IOEventListeners) {
window.IOEventListeners.forEach(([target, type, handler]) => {
target.removeEventListener(type, handler)
});
}
window.IOEventListeners = []
window.IOEventListener = (target, type, handler) => {
target.addEventListener(type, handler)
window.IOEventListeners.push([target, type, handler])
}
IOEventListener(window, 'resize', resizeSvg)
IOEventListener(document, 'keydown', (e) => {
e.key === '.' && toggle();
e.key === ',' && revealNext();
e.key === 'n' && reloadOccs();
})
// Remove the `//` to auto enable click to reveal
// If you don't remove the `//`, you will have to press `,` or `n` atleast one time
// to enable click to reveal
//swapToSvg();
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment