feat(ipub): make ipub-background containerized into ipub-body
This commit is contained in:
@@ -28,49 +28,84 @@ class IPUBBackground extends IPUBElement {
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
static #observer = (() => {
|
||||
/** @type {Map<string, IPUBBackground>} */
|
||||
const instancesOnScreen = new Map();
|
||||
|
||||
document.addEventListener("scroll", () => {
|
||||
for (const [_, instance] of instancesOnScreen) {
|
||||
const perc = getPercentageInView(
|
||||
instance.querySelector("img") || instance,
|
||||
static #instancesOnScreen = {
|
||||
/** @type {Map<IPUBBody, Set<IPUBBackground>>} */
|
||||
map: new Map(),
|
||||
/**
|
||||
* @param {IPUBBackground} background
|
||||
*/
|
||||
add(background) {
|
||||
const body = getAncestor(background, IPUBBody.elementName);
|
||||
if (!body) {
|
||||
console.error(
|
||||
`IPUBBackground: ${background.id} does not have a valid ipub-body ancestor`,
|
||||
);
|
||||
instance.fade(perc);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return new IntersectionObserver((entries) =>
|
||||
entries.forEach((e) => {
|
||||
let instance = e.target.parentElement;
|
||||
let set = this.map.get(body);
|
||||
if (!set) {
|
||||
set = new Set();
|
||||
body.addEventListener("scroll", () => {
|
||||
for (const instance of set.values()) {
|
||||
const perc = getPercentageInView(
|
||||
instance.querySelector("img") || instance,
|
||||
);
|
||||
instance.fade(perc);
|
||||
}
|
||||
});
|
||||
}
|
||||
set.add(background);
|
||||
this.map.set(body, set);
|
||||
},
|
||||
/**
|
||||
* @param {IPUBBackground} background
|
||||
*/
|
||||
remove(background) {
|
||||
const body = getAncestor(background, IPUBBody.elementName);
|
||||
if (!body) {
|
||||
console.error(
|
||||
`IPUBBackground: ${background.id} does not have a valid ipub-body ancestor`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
instance.tagName.toLowerCase() !==
|
||||
IPUBBackground.elementName.toLowerCase()
|
||||
) {
|
||||
instance = instance.parentElement;
|
||||
}
|
||||
const set = this.map.get(body);
|
||||
if (!set) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
instance.tagName.toLowerCase() !==
|
||||
IPUBBackground.elementName.toLowerCase()
|
||||
) {
|
||||
console.error(
|
||||
"IPUBBackground: malformed <ipub-background> element",
|
||||
e.target,
|
||||
);
|
||||
return;
|
||||
}
|
||||
set.delete(background);
|
||||
|
||||
if (e.intersectionRatio > 0 && instance.id) {
|
||||
instancesOnScreen.set(instance.id, instance);
|
||||
} else if (instance.id) {
|
||||
instancesOnScreen.delete(instance.id);
|
||||
}
|
||||
}),
|
||||
);
|
||||
})();
|
||||
if (set.size === 0) {
|
||||
this.map.delete(body);
|
||||
}
|
||||
},
|
||||
};
|
||||
static addToScreen() {}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
static #observer = new IntersectionObserver((entries) => {
|
||||
for (const { intersectionRatio, target: image } of entries) {
|
||||
const instance = getAncestor(image, IPUBBackground.elementName);
|
||||
|
||||
if (!instance) {
|
||||
console.error(
|
||||
"IPUBBackground: malformed <ipub-background> element",
|
||||
image,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (intersectionRatio > 0 && instance.id) {
|
||||
IPUBBackground.#instancesOnScreen.add(instance);
|
||||
} else if (instance.id) {
|
||||
IPUBBackground.#instancesOnScreen.remove(instance);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
@@ -126,8 +161,6 @@ class IPUBBackground extends IPUBElement {
|
||||
* @returns {void | Promise<void>}
|
||||
*/
|
||||
fade(perc) {
|
||||
console.debug(`IPUBBackground: ${this.id} is ${perc} on screen`);
|
||||
|
||||
if (!this.style.getPropertyValue("--ipub-fade")) {
|
||||
this.style.setProperty("--ipub-fade", `${perc}%`);
|
||||
return;
|
||||
@@ -264,7 +297,19 @@ class IPUBInteraction extends IPUBElement {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} el
|
||||
* @param {string} tagName
|
||||
* @returns {HTMLElement | undefined}
|
||||
*/
|
||||
function getAncestor(el, tagName) {
|
||||
if (!el.parentElement) {
|
||||
return undefined;
|
||||
}
|
||||
if (el.parentElement.tagName.toLowerCase() === tagName.toLowerCase()) {
|
||||
return el.parentElement;
|
||||
}
|
||||
return getAncestor(el.parentElement, tagName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Readonly<Element>} el
|
||||
@@ -330,3 +375,4 @@ function getPercentageInView(element) {
|
||||
|
||||
return Math.round((inView / globalThis.innerHeight) * 100);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,36 +84,43 @@ ipub-body {
|
||||
}
|
||||
|
||||
ipub-background {
|
||||
--ipub-mask: linear-gradient(
|
||||
rgba(0, 0, 0, 0) 0%,
|
||||
rgba(0, 0, 0, 1) calc(100% + calc(var(--ipub-fade, 100%) * -1))
|
||||
);
|
||||
|
||||
--ipub-width: 100vw;
|
||||
--ipub-height: 100vh;
|
||||
|
||||
&[sticky] {
|
||||
display: inline-block;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
position: sticky;
|
||||
align-self: start;
|
||||
display: inline-block;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
position: sticky;
|
||||
align-self: start;
|
||||
|
||||
&:first-of-type,
|
||||
&[nofade] {
|
||||
--ipub-mask: unset;
|
||||
}
|
||||
|
||||
&[fade] img {
|
||||
img {
|
||||
/* For testing */
|
||||
/* background-image: linear-gradient( */
|
||||
/* rgba(266, 0, 0, 1) 0%, */
|
||||
/* rgba(0, 266, 0, 1) calc(100% + calc(var(--ipub-fade, 100%) * -1)), */
|
||||
/* rgba(266, 0, 266, 1) 100% */
|
||||
/* ) !important; */
|
||||
--mask: linear-gradient(
|
||||
rgba(0, 0, 0, 0) 0%,
|
||||
rgba(0, 0, 0, 1) calc(100% + calc(var(--ipub-fade, 100%) * -1))
|
||||
) !important;
|
||||
/* background-image: var(--mask); */
|
||||
mask-image: var(--mask);
|
||||
-webkit-mask-image: var(--mask);
|
||||
mask-image: var(--ipub-mask);
|
||||
-webkit-mask-image: var(--ipub-mask);
|
||||
}
|
||||
|
||||
& > picture {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
width: var(--ipub-width);
|
||||
height: var(--ipub-height);
|
||||
@@ -125,6 +132,9 @@ ipub-background {
|
||||
}
|
||||
/* Support standalone img element */
|
||||
& > img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
object-fit: cover;
|
||||
width: var(--ipub-width);
|
||||
|
||||
Reference in New Issue
Block a user