Теперь добавим второй график, а в качестве оси X используем шкалу временных отрезков:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://d3js.org/d3.v3.min.js"> </script> <style> .axis path, .axis line { fill: none; stroke: #333; } .axis .grid-line { stroke: #000; stroke-opacity: 0.2; } .axis text { font: 10px Arial; } </style> <body> <script type="text/javascript"> var height = 500, width = 600, margin=30, usdData = [ {date: new Date(2015, 02, 19), rate: 61.34}, {date: new Date(2015, 02, 24), rate: 59.44}, {date: new Date(2015, 02, 28), rate: 57.72}, {date: new Date(2015, 03, 3), rate: 56.99}, {date: new Date(2015, 03, 8), rate: 55.33}, {date: new Date(2015, 03, 11), rate: 51.06}, ], eurData = [ {date: new Date(2015, 02, 19), rate: 65.01}, {date: new Date(2015, 02, 24), rate: 64.15}, {date: new Date(2015, 02, 28), rate: 62.56}, {date: new Date(2015, 03, 3), rate: 61.69}, {date: new Date(2015, 03, 8), rate: 60.41}, {date: new Date(2015, 03, 11), rate: 54.27}, ]; var svg = d3.select("body").append("svg") .attr("class", "axis") .attr("width", width) .attr("height", height); // длина оси X= ширина контейнера svg - отступ слева и справа var xAxisLength = width - 2 * margin; // длина оси Y = высота контейнера svg - отступ сверху и снизу var yAxisLength = height - 2 * margin; // находим максимальное значение для оси Y var maxValue = d3.max([d3.max(eurData, function(d) { return d.rate; }), d3.max(usdData, function(d) { return d.rate; })]); // находим минимальное значение для оси Y var minValue = d3.min([d3.min(eurData, function(d) { return d.rate; }), d3.min(usdData, function(d) { return d.rate; })]); // функция интерполяции значений на ось Х var scaleX = d3.time.scale() // от 1 января 2015 года до текущей даты .domain([d3.min(usdData, function(d) { return d.date; }), d3.max(usdData, function(d) { return d.date; })]) .range([0, xAxisLength]); // функция интерполяции значений на ось Y var scaleY = d3.scale.linear() .domain([maxValue, minValue]) .range([0, yAxisLength]); // создаем ось X var xAxis = d3.svg.axis() .scale(scaleX) .orient("bottom") .tickFormat(d3.time.format('%e.%m')); // создаем ось Y var yAxis = d3.svg.axis() .scale(scaleY) .orient("left"); // отрисовка оси Х svg.append("g") .attr("class", "x-axis") .attr("transform", // сдвиг оси вниз и вправо "translate(" + margin + "," + (height - margin) + ")") .call(xAxis); // отрисовка оси Y svg.append("g") .attr("class", "y-axis") .attr("transform", // сдвиг оси вниз и вправо на margin "translate(" + margin + "," + margin + ")") .call(yAxis); // создаем набор вертикальных линий для сетки d3.selectAll("g.x-axis g.tick") .append("line") // добавляем линию .classed("grid-line", true) // добавляем класс .attr("x1", 0) .attr("y1", 0) .attr("x2", 0) .attr("y2", - (height - 2 * margin)); // рисуем горизонтальные линии d3.selectAll("g.y-axis g.tick") .append("line") .classed("grid-line", true) .attr("x1", 0) .attr("y1", 0) .attr("x2", xAxisLength) .attr("y2", 0); createChart(usdData, "steelblue", "usd"); createChart(eurData, "#FF7F0E", "euro"); // обща функция для создания графиков function createChart (data, colorStroke, label){ // функция, создающая по массиву точек линии var line = d3.svg.line() .x(function(d) { return scaleX(d.date)+margin; }) .y(function(d){return scaleY(d.rate)+margin;}); var g = svg.append("g"); g.append("path") .attr("d", line(data)) .style("stroke", colorStroke) .style("stroke-width", 2); // добавляем отметки к точкам svg.selectAll(".dot "+ label) .data(data) .enter().append("circle") .style("stroke", colorStroke) .style("fill", "white") .attr("class", "dot " + label) .attr("r", 3.5) .attr("cx", function(d) { return scaleX(d.date)+margin; }) .attr("cy", function(d) { return scaleY(d.rate)+margin; }); }; </script> </body> </html>
Для каждого графика определен свой массив данных: usdData и eurData. Чтобы автоматизировать построение оси Y по данным из этих массивов находится минимальное и максимальное значения:
var maxValue = d3.max([d3.max(eurData, function(d) { return d.rate; }), d3.max(usdData, function(d) { return d.rate; })]); var minValue = d3.min([d3.min(eurData, function(d) { return d.rate; }), d3.min(usdData, function(d) { return d.rate; })]);
Затем эти значения применяются для создания функции интерполяции значений на ось Y:
var scaleY = d3.scale.linear() .domain([maxValue, minValue]) .range([0, yAxisLength]);
На оси X будут располагаться даты, и так как даты обоих массивов совпадают, здесь просто берется минимальная и максимальная дата из первого массива. Хотя опять же можно было бы находить по двум и более массивам минимальную и максимальную даты.
При создании оси Х ее метки форматируются в определенный формат, а именно в формат '%e.%m' (день.месяц):
var xAxis = d3.svg.axis() .scale(scaleX) .orient("bottom") .tickFormat(d3.time.format('%e.%m'));
И так как для создания двух графиков нам надо выполнить фактически одни и те же действия, то весь функционал по их созданию выделяется в
дополнительную функцию createChart()
.