7

我有一张我正在使用 flot 绘制的图表。当有人将鼠标悬停在文本上时,我想更改数据图的颜色。目前,我通过每次需要突出显示某些内容时重新绘制整个图表来做到这一点。这非常慢(对于简单的图表大约需要 30 毫秒,对于更复杂的图表则需要 100 毫秒)。既然我想做的就是改变颜色,有没有更快的解决方案?

4

1 回答 1

12

您可以立即采取一些措施来优化 Flot 的绘图过程。如果您不需要图表上的点,请将它们关闭,这可以显着减少绘图时间。您还应该通过将选项设置为 0 来关闭阴影shadowSize,以提高速度。

除了这两个调整之外,您还必须更改 flot 源代码才能单独突出显示一个系列。我已经创建了一个可以做到这一点的补丁,以及一个允许您自动或手动突出显示系列的小插件。补丁和插件可以比重新绘制整个图形三倍,它实际上还消除了取消突出显示系列所需的时间,因为它使用了 flot 的“叠加”功能。

下面有 jquery.flot.js 的补丁和 highlightSeries 插件的源代码,我创建了一个演示页面,让您可以看到各种设置之间的差异以及补丁/插件组合。

浮动补丁

--- .\jquery.flot.js
+++ .\jquery.flot.js
@@ -147,6 +147,7 @@
         plot.setData = setData;
         plot.setupGrid = setupGrid;
         plot.draw = draw;
+        plot.drawSeries = drawSeries;
         plot.getPlaceholder = function() { return placeholder; };
         plot.getCanvas = function() { return canvas; };
         plot.getPlotOffset = function() { return plotOffset; };
@@ -164,6 +165,7 @@
         plot.highlight = highlight;
         plot.unhighlight = unhighlight;
         plot.triggerRedrawOverlay = triggerRedrawOverlay;
+        plot.drawOverlay = drawOverlay;
         plot.pointOffset = function(point) {
             return { left: parseInt(axisSpecToRealAxis(point, "xaxis").p2c(+point.x) + plotOffset.left),
                      top: parseInt(axisSpecToRealAxis(point, "yaxis").p2c(+point.y) + plotOffset.top) };
@@ -1059,7 +1061,7 @@
                 drawGrid();

             for (var i = 0; i < series.length; ++i)
-                drawSeries(series[i]);
+                drawSeries(series[i], ctx);

             executeHooks(hooks.draw, [ctx]);

@@ -1265,16 +1267,16 @@
             placeholder.append(html.join(""));
         }

