• virtual-scroller(下)


    <html>
    <head>
        <meta charset="UTF-8">
        <title>test</title>
    
        <style type="text/css">
            .viewpoint {
                margin: 20px auto;
                width: 380px;
                height: 301px;
                border: 1px solid #333;
                overflow-y:auto;
            }
            .canvas {
                position: relative;
                height: auto;
            }
            .row {
                position: absolute;
                height: 10px;
                line-height: 10px;
            }
        </style>
        <script src="jquery.js"></script>
    </head>
    <body>
        <div class="viewpoint">
            <div class="canvas"></div>
        </div>
        <div class="log"></div>
        <script>
            var lineHeight = 10;
            var viewpointHeight = $('.viewpoint').height();
            var data = new Array(909).fill(0).map((d, i) => ({ v: i }));
            var limit = Math.min(Math.ceil(viewpointHeight/ lineHeight) - 1, data.length - 1);
    
            $('.canvas').height(lineHeight * data.length);
    
            var buffer = {
                start: 0,
                end: limit,
                limit: limit,
                total: data.length,
                domain:[0, limit],
                isAmong(index) {
                    return buffer.start <= index && index <= buffer.end;
                },
                preLoad(dir, current) {
                    if (dir === 0) return false;
    
                    var start = buffer.start;
                    var end = buffer.end;
                    var cacheTwice = 3;
    
                    // scroll up
                    if (dir < 0 && start === 0) return false;
                    if (dir < 0 && current < Math.max(0, start + buffer.limit)) {
                        if (buffer.isAmong(current)) {
                            end = start - 1;
                            start = Math.max(0, end - buffer.limit);
                        } else {
                            end = current + buffer.limit;
                            start = Math.max(0, current - 2 * buffer.limit);
                            // cacheTwice = 2;
                        }
    
                        buffer.domain = [start, end];
                        buffer.start = start;
                        buffer.end = Math.min(start + cacheTwice * buffer.limit, buffer.end);
                        return true;
                    } 
    
                    // scroll down
                    if (dir > 0 && end === buffer.total) return false;
                    if (dir > 0 && current > end - buffer.limit) {
                        if (buffer.isAmong(current)) {
                            start = end + 1;
                            end = Math.min(buffer.total, start + buffer.limit); 
                        } else {
                            start = current - buffer.limit;
                            end = Math.min(buffer.total, current + 2 * buffer.limit);
                            // cacheTwice = 2;
                        }
    
                        buffer.domain = [start, end];
                        buffer.end = end;
                        buffer.start = Math.max(buffer.start, end - cacheTwice * buffer.limit);
                        return true;
                    }
                    
                    return false;
                }
            };
            var scroller = { 
                dir: 0, // -1,0,-1
                preIndex: 0,
                index: 0,
                on(fn) {
                    this.fn = function(offsetTop) {
                        log('current', offsetTop);
                        scroller.dir = offsetTop - scroller.preIndex;
                        scroller.index = ~~((scroller.preIndex = offsetTop)/ lineHeight);
                        if (buffer.preLoad(scroller.dir, scroller.index)) {
                            fn(
                                scroller.dir > 0 ? 1 : -1, 
                                buffer.domain, 
                                buffer.start, 
                                buffer.end, 
                                scroller.index,
                                buffer.total
                            );
                        }
                    };
                }, 
                fire() {this.fn.apply(this, arguments);} 
            };
    
            var dataView = {
                nodeList: [],
                init() {
                    var domain = buffer.domain;
                    dataView.render(1, domain);
                },
                fullNodes() {
                    return dataView.nodeList.length >= 3 * limit;
                },
                getNodes(dir, first, last) {
                    if (dataView.fullNodes()) {
                        let selected;
    
                        if (dir > 0) {
                            selected = dataView.nodeList.slice(0, last - first + 1);
                            dataView.nodeList = dataView.nodeList.slice(last - first + 1).concat(selected);
                            
                        } else {
                            selected = dataView.nodeList.slice(first - last - 1);
                            dataView.nodeList = selected.concat(dataView.nodeList.slice(0, first - last - 1));
                        }
                        
                        return selected;
                    }
                    
                    var nodes = [];
                    for (let i = first; i <= last; i++) {
                         nodes.push(function() {
                              var $node = $('<div/>').addClass('row');
    
                              return {
                                  src: $node,
                                  set(row, top) {
                                      return $node.css('top', top * lineHeight).text(row.v);
                                 }
                              };
                         }());
                    }
    
                    if (dir > 0) {
                        dataView.nodeList = dataView.nodeList.concat(nodes);
                    } else {
                        dataView.nodeList = nodes.concat(dataView.nodeList);
                    }
    
                    return nodes;
                },
                render(dir, [first, last]) {
                    var nodes = dataView.getNodes(dir, first, last);
                    console.log(nodes.length);
    
                    if (dataView.isFullNodes) {
                        data.slice(first, last + 1).forEach((row, i) => {
                            nodes[i].set(row, first + i);
                        });
    
                        return;
                    }
                    var parent = $('<div/>');
    
                    data.slice(first, last + 1).forEach((row, i) => {
                        parent.append(nodes[i].set(row, first + i));
                    });
    
                    $('.canvas').append(parent.children());
    
                    if (dataView.fullNodes()) {
                        dataView.isFullNodes = true;
                    }        
                }
            };
            
    
            document.querySelector('.viewpoint').addEventListener('scroll', function(evt) {
                // console.log(this.scrollTop);
                scroller.fire(this.scrollTop);
            });
    
            scroller.on(function(dir, domain, start, end, offsetTop, total) {
                console.log(`${dir}, add:[${domain}] [${start}-${end}], ${offsetTop}, nodes:${dataView.nodeList.length}`);
                dataView.render(dir, domain);
            });
    
            dataView.init();
    
    
            var $log = document.querySelector('.log');
            function log(...args) {
                $log.innerHTML = args;
            }
        </script>
    </body>
    </html>
     1 var lockColumnManager = {
     2             data: [],
     3             totalOffset: 0,
     4             add(col) {
     5                 this.data.unshift(col);
     6                 this.reCalc();
     7             },
     8             remove(delCol) {
     9                 this.data = this.data.filter(col => col !== delCol);
    10                 this.reCalc();
    11             },
    12             reCalc(){
    13                 this.totalOffset = this.data.reduce((offset, col) => {
    14                     offset += col.w;
    15                     col.offsetLeft = offset;
    16                     return offset;
    17                 }, 0);
    18             }
    19         };
  • 相关阅读:
    17ES6 Symbol的内置属性
    08ES6 箭头函数以及声明特点
    12ES6 rest参数
    15ES6 Symbol的介绍与创建
    js函数arguments的运用简单实例
    10ES6 箭头函数的实践与应用场景
    18ES6 迭代器
    11ES6 函数参数的默认值设置
    14ES6 扩展运算符的应用
    CSharp: Strategy Pattern in donet core 3
  • 原文地址:https://www.cnblogs.com/zhoulingfeng/p/7271345.html
Copyright © 2020-2023  润新知