D3.js错误的折线图方向

时间:2017-04-29 08:35:40

标签: javascript d3.js

我正在使用d3.js来显示多个折线图。

我有两个数据阵列要比较,首先我使用x轴(底部),第二个 - x2轴(顶部)。 但我在这里遇到了一些错误。看起来像这样

enter image description here

线路方向完全错误。

有谁知道我应该在哪里找到这种行为的原因?

代码在这里

function chart(dataArray, colors) {

    var data = dataArray.nodes;
    // console.log(dataArray.nodes2)

    $('#visualisation').empty();
    $('.no-data').hide();

    var MARGINS = {top: 20, right: 20, bottom: 30, left: 30},
        WIDTH = parseInt($('.page .container').outerWidth())*0.75 - MARGINS.left - MARGINS.right -45,
        HEIGHT = parseInt($('#visualisation').outerHeight()) - MARGINS.top - MARGINS.bottom;


    var canvas = d3.select("#visualisation");

    var parseTime = d3.timeParse("%Y-%m-%d");

    var yDomain = [d3.min(data.yAxis, function(d) {return Math.min(d)}), d3.max(data.yAxis, function(d) {return Math.max(d);})];
    // var yDomain = [d3.min(dataArray.nodes2.yAxis, function(d) {return Math.min(d)}), d3.max(dataArray.nodes2.yAxis, function(d) {return Math.max(d);})];
    var zDomain = [d3.min(data.zAxis, function(d) {return Math.min(d)}), d3.max(data.zAxis, function(d) {return Math.max(d);})];



    xScale = d3.scaleTime().range([0, WIDTH]);
    x2Scale = d3.scaleTime().range([0, WIDTH]);
    yScale = d3.scaleLinear().range([HEIGHT, 0]);
    zScale = d3.scaleLinear().range([HEIGHT, 0]);

    xScale.domain(d3.extent(data.xAxis, function(d) { return parseTime(d); }));



    yScale.domain(yDomain);
    zScale.domain(zDomain);

    xAxis = d3.axisBottom()
        .scale(xScale)
        .ticks(10)
        .tickSizeInner(-HEIGHT)
        .tickPadding(10)
        .tickSizeOuter(0);



    yAxis = d3.axisLeft()
        .scale(yScale)
        .tickSizeInner(-WIDTH)
        .tickPadding(10)
        .tickSizeOuter(0)
        .ticks(15);

    zAxis = d3.axisLeft()
        .scale(zScale)
        .ticks(10)

    vis = canvas.append("svg:g")
        .attr("transform", "translate(25,25)")


    vis.append("svg:g")
        .call(zAxis)
        .attr("transform",
            "translate(" + (WIDTH + 30)+ ",0)")
        .attr('y', 120 -MARGINS.left);

    vis.append("svg:g")
        .attr('class', 'line-transparent')
        .attr("width", WIDTH + MARGINS.left + MARGINS.right)
        .attr("height", HEIGHT + MARGINS.top + MARGINS.bottom)
        .attr("transform", "translate(25," + HEIGHT + ")")
        .call(xAxis);



    vis.append("svg:g")
        .call(yAxis)
        .attr('class', 'line-transparent')
        .attr("transform",
            "translate(" + MARGINS.left + ",0)")
        .attr('y', 20 -MARGINS.left);


    var zLineGen = d3.line()
        .x(function(d) {
            return xScale(parseTime(d.from)) + 30;
        })
        .y(function(d, name) {
            var names = Object.keys(d);
            return zScale(d[names[1]]);
        });

    if (dataArray.nodes2) {

        x2Scale.domain(d3.extent(dataArray.nodes2.xAxis, function(d) { return parseTime(d); }));
        x2Axis = d3.axisTop()
            .scale(x2Scale)
        vis.append("svg:g")
            .attr('class', 'line-transparent')
            .attr("width", WIDTH + MARGINS.left + MARGINS.right)
            .attr("height", HEIGHT + MARGINS.top + MARGINS.bottom)
            .attr("transform", "translate(25,0)")
            // .attr('y', 0)
            .call(x2Axis);

        makeLines(vis, dataArray.nodes2, 2)
        makeLabels(dataArray.nodes2.options,1, dataArray.nodes2.colors)
        //TODO separate it to function
        var line2 = vis.selectAll('.scale_2')
            .data(dataArray.nodes2.data);

        line2.each(function (d) {
            d.items.forEach(function (r) {
                var newNode = vis.append('g');
                newNode
                    .attr('class', 'chart-dot')
                    .append('text')
                    .attr('x', function (el) {
                        var names = Object.keys(r);
                        var text = r.label + ': ' + r[names[1]];
                        var tWidth = getTextWidth(text, 10, 'Arial');
                        if (x2Scale(parseTime(r.from)) > WIDTH/2) {
                            return x2Scale(parseTime(r.from)) - (tWidth + 10)
                        } else {
                            return x2Scale(parseTime(r.from)) + 30
                        }
                    })
                    .attr('y', function () {
                        var names = Object.keys(r);
                        if (r.price == true) {
                            return zScale(r[names[1]]);
                        } else {
                            return yScale(r[names[1]]);
                        }
                    })
                    .attr('font-size', '10')
                    .attr('class', 'chart-dot-text')
                    .text(function () {
                        var names = Object.keys(r);
                        return r.from + ' - ' + r.label + ': ' + r[names[1]];
                    });

                newNode.append('circle')
                    .attr('cx', function () {
                        return x2Scale(parseTime(r.from)) + 30
                    })
                    .attr('cy', function () {
                        var names = Object.keys(r);
                        if (r.price == true) {
                            return zScale(r[names[1]]);
                        } else {
                            return yScale(r[names[1]]);
                        }
                    })
                    .attr('r', 5)
            })
        })
        //
    }

    makeLines(vis, data, 1)

    var line = vis.selectAll('.scale_1')
        .data(data.data);

    line.each(function (d) {
        d.items.forEach(function (r) {
            var newNode = vis.append('g');
            newNode
                .attr('class', 'chart-dot')
                .append('text')
                .attr('x', function (el) {
                    var names = Object.keys(r);
                    var text = r.label + ': ' + r[names[1]];
                    var tWidth = getTextWidth(text, 10, 'Arial');
                    if (xScale(parseTime(r.from)) > WIDTH/2) {
                        return xScale(parseTime(r.from)) - (tWidth + 10)
                    } else {
                        return xScale(parseTime(r.from)) + 30
                    }
                })
                .attr('y', function () {
                    var names = Object.keys(r);
                    if (r.price == true) {
                        return zScale(r[names[1]]);
                    } else {
                        return yScale(r[names[1]]);
                    }
                })
                .attr('font-size', '10')
                .attr('class', 'chart-dot-text')
                .text(function () {
                    var names = Object.keys(r);
                    return r.label + ': ' + r[names[1]];
                });

            newNode.append('circle')
                .attr('cx', function () {
                    return xScale(parseTime(r.from)) + 30
                })
                .attr('cy', function () {
                    var names = Object.keys(r);
                    if (r.price == true) {
                        return zScale(r[names[1]]);
                    } else {
                        return yScale(r[names[1]]);
                    }
                })
                    .attr('r', 5)
        })
    })

    function makeLines(vis, data, scale) {

        var i = 0;

        data.data.forEach(function (row) {

            if (scale == 1) {
                var stroke = colors[i];
            } else {
                var stroke = colors[(colors.length -1) - i]
            }

            vis.append('svg:path')
                .attr('d', function (d) {
                    if (row.price == true) {
                        return zLineGen(row.items)
                    } else {
                        return lineGen(row.items, scale);
                    }
                })
                .attr('stroke', stroke)
                .attr('stroke-width', 2)
                .attr('id', function () {
                    if (scale == 1) {
                        return row.name
                    } else {
                        return row.name + '_comparison'
                    }
                })
                .attr('fill', 'none')
                .attr('class', 'chart-line scale_' + scale)
                .attr('data-scale', scale)
                .on('mousemove', function (d) {
                    var x = xScale.invert(d3.mouse(this)[0]);
                    var y = yScale.invert(d3.mouse(this)[1]);
                });
            i++;
        });
    }

    function lineGen(s,scale) {
        // console.log(scale)

        if (scale == 1) {
            var newlineGen = d3.line()
                .x(function(d) {
                    return xScale(parseTime(d.from)) + 30;
                })
                .y(function(d, name) {
                    var names = Object.keys(d);
                    return yScale(d[names[1]]);
                });
        } else {
            var newlineGen = d3.line()
                .x(function(d,x) {
                    return x2Scale(parseTime(d.from)) + 30;
                })
                .y(function(d, name) {
                    var names = Object.keys(d);
                    return yScale(d[names[1]]);
                });
        }
        return newlineGen(s)
    }


    function getTextWidth(text, fontSize, fontFace) {
        var a = document.createElement('canvas');
        var b = a.getContext('2d');
        b.font = fontSize + 'px ' + fontFace;
        return b.measureText(text).width;
    }


    function mousemove() {
        var x0 = xScale.invert(d3.mouse(this)[0]);
        var y0 = yScale.invert(d3.mouse(this)[1]);
    };
}

