Amcharts使用子弹图对stackbyvalue进行排序

时间:2018-06-18 05:34:43

标签: javascript jquery amcharts

我正在使用amcharts的stackByValue来排列堆栈柱形图。我想在每个图表上添加一个项目符号,以检查它们是否符合某个目标。目前发生的事情是将子弹点添加到堆积图表中是否有一种方法可以在不删除stackByValue的情况下执行此操作?

这是我的JsFiddle:`http://jsfiddle.net/sky5rvdz/13/

$(document).ready(function() {
    AmCharts.addInitHandler(function(chart) {
        // Check if enabled
        if (chart.valueAxes === undefined || chart.valueAxes.length === 0 || !chart.valueAxes[0].stackByValue)
            return;

        // Disable built-in stacking
        chart.valueAxes[0].stackType = "none";

        // Prepare all graphs
        for (var i = 0; i < chart.graphs.length; i++) {
            var graph = chart.graphs[i];
            graph.originalValueField = graph.valueField;
            graph.valueField = graph.originalValueField + "Close";
            graph.openField = graph.originalValueField + "Open";
            graph.clustered = false;
            if (graph.labelText)
                graph.labelText = graph.labelText.split("[[value]]").join("[[" + graph.originalValueField + "]]");
            if (graph.balloonText)
                graph.balloonText = graph.balloonText.split("[[value]]").join("[[" + graph.originalValueField + "]]");
        }

        // Go through each category and order values
        for (var i = 0; i < chart.dataProvider.length; i++) {

            // Assemble intermediate array of data point items
            var dp = chart.dataProvider[i];
            var items = [];
            var sum = 0;
            for (var x = 0; x < chart.graphs.length; x++) {
                var graph = chart.graphs[x];
                items.push({
                    "graph": graph,
                    "value": dp[graph.originalValueField]
                });
            }

            var sortValue = 0;

            // Order according to value
            items.sort(function(a, b) {
                if (sortValue == 0) {

                    return a.value - b.value;
                } else {

                    return b.value - a.value;
                }

            });

            // Calculate open and close fields
            var offset = 0;
            for (var x = 0; x < items.length; x++) {
                var item = items[x];
                dp[item.graph.openField] = offset;
                dp[item.graph.valueField] = offset + dp[item.graph.originalValueField];
                offset = dp[item.graph.valueField];
            }
        }
    }, ["serial"]);

    var response = [{
        "name": "Jan",
        "target": 2062186.74,
        "USA": 0,
        "MAN": 605873.95,
        "PAN": 759763.5
    }, {
        "name": "Feb",
        "target": 1492210.81,
        "MAN": 499538.43,
        "PAN": 559504.95,
        "USA": 5850
    }, {
        "name": "Mar",
        "target": 1455750,
        "MAN": 403715.2,
        "PAN": 694353.95,
        "USA": 0
    }, {
        "name": "Apr",
        "target": 2008623.96,
        "USA": 0,
        "MAN": 409993.3,
        "PAN": 511030
    }];

    var graphs = Object.keys(response[0]).reduce(function(graphsArray, key) {
        if (key !== "name" && key !== "target") {
            graphsArray.push({
                "balloonText": "<b>[[value]]</b>",
                "balloonFunction": function(item, graph) {
                    var result = graph.balloonText;
                    for (var key in item.dataContext) {
                        if (item.dataContext.hasOwnProperty(key) && !isNaN(item.dataContext[key])) {
                            var formatted = AmCharts.formatNumber(item.dataContext[key], {
                                precision: chart.precision,
                                decimalSeparator: chart.decimalSeparator,
                                thousandsSeparator: chart.thousandsSeparator
                            }, 2);
                            result = result.replace("[[" + key + "]]", formatted);
                        }
                    }
                    return result;
                },
                "fillAlphas": 0.8,
                "labelText": "[[title]]<br>",
                "labelPosition": "middle",
                "lineAlpha": 0.3,
                "title": key,
                "type": "column",
                "color": "#000000",
                //"showAllValueLabels": true,
                "valueField": key
            });
        }
        if (key === "target") {
            graphsArray.push({
                "balloonText": "<b>[[value]]</b>",
                "balloonFunction": function(item, graph) {
                    var result = graph.balloonText;
                    for (var key in item.dataContext) {
                        if (item.dataContext.hasOwnProperty(key) && !isNaN(item.dataContext[key])) {
                            var formatted = AmCharts.formatNumber(item.dataContext[key], {
                                precision: chart.precision,
                                decimalSeparator: chart.decimalSeparator,
                                thousandsSeparator: chart.thousandsSeparator
                            }, 2);
                            result = result.replace("[[" + key + "]]", formatted);
                        }
                    }
                    return result;
                },
                "valueAxis": "v2",
                "lineAlpha": 0,
                "bullet": "round",
                "bulletSize": 20,
                "title": "target",
                "type": "line",

                "valueField": "target"
            });
        }
        return graphsArray;
    }, []);

    var chart = AmCharts.makeChart("chartdiv", {
        "type": "serial",
        "theme": "light",
        "legend": {
            "horizontalGap": 10,
            "maxColumns": 1,
            "position": "right",
            "useGraphSettings": true,
            "markerSize": 10
        },
        "numberFormatter": {
            "precision": 1,
            "decimalSeparator": ".",
            "thousandsSeparator": ","
        },
        "dataProvider": response,
        "valueAxes": [{
            "id": "v1",
            "stackType": "regular",
            /**
             * A proprietary setting `stackByValue` which is not an
             * official config option. It will be used by our custom
             * plugin
             */
            "stackByValue": true,
            "axisAlpha": 0.3,
            "gridAlpha": 0
        }, , {
            "id": "v2",
            "axisAlpha": 0.3,
            "gridAlpha": 0,
            "position": "top",

            "title": "Target"
        }],
        "gridAboveGraphs": true,
        "startDuration": 0,
        "graphs": graphs,
        "categoryField": "name",
        "categoryAxis": {
            "gridPosition": "start",
            "axisAlpha": 0,
            "gridAlpha": 0,
            "position": "left"
        },
        "export": {
            "enabled": true
        }

    });

    console.log(graphs);
    console.log(response);

    Object.keys(response[0]).forEach(key => {
        console.log(key) // returns the keys in an object
        // console.log(a[key])  // returns the appropriate value 
    })
});

1 个答案:

答案 0 :(得分:1)

问题在于,按值排序插件假定需要对所有图形进行排序和修改,才能使用打开/关闭字段来实现此效果,从而导致将子弹移动到错误的位置。由于您有多个轴,因此可以修改插件以检查图形是否属于第一个轴,并设置一个用于正确重新添加点的标志:

SELECT t.col.value('(./QuestionId)[1]','int') AS QuestionId,
       t1.Col.value('(text())[1]', 'varchar(max)') AS Options
FROM @questions.nodes ('/Questions/Question') t(Col) OUTER APPLY 
     t.Col.nodes('Options/*') t1(Col);

您还需要同步轴的最小/最大值,以使目标相对于堆叠的条正确放置。您可以通过 // Go through each category and order values for (var i = 0; i < chart.dataProvider.length; i++) { // ... for (var x = 0; x < chart.graphs.length; x++) { var graph = chart.graphs[x]; items.push({ "graph": graph, // check if this graph's data points need to be omitted from the sorting process. "ignoreSort": (graph.valueAxis && graph.valueAxis !== chart.valueAxes[0].id), "value": dp[graph.originalValueField] }); } // ... // Calculate open and close fields var offset = 0; for (var x = 0; x < items.length; x++) { var item = items[x]; if (!item.ignoreSort) { //process the pont as normal if it doesn't have the flag set with open/value fields dp[item.graph.openField] = offset; dp[item.graph.valueField] = offset + dp[item.graph.originalValueField]; offset = dp[item.graph.valueField]; } else { //otherwise treat the point as a normal graph and use the value field dp[item.graph.valueField] = dp[item.graph.originalValueField] } } } 使用另一个自定义插件来实现此目的:

addInitHandler

Updated fiddle