Last active
July 14, 2018 21:30
-
-
Save minikomi/a761e8eaf2f15bf0b1caf89cde19ecd8 to your computer and use it in GitHub Desktop.
Lazy loading image for reagent
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
(ns frontend.lazy | |
(:require [reagent.core :as r] | |
[goog.dom :as gdom] | |
[goog.events.EventType :as event-type] | |
[goog.events :as events]) | |
(:import goog.async.Throttle)) | |
(defonce initialized-lazy-load (atom false)) | |
(defonce lazy-els (atom {})) | |
(defonce lazy-loaded (r/atom #{})) | |
(defn is-scrolled-into-view [el] | |
(let [el-top (.-top (.getBoundingClientRect el))] | |
(and (<= 0 el-top) | |
(>= (.-innerHeight js/window) el-top)))) | |
(defn init-scroll-listener [f] | |
(let [thr (Throttle. #(f (.-y (gdom/getDocumentScroll))) 300)] | |
(events/listen js/window event-type/SCROLL #(.fire thr))) | |
(f (.-y (gdom/getDocumentScroll)))) | |
(defn unregister-lazy-load [el] | |
(swap! lazy-els dissoc el)) | |
(defn check-offsets [_] | |
(doseq [[el data] @lazy-els] | |
(when (is-scrolled-into-view el) | |
(set! (.-src (:img-obj data)) (:src data)) | |
(unregister-lazy-load el)))) | |
(defn register-lazy-load [src el] | |
(when-not @initialized-lazy-load | |
(reset! initialized-lazy-load true) | |
(init-scroll-listener check-offsets)) | |
(when-not (@lazy-loaded src) | |
(let [img-obj (js/Image.)] | |
(set! (.-onload img-obj) | |
(fn [_] | |
(swap! lazy-loaded conj src))) | |
(if (is-scrolled-into-view el) | |
(set! (.-src img-obj) src) | |
(swap! lazy-els assoc el {:img-obj img-obj :src src}))))) | |
(defn -mount-or-update [this _] | |
(register-lazy-load (:src (r/props this)) (r/dom-node this))) | |
(defn lazy-loading-image [{:keys [wrapper-class src alt]}] | |
(r/create-class | |
{:component-did-mount | |
-mount-or-update | |
:component-did-update | |
-mount-or-update | |
:component-will-unmount | |
(fn [this _] | |
(unregister-lazy-load (r/dom-node this))) | |
:reagent-render | |
(fn [{:keys [wrapper-class src alt]}] | |
[:span.lazy-wrapper | |
{:class wrapper-class} | |
(if-not (get @lazy-loaded src) | |
[:span.loader] | |
[:img.loaded {:src src :alt alt}])])})) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment