Last active
December 31, 2023 16:32
-
-
Save sarsamurmu/fd6d48b98c5b530417d4a80e1f10e796 to your computer and use it in GitHub Desktop.
Image Occlusion Enhanced One by One
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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