Теперь добавим к горизонтальной оси и вертикальную, чтобы образовалась полноценная координатная плоскость.
<!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; shape-rendering: crispedges; stroke-opacity: 0.2; } .axis text { font: 10px Verdana; } </style> <body> <script type="text/javascript"> var height = 500, width = 500, margin = 30; 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; // функция интерполяции значений на ось Х var scaleX = d3.scale.linear() .domain([0, 100]) .range([0, xAxisLength]); var scaleY = d3.scale.linear() .domain([100, 0]) .range([0, yAxisLength]); // создаем ось X var xAxis = d3.svg.axis() .scale(scaleX) .orient("bottom"); var yAxis = d3.svg.axis() .scale(scaleY) .orient("left"); // отрисовка оси svg.append("g") .attr("class", "x-axis") .attr("transform", // сдвиг оси вниз и вправо "translate(" + margin + "," + (height - margin) + ")") .call(xAxis); 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", - (yAxisLength)); // рисуем горизонтальные линии 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); </script> </body> </html>
Здесь мы не устанавливаем количество делений с помощью метода ticks
и при делении осей на отрезки полностью полагаемся на d3.js,
которая поделит оси на интервалы автоматически, причем по оси X откладывается столько же делений, сколько и по оси Y:
var xAxis = d3.svg.axis() .scale(scaleX) .orient("bottom"); var yAxis = d3.svg.axis() .scale(scaleY) .orient("left");
Но при необходимости мы также могли бы настроить деление оси: d3.svg.axis().scale(scaleX).orient("bottom").ticks(5)
Чтобы горизонтальная ось должным образом соприкасалась с вертикальной, надо сместить ее вниз по вертикали на величину, равную длине вертикальной, и соответственно у обеих осей будет одно и то же смещение по горизонтали:
svg.append("g") .attr("class", "x-axis") .attr("transform", // сдвиг оси вниз и вправо "translate(" + margin + "," + (height - margin) + ")") .call(xAxis);
Затем получаем выше добавленный элемент и выбираем в нем все элементы g.tick
, которые добавляются автоматически и представляют отдельные деления,
и добавляем по ним линии с помощью элемента line
:
d3.selectAll("g.x-axis g.tick") .append("line") // добавляем линию .classed("grid-line", true) // добавляем класс .attr("x1", 0) .attr("y1", 0) .attr("x2", 0) .attr("y2", - (yAxisLength));
Каждая линия задается двумя точками с координатами (x1, y1) - начальная точка и (x2, y2) - конечная точка. Если первая точка определяется на оси X, то для определения y-составляющей второй точки используется yAxisLength, что аналогично выражению (height - 2 * margin). То есть линия будет идти с оси X вверх.
Построение горизонтальных линий будет аналогично.
Если мы обратимся к графику в инспекторе элементов, то увидим его сложную структуру: