Hiệu ứng cuộn chuột mượt mà cho blogspot
/ lúc / 43 bình luận
Hello xin chào tất cả các bạn, chào mừng các bạn đã quay lại với blog Star Dũng Blog.
Hôm nay mình sẽ hướng dẫn các bạn tạo hiệu ứng chuột mượt mà cho blogspot. Bắt đầu nhé.

Ảnh minh họa

Các bước thực hiện

Bước 1: Truy cập chỉnh sửa HTML của blogger.
Bước 2: Copy đoạn code dưới đây vào sau phần<body
<!--Scrollbar-->
<script type='text/javascript'>
(function () {
// Scroll Variables (tweakable)
var defaultOptions = {
    // Scrolling Core
    frameRate        : 150, // [Hz]
    animationTime    : 400, // [ms]
    stepSize         : 120, // [px]
    // Pulse (less tweakable)
    // ratio of "tail" to "acceleration"
    pulseAlgorithm   : true,
    pulseScale       : 4,
    pulseNormalize   : 1,
    // Acceleration
    accelerationDelta : 20,  // 20
    accelerationMax   : 1,   // 1
    // Keyboard Settings
    keyboardSupport   : true,  // option
    arrowScroll       : 50,     // [px]
    // Other
    touchpadSupport   : true,
    fixedBackground   : true,
    excluded          : '' 
};
var options = defaultOptions;
// Other Variables
var isExcluded = false;
var isFrame = false;
var direction = { x: 0, y: 0 };
var initDone  = false;
var root = document.documentElement;
var activeElement;
var observer;
var deltaBuffer = [];
var isMac = /^Mac/.test(navigator.platform);
var key = { left: 37, up: 38, right: 39, down: 40, spacebar: 32,
            pageup: 33, pagedown: 34, end: 35, home: 36 };
/***********************************************
 * SETTINGS
 ***********************************************/
var options = defaultOptions;
/***********************************************
 * INITIALIZE
 ***********************************************/
/**
 * Tests if smooth scrolling is allowed. Shuts down everything if not.
 */
function initTest() {
    if (options.keyboardSupport) {
        addEvent('keydown', keydown);
    }
}
/**
 * Sets up scrolls array, determines if frames are involved.
 */
function init() {
    if (initDone || !document.body) return;
    initDone = true;
    var body = document.body;
    var html = document.documentElement;
    var windowHeight = window.innerHeight;
    var scrollHeight = body.scrollHeight; 
    // check compat mode for root element
    root = (document.compatMode.indexOf('CSS') >= 0) ? html : body;
    activeElement = body; 
    initTest();
    // Checks if this script is running in a frame
    if (top != self) {
        isFrame = true;
    }
    /**
     * This fixes a bug where the areas left and right to
     * the content does not trigger the onmousewheel event
     * on some pages. e.g.: html, body { height: 100% }
     */
    else if (scrollHeight > windowHeight &&
            (body.offsetHeight <= windowHeight ||
             html.offsetHeight <= windowHeight)) {
        var fullPageElem = document.createElement('div');
        fullPageElem.style.cssText = 'position:absolute; z-index:-10000; ' +
                                     'top:0; left:0; right:0; height:' +
                                      root.scrollHeight + 'px';
        document.body.appendChild(fullPageElem);     
        // DOM changed (throttled) to fix height
        var pendingRefresh;
        var refresh = function () {
            if (pendingRefresh) return; // could also be: clearTimeout(pendingRefresh);
            pendingRefresh = setTimeout(function () {
                if (isExcluded) return; // could be running after cleanup
                fullPageElem.style.height = '0';
                fullPageElem.style.height = root.scrollHeight + 'px';
                pendingRefresh = null;
            }, 500); // act rarely to stay fast
        };
        setTimeout(refresh, 10);
        // TODO: attributeFilter?
        var config = {
            attributes: true,
            childList: true,
            characterData: false
            // subtree: true
        };
        observer = new MutationObserver(refresh);
        observer.observe(body, config);
        if (root.offsetHeight <= windowHeight) {
            var clearfix = document.createElement('div'); 
            clearfix.style.clear = 'both';
            body.appendChild(clearfix);
        }
    }
    // disable fixed background
    if (!options.fixedBackground && !isExcluded) {
        body.style.backgroundAttachment = 'scroll';
        html.style.backgroundAttachment = 'scroll';
    }
}
/**
 * Removes event listeners and other traces left on the page.
 */
function cleanup() {
    observer && observer.disconnect();
    removeEvent(wheelEvent, wheel);
    removeEvent('mousedown', mousedown);
    removeEvent('keydown', keydown);
}
/************************************************
 * SCROLLING
 ************************************************/
var que = [];
var pending = false;
var lastScroll = Date.now();
/**
 * Pushes scroll actions to the scrolling queue.
 */
function scrollArray(elem, left, top) { 
    directionCheck(left, top);
    if (options.accelerationMax != 1) {
        var now = Date.now();
        var elapsed = now - lastScroll;
        if (elapsed < options.accelerationDelta) {
            var factor = (1 + (50 / elapsed)) / 2;
            if (factor > 1) {
                factor = Math.min(factor, options.accelerationMax);
                left *= factor;
                top  *= factor;
            }
        }
        lastScroll = Date.now();
    }
   // push a scroll command
    que.push({
        x: left,
        y: top,
        lastX: (left < 0) ? 0.99 : -0.99,
        lastY: (top  < 0) ? 0.99 : -0.99,
        start: Date.now()
    });     
    // don't act if there's a pending queue
    if (pending) {
        return;
    }
    var scrollWindow = (elem === document.body); 
    var step = function (time) {     
        var now = Date.now();
        var scrollX = 0;
        var scrollY = 0;   
        for (var i = 0; i < que.length; i++) {         
            var item = que[i];
            var elapsed  = now - item.start;
            var finished = (elapsed >= options.animationTime);         
            // scroll position: [0, 1]
            var position = (finished) ? 1 : elapsed / options.animationTime;         
            // easing [optional]
            if (options.pulseAlgorithm) {
                position = pulse(position);
            }         
            // only need the difference
            var x = (item.x * position - item.lastX) >> 0;
            var y = (item.y * position - item.lastY) >> 0;         
            // add this to the total scrolling
            scrollX += x;
            scrollY += y;                     
            // update last values
            item.lastX += x;
            item.lastY += y;     
            // delete and step back if it's over
            if (finished) {
                que.splice(i, 1); i--;
            }         
        }
        // scroll left and top
        if (scrollWindow) {
            window.scrollBy(scrollX, scrollY);
        }
        else {
            if (scrollX) elem.scrollLeft += scrollX;
            if (scrollY) elem.scrollTop  += scrollY;                 
        }     
        // clean up if there's nothing left to do
        if (!left && !top) {
            que = [];
        }     
        if (que.length) {
            requestFrame(step, elem, (1000 / options.frameRate + 1));
        } else {
            pending = false;
        }
    }; 
    // start a new queue of actions
    requestFrame(step, elem, 0);
    pending = true;
}
/***********************************************
 * EVENTS
 ***********************************************/
/**
 * Mouse wheel handler.
 * @param {Object} event
 */
function wheel(event) {
    if (!initDone) {
        init();
    } 
    var target = event.target;
    var overflowing = overflowingAncestor(target);
    // use default if there's no overflowing
    // element or default action is prevented 
    // or it's a zooming event with CTRL
    if (!overflowing || event.defaultPrevented || event.ctrlKey) {
        return true;
    } 
    // leave embedded content alone (flash & pdf)
    if (isNodeName(activeElement, 'embed') ||
       (isNodeName(target, 'embed') && /\.pdf/i.test(target.src)) ||
       isNodeName(activeElement, 'object')) {
        return true;
    }
    var deltaX = -event.wheelDeltaX || event.deltaX || 0;
    var deltaY = -event.wheelDeltaY || event.deltaY || 0; 
    if (isMac) {
        if (event.wheelDeltaX && isDivisible(event.wheelDeltaX, 120)) {
            deltaX = -120 * (event.wheelDeltaX / Math.abs(event.wheelDeltaX));
        }
        if (event.wheelDeltaY && isDivisible(event.wheelDeltaY, 120)) {
            deltaY = -120 * (event.wheelDeltaY / Math.abs(event.wheelDeltaY));
        }
    } 
    // use wheelDelta if deltaX/Y is not available
    if (!deltaX && !deltaY) {
        deltaY = -event.wheelDelta || 0;
    }
    // line based scrolling (Firefox mostly)
    if (event.deltaMode === 1) {
        deltaX *= 40;
        deltaY *= 40;
    } 
    // check if it's a touchpad scroll that should be ignored
    if (!options.touchpadSupport && isTouchpad(deltaY)) {
        return true;
    }
    // scale by step size
    // delta is 120 most of the time
    // synaptics seems to send 1 sometimes
    if (Math.abs(deltaX) > 1.2) {
        deltaX *= options.stepSize / 120;
    }
    if (Math.abs(deltaY) > 1.2) {
        deltaY *= options.stepSize / 120;
    } 
    scrollArray(overflowing, deltaX, deltaY);
    event.preventDefault();
    scheduleClearCache();
}
/**
 * Keydown event handler.
 * @param {Object} event
 */
function keydown(event) {
    var target   = event.target;
    var modifier = event.ctrlKey || event.altKey || event.metaKey ||
                  (event.shiftKey && event.keyCode !== key.spacebar); 
    // our own tracked active element could've been removed from the DOM
    if (!document.contains(activeElement)) {
        activeElement = document.activeElement;
    }
    // do nothing if user is editing text
    // or using a modifier key (except shift)
    // or in a dropdown
    // or inside interactive elements
    var inputNodeNames = /^(textarea|select|embed|object)$/i;
    var buttonTypes = /^(button|submit|radio|checkbox|file|color|image)$/i;
    if ( inputNodeNames.test(target.nodeName) ||
         isNodeName(target, 'input') && !buttonTypes.test(target.type) ||
         isNodeName(activeElement, 'video') ||
         isInsideYoutubeVideo(event) ||
         target.isContentEditable ||
         event.defaultPrevented   ||
         modifier ) {
      return true;
    } 
    // spacebar should trigger button press
    if ((isNodeName(target, 'button') ||
         isNodeName(target, 'input') && buttonTypes.test(target.type)) &&
        event.keyCode === key.spacebar) {
      return true;
    } 
    var shift, x = 0, y = 0;
    var elem = overflowingAncestor(activeElement);
    var clientHeight = elem.clientHeight;
    if (elem == document.body) {
        clientHeight = window.innerHeight;
    }
    switch (event.keyCode) {
        case key.up:
            y = -options.arrowScroll;
            break;
        case key.down:
            y = options.arrowScroll;
            break;       
        case key.spacebar: // (+ shift)
            shift = event.shiftKey ? 1 : -1;
            y = -shift * clientHeight * 0.9;
            break;
        case key.pageup:
            y = -clientHeight * 0.9;
            break;
        case key.pagedown:
            y = clientHeight * 0.9;
            break;
        case key.home:
            y = -elem.scrollTop;
            break;
        case key.end:
            var damt = elem.scrollHeight - elem.scrollTop - clientHeight;
            y = (damt > 0) ? damt+10 : 0;
            break;
        case key.left:
            x = -options.arrowScroll;
            break;
        case key.right:
            x = options.arrowScroll;
            break;         
        default:
            return true; // a key we don't care about
    }
    scrollArray(elem, x, y);
    event.preventDefault();
    scheduleClearCache();
}
/**
 * Mousedown event only for updating activeElement
 */
function mousedown(event) {
    activeElement = event.target;
}
/***********************************************
 * OVERFLOW
 ***********************************************/
var uniqueID = (function () {
    var i = 0;
    return function (el) {
        return el.uniqueID || (el.uniqueID = i++);
    };
})();
var cache = {}; // cleared out after a scrolling session
var clearCacheTimer;
//setInterval(function () { cache = {}; }, 10 * 1000);
function scheduleClearCache() {
    clearTimeout(clearCacheTimer);
    clearCacheTimer = setInterval(function () { cache = {}; }, 1*1000);
}
function setCache(elems, overflowing) {
    for (var i = elems.length; i--;)
        cache[uniqueID(elems[i])] = overflowing;
    return overflowing;
}
//  (body)                (root)
//         | hidden | visible | scroll |  auto  |
// hidden  |   no   |    no   |   YES  |   YES  |
// visible |   no   |   YES   |   YES  |   YES  |
// scroll  |   no   |   YES   |   YES  |   YES  |
// auto    |   no   |   YES   |   YES  |   YES  |
function overflowingAncestor(el) {
    var elems = [];
    var body = document.body;
    var rootScrollHeight = root.scrollHeight;
    do {
        var cached = cache[uniqueID(el)];
        if (cached) {
            return setCache(elems, cached);
        }
        elems.push(el);
        if (rootScrollHeight === el.scrollHeight) {
            var topOverflowsNotHidden = overflowNotHidden(root) && overflowNotHidden(body);
            var isOverflowCSS = topOverflowsNotHidden || overflowAutoOrScroll(root);
            if (isFrame && isContentOverflowing(root) ||
               !isFrame && isOverflowCSS) {
                return setCache(elems, getScrollRoot());
            }
        } else if (isContentOverflowing(el) && overflowAutoOrScroll(el)) {
            return setCache(elems, el);
        }
    } while (el = el.parentElement);
}
function isContentOverflowing(el) {
    return (el.clientHeight + 10 < el.scrollHeight);
}
// typically for <body> and <html>
function overflowNotHidden(el) {
    var overflow = getComputedStyle(el, '').getPropertyValue('overflow-y');
    return (overflow !== 'hidden');
}
// for all other elements
function overflowAutoOrScroll(el) {
    var overflow = getComputedStyle(el, '').getPropertyValue('overflow-y');
    return (overflow === 'scroll' || overflow === 'auto');
}
/***********************************************
 * HELPERS
 ***********************************************/
function addEvent(type, fn) {
    window.addEventListener(type, fn, false);
}
function removeEvent(type, fn) {
    window.removeEventListener(type, fn, false);
}
function isNodeName(el, tag) {
    return (el.nodeName||'').toLowerCase() === tag.toLowerCase();
}
function directionCheck(x, y) {
    x = (x > 0) ? 1 : -1;
    y = (y > 0) ? 1 : -1;
    if (direction.x !== x || direction.y !== y) {
        direction.x = x;
        direction.y = y;
        que = [];
        lastScroll = 0;
    }
}
var deltaBufferTimer;
if (window.localStorage && localStorage.SS_deltaBuffer) {
    deltaBuffer = localStorage.SS_deltaBuffer.split(',');
}
function isTouchpad(deltaY) {
    if (!deltaY) return;
    if (!deltaBuffer.length) {
        deltaBuffer = [deltaY, deltaY, deltaY];
    }
    deltaY = Math.abs(deltaY)
    deltaBuffer.push(deltaY);
    deltaBuffer.shift();
    clearTimeout(deltaBufferTimer);
    deltaBufferTimer = setTimeout(function () {
        if (window.localStorage) {
            localStorage.SS_deltaBuffer = deltaBuffer.join(',');
        }
    }, 1000);
    return !allDeltasDivisableBy(120) && !allDeltasDivisableBy(100);
}
function isDivisible(n, divisor) {
    return (Math.floor(n / divisor) == n / divisor);
}
function allDeltasDivisableBy(divisor) {
    return (isDivisible(deltaBuffer[0], divisor) &&
            isDivisible(deltaBuffer[1], divisor) &&
            isDivisible(deltaBuffer[2], divisor));
}
function isInsideYoutubeVideo(event) {
    var elem = event.target;
    var isControl = false;
    if (document.URL.indexOf ('www.youtube.com/watch') != -1) {
        do {
            isControl = (elem.classList &&
                         elem.classList.contains('html5-video-controls'));
            if (isControl) break;
        } while (elem = elem.parentNode);
    }
    return isControl;
}
var requestFrame = (function () {
      return (window.requestAnimationFrame       ||
              window.webkitRequestAnimationFrame ||
              window.mozRequestAnimationFrame    ||
              function (callback, element, delay) {
                 window.setTimeout(callback, delay || (1000/60));
             });
})();
var MutationObserver = (window.MutationObserver ||
                        window.WebKitMutationObserver ||
                        window.MozMutationObserver);
var getScrollRoot = (function() {
  var SCROLL_ROOT;
  return function() {
    if (!SCROLL_ROOT) {
      var dummy = document.createElement('div');
      dummy.style.cssText = 'height:10000px;width:1px;';
      document.body.appendChild(dummy);
      var bodyScrollTop  = document.body.scrollTop;
      var docElScrollTop = document.documentElement.scrollTop;
      window.scrollBy(0, 1);
      if (document.body.scrollTop != bodyScrollTop)
        (SCROLL_ROOT = document.body);
      else
        (SCROLL_ROOT = document.documentElement);
      window.scrollBy(0, -1);
      document.body.removeChild(dummy);
    }
    return SCROLL_ROOT;
  };
})();
/***********************************************
 * PULSE (by Michael Herf)
 ***********************************************/
/**
 * Viscous fluid with a pulse for part and decay for the rest.
 * - Applies a fixed force over an interval (a damped acceleration), and
 * - Lets the exponential bleed away the velocity over a longer interval
 * - Michael Herf, http://stereopsis.com/stopping/
 */
function pulse_(x) {
    var val, start, expx;
    // test
    x = x * options.pulseScale;
    if (x < 1) { // acceleartion
        val = x - (1 - Math.exp(-x));
    } else {     // tail
        // the previous animation ended here:
        start = Math.exp(-1);
        // simple viscous drag
        x -= 1;
        expx = 1 - Math.exp(-x);
        val = start + (expx * (1 - start));
    }
    return val * options.pulseNormalize;
}
function pulse(x) {
    if (x >= 1) return 1;
    if (x <= 0) return 0;

    if (options.pulseNormalize == 1) {
        options.pulseNormalize /= pulse_(1);
    }
    return pulse_(x);
}
var wheelEvent;
if ('onwheel' in document.createElement('div'))
    wheelEvent = 'wheel';
else if ('onmousewheel' in document.createElement('div'))
    wheelEvent = 'mousewheel';

if (wheelEvent) {
    addEvent(wheelEvent, wheel);
    addEvent('mousedown', mousedown);
    addEvent('load', init);
}
})();
</script>
 *Lưu ý: Nhớ mã hóa code trước khi cho đoạn code vào nhé.
