Skip to content

Instantly share code, notes, and snippets.

@kevinkace
Created April 30, 2017 20:15
Show Gist options
  • Select an option

  • Save kevinkace/e6884a41a1bafcdc60f11843d44885cd to your computer and use it in GitHub Desktop.

Select an option

Save kevinkace/e6884a41a1bafcdc60f11843d44885cd to your computer and use it in GitHub Desktop.
// pref:
// lazyload
// - content img
// - background img
// fe:
const pify = require("pify");
// returns path of img when loaded
// load(path).then((path) => { /* asset is loaded */ })
function load(path) {
const imgEl = document.createElement("img");
pify(imgEl.addEventListener)("onload")
.then((e) => {
return path;
});
imgEl.src(path);
}
function viewport(domEl, opts) {
const bcr = domEl.getBoundingClientRect(),
top = bcr.top + (opts.offsetTop || 0),
bottom = bcr.bottom + (opts.offsetBottom || 0);
function check() {
bcr.top < 0 && bcr.bottom > window.innerHeight || // img spanning vp
bcr.top > 0 && bcr.bottom < window.innerHeight || // img top in vp
bcr.bottom > 0 && bcr.top < window.innerHeight; // img bottom in vp
}
// assuming vScroll only...
return new Promise((resolve, reject) => {
if(check()) {
resolve(true);
}
state.document.scrollY.map((value) => {
if(check()) {
resolve(true);
}
});
})
}
// load
const comp = {
oninit : () => {
load(path, {
startLoading : true, // true == immediately, number = distance from viewport in px
width : 400, // not needed?
height : 300 // needed for measuring from bottom of img if above viewport
})
.then(vnode.state.img);
},
view : () => [
vnode.state.img() ? m(img, vnode.state.img()) : null,
m(img, vnode.state.img.attrs)
]
};
const img = {
oninit : (vnode) => {
vnode.state.src = stream(vnode.attrs.smallSrc);
vnode.state.srcset = stream();
},
oncreate : (vnode) => {
viewport(vnode.dom) // must ensure dom is sized, style attr?
.then((dom) => {
// domEl is within/near viewport
vnode.state.src(vnode.attrs.src);
});
},
view : (vnode) =>
m("img", {
width : vnode.attrs.width,
height : vnode.attrs.height,
src : vnode.state.src(),
srcset : vnode.state.srcset(),
sizes : vnode.state.sizes()
})
}
const img2 = {
oninit : (vnode) => {
vnode.state.src = vnode.attrs.smallSrc;
vnode.state.background = stream(vnode.attrs.bgLowRes);
},
oncreate : (vnode) => {
viewport(vnode.dom) // must ensure dom is sized, style attr?
.then((dom) => load(vnode.state.src))
.then((src) => {
// domEl is within/near viewport
vnode.state.background(vnode.attrs.src);
});
},
view : (vnode) =>
m("div", {
width : vnode.attrs.width,
height : vnode.attrs.height,
backgroundImage : vnode.state.background()
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment