Удаление пустого пространства по оси D3

1

Я создаю линейную диаграмму с d3js. Некоторые данные перекрывают друг друга. Как это:

Изображение 174551

(См. Эти 4 строки внизу). Вот как выглядят эти 4 строки после удаления остальных строк:

Изображение 174551

Я хочу, чтобы как-то удалить эти пустые вертикальные пространства, где нет данных.

Любой возможный способ сделать это?

  • 0
    Можете ли вы предоставить код или ссылку на jsfiddle?
  • 0
    Кстати, посмотрите на этот пример. Может быть, это даст вам какие-либо идеи, как решить вашу задачу: bl.ocks.org/d3noob/e34791a32a54e015f57d
Показать ещё 2 комментария
Теги:
d3.js
svg
charts
visualization

2 ответа

0
Лучший ответ

То, что вы хотите, это сломанная ось Y. Что-то вроде этого:

Изображение 174551

Прежде чем мы продолжим, очень важно, чтобы вы сказали пользователю, что ось разбита, четко и явно. И добавьте символ на ось, показывая, что он сломан:

Изображение 174551

В противном случае вы лежите с данными!

Вернемся к вашему вопросу: чтобы создать сломанную ось Y, вам просто нужно добавить середины к вашей шкале y (как в домене, так и в диапазоне).

Давайте посмотрим на это в демо. Это базовая диаграмма, вы можете видеть, что на нижнем конце есть цепочка строк (от 0 до 12 по оси y), как и ваша диаграмма:

var w = 400, h = 300;
var data = [1, 3, 4, 7, 10, 11, 12, 160, 180, 210, 230];
var svg = d3.select("body")
	.append("svg")
  .attr("width", w)
  .attr("height", h);
var scale = d3.scaleLinear()
	.domain([0, 230])
  .range([h - 4, 4]);
var colors = d3.scaleOrdinal(d3.schemeCategory10);
var lines = svg.selectAll(null)
	.data(data)
  .enter()
  .append("line")
  .attr("x1", 30)
  .attr("x2", w)
  .attr("y1", function(d){ return scale(d)})
  .attr("y2", function(d){ return scale(d)})
  .style("stroke", function(d, i){ return colors(i)})
  .style("shape-rendering", "crispEdges");
var axis = d3.axisLeft(scale)(svg.append("g").attr("transform", "translate(30,0)"))
<script src="https://d3js.org/d3.v4.min.js"></script>

Очень сложно рассказать об этом здесь. Итак, позвольте сломать ось Y, создав средние точки в масштабе. В моей демонстрации я сделал это:

var scale = d3.scaleLinear()
    .domain([0, 15, 150, 230])
    .range([h - 4, h / 2 , h / 2, 4]);

Это означает, что все значения от 15 до 150 будут расположены в одной и той же точке шкалы.

Вот результат, используя те же данные:

var w = 500,
  h = 400;
var data = [1, 3, 4, 7, 10, 11, 12, 160, 180, 210, 230];
var svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("height", h);
var scale = d3.scaleLinear()
  .domain([0, 15, 150, 230])
  .range([h - 4, h / 2, h / 2, 4]);
var colors = d3.scaleOrdinal(d3.schemeCategory10);
var lines = svg.selectAll(null)
  .data(data)
  .enter()
  .append("line")
  .attr("x1", 30)
  .attr("x2", w)
  .attr("y1", function(d) {
    return scale(d)
  })
  .attr("y2", function(d) {
    return scale(d)
  })
  .style("stroke", function(d, i) {
    return colors(i)
  })
  .style("shape-rendering", "crispEdges");
var axis = d3.axisLeft(scale).tickValues([0, 5, 10, 15, 160, 180, 200, 220])(svg.append("g").attr("transform", "translate(30,0)"))
<script src="https://d3js.org/d3.v4.min.js"></script>

Конечно, я должен был установить значения тика явно.

0

Нелинейное масштабирование может решить вашу проблему.
Например, .scalePow или .logScale вместо.scaleLinear:

var y = d3.scalePow()
  .exponent(0.3)
  .domain([0, 1000, 10000, 60000])
  .range([height, 0]);

См. Обновленный скрипт.

  • 0
    Я пытался поиграть с этим, но я считаю, что он не работает для моего набора данных. Может быть, это как-то связано с моей осью X в формате datetime? Вот как выглядят мои данные -> i.imgur.com/yDb8Fl8.png
  • 0
    Разве предоставленная вами скрипка не содержит ваш набор данных?
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню