From 9b24338739dcbb6a130e3ca9d54933bf20ef0ffc Mon Sep 17 00:00:00 2001 From: Andrew Stephens Date: Mon, 16 Jan 2023 10:28:44 -0500 Subject: [PATCH] Prevent lengthy processing if the element is offscreen removed some console messages --- as-dithered-image.js | 37 +++++++++++++++++++++++++++++++++---- ditherworker.js | 1 - test.html | 2 ++ 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/as-dithered-image.js b/as-dithered-image.js index c1e9aa2..fd26bd8 100644 --- a/as-dithered-image.js +++ b/as-dithered-image.js @@ -24,7 +24,6 @@ class ASDitheredImage extends HTMLElement { this.worker_.onmessage = ((e) => { const imageData = e.data.imageData - console.log("Image painted ", imageData.width, imageData.height) this.context_.putImageData(imageData, 0, 0) }).bind(this) @@ -77,9 +76,21 @@ class ASDitheredImage extends HTMLElement { }).bind(this)) resizeObserver.observe(this.canvas_) + + // since we avoid drawing the image if the element of far offscreen we need to use + // an IntersectionObserver to notify use when the element is likely to be displayed + const intersectionObserver = new IntersectionObserver(((intersections) => { + if (intersections.length > 0) { + if (intersections[0].isIntersecting) { + this.force_refresh_ = true + this.requestUpdate() + } + } + }).bind(this), { root: null, rootMargin: "1000px", threshold: [0] }) + intersectionObserver.observe(this) + this.force_refresh_ = true this.requestUpdate() - } static get observedAttributes() { return ["src", "crunch", "alt", "cutoff"] } @@ -140,9 +151,29 @@ class ASDitheredImage extends HTMLElement { return window.devicePixelRatio } + isInOrNearViewport() { + // this only handles vertical scrolling, could be extended later to handle horizontal + // but it probably doesn't matter + const margin = 1500 + const r = this.getBoundingClientRect() + + const viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight) + const above = r.bottom + margin < 0 + const below = r.top - margin > viewHeight + + return (!above && !below) + } + // all drawing is funneled through requestUpdate so that multiple calls are coalesced to prevent // processing the image multiple times for no good reason requestUpdate() { + + if (this.original_image_ != undefined) { + if (this.isInOrNearViewport() == false) { + return // suppress update, the intersection observer will call us back as the element scrolls into view + } + } + window.requestAnimationFrame(((timestamp) => { if ((this.force_refresh_ == false)) { return @@ -172,7 +203,6 @@ class ASDitheredImage extends HTMLElement { this.original_image_ = image this.ignore_next_resize_ = true this.canvas_.style.aspectRatio = this.original_image_.width + "/" + this.original_image_.height - console.log("Setting Aspect Ratio to ", this.style.aspectRatio) this.force_refresh_ = true this.requestUpdate() }).bind(this)) @@ -204,7 +234,6 @@ class ASDitheredImage extends HTMLElement { const calculatedWidth = Math.round(rect.width * screenPixelsToBackingStorePixels) const calculatedHeight = Math.round(rect.height * screenPixelsToBackingStorePixels) - console.log(calculatedWidth, "x", calculatedHeight, "(" + screenPixelsToBackingStorePixels + ")") let adjustedPixelSize = screenPixelsToBackingStorePixels * this.crunchFactor_ // double check - we may have already painted this image diff --git a/ditherworker.js b/ditherworker.js index fdaf979..f6fae41 100644 --- a/ditherworker.js +++ b/ditherworker.js @@ -1,5 +1,4 @@ onmessage = function (e) { - console.log("Worker: start", e.data) const result = dither(e.data.imageData, e.data.pixelSize, e.data.cutoff) const reply = {} diff --git a/test.html b/test.html index b16ccd8..48d7839 100644 --- a/test.html +++ b/test.html @@ -14,6 +14,8 @@ } +
+