Bước 3: Lưu mẫu lại và...

Lời kết

Thật đơn giản phải không nào. Nhớ ghé thăm Blog mình để biết nhiều thủ thuật hay nhé.
Cảm ơn các bạn đã xem. Chúc các bạn thành công.

HIỆN ĐANG CÓ 43 BÌNH LUẬN

Hữu ích :D

TRẢ LỜI
avatar
Star Cường IT ­

Không có demo khó hình dung nó mượt ntn :v

TRẢ LỜI

sửa lại liên kết Ngọc Tính IT kìa bác

TRẢ LỜI

Lk tôi đâu :3

TRẢ LỜI

Cảm ơn ạ :D

TRẢ LỜI

Demo trực tiếp trên bài này mà anh

TRẢ LỜI

Chào bác :)

TRẢ LỜI

Bác phát triển thêm rồi quay lại đi bác :(

TRẢ LỜI

chuột hỏng mẹ nó cái con lawnmeos cuộn đc lên k bít :v

TRẢ LỜI

Vãi cả luôn, sắm cái mới đi anh :(

TRẢ LỜI

Văn Dũng Y Tế đã Comeback và qua TT này

TRẢ LỜI

ok bác TTT :D

TRẢ LỜI

Công nhận cho code vào cảm giác mượt ghê!

TRẢ LỜI

https://media.tenor.co/images/709f4f088a868d7992287ce7b5d919f5/tenor.gif

TRẢ LỜI
avatar
Nguyễn Phỏm IT

hay lắm bác :))

