Масштаб в разных единицах

Как использовать D3 для преобразования и отображения нужной информации из разных единиц

Например

Все данные в mm..

[ 
    { label: 'sample1', x: 300 }, 
    { label: 'sample2', x: 1200 }, 
    { label: 'sample3', x: 4150 } 
]

Итак, вопрос в том, как я могу создать шкалу, которая понимает sample3 должен быть указан в том же месте после 4 и до 5.

Рассматривать

  1. 10000, это просто образец, может быть 102301 или любое значение
  2. Я хочу использовать шкалу D3, если это возможно, чтобы сделать это преобразование

попытка

let scaleX = d3.scale.linear().domain([-10, 10]).range([0, 500]) // Missing the mm information...

2 ответа

Решение

У вас есть концептуальная проблема здесь:

  • Отображение входа (домена) на выход (диапазон): это задача масштаба.
  • Форматирование числа и единицы (если есть) на оси: это задача генератора оси

Таким образом, в вашей шкале вам нужно настроить домен так, чтобы он принимал необработанные, фактические данные (то есть данные такими, какие они есть):

var scale = d3.scaleLinear()
    .domain([-10000, 10000])//the extent of your actual data
    .range([min, max]);

И в генераторе весов вы меняете значение на дисплее. Здесь я просто делю его на 1000 и добавляю "мм":

var axis = d3.axisBottom(scale)
    .tickFormat(d => d / 1000 + "mm");

Обратите внимание, что я использую D3 v4 в этих фрагментах.

Вот демонстрация с использованием этих значений: -7500, 500 и 4250. Вы можете видеть, что круги находятся в адекватном положении, но ось показывает значения в мм.

var data = [-7500, 500, 4250];

var svg = d3.select("body")
  .append("svg")
  .attr("width", 500)
  .attr("height", 200);

var scale = d3.scaleLinear()
  .domain([-10000, 10000])
  .range([20, 480]);

var axis = d3.axisBottom(scale)
  .tickFormat(d => d / 1000 + "mm");

var circles = svg.selectAll("foo")
  .data(data)
  .enter()
  .append("circle")
  .attr("r", 4)
  .attr("fill", "teal")
  .attr("cy", 40)
  .attr("cx", d => scale(d));

var g = svg.append("g")
  .attr("transform", "translate(0,60)")
  .call(axis);
<script src="https://d3js.org/d3.v4.js"></script>

Я нашел способ сделать это..

const SIZE_MM = 10000
const SIZE_PX = 500
const scaleFormat = d3.scale.linear().domain([0, SIZE_MM]).range([-10, 10])
const ticksFormat = d => Math.round(scaleFormat(d))
const ticks = SIZE_MM / SIZE_PX 

const lineScale = d3.scale.linear().domain([0, SIZE_MM ]).range([0, SIZE_PX])
lineScale(9500)
// 475
Другие вопросы по тегам