-        function drawSeries(series) {
+        function drawSeries(series, ctx) {
             if (series.lines.show)
-                drawSeriesLines(series);
+                drawSeriesLines(series, ctx);
             if (series.bars.show)
-                drawSeriesBars(series);
+                drawSeriesBars(series, ctx);
             if (series.points.show)
-                drawSeriesPoints(series);
+                drawSeriesPoints(series, ctx);
         }

-        function drawSeriesLines(series) {
+        function drawSeriesLines(series, ctx) {
             function plotLine(datapoints, xoffset, yoffset, axisx, axisy) {
                 var points = datapoints.points,
                     ps = datapoints.pointsize,
@@ -1522,7 +1524,7 @@
             ctx.restore();
         }

-        function drawSeriesPoints(series) {
+        function drawSeriesPoints(series, ctx) {
             function plotPoints(datapoints, radius, fillStyle, offset, circumference, axisx, axisy) {
                 var points = datapoints.points, ps = datapoints.pointsize;

@@ -1675,7 +1677,7 @@
             }
         }

-        function drawSeriesBars(series) {
+        function drawSeriesBars(series, ctx) {
             function plotBars(datapoints, barLeft, barRight, offset, fillStyleCallback, axisx, axisy) {
                 var points = datapoints.points, ps = datapoints.pointsize;

@@ -1942,7 +1944,7 @@

                 if (hi.series.bars.show)
                     drawBarHighlight(hi.series, hi.point);
-                else
+                else if (hi.series.points.show)
                     drawPointHighlight(hi.series, hi.point);
             }
             octx.restore();

高亮系列插件

/*
Flot plugin for highlighting series.

    highlightSeries: {
        autoHighlight: true (default) or false
        , color: color
    }

If "autoHighlight" is true (the default) and the plot's "hoverable" setting is true
series are highlighted when the mouse hovers near an item.
"color" is the color of the highlighted series (default is "red").

The plugin also adds two public methods that allow you to highlight and
unhighlight a series manually by specifying a series by label, index or object.

    - highlightSeries(series, [color])

    - unHighlightSeries(series)
*/

(function ($) {
    var log = (function () {
        var out = $("#out");
        return function () {
            if (!arguments) { return; }
            var msg = Array.prototype.slice.call(arguments).join(" ");
            if (!out.length) {
                out = $("#out");
            }
            if (out.length) {
                out.text(msg);
            }
        };
    })();

    var options = {
        highlightSeries: {
            autoHighlight: true
            , color: "black"
            , _optimized: true
            , _debug: false
        }
    };

    function init(plot) {
        var highlightedSeries = {};
        var originalColors = {};

        function highlightSeries(series, color) {
            var
                seriesAndIndex = getSeriesAndIndex(series)
                , options = plot.getOptions().highlightSeries;

            series = seriesAndIndex[1];

            highlightedSeries[seriesAndIndex[0]] = series;
            originalColors[seriesAndIndex[0]] = series.color;

            series.color = color || options.color;

            if (options._debug) { var start = new Date(); }
            if (options._optimized) {
                if (plot.drawOverlay && options._debug) {
                    plot.drawOverlay();
                }
                else {
                    plot.triggerRedrawOverlay();
                }
            }
            else {
                plot.draw();
            }
            if (options._debug) { 
                log("Time taken to highlight:", (new Date()).getTime() - start.getTime(), "ms");
            }
        };
        plot.highlightSeries = highlightSeries;

        function unHighlightSeries(series) {
            var
                seriesAndIndex = getSeriesAndIndex(series)
                , options = plot.getOptions().highlightSeries;

            seriesAndIndex[1].color = originalColors[seriesAndIndex[0]];

            if (options._debug) { var start = new Date(); }
            if (options._optimized) {
                delete highlightedSeries[seriesAndIndex[0]];
                if (plot.drawOverlay && options._debug) {
                    plot.drawOverlay();
                }
                else {
                    plot.triggerRedrawOverlay();
                }
            }
            else {
                plot.draw();
            }
            if (options._debug) { 
                log("Time taken to un-highlight:", (new Date()).getTime() - start.getTime(), "ms");
            }
        };
        plot.unHighlightSeries = unHighlightSeries;

        plot.hooks.bindEvents.push(function (plot, eventHolder) {
            if (!plot.getOptions().highlightSeries.autoHighlight) {
                return;
            }

            var lastHighlighted = null;
            plot.getPlaceholder().bind("plothover", function (evt, pos, item) {
                if (item && lastHighlighted !== item.series) {
                    for(var seriesIndex in highlightedSeries) {
                        delete highlightedSeries[seriesIndex];
                    }
                    if (lastHighlighted) {
                        unHighlightSeries(lastHighlighted);
                    }
                    lastHighlighted = item.series;
                    highlightSeries(item.series);
                }
                else if (!item && lastHighlighted) {
                    unHighlightSeries(lastHighlighted);
                    lastHighlighted = null;
                }
            });
        });

        function getSeriesAndIndex(series) {
            var allPlotSeries = plot.getData();
            if (typeof series == "number") {
                return [series, allPlotSeries[series]];
            }
            else {
                for (var ii = 0; ii < allPlotSeries.length; ii++) {
                    var plotSeries = allPlotSeries[ii];
                    if (
                        plotSeries === series
                        || plotSeries.label === series
                        || plotSeries.label === series.label
                    ) {
                        return [ii, plotSeries];
                    }
                }
            }
        }

        plot.hooks.drawOverlay.push(function (plot, ctx) {
            for(var seriesIndex in highlightedSeries) {
                plot.drawSeries(highlightedSeries[seriesIndex], ctx);
            }
        });
    }

    $.plot.plugins.push({
        init: init,
        options: options,
        name: "highlightSeries",
        version: "1.0"
    });
})(jQuery);
于 2010-05-12T06:39:04.293 回答