TRẢ LỜI

Cảm ơn bác :D
https://media.tenor.co/images/709f4f088a868d7992287ce7b5d919f5/tenor.gif

TRẢ LỜI

Mượt vô cùng luôn :v

TRẢ LỜI

Cảm ơn bác :)

TRẢ LỜI
avatar
Nguyễn Ngọc Quí Đz

ok tốt đấy

TRẢ LỜI

Qua TT nha bạn (3)

TRẢ LỜI
avatar
Star Nguyễn IT

Hello :V Qua TT vs bác đây

TRẢ LỜI

Hay lắm em

TRẢ LỜI

Cảm ơn ạ :)

TRẢ LỜI

Hello anh :D TTT nha anh

TRẢ LỜI

Cảm ơn anh :)

TRẢ LỜI

Giáng sinh vui vẻ nhá :)))

TRẢ LỜI

Cảm ơn ạ. Giáng sinh vui vẻ:)

TRẢ LỜI

#doiguocmoc ?

TRẢ LỜI
avatar
Star Dương Design

Hay lắm bác

TRẢ LỜI

Cảm ơn bác :)

TRẢ LỜI

Sửa rồi bác :(

TRẢ LỜI

Thấy bài này bên Đôi Guốc Mộc nên tui nói thôi, à mà còn 1 slot lk đấy, bác qua cmt kẻo mất nhá :3

TRẢ LỜI

Cảm ơn bác để tôi xem lại cái này tôi lấy code trên facebook nên mang lại chia sẻ cho anh em :(

TRẢ LỜI

Còn 1 slot lk nè, bác lấy ko ?

TRẢ LỜI

Có bác :)

TRẢ LỜI

Qua cmt nhanh gọn lẹ đê :v

TRẢ LỜI

Cho xin link bác
+ tên

TRẢ LỜI
avatar
OFFICIAL STAR KHÁNH

hay được chưa @@@

TRẢ LỜI

Cảm ơn :)

TRẢ LỜI

Một số lưu ý khi bình luận

Mọi bình luận sai nội quy sẽ bị xóa mà không cần báo trước (xem nội quy).

Bấm Thông báo cho tôi bên dưới khung bình luận để nhận thông báo khi admin trả lời.

Bạn có thể dùng ảnh động hoặc mã hóa code HTML để bình luận.