Sparkline rendering is slow and hangs browser

2019-04-11 17:38发布

Sparklines are awesome for doing little inline graphs. However, if the container they are in is hidden, you can't simply draw them behind the scenes and then show them. You must first display the container and then call the $.sparkline_display_visible method.

This is ok, except that it's really slow if you have a lot of graphs. I have a little over 200 graphs (and will eventually scale to more) to render and it takes around 4000ms to render them all, hanging the browser. Does anyone know how to either speed up this process (doubtful) or improve perceived performance by not hanging the browser? I tried to add a timer so each graph would show up one at a time while being rendered, but that still takes a while with 200+ graphs and the effect is a bit distracting to the user.

Thanks

3条回答
女痞
2楼-- · 2019-04-11 18:21

Solution for not hang browser with rendering sparklines is to call it async (with offset time setting events to queue). See sample:

var sparklinesGantt = new Array();
var sprklGanttCounter = 0;
var sprklBlockQuickShow = 20; // sync elements count
var sprklBlockSofort = 15; // async elemenbts count quick show
var sprklBlockGroesse = 2; // block size for async

var renderGanttSparkline = function(obj) {
    $(obj).css('padding-right','0px').sparkline('html', {
        width: '100px',
        height: '16px',
        type: 'bullet',
        targetWidth: 2,
        performanceColor: '#d3d3d3',
        targetColor: '#ffa500',
        rangeColors: ['#d3d3d3', '#4169e1', '#d3d3d3']
    });
};
var renderGanttSparklineAtom = function() {
    var sprklCounterBlockNext = sprklGanttCounter + sprklBlockGroesse;
    for (var c = sprklGanttCounter;sprklGanttCounter<sprklCounterBlockNext;c++) {
        var obj = sparklinesGantt[sprklGanttCounter];
        sprklGanttCounter++;
        renderGanttSparkline(obj);
    }
    if (sprklGanttCounter < sparklinesGantt.length) {
        setTimeout(renderGanttSparklineAtom, 1);
    }
};
var ganttSparkline = function(id) {
    var selector = ".gantt_sprkl";
    if (id) {
        selector = "#"+id;
    }
    if ($(selector).size() < sprklBlockQuickShow) {
        renderGanttSparkline($(selector));
    } else {
        sparklinesGantt = jQuery.makeArray($(selector));
        sprklGanttCounter = 0;
        while (sprklGanttCounter<sprklBlockSofort) {
            var obj = sparklinesGantt[sprklGanttCounter];
            sprklGanttCounter++;
            renderGanttSparkline(obj);
        }   
        setTimeout(renderGanttSparklineAtom, 1);
    }
};
$(document).ready(function() {
    ganttSparkline();
});

Bye

here is the testing page

查看更多
Root(大扎)
3楼-- · 2019-04-11 18:27

You can easily avoid hanging the browser by not doing them all at the same time. It is usually OK to render graphs asynchronously when they come into the viewport.

See http://mleibman.github.com/SlickGrid/examples/example10-async-post-render.html for a working example.

查看更多
Rolldiameter
4楼-- · 2019-04-11 18:37

You could have the plugin render the graph for the ones that are visible on load then loop through the hidden ones and have it render those in groups of 10. Will make it so the browser doesn't hang and will "pre-render" the hidden ones before you need them.

var sparklines = $('.inlinesparkline').sparkline();
var hidden = sparklines.parent().filter(':hidden').addClass('needsSparkline');

(function loopy(){
    var objs = hidden.filter(':lt(10)').removeClass('needsSparkline');
    hidden = hidden.filter('.needsSparkline');
    if (objs.length) {
        objs.css({
            'display':'',
            'visibility':'hidden'
        });
        $.sparkline_display_visible();
        objs.css({
            'display':'none',
            'visibility':''
        });
        hidden.length && setTimeout( loopy, 250 );
    }
})();
查看更多
登录 后发表回答