หน้าเว็บ

วันอาทิตย์ที่ 26 พฤษภาคม พ.ศ. 2556

ImageLoader (lazy load image and automatic reposition) : javascript, jQuery

คงมีคำถามว่าเอาไว้ทำอะไร โผล่ขึ้นมาในหัวแน่นอน ใช่มั้ยครับครับ

        ผมเอาไว้ load image แบบ lazy ครับ  คือไว้โหลดรูปภาพมาทีหลัง  หลังจากที่ load หน้าเว็บ หรือ ขึ้นโครงหน้าเว็บเสร็จ  สำหรับคนที่ทำ page speed ก็คงจะเข้าใจครับ  ว่านี่เป็นวิธีการนึง  ที่จะทำให้หน้าเว็บ  คุณโหลดเร็วขึ้น

        และมันยังจัด position ให้เราอัตโนมัติด้วย  เช่น  บางทีโหลดมาแล้ว  เราต้องมานั่งคำนวณเองว่า image size ขนาดนี้  ต้อง margin เท่านี้  เพื่อจัดให้มันอยู่ตรงกลางพอดี    ถ้า image เล็กไป  มันก็ไม่เต็ม frame  หรือ image ใหญ่ไป  มันก็ล้นออกจาก frame อีก  น่าปวดหัวครับ  ถ้าจะต้องมานั่งคำนวณใหม่  เองทั้งหมด

        ใช้นี่แหล่ะครับ  ง่ายสุดๆล่ะ  ให้ผมปวดหัวคนเดียวก็พอครับ  คนอื่นๆ  เชิญเอาไปใช้ ง่ายๆ  สบายๆ  เลยครับ


example to use
html
    <div style="width : 100px; height : 200px;">
        <img class="lazy" src="http://na5cent.blogspot.com/images/fakeImage.jpg" data-source="http://na5cent.blogspot.com/images/user.jpg"/>
    </div>

src="http://na5cent.blogspot.com/images/fakeImage.jpg" คือ image ที่มี size เป็น 1x1 pixel ไว้ป้องกัน image error ตอน load หน้าเว็บครับ
data-source="http://na5cent.blogspot.com/images/user.jpg" คือ image จริงๆ ที่จะแสดงครับ

css
    .image-wrapper{
        overflow : hidden;
    }

javascript
    var imageLoader = new ImageLoader();
    imageLoader.load('img.lazy').then(function(image, status){
        console.log(image.attr('src'));
    }); 

ImageLoader.js
/** 
 * @description for load image (lazy load) from  web server then compute new image size and automatic reposition
 * @author  redcrow
 * @create  18/05/2013
 * @updator redcrow
 * @update  26/05/2013 
 * @link    http://na5cent.blogspot.com/2013/05/imageloader-lazy-load-image-and.html
 */
var ImageLoader = function() {
    var _DEFAULT_TIME_LOAD = 100;
    var _DEFAULT_STEP_LOAD = 10;

    var _TIME_LOAD;
    var _STEP_LOAD;

    function ImageItem(image, callbackList_, time) {
        image.css({
            'visibility': 'hidden'
        });
        
        var parent = image.parent();
        parent.addClass('image-wrapper');

        var imageItemTimeout = setTimeout(function() {
            window.clearTimeout(imageItemTimeout);
            
            var dataSource = image.data('source');
            if (dataSource) {
                var img = new Image();
                img.src = dataSource;

                img.onload = function(){
                    image.attr('src', dataSource);

                    var oldWidth = img.width;
                    var oldHeight = img.height;

                    var newWidth = parent.width();
                    var newHeight = parent.height();

                    //set standard scale ===================================
                    newHeight = 0;

                    var percentWidth = newWidth / oldWidth;
                    var percentHeight = newHeight / oldHeight;

                    if (newHeight === 0) {
                        newHeight = percentWidth * oldHeight;
                    }

                    if (newWidth === 0) {
                        newWidth = percentHeight * oldWidth;
                    }
                    //set standard scale ===================================


                    //compute new scale ====================================
                    oldWidth = newWidth;
                    oldHeight = newHeight;
                    
                    var parentWidth = parent.width();
                    var parentHeight = parent.height();

                    var widthSpace = parentWidth - oldWidth;
                    var heightSpace = parentHeight - oldHeight;

                    if (widthSpace > 0) {
                        newHeight = 0;
                        newWidth = parentWidth;
                    }

                    if (heightSpace > 0) {
                        newWidth = 0;
                        newHeight = parentHeight;
                    }

                    percentWidth = newWidth / oldWidth;
                    percentHeight = newHeight / oldHeight;

                    if (newHeight === 0) {
                        newHeight = percentWidth * oldHeight;
                    }

                    if (newWidth === 0) {
                        newWidth = percentHeight * oldWidth;
                    }
                    //compute new scale ====================================


                    newWidth = parseInt(newWidth);
                    newHeight = parseInt(newHeight);
                    
                    var marginTop = parseInt((-1) * (newHeight - parentHeight) / 2);
                    var marginLeft = parseInt((-1) * (newWidth - parentWidth) / 2);

                    image.attr('width', newWidth);
                    image.attr('height', newHeight);

                    image.css({
                        'visibility': 'visible',
                        'margin-top': marginTop + 'px',
                        'margin-left': marginLeft + 'px'
                    });
                    
                    for (var index in callbackList_) {
                        callbackList_[index](image, 'SUCCESS');
                    }
                };

                img.onerror = function() {
                    for (var index in callbackList_) {
                        callbackList_[index](image, 'FAIL');
                    }
                };

                image.removeAttr('data-source');
            }
        }, time * _STEP_LOAD);
    }

    function _load(imageSelector, callback) {
        var callbackList_ = [];
        if (callback) {
            callbackList_.push(callback);
        }

        this.then = function(cb) {
            if (cb) {
                callbackList_.push(cb);
            }
        };

        var imageTimeout = setTimeout(function() {
            window.clearTimeout(imageTimeout);

            $(imageSelector).each(function(index) {
                new ImageItem($(this), callbackList_, index);
            });
        }, _TIME_LOAD);
    }

    return {
        setConfigs: function(config) {
            _TIME_LOAD = config.DEFAULT_TIME_LOAD || _DEFAULT_TIME_LOAD;
            _STEP_LOAD = config.DEFAULT_STEP_LOAD || _DEFAULT_STEP_LOAD;
        },
        load: function(imageSelector, callback) {
            return new _load(imageSelector, callback);
        }
    };
};

ไม่มีความคิดเห็น:

แสดงความคิดเห็น