数据在这里

{
"nodes": {
    "data": [
        {
            "name": "sum_ordered",
            "items": [
                {
                    "from": "2017-03-01",
                    "sum_ordered": "3",
                    "price": false,
                    "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)"
                },
                {
                    "from": "2017-03-06",
                    "sum_ordered": "5",
                    "price": false,
                    "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)"
                },
                {
                    "from": "2017-03-10",
                    "sum_ordered": "116",
                    "price": false,
                    "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)"
                },
                {
                    "from": "2017-03-20",
                    "sum_ordered": "51",
                    "price": false,
                    "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)"
                }
            ],
            "price": false
        },
        {
            "name": "sum_income",
            "items": [
                {
                    "from": "2017-03-01",
                    "sum_income": "0",
                    "price": false,
                    "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)"
                },
                {
                    "from": "2017-03-06",
                    "sum_income": "0",
                    "price": false,
                    "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)"
                },
                {
                    "from": "2017-03-10",
                    "sum_income": "0",
                    "price": false,
                    "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)"
                },
                {
                    "from": "2017-03-20",
                    "sum_income": "0",
                    "price": false,
                    "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)"
                }
            ],
            "price": false
        },
        {
            "name": "sum_sales_by_payment",
            "items": [
                {
                    "from": "2017-03-01",
                    "sum_sales_by_payment": "7",
                    "price": false,
                    "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)"
                },
                {
                    "from": "2017-03-06",
                    "sum_sales_by_payment": "5",
                    "price": false,
                    "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)"
                },
                {
                    "from": "2017-03-10",
                    "sum_sales_by_payment": "53",
                    "price": false,
                    "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)"
                },
                {
                    "from": "2017-03-20",
                    "sum_sales_by_payment": "18",
                    "price": false,
                    "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)"
                }
            ],
            "price": false
        }
    ],
    "xAxis": [
        "2017-03-20",
        "2017-03-20",
        "2017-03-20",
        "2017-03-20",
        "2017-03-10",
        "2017-03-10",
        "2017-03-10",
        "2017-03-10",
        "2017-03-06",
        "2017-03-06",
        "2017-03-06",
        "2017-03-06",
        "2017-03-01",
        "2017-03-01",
        "2017-03-01",
        "2017-03-01"
    ],
    "yAxis": [
        "116",
        "53",
        "51",
        "18",
        "7",
        "5",
        "5",
        "3",
        "0",
        "0",
        "0",
        "0"
    ],
    "zAxis": [],
    "x2Domain": {
        "from": "2017-03-01",
        "to": "2017-03-20"
    },
    "colors": [
        "#19c2ff",
        "#ff9019",
        "#6fc522",
        "#e95fcd",
        "#a02424",
        "#6a56c1",
        "#4fc494",
        "#ffd324",
        "#ff78be"
    ],
    "options": [
        {
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)",
            "color": "#19c2ff",
            "id": "sum_ordered"
        },
        {
            "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)",
            "color": "#ff9019",
            "id": "sum_income"
        },
        {
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)",
            "color": "#6fc522",
            "id": "sum_sales_by_payment"
        }
    ]
},
"nodes2": {
    "data": [
        {
            "name": "sum_ordered",
            "items": [
                {
                    "from": "2017-03-01",
                    "sum_ordered": "19",
                    "price": false,
                    "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)"
                },
                {
                    "from": "2017-03-09",
                    "sum_ordered": "1",
                    "price": false,
                    "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)"
                },
                {
                    "from": "2017-03-10",
                    "sum_ordered": "15",
                    "price": false,
                    "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)"
                },
                {
                    "from": "2017-01-30",
                    "sum_ordered": "2",
                    "price": false,
                    "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)"
                }
            ],
            "price": false
        },
        {
            "name": "sum_income",
            "items": [
                {
                    "from": "2017-03-01",
                    "sum_income": "0",
                    "price": false,
                    "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)"
                },
                {
                    "from": "2017-03-09",
                    "sum_income": "0",
                    "price": false,
                    "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)"
                },
                {
                    "from": "2017-03-10",
                    "sum_income": "0",
                    "price": false,
                    "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)"
                },
                {
                    "from": "2017-01-30",
                    "sum_income": "0",
                    "price": false,
                    "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)"
                }
            ],
            "price": false
        },
        {
            "name": "sum_sales_by_payment",
            "items": [
                {
                    "from": "2017-03-01",
                    "sum_sales_by_payment": "5",
                    "price": false,
                    "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)"
                },
                {
                    "from": "2017-03-09",
                    "sum_sales_by_payment": "0",
                    "price": false,
                    "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)"
                },
                {
                    "from": "2017-03-10",
                    "sum_sales_by_payment": "11",
                    "price": false,
                    "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)"
                },
                {
                    "from": "2017-01-30",
                    "sum_sales_by_payment": "1",
                    "price": false,
                    "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)"
                }
            ],
            "price": false
        }
    ],
    "xAxis": [
        "2017-03-10",
        "2017-03-10",
        "2017-03-10",
        "2017-03-10",
        "2017-03-09",
        "2017-03-09",
        "2017-03-09",
        "2017-03-09",
        "2017-03-01",
        "2017-03-01",
        "2017-03-01",
        "2017-03-01",
        "2017-01-30",
        "2017-01-30",
        "2017-01-30",
        "2017-01-30"
    ],
    "yAxis": [
        "19",
        "15",
        "11",
        "5",
        "2",
        "1",
        "1",
        "0",
        "0",
        "0",
        "0",
        "0"
    ],
    "zAxis": [],
    "x2Domain": {
        "from": "2017-01-30",
        "to": "2017-03-10"
    },
    "colors": [
        "#19c2ff",
        "#ff9019",
        "#6fc522",
        "#e95fcd",
        "#a02424",
        "#6a56c1",
        "#4fc494",
        "#ffd324",
        "#ff78be"
    ],
    "options": [
        {
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)",
            "color": "#19c2ff",
            "id": "sum_ordered"
        },
        {
            "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)",
            "color": "#ff9019",
            "id": "sum_income"
        },
        {
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)",
            "color": "#6fc522",
            "id": "sum_sales_by_payment"
        }
    ]
}

}

