2016-10-06 2 views
2

Я очень внимательно слежу за this post о переходах линии D3, реализуя что-то похожее на this, за исключением наличия переходов по оси.D3 Масштабирование оси оси и переход к траектории

Конечная цель - отображать точки данных в реальном времени.

Я определил ось, например, так:

var x = d3.time.scale() 
    .domain([now - (n - 2) * duration, now - duration]) 
    .range([0, width]); 

var y = d3.scale.linear() 
    .range([height, 0]) 
    .domain([0, 100]) 

var axisx = svg.append('g') 
    .attr('class', 'x axis') 
    .attr('transform', `translate(0, ${height})`) 
    .call(x.axis = d3.svg.axis().scale(x).orient('bottom').tickPadding(10)); 

var axisy = svg.append('g') 
    .attr('class', 'y axis') 
    .attr('transform', `translate(${width}, 0)`) 
    .call(y.axis = d3.svg.axis().scale(y).orient('right').tickPadding(10)); 

И линия так:

var line = d3.svg.line() 
    .interpolate('basis') 
    .x(function(d, i) { return x(now - (n - 1 - i) * duration); }) 
    .y(function(d, i) { return y(d); }); 

Я добавляю переходную функцию, как связанные с должностями переговоры о переходе на точки по горизонтали со временем:

(function tick() { 

    transition = transition.each(function() { 

     // Update the domain of the x-axis 
     now = new Date(); 
     x.domain([now - (n - 2) * duration, now - duration]); 

     // Push the new data point 
     data.push(temperature); 

     // Redraw the line 
     svg.select('.line') 
      .attr('d', line) 
      .attr('transform', null); 

     // Slide the x-axis left 
     axisx.call(x.axis); 

     // Slide the line left 
     path.transition() 
      .attr('transform', `translate(${x(now - (n - 1) * duration)})`); 

     // Pop the old data point off the front 
     data.shift(); 

    }).transition().each('start', tick); 
})(); 

До сих пор все хорошо работает, когда домен оси Y фиксирован. Я хотел, чтобы динамически изменять размер домена и маркировки оси Y, поэтому я добавил следующие функции перехода:

y.domain([ 
    Math.min.apply(Math, data) - 10, 
    Math.max.apply(Math, data) + 10 
]) 
axisy.call(y.axis); 

И, в то время как масштаб по оси Y, кажется, правильно настроить, там это заметно глюк эффект, когда линия перерисовывается каждый раз, когда функция перехода напомнить (не между каждой переходной функцией клеща):

Chart Redraw Glitch

Очевидно, что проблема в том, что я не анимировать вертикальное перемещение линии между фазами. Итак, первый вопрос: есть ли простой способ в D3 сделать это?

Я понимаю, что настройка домена на основе максимального и минимального количества данных представляет собой проблему, потому что больше не происходит последовательное переключение данных, это также масштабирование.

Так что я думаю, что я, вероятно, конец того, чтобы рассчитаться с установкой домена следующим образом:

y.domain([temperature - 10, temperature + 10]); 

Где окно фиксируется. Тогда я думаю, что придется изменить переход так, что он имеет атрибут:

.attr('transform', `translate(${x(now - (n - 1) * duration)}, ${y(data[1] - data[0]}))`); 

Я могу видеть, что это transform будет вызывать соответствующую y функцию line, но я не знаю, как я должен переопределить его. Я пробовал:

.y(function(d, i) { return y(d/i); }); 

Но это не работает.

Как я могу заставить эти линейные переходы работать? Большое спасибо за вашу помощь, и я приношу свои извинения за столь глубокий и длительный вопрос.

Link to full gist of code.

+0

Привет, Джеймс, хороший пример. Вы фиксировали свой смысл с тех пор, как вы разместили этот вопрос? Я скопировал ваш код и не сталкивался с проблемой, которую вы описываете в своем вопросе. Посмотрите сами (извините за уродливый стиль css): https://bl.ocks.org/phvaillant/ff9135e0b03d76d67c368b5c7477f402 –

+0

Спасибо за ответ! Наверное, я плохо работал, объясняя, что происходит. Возьмите тот же смысл, который вы только что создали, и добавьте 'y.domain ([Math.min.apply (Math, data) - 10, Math.max.apply (Math, data) + 10]); axisy.call (y.axis); 'в цикле перехода/анимации, и вы увидите проблему, о которой я говорю. Суть, которую я предоставил, - это просто базовый код, поверх которого я пытаюсь различными способами анимировать линию вертикально по мере изменения области оси y (которая сама имеет плавный переход). –

+0

Я вижу, мой плохой. Я также заинтересован в ответе, если кто-то найдет один (рассмотрен вопрос). Этот эффект глюка сопротивляется всем моим попыткам. –

ответ

0

EDIT: я понял, что моя старая методология была неправильно во многих случаях, и удалены примеры кода/вычисления. Я обновлю, когда смогу выяснить, что пошло не так ...

Это крутая проблема. Пример, на который вы ссылаетесь (Майк Босток), просто интерполирует перевод в направлении X, чтобы плавно сдвигать кривую влево, когда она обновляется.Однако в вашем примере вы также хотите изменить масштаб оси Y в реальном времени -

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

Вы можете сделать все это с помощью преобразования [SVG Matrix] [1]. Вам просто нужно выяснить, каковы ваши константы (a, b, c, d, e, f). Их можно рассчитать, используя старые и новые шкалы.

+0

Я серьезно ценю ваш ответ! Я рассмотрю матричные преобразования. Я проверил образцы кода, которые вы предоставили, и они, похоже, работали, поэтому я не уверен, где вы заметили неправильные вычисления. Я еще поиграю с этим. –

+0

Перевод, казалось, работал правильно, но масштабирование было выключено и вызывало артефакты, похожие на то, что вы изначально видели. Я думаю, что мой оригинальный образец, казалось, работал, потому что он не масштабировал ось Y, а просто менял его. – Joel

Смежные вопросы