2015-02-25 3 views
0

Я пишу виджет, который отображает значение с возможностью анимировать новое значение, когда это необходимо. Частью отображения номера является возможность отображения символа. Например, процентный символ (%).Цепочки (синхронизация) зависимых переходов с использованием d3

Я смог правильно закодировать переходы, используя d3 и цвет. Значение отлично работает. Переход на цвет символа работает, однако переход для положения символа не синхронизирован.

В моем примере код демонстрирует случайные изменения значений. Но позиция символа всегда соответствует предыдущему случайному значению, а не текущему значению.

JSFiddle проблемы здесь: https://jsfiddle.net/metalskin/ektvL7kj/

Код выглядит следующим образом:

<!doctype html> 
<html style="height: 100%"> 
<head> 
    <meta charset="UTF-8"> 
    <title>Test Arc Graph</title> 
    <style> 
     body { 
     width: 100%; 
     height: 100%; 
     } 
     .mainDiv { 
     width: 100%; 
     height: 25%; 
     display: block; 
     overflow: hidden; 
     } 
     .widget { 
     width: 25%; 
     height: 100%; 
     float: left; 
     } 
     #numWidget { 
     width: 100%; 
     height: 100%; 
     } 
    </style>  
</head> 
<body> 
    <div class="mainDiv"> 
    <div id="widgetDiv" class="widget" /> 
    </div> 
    <script type="text/javascript" src="js/d3.min.js"></script> 
    <script> 

    var value = setValue(0, 0, false); 

    var svg = d3.select("#widgetDiv").append("svg") 
     .attr("id", "numWidget") 
     .attr("viewBox", "0 0 100 100") 
     .attr("perserveAspectRatio", "meet") 
     .append("g"); 

    var textInst = svg.append("text") 
     .attr("id", "numValue") 
     .attr("dx", 50) 
     .attr("dy", 50) 
     .text(value) 
     .attr("text-anchor", "middle") 
     .attr("dominant-baseline", "central") 
     .attr("font-family", "sans-serif") 
     .style("font-weight", "bold") 
     .style("font-size", "3em") 
     .attr("fill", determineForegroundColor(value)); 

    var symbolInst = svg.append("text") 
     .attr("id", "numSymbol") 
     .attr("dx", 51 + (textInst.node().getBBox().width/2)) 
     .attr("dy", 53) 
     .text("%") 
     .attr("text-anchor", "begin") 
     .attr("baseline-shift", "super") 
     .attr("font-family", "sans-serif") 
     .style("font-weight", "bold") 
     .style("font-size", "1em") 
     .attr("fill", determineForegroundColor(value)); 

    setInterval(function() { 
     var min = -120; 
     var max = 120; 
     // calc a int random value between min and max 
     var newValue = Math.floor(Math.random() * (max - min)) + min; 
     value = setValue(value, newValue, true, textInst, symbolInst); 
    }, 1500); 

    function determineForegroundColor(val) { 
     if(val <= 80) { 
     return "rgb(100,100,100)"; 
     } else if(val >= 100) { 
     return "rgb(200,50,50)"; 
     } 

     return "rgb(200,200,50)"; 
    } 

    function setValue(oldValue, newValue, redraw, textValueInst, symbolInst) { 
     var format = d3.format("f"); 

     if(redraw) { 
     (function(replacementValue, textInst) { 
      textInst.transition() 
      .duration(750) 
      .ease('linear') 
      .style("fill", determineForegroundColor()) 
      .tween('text', function() { 
       var ip = d3.interpolate(oldValue, replacementValue); 
       return function(t) { 
       this.textContent = format(ip(t)); 
       }; 
      }) 
//   .each(function() { 
//    d3.select(this); 
//    symbolInst 
//    .style("fill", determineForegroundColor()) 
//    .attr("dx", 51 + (textInst.node().getBBox().width/2)); 
//   }) 
      ; 

      symbolInst.transition() 
      .duration(750) 
      .ease('linear') 
      .style("fill", determineForegroundColor()) 
      .attr("dx", 51 + (textInst.node().getBBox().width/2)); 
     })(newValue, textValueInst); 
     } 

     return newValue; 
    };  

    </script> 
</body> 
</html> 

Закомментированный из кода является попытка использования each. Когда это раскомментировано, и переход непосредственно после этого прокомментирован, поведение не меняется. Я думал, используя each Я бы получил event во время перехода, чтобы я мог смещать символ на основе текущего значения текстового компонента значения. Я нашел несколько doco, которые предложили сделать d3.select(this), но я не мог понять, в чем проблема.

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

ответ

1

Вы можете группировать переходы текстового элемента и компенсировать знак% в функции tween.

textInst.transition() 
    .duration(750) 
    .ease('linear') 
    .style("fill", determineForegroundColor()) 
    .tween('text', function() { 
    var ip = d3.interpolate(oldValue, replacementValue); 
    return function(t) {     
     this.textContent = format(ip(t)); 
     symbolInst 
     .style("fill", determineForegroundColor()) 
     .attr("dx", 51 + (textInst.node().getBBox().width/2)); 
    }; 
    }); 

Вот ваши updated fiddle

+0

Спасибо за то ahmohamed, я знал, что это будет что-то вдоль этих линий. Моя ошибка заключалась в том, что я пытался использовать функцию «tween», а не внутри функции возврата внутри функции «tween». :-) – Metalskin

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