1 个答案:

答案 0 :(得分:1)

在您的数据中,nodes2.data未正确排序。 d3不会为您排序数据,而是根据情况对其进行绘制。

这是一个正在运行的样本,数据已正确排序:



<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
</head>

<body>
  <svg id="visualisation" width="900" height="900"></svg>
  <script>
    var data = {
      "nodes": {
        "data": [{
          "name": "sum_ordered",
          "items": [{
            "from": "2017-03-01",
            "sum_ordered": "3",
            "price": false,
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)"
          }, {
            "from": "2017-03-06",
            "sum_ordered": "5",
            "price": false,
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)"
          }, {
            "from": "2017-03-10",
            "sum_ordered": "116",
            "price": false,
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)"
          }, {
            "from": "2017-03-20",
            "sum_ordered": "51",
            "price": false,
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)"
          }],
          "price": false
        }, {
          "name": "sum_income",
          "items": [{
            "from": "2017-03-01",
            "sum_income": "0",
            "price": false,
            "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)"
          }, {
            "from": "2017-03-06",
            "sum_income": "0",
            "price": false,
            "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)"
          }, {
            "from": "2017-03-10",
            "sum_income": "0",
            "price": false,
            "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)"
          }, {
            "from": "2017-03-20",
            "sum_income": "0",
            "price": false,
            "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)"
          }],
          "price": false
        }, {
          "name": "sum_sales_by_payment",
          "items": [{
            "from": "2017-03-01",
            "sum_sales_by_payment": "7",
            "price": false,
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)"
          }, {
            "from": "2017-03-06",
            "sum_sales_by_payment": "5",
            "price": false,
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)"
          }, {
            "from": "2017-03-10",
            "sum_sales_by_payment": "53",
            "price": false,
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)"
          }, {
            "from": "2017-03-20",
            "sum_sales_by_payment": "18",
            "price": false,
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)"
          }],
          "price": false
        }],
        "xAxis": [
          "2017-03-20",
          "2017-03-20",
          "2017-03-20",
          "2017-03-20",
          "2017-03-10",
          "2017-03-10",
          "2017-03-10",
          "2017-03-10",
          "2017-03-06",
          "2017-03-06",
          "2017-03-06",
          "2017-03-06",
          "2017-03-01",
          "2017-03-01",
          "2017-03-01",
          "2017-03-01"
        ],
        "yAxis": [
          "116",
          "53",
          "51",
          "18",
          "7",
          "5",
          "5",
          "3",
          "0",
          "0",
          "0",
          "0"
        ],
        "zAxis": [],
        "x2Domain": {
          "from": "2017-03-01",
          "to": "2017-03-20"
        },
        "colors": [
          "#19c2ff",
          "#ff9019",
          "#6fc522",
          "#e95fcd",
          "#a02424",
          "#6a56c1",
          "#4fc494",
          "#ffd324",
          "#ff78be"
        ],
        "options": [{
          "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)",
          "color": "#19c2ff",
          "id": "sum_ordered"
        }, {
          "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)",
          "color": "#ff9019",
          "id": "sum_income"
        }, {
          "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)",
          "color": "#6fc522",
          "id": "sum_sales_by_payment"
        }]
      },
      "nodes2": {
        "data": [{
          "name": "sum_ordered",
          "items": [{
            "from": "2017-01-30",
            "sum_ordered": "2",
            "price": false,
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)"
          }, {
            "from": "2017-03-01",
            "sum_ordered": "19",
            "price": false,
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)"
          }, {
            "from": "2017-03-09",
            "sum_ordered": "1",
            "price": false,
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)"
          }, {
            "from": "2017-03-10",
            "sum_ordered": "15",
            "price": false,
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)"
          }],
          "price": false
        }, {
          "name": "sum_income",
          "items": [{
            "from": "2017-01-30",
            "sum_income": "0",
            "price": false,
            "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)"
          }, {
            "from": "2017-03-01",
            "sum_income": "0",
            "price": false,
            "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)"
          }, {
            "from": "2017-03-09",
            "sum_income": "0",
            "price": false,
            "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)"
          }, {
            "from": "2017-03-10",
            "sum_income": "0",
            "price": false,
            "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)"
          }],
          "price": false
        }, {
          "name": "sum_sales_by_payment",
          "items": [{
            "from": "2017-01-30",
            "sum_sales_by_payment": "1",
            "price": false,
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)"
          }, {
            "from": "2017-03-01",
            "sum_sales_by_payment": "5",
            "price": false,
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)"
          }, {
            "from": "2017-03-09",
            "sum_sales_by_payment": "0",
            "price": false,
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)"
          }, {
            "from": "2017-03-10",
            "sum_sales_by_payment": "11",
            "price": false,
            "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)"
          }],
          "price": false
        }],
        "xAxis": [
          "2017-03-10",
          "2017-03-10",
          "2017-03-10",
          "2017-03-10",
          "2017-03-09",
          "2017-03-09",
          "2017-03-09",
          "2017-03-09",
          "2017-03-01",
          "2017-03-01",
          "2017-03-01",
          "2017-03-01",
          "2017-01-30",
          "2017-01-30",
          "2017-01-30",
          "2017-01-30"
        ],
        "yAxis": [
          "19",
          "15",
          "11",
          "5",
          "2",
          "1",
          "1",
          "0",
          "0",
          "0",
          "0",
          "0"
        ],
        "zAxis": [],
        "x2Domain": {
          "from": "2017-01-30",
          "to": "2017-03-10"
        },
        "colors": [
          "#19c2ff",
          "#ff9019",
          "#6fc522",
          "#e95fcd",
          "#a02424",
          "#6a56c1",
          "#4fc494",
          "#ffd324",
          "#ff78be"
        ],
        "options": [{
          "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u0417\\u0430\\u043a\\u0430\\u0437\\u0430\\u043d\\u043e (\\u0448\\u0442)",
          "color": "#19c2ff",
          "id": "sum_ordered"
        }, {
          "label": "\\u041f\\u043e\\u0441\\u0442\\u0443\\u043f\\u043b\\u0435\\u043d\\u0438\\u044f (\\u0448\\u0442)",
          "color": "#ff9019",
          "id": "sum_income"
        }, {
          "label": "\\u0412\\u0441\\u0435\\u0433\\u043e \\u041f\\u0440\\u043e\\u0434\\u0430\\u0436\\u0438 \\u043f\\u043e \\u043e\\u043f\\u043b\\u0430\\u0442\\u0430\\u043c (\\u0448\\u0442)",
          "color": "#6fc522",
          "id": "sum_sales_by_payment"
        }]
      }
    }

    chart(data, ['red', 'green', 'blue', 'orange'])


    function chart(dataArray, colors) {

      var data = dataArray.nodes;
      // console.log(dataArray.nodes2)

      //$('#visualisation').empty();
      //$('.no-data').hide();

      var MARGINS = {
          top: 20,
          right: 20,
          bottom: 30,
          left: 30
        },
        WIDTH = 600,
        HEIGHT = 600;


      var canvas = d3.select("#visualisation");

      var parseTime = d3.timeParse("%Y-%m-%d");

      var yDomain = [d3.min(data.yAxis, function(d) {
        return Math.min(d)
      }), d3.max(data.yAxis, function(d) {
        return Math.max(d);
      })];
      // var yDomain = [d3.min(dataArray.nodes2.yAxis, function(d) {return Math.min(d)}), d3.max(dataArray.nodes2.yAxis, function(d) {return Math.max(d);})];
      var zDomain = [d3.min(data.zAxis, function(d) {
        return Math.min(d)
      }), d3.max(data.zAxis, function(d) {
        return Math.max(d);
      })];



      xScale = d3.scaleTime().range([0, WIDTH]);
      x2Scale = d3.scaleTime().range([0, WIDTH]);
      yScale = d3.scaleLinear().range([HEIGHT, 0]);
      zScale = d3.scaleLinear().range([HEIGHT, 0]);


      for (var i = 0; i < data.xAxis.length; i++) {
        data.xAxis[i] = parseTime(data.xAxis[i]);
      }
      data.xAxis.sort();

      // console.log(data.xAxis)

      xScale.domain(d3.extent(data.xAxis, function(d) {
        return d;
      }));



      yScale.domain(yDomain);
      zScale.domain(zDomain);

      xAxis = d3.axisBottom()
        .scale(xScale)
        .ticks(10)
        .tickSizeInner(-HEIGHT)
        .tickPadding(10)
        .tickSizeOuter(0);



      yAxis = d3.axisLeft()
        .scale(yScale)
        .tickSizeInner(-WIDTH)
        .tickPadding(10)
        .tickSizeOuter(0)
        .ticks(15);

      zAxis = d3.axisLeft()
        .scale(zScale)
        .ticks(10)

      vis = canvas.append("svg:g")
        .attr("transform", "translate(25,25)")


      vis.append("svg:g")
        .call(zAxis)
        .attr("transform",
          "translate(" + (WIDTH + 30) + ",0)")
        .attr('y', 120 - MARGINS.left);

      vis.append("svg:g")
        .attr('class', 'line-transparent')
        .attr("width", WIDTH + MARGINS.left + MARGINS.right)
        .attr("height", HEIGHT + MARGINS.top + MARGINS.bottom)
        .attr("transform", "translate(25," + HEIGHT + ")")
        .call(xAxis);



      vis.append("svg:g")
        .call(yAxis)
        .attr('class', 'line-transparent')
        .attr("transform",
          "translate(" + MARGINS.left + ",0)")
        .attr('y', 20 - MARGINS.left);


      var zLineGen = d3.line()
        .x(function(d) {
          return xScale(parseTime(d.from)) + 30;
        })
        .y(function(d, name) {
          var names = Object.keys(d);
          return zScale(d[names[1]]);
        });

      if (dataArray.nodes2) {


        for (var i = 0; i < dataArray.nodes2.xAxis.length; i++) {
          dataArray.nodes2.xAxis[i] = parseTime(dataArray.nodes2.xAxis[i]);
        }
        dataArray.nodes2.xAxis.sort();

        // console.log(dataArray.nodes2.xAxis)

        x2Scale.domain(d3.extent(dataArray.nodes2.xAxis, function(d) {
          return d;
        }));
        x2Axis = d3.axisTop()
          .scale(x2Scale)
        vis.append("svg:g")
          .attr('class', 'line-transparent')
          .attr("width", WIDTH + MARGINS.left + MARGINS.right)
          .attr("height", HEIGHT + MARGINS.top + MARGINS.bottom)
          .attr("transform", "translate(25,0)")
          // .attr('y', 0)
          .call(x2Axis);

        makeLines(vis, dataArray.nodes2, 2)
          //makeLabels(dataArray.nodes2.options, 1, dataArray.nodes2.colors)
          //TODO separate it to function
        var line2 = vis.selectAll('.scale_2')
          .data(dataArray.nodes2.data);

        line2.each(function(d) {
            d.items.forEach(function(r) {
              var newNode = vis.append('g');
              newNode
                .attr('class', 'chart-dot')
                .append('text')
                .attr('x', function(el) {
                  var names = Object.keys(r);
                  var text = r.label + ': ' + r[names[1]];
                  var tWidth = getTextWidth(text, 10, 'Arial');
                  if (x2Scale(parseTime(r.from)) > WIDTH / 2) {
                    return x2Scale(parseTime(r.from)) - (tWidth + 10)
                  } else {
                    return x2Scale(parseTime(r.from)) + 30
                  }
                })
                .attr('y', function() {
                  var names = Object.keys(r);
                  if (r.price == true) {
                    return zScale(r[names[1]]);
                  } else {
                    return yScale(r[names[1]]);
                  }
                })
                .attr('font-size', '10')
                .attr('class', 'chart-dot-text')
                .text(function() {
                  var names = Object.keys(r);
                  //return r.from + ' - ' + r.label + ': ' + r[names[1]];
                });

              newNode.append('circle')
                .attr('cx', function() {
                  return x2Scale(parseTime(r.from)) + 30
                })
                .attr('cy', function() {
                  var names = Object.keys(r);
                  if (r.price == true) {
                    return zScale(r[names[1]]);
                  } else {
                    return yScale(r[names[1]]);
                  }
                })
                .attr('r', 5)
            })
          })
          //
      }

      makeLines(vis, data, 1)

      var line = vis.selectAll('.scale_1')
        .data(data.data);

      line.each(function(d) {
        d.items.forEach(function(r) {
          var newNode = vis.append('g');
          newNode
            .attr('class', 'chart-dot')
            .append('text')
            .attr('x', function(el) {
              var names = Object.keys(r);
              var text = r.label + ': ' + r[names[1]];
              var tWidth = getTextWidth(text, 10, 'Arial');
              if (xScale(parseTime(r.from)) > WIDTH / 2) {
                return xScale(parseTime(r.from)) - (tWidth + 10)
              } else {
                return xScale(parseTime(r.from)) + 30
              }
            })
            .attr('y', function() {
              var names = Object.keys(r);
              if (r.price == true) {
                return zScale(r[names[1]]);
              } else {
                return yScale(r[names[1]]);
              }
            })
            .attr('font-size', '10')
            .attr('class', 'chart-dot-text')
            .text(function() {
              var names = Object.keys(r);
              //return r.label + ': ' + r[names[1]];
            });

          newNode.append('circle')
            .attr('cx', function() {
              return xScale(parseTime(r.from)) + 30
            })
            .attr('cy', function() {
              var names = Object.keys(r);
              if (r.price == true) {
                return zScale(r[names[1]]);
              } else {
                return yScale(r[names[1]]);
              }
            })
            .attr('r', 5)
        })
      })

      function makeLines(vis, data, scale) {

        var i = 0;

        data.data.forEach(function(row) {

          if (scale == 1) {
            var stroke = colors[i];
          } else {
            var stroke = colors[(colors.length - 1) - i]
          }

          vis.append('svg:path')
            .attr('d', function(d) {
              if (row.price == true) {
                console.log(row.items)
                return zLineGen(row.items)
              } else {
                console.log(row.items)
                return lineGen(row.items, scale);
              }
            })
            .attr('stroke', stroke)
            .attr('stroke-width', 2)
            .attr('id', function() {
              if (scale == 1) {
                return row.name
              } else {
                return row.name + '_comparison'
              }
            })
            .attr('fill', 'none')
            .attr('class', 'chart-line scale_' + scale)
            .attr('data-scale', scale)
            .on('mousemove', function(d) {
              var x = xScale.invert(d3.mouse(this)[0]);
              var y = yScale.invert(d3.mouse(this)[1]);
            });
          i++;
        });
      }

      function lineGen(s, scale) {
        // console.log(scale)

        if (scale == 1) {
          var newlineGen = d3.line()
            .x(function(d) {
              return xScale(parseTime(d.from)) + 30;
            })
            .y(function(d, name) {
              var names = Object.keys(d);
              return yScale(d[names[1]]);
            });
        } else {
          var newlineGen = d3.line()
            .x(function(d, x) {
              //console.log(d)
              return x2Scale(parseTime(d.from)) + 30;
            })
            .y(function(d, name) {
              var names = Object.keys(d);
              return yScale(d[names[1]]);
            });
        }
        return newlineGen(s)
      }


      function getTextWidth(text, fontSize, fontFace) {
        var a = document.createElement('canvas');
        var b = a.getContext('2d');
        b.font = fontSize + 'px ' + fontFace;
        return b.measureText(text).width;
      }


      function mousemove() {
        var x0 = xScale.invert(d3.mouse(this)[0]);
        var y0 = yScale.invert(d3.mouse(this)[1]);
      };
    }
  </script>
</body>

</html>
&#13;
&#13;
&#13;