Merge pull request #3144 from jellyfin/blurhash-worker
Decode blurhash in a WebWorker
This commit is contained in:
commit
0277726418
6 changed files with 151 additions and 114 deletions
87
package-lock.json
generated
87
package-lock.json
generated
|
@ -3082,7 +3082,8 @@
|
|||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.0.tgz",
|
||||
"integrity": "sha512-ttOkEkoalEHa7RaFYpM0ErK1xc4twg3Am9hfHhL7MVqlHebnkYd2wuI/ZqTDj0cVzZho6PdinY0phFZV3O0Mzg==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@webpack-cli/info": {
|
||||
"version": "1.4.0",
|
||||
|
@ -3097,7 +3098,8 @@
|
|||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.0.tgz",
|
||||
"integrity": "sha512-ZkVeqEmRpBV2GHvjjUZqEai2PpUbuq8Bqd//vEYsp63J8WyexI8ppCqVS3Zs0QADf6aWuPdU+0XsPI647PVlQA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@xmldom/xmldom": {
|
||||
"version": "0.7.5",
|
||||
|
@ -3142,13 +3144,15 @@
|
|||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
|
||||
"integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"acorn-jsx": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
|
||||
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"aggregate-error": {
|
||||
"version": "3.1.0",
|
||||
|
@ -3205,7 +3209,8 @@
|
|||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
||||
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"alphanum-sort": {
|
||||
"version": "1.0.2",
|
||||
|
@ -4648,7 +4653,8 @@
|
|||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-2.0.1.tgz",
|
||||
"integrity": "sha512-i8vLRZTnEH9ubIyfdZCAdIdgnHAUeQeByEeQ2I7oTilvP9oHO6RScpeq3GsFUVqeB8uZgOQ9pw8utofNn32hhQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"csso": {
|
||||
"version": "4.2.0",
|
||||
|
@ -5801,7 +5807,8 @@
|
|||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz",
|
||||
"integrity": "sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"eslint-rule-composer": {
|
||||
"version": "0.3.0",
|
||||
|
@ -6025,7 +6032,8 @@
|
|||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/expose-loader/-/expose-loader-3.1.0.tgz",
|
||||
"integrity": "sha512-2RExSo0yJiqP+xiUue13jQa2IHE8kLDzTI7b6kn+vUlBVvlzNSiLDzo4e5Pp5J039usvTUnxZ8sUOhv0Kg15NA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"express": {
|
||||
"version": "4.17.2",
|
||||
|
@ -7030,7 +7038,8 @@
|
|||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
|
||||
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"idb": {
|
||||
"version": "6.1.2",
|
||||
|
@ -7763,7 +7772,7 @@
|
|||
},
|
||||
"libass-wasm": {
|
||||
"version": "git+https://github.com/jellyfin/JavascriptSubtitlesOctopus.git#f4625ac313b318bd5d2e0ae18679ff516370bae6",
|
||||
"from": "git+https://github.com/jellyfin/JavascriptSubtitlesOctopus.git#4.0.0-jf-4"
|
||||
"from": "libass-wasm@git+https://github.com/jellyfin/JavascriptSubtitlesOctopus.git#4.0.0-jf-4"
|
||||
},
|
||||
"lie": {
|
||||
"version": "3.1.1",
|
||||
|
@ -9058,25 +9067,29 @@
|
|||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.1.tgz",
|
||||
"integrity": "sha512-lgZBPTDvWrbAYY1v5GYEv8fEO/WhKOu/hmZqmCYfrpD6eyDWWzAOsl2rF29lpvziKO02Gc5GJQtlpkTmakwOWg==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-discard-duplicates": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.1.tgz",
|
||||
"integrity": "sha512-svx747PWHKOGpAXXQkCc4k/DsWo+6bc5LsVrAsw+OU+Ibi7klFZCyX54gjYzX4TH+f2uzXjRviLARxkMurA2bA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-discard-empty": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.1.tgz",
|
||||
"integrity": "sha512-vfU8CxAQ6YpMxV2SvMcMIyF2LX1ZzWpy0lqHDsOdaKKLQVQGVP1pzhrI9JlsO65s66uQTfkQBKBD/A5gp9STFw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-discard-overridden": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.1.tgz",
|
||||
"integrity": "sha512-Y28H7y93L2BpJhrdUR2SR2fnSsT+3TVx1NmVQLbcnZWwIUpJ7mfcTC6Za9M2PG6w8j7UQRfzxqn8jU2VwFxo3Q==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-double-position-gradients": {
|
||||
"version": "3.0.4",
|
||||
|
@ -9692,7 +9705,8 @@
|
|||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
|
||||
"integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-modules-local-by-default": {
|
||||
"version": "4.0.0",
|
||||
|
@ -9748,7 +9762,8 @@
|
|||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.1.tgz",
|
||||
"integrity": "sha512-6J40l6LNYnBdPSk+BHZ8SF+HAkS4q2twe5jnocgd+xWpz/mx/5Sa32m3W1AA8uE8XaXN+eg8trIlfu8V9x61eg==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-normalize-display-values": {
|
||||
"version": "5.0.1",
|
||||
|
@ -10150,7 +10165,8 @@
|
|||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.2.tgz",
|
||||
"integrity": "sha512-xfdkU128CkKKKVAwkyt0M8OdnelJ3MRcIRAPPQkRpoPeuzWY3RIeg7piRCpZ79MK7Q16diLXMMAD9dN5mauPlQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-selector-not": {
|
||||
"version": "5.0.0",
|
||||
|
@ -10225,7 +10241,8 @@
|
|||
"version": "0.36.2",
|
||||
"resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.36.2.tgz",
|
||||
"integrity": "sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-unique-selectors": {
|
||||
"version": "5.0.2",
|
||||
|
@ -11495,6 +11512,14 @@
|
|||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
|
||||
"dev": true
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
|
||||
|
@ -11542,14 +11567,6 @@
|
|||
"define-properties": "^1.1.3"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"stringify-entities": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz",
|
||||
|
@ -11633,7 +11650,8 @@
|
|||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz",
|
||||
"integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"style-search": {
|
||||
"version": "0.1.0",
|
||||
|
@ -11845,7 +11863,8 @@
|
|||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz",
|
||||
"integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"postcss-selector-parser": {
|
||||
"version": "6.0.8",
|
||||
|
@ -13663,7 +13682,8 @@
|
|||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-7.0.1.tgz",
|
||||
"integrity": "sha512-iLBFYz6VRYyLJEJsBJ8M3TCqNcckVzz4wFounSc5Oez35ogE/X+aoC5fFu103Ot7NyvjU3/xqIXn93Gp3kJk4g==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -15340,15 +15360,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"worker-plugin": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/worker-plugin/-/worker-plugin-5.0.1.tgz",
|
||||
"integrity": "sha512-Pn7+19jIiANcGuTSGdy+vrzyF+SGH03A5wV8iu4jRTMAOfAC9bNeiHo4+l5tPS7F0uvICMBv+h8UCvL7lunxcA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loader-utils": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
|
|
|
@ -55,8 +55,7 @@
|
|||
"webpack-cli": "^4.9.1",
|
||||
"webpack-dev-server": "^4.7.2",
|
||||
"webpack-merge": "^5.8.0",
|
||||
"workbox-webpack-plugin": "^6.2.4",
|
||||
"worker-plugin": "^5.0.1"
|
||||
"workbox-webpack-plugin": "^6.2.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/noto-sans": "^4.5.1",
|
||||
|
|
16
src/components/images/blurhash.worker.ts
Normal file
16
src/components/images/blurhash.worker.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* eslint-disable no-restricted-globals */
|
||||
import { decode } from 'blurhash';
|
||||
|
||||
self.onmessage = ({ data: { hash, width, height } }): void => {
|
||||
try {
|
||||
self.postMessage({
|
||||
pixels: decode(hash, width, height),
|
||||
hsh: hash,
|
||||
width: width,
|
||||
height: height
|
||||
});
|
||||
} catch {
|
||||
throw new TypeError(`Blurhash ${hash} is not valid`);
|
||||
}
|
||||
};
|
||||
/* eslint-enable no-restricted-globals */
|
|
@ -1,7 +1,21 @@
|
|||
import * as lazyLoader from '../lazyLoader/lazyLoaderIntersectionObserver';
|
||||
import * as userSettings from '../../scripts/settings/userSettings';
|
||||
import { decode, isBlurhashValid } from 'blurhash';
|
||||
import './style.scss';
|
||||
// eslint-disable-next-line compat/compat
|
||||
const worker = new Worker(new URL('./blurhash.worker.ts', import.meta.url));
|
||||
const targetDic = {};
|
||||
worker.addEventListener(
|
||||
'message',
|
||||
({ data: { pixels, hsh, width, height } }) => {
|
||||
const elems = targetDic[hsh];
|
||||
if (elems && elems.length) {
|
||||
for (const elem of elems) {
|
||||
drawBlurhash(elem, pixels, width, height);
|
||||
}
|
||||
delete targetDic[hsh];
|
||||
}
|
||||
}
|
||||
);
|
||||
/* eslint-disable indent */
|
||||
|
||||
export function lazyImage(elem, source = elem.getAttribute('data-src')) {
|
||||
|
@ -12,42 +26,45 @@ import './style.scss';
|
|||
fillImageElement(elem, source);
|
||||
}
|
||||
|
||||
function itemBlurhashing(target, blurhashstr) {
|
||||
if (isBlurhashValid(blurhashstr)) {
|
||||
// Although the default values recommended by Blurhash developers is 32x32, a size of 18x18 seems to be the sweet spot for us,
|
||||
function drawBlurhash(target, pixels, width, height) {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const ctx = canvas.getContext('2d');
|
||||
const imgData = ctx.createImageData(width, height);
|
||||
|
||||
imgData.data.set(pixels);
|
||||
ctx.putImageData(imgData, 0, 0);
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
// This class is just an utility class, so users can customize the canvas using their own CSS.
|
||||
canvas.classList.add('blurhash-canvas');
|
||||
|
||||
target.parentNode.insertBefore(canvas, target);
|
||||
target.classList.add('blurhashed');
|
||||
target.removeAttribute('data-blurhash');
|
||||
});
|
||||
}
|
||||
|
||||
function itemBlurhashing(target, hash) {
|
||||
try {
|
||||
// Although the default values recommended by Blurhash developers is 32x32, a size of 20x20 seems to be the sweet spot for us,
|
||||
// improving the performance and reducing the memory usage, while retaining almost full blur quality.
|
||||
// Lower values had more visible pixelation
|
||||
const width = 18;
|
||||
const height = 18;
|
||||
let pixels;
|
||||
try {
|
||||
pixels = decode(blurhashstr, width, height);
|
||||
} catch (err) {
|
||||
console.error('Blurhash decode error: ', err);
|
||||
target.classList.add('non-blurhashable');
|
||||
return;
|
||||
}
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const ctx = canvas.getContext('2d');
|
||||
const imgData = ctx.createImageData(width, height);
|
||||
const width = 20;
|
||||
const height = 20;
|
||||
targetDic[hash] = (targetDic[hash] || []).filter(item => item !== target);
|
||||
targetDic[hash].push(target);
|
||||
|
||||
imgData.data.set(pixels);
|
||||
ctx.putImageData(imgData, 0, 0);
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
canvas.classList.add('blurhash-canvas');
|
||||
if (userSettings.enableFastFadein()) {
|
||||
canvas.classList.add('lazy-blurhash-fadein-fast');
|
||||
} else {
|
||||
canvas.classList.add('lazy-blurhash-fadein');
|
||||
}
|
||||
|
||||
target.parentNode.insertBefore(canvas, target);
|
||||
target.classList.add('blurhashed');
|
||||
target.removeAttribute('data-blurhash');
|
||||
worker.postMessage({
|
||||
hash,
|
||||
width,
|
||||
height
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
target.classList.add('non-blurhashable');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,14 +82,25 @@ import './style.scss';
|
|||
}
|
||||
|
||||
if (entry.intersectionRatio > 0) {
|
||||
if (source) fillImageElement(target, source);
|
||||
if (source) {
|
||||
fillImageElement(target, source);
|
||||
}
|
||||
} else if (!source) {
|
||||
requestAnimationFrame(() => {
|
||||
emptyImageElement(target);
|
||||
});
|
||||
emptyImageElement(target);
|
||||
}
|
||||
}
|
||||
|
||||
function onAnimationEnd(event) {
|
||||
const elem = event.target;
|
||||
requestAnimationFrame(() => {
|
||||
const canvas = elem.previousSibling;
|
||||
if (elem.classList.contains('blurhashed') && canvas && canvas.tagName === 'CANVAS') {
|
||||
canvas.classList.add('lazy-hidden');
|
||||
}
|
||||
});
|
||||
elem.removeEventListener('animationend', onAnimationEnd);
|
||||
}
|
||||
|
||||
function fillImageElement(elem, url) {
|
||||
if (url === undefined) {
|
||||
throw new TypeError('url cannot be undefined');
|
||||
|
@ -82,6 +110,7 @@ import './style.scss';
|
|||
preloaderImg.src = url;
|
||||
|
||||
elem.classList.add('lazy-hidden');
|
||||
elem.addEventListener('animationend', onAnimationEnd);
|
||||
|
||||
preloaderImg.addEventListener('load', () => {
|
||||
requestAnimationFrame(() => {
|
||||
|
@ -92,25 +121,22 @@ import './style.scss';
|
|||
}
|
||||
elem.removeAttribute('data-src');
|
||||
|
||||
elem.classList.remove('lazy-hidden');
|
||||
if (userSettings.enableFastFadein()) {
|
||||
elem.classList.add('lazy-image-fadein-fast');
|
||||
} else {
|
||||
elem.classList.add('lazy-image-fadein');
|
||||
}
|
||||
|
||||
const canvas = elem.previousSibling;
|
||||
if (elem.classList.contains('blurhashed') && canvas && canvas.tagName === 'CANVAS') {
|
||||
canvas.classList.remove('lazy-image-fadein-fast', 'lazy-image-fadein');
|
||||
canvas.classList.add('lazy-hidden');
|
||||
}
|
||||
elem.classList.remove('lazy-hidden');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function emptyImageElement(elem) {
|
||||
// block repeated call - requestAnimationFrame twice for one image
|
||||
if (elem.getAttribute('data-src')) return;
|
||||
elem.removeEventListener('animationend', onAnimationEnd);
|
||||
const canvas = elem.previousSibling;
|
||||
if (canvas && canvas.tagName === 'CANVAS') {
|
||||
canvas.classList.remove('lazy-hidden');
|
||||
}
|
||||
|
||||
let url;
|
||||
|
||||
|
@ -125,16 +151,6 @@ import './style.scss';
|
|||
|
||||
elem.classList.remove('lazy-image-fadein-fast', 'lazy-image-fadein');
|
||||
elem.classList.add('lazy-hidden');
|
||||
|
||||
const canvas = elem.previousSibling;
|
||||
if (canvas && canvas.tagName === 'CANVAS') {
|
||||
canvas.classList.remove('lazy-hidden');
|
||||
if (userSettings.enableFastFadein()) {
|
||||
canvas.classList.add('lazy-image-fadein-fast');
|
||||
} else {
|
||||
canvas.classList.add('lazy-image-fadein');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function lazyChildren(elem) {
|
||||
|
|
|
@ -1,17 +1,3 @@
|
|||
.lazy-image-fadein {
|
||||
opacity: 1;
|
||||
transition: opacity 0.5s;
|
||||
}
|
||||
|
||||
.lazy-image-fadein-fast {
|
||||
opacity: 1;
|
||||
transition: opacity 0.1s;
|
||||
}
|
||||
|
||||
.lazy-hidden {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@keyframes fadein {
|
||||
from {
|
||||
opacity: 0;
|
||||
|
@ -22,12 +8,18 @@
|
|||
}
|
||||
}
|
||||
|
||||
.lazy-blurhash-fadein-fast {
|
||||
.lazy-image-fadein {
|
||||
opacity: 1;
|
||||
animation: fadein 0.5s;
|
||||
}
|
||||
|
||||
.lazy-image-fadein-fast {
|
||||
opacity: 1;
|
||||
animation: fadein 0.1s;
|
||||
}
|
||||
|
||||
.lazy-blurhash-fadein {
|
||||
animation: fadein 0.4s;
|
||||
.lazy-hidden {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.blurhash-canvas {
|
||||
|
|
|
@ -13,7 +13,10 @@
|
|||
callback(entry);
|
||||
});
|
||||
},
|
||||
{rootMargin: '25%'});
|
||||
{
|
||||
rootMargin: '50%',
|
||||
threshold: 0
|
||||
});
|
||||
|
||||
this.observer = observer;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue