preface


H5 pull-down refresh after the implementation of traditional pull-down scenes, we went to the native APP. The scenes we met were not only full-screen pull-down refresh, but more scenes were partial elements pull-down refresh, such as list pull-down refresh operation. So HERE I am again, for such scenes, we should optimize our pullRefresh, let’s start

Results show


One is the local element list drop-down refresh effect and the other is the whole page drop-down refresh effect


The overall code


Without further ado, put the code

/ * * *@param {Object} options* const pullObj = pullRefresh(options); * pullObj.init(); Initializes the * /

const parseTime = (timestamp) = > {
    const a = new Date(timestamp);
    const h = a.getHours();
    const s = a.getMinutes();
    const double = t= > t > 9 ? t : "0" + t;
    return double(h) + ":" + double(s);
}
const loadingIcon = "loading.png";
const defaultOptions = {
    parEl: document.body, // Parent element (big box that doesn't move)
    tarEl: "app".// Target element (sliding subbox)
    pullCallback: () = > { // Valid pull-down callback, usually to get the data internally and call the Finish () method
        window.location.reload(); }};export function pullRefresh(_options) {
    constoptions = { ... defaultOptions, ... _options };let lastUpdateTime = new Date().getTime();
    let { parEl, tarEl, pullCallback } = options;
    if(typeof parEl === "string") {
        parEl = document.getElementById(parEl);
    }
    if(typeof tarEl === "string") {
        tarEl = document.getElementById(tarEl);
    }
    const appStyleCache = tarEl.style;
    const tarElPosition = appStyleCache.position;
    const parTopDistance = parEl.getBoundingClientRect().top;
    if(! tarElPosition) { tarEl.style["position"] = "relative";
        appStyleCache["position"] = "relative";
    }
    const pullTextEl = document.createElement("p");

    pullTextEl.style = "width: 100%; text-align: center; position: absolute; z-index: 0; left: 0; top: -50px; font-size: 12px; line-height: 16px; color: #666; display: none;";
    const loadImg = document.createElement("i");
    loadImg.style = `display: inline-block; width: 15px; height: 15px; margin-right: 5px; background: url('${loadingIcon}'); background-size: 100% 100%; vertical-align: middle; animation: looprotate 2s linear infinite; `;
    const loadText = document.createElement("span");
    loadImg.style.opacity = 0;
    // Whether a valid pull-back flag bit is executed
    let refreshStatus = false;
    const isQBrowser = () = > { // Qq is a browser
        const ua = navigator.userAgent.toLowerCase();
        return!!!!! ua.match(/mqqbrowser|qzone|qqbrowser/i);
    };
    const finish = () = > {
        if(isQBrowser()) return;
        lastUpdateTime = new Date().getTime();
        loadImg.style.opacity = 0;
        loadText.innerText = 'Refresh succeeded \n Last updated:${parseTime(lastUpdateTime)}`;
        setTimeout(() = > {
            tarEl.style["transition"] = "The transform 0.2 s";
            tarEl.style["transform"] = "translate(0, 0)";
            setTimeout(() = > {
                pullTextEl.style["display"] = "none";
                // tarEl.style = appStyleCache;
            }, 400);
        }, 500);
    };
    const init = () = > {
        if(isQBrowser()) return;
        tarEl.appendChild(pullTextEl);
        pullTextEl.appendChild(loadImg);
        pullTextEl.appendChild(loadText);
        let startP, moveLen;
        // Pull-down processing
        const pullHandler = (moveLen) = > {
            // Drop down the distance from the top of the viewport
            const tarTopDistance = tarEl.getBoundingClientRect().top;
            // Drop down how far the element is from the top of the parent
            const toParTopDistance = tarTopDistance - parTopDistance;
            // Valid drop down to do processing
            if(toParTopDistance >= 0) {
                if(pullTextEl.style["display"= = ="none") {
                    // Display the prompt text only when it is valid
                    pullTextEl.style["display"] = "block";
                }
                // Drop down effect
                if(moveLen > 0 && moveLen < 50){
                    tarEl.style["transform"] = "translate(0, " + moveLen + "px)";
                } else if(moveLen >= 50 && moveLen < 100) { // To refresh the flag, the pull-down damping increases
                    const _moveLen = 50 + (moveLen - 50) * 0.6;
                    tarEl.style["transform"] = "translate(0, " + _moveLen + "px)";
                } else if(moveLen >= 100) { // When the drop exceeds 100, the drop damping increases again
                    const _moveLen = (50 + ( 100 - 50) *0.6) + (moveLen - 100) * 0.2;
                    tarEl.style["transform"] = "translate(0, " + _moveLen + "px)";
                }
                // Pull-down trigger
                if(toParTopDistance < 55) {
                    loadText.innerText = 'Pull down to refresh... \n Last Updated:${parseTime(lastUpdateTime)}`;
                    refreshStatus = false;
                } else {
                    loadText.innerText = 'Release immediately refresh... \n Last Updated:${parseTime(lastUpdateTime)}`;
                    refreshStatus = true; }}}; tarEl.addEventListener("touchstart".(e) = > {
            startP = e.touches[0].pageY;
            tarEl.style["transition"] = "transform 0s";
        });
        tarEl.addEventListener("touchmove".(e) = > {
            moveLen = e.touches[0].pageY - startP;
            pullHandler(moveLen);
        });
        tarEl.addEventListener("touchend".() = > {
            // Drop down the distance from the top of the viewport
            const tarTopDistance = tarEl.getBoundingClientRect().top;
            // Drop down how far the element is from the top of the parent
            const toParTopDistance = tarTopDistance - parTopDistance;
            if(toParTopDistance > 0) { // When a valid pull-down occurs, the animation returns, resetting the style
                if(refreshStatus) {
                    loadImg.style.opacity = 1;
                    loadText.innerText = 'Refreshing data... \n Last Updated:${parseTime(lastUpdateTime)}`;
                    pullCallback && pullCallback();
                    tarEl.style["transition"] = "The transform 0.4 s";
                    tarEl.style["transform"] = "translate(0, 55px)";
                } else {
                    tarEl.style["transition"] = "The transform 0.4 s";
                    tarEl.style["transform"] = "translate(0, 0)";
                    setTimeout(() = > {
                        pullTextEl.style["display"] = "none";
                        tarEl.style = appStyleCache;
                    }, 400); }}else { // Direct reset style with no valid pull-down occurred
                pullTextEl.style["display"] = "none"; tarEl.style = appStyleCache; }}); };return {
        init,
        finish
    };
}
Copy the code

How to use


This optimization updates the input method to accept an Option object

const pullRefreshObj = pullRefresh({
    parEl: "pullParEl".// Act on the parent element
    tarEl: "pullTarEl".// Target action element
    pullCallback: async() = > {// Generates a valid pull-down release trigger callback method
        awaityourHandler(); pullRefreshObj.finish(); }}); pullRefreshObj.init();/ / initialization
Copy the code

conclusion


Yes, following the first version of the pull-down refresh, we have successfully captured the heart of the user, experience up, but also worry to keep users? Salute every front-end coder; The new one;