переход d3 js по массиву прямоугольников не работает

#javascript #d3.js #transition

#javascript #d3.js #переход

Вопрос:

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

В начале я установил две переменные среднего и высокого диапазона, которые разделяют мои сегменты на 3 группы — зеленые, желтые и красные. Затем я создаю 2 массива. rectArrays содержит мои сегменты / прямоугольники. colorArray содержит цвет для каждого прямоугольника.

В функции animate() я использую эти массивы для целей перехода. На данный момент первые 25 сегментов должны быть анимированы как зеленые, затем несколько желтых, а остальные сегменты должны быть красными. Переход между цветами не работает, когда должно быть включено более 25 сегментов. Все они либо желтые, либо красные. Похоже, что переход запоминает только цвет, который сохраняется в последнем индексе перед выходом из цикла for в моей функции animate. Есть 3 случая, когда анимация может идти слева направо и наоборот.

На этом рисунке показан нежелательный эффект.Первая половина сегментов должна быть зеленой, а остальные 5 желтыми. Но по какой-то причине все они желтые. Вот мой скрипичный код

Спасибо за любые предложения

 var configObject = {

    svgWidth : 1000,
    svgHeight : 500,


    minValue : 1,
    maxValue : 100,

    midRange : 50,
    highRange : 75,

    numberOfSegments : 50
};
//define variables
var newValue;
var gaugeValue = configObject.minValue - 1;
var mySegmentMappingScale;
var reverseScale;
var rectArray=[];
var segmentIndex=configObject.maxValue/configObject.numberOfSegments;
var dynamicArc=true;
var staticArc="yellow";
var gradientArray=[];
var colorArray=[];
var rectWidth=(configObject.svgWidth/1.5)/configObject.numberOfSegments;
var rectPadding=3;


getColor();
setmySegmentMappingScale(); 
//define svg
var svg = d3.select("body").append("svg")
    .attr("width", configObject.svgWidth)
    .attr("height", configObject.svgHeight)
    .append("g")
    .attr("transform", 'translate('  0  ','   configObject.svgHeight/2   ')');


var valueLabel= svg.append("text")
    .attr('x',0)
    .attr('y', (configObject.svgHeight/13) 15)
    .attr('transform',"translate("   0   ","   0   ")")
    .text(configObject.minValue)
    .attr('fill', "white");




    var HueGreenIndex=1;
    var HueYellowIndex=1;
    var HueRedIndex=1;
    function addGradient(c){
        //debugger
         if (c=="green"){
             var hslString =d3.hsl(HueGreenIndex   160, .40, .29).toString();
                HueGreenIndex=HueGreenIndex 0.5;
                return hslString; 
         }
        else if(c=="yellow"){
            var hslString=d3.hsl(HueYellowIndex   39, .67, .57).toString();
                HueYellowIndex=HueYellowIndex 0.5;
                return hslString;

        }
        else if (c=="red"){
            var hslString=d3.hsl(1 HueRedIndex , 1, .58).toString();
                HueRedIndex=HueRedIndex 0.10;
             return hslString;  

        }
    }

    function getColor(){
            if (dynamicArc){

                for(i = 0; i <= configObject.numberOfSegments; i  ){
                   if(i<=(configObject.numberOfSegments/100)*configObject.midRange){

                        //gradientArray.push(addGradient("green"));
                        colorArray.push("green");
                    }
                    else if(i > ((configObject.numberOfSegments/100)*configObject.midRange) amp;amp; i<= ((configObject.numberOfSegments/100)*configObject.highRange)){
                        //gradientArray.push(addGradient("yellow"));
                        colorArray.push("yellow");
                    }
                    else if (i > ((configObject.numberOfSegments/100)*configObject.highRange)){
                        //gradientArray.push(addGradient("red"));
                        colorArray.push("red");
                    }

                }
            }
            else{
                if (staticArc=="green"){
                    //gradientArray.push(addGradient("green"));
                    colorArray.push("green")
                }
                else if(staticArc=="yellow"){
                    //gradientArray.push(addGradient("yellow"));
                    colorArray.push("yellow")
                }
                else {
                    //gradientArray.push(addGradient("red"));
                    colorArray.push("red")
                }
            }

    }


    for(i = 0; i <= configObject.numberOfSegments; i  ){
        var myRect=svg.append("rect")
            .attr("fill", "#2D2D2D")
            .attr("x",i * rectWidth) 
            .attr("y", 0)
            .attr("id","rect" i)
            .attr("width", rectWidth-rectPadding)
            .attr("height",  configObject.svgHeight/13);    

             rectArray.push(myRect);

        }
//define scale
    function setmySegmentMappingScale(){
            var domainArray = [];
            var x=0;
            for(i = configObject.minValue; i <= configObject.maxValue 1; i = i   (configObject.maxValue - configObject.minValue)/configObject.numberOfSegments){
              if(Math.floor(i) != domainArray[x-1]){ 
                   var temp=Math.floor(i);
                   domainArray.push(Math.floor(i));
                   x  ;
               }
           }

            var rangeArray = [];
            for(i = 0; i <= configObject.numberOfSegments 1; i  ){//  <=
                rangeArray.push(i);
            }
            mySegmentMappingScale = d3.scale.threshold().domain(domainArray).range(rangeArray);
            reverseScale= d3.scale.threshold().domain(rangeArray).range(domainArray);

        }
    function widgetScale (x,y,r){   
        return (x*r)/y;
    }
//generate random number
    function generate(){
        var randomNumber = Math.random() * (configObject.maxValue - configObject.minValue)   configObject.minValue;     
        newValue = Math.floor(randomNumber);
        animateSVG();
    }



    function animateSVG(){

    var previousSegment = mySegmentMappingScale(gaugeValue) -1;
    var newSegment = mySegmentMappingScale(newValue) -1;


        if(previousSegment <= -1 amp;amp; newSegment > -1){

            for(i = 0; i <= newSegment; i  ){ 
            var temp=colorArray[i];

                rectArray[i].transition()
                    .ease("linear")
                    .duration(50)
                    .delay(function(d){return i * 90})
                    .styleTween("fill", function() { return d3.interpolateRgb( getComputedStyle(this).getPropertyValue("fill"), temp );});

                valueLabel.transition()
                    .ease("linear")
                    .duration(50)
                    .delay(function(d){return i * 90})
                    .text(i==newSegment ? newValue : i*segmentIndex);

                valueLabel.transition()
                    .ease("linear")
                    .duration(50)
                    .delay(function(d){return i * 90})
                    .attr("transform","translate("   (i * (rectWidth) (rectWidth))   ","   0   ")")

            }
        }
        else if(newSegment > previousSegment){

            for(i = previousSegment; i <= newSegment; i  ){

            var temp=colorArray[i];
                rectArray[i].transition()
                    .ease("linear")
                    .duration(50)
                    .delay(function(d){return i * 90})
                    .styleTween("fill", function() { return d3.interpolateRgb( getComputedStyle(this).getPropertyValue("fill"),temp);});

                valueLabel.transition()
                    .ease("linear")
                    .duration(50)
                    .delay(function(d){return i * 90})
                    .text(i==newSegment ? newValue : i*segmentIndex);

                valueLabel.transition()
                    .ease("linear")
                    .duration(50)
                    .delay(function(d){return i * 90})
                    .attr("transform","translate("   (i * (rectWidth) (rectWidth))   ","   0   ")")

            }
        }
        else if(newSegment < previousSegment){


            for(i = previousSegment; i > newSegment; i--){
            var temp=colorArray[i];

                rectArray[i].transition()
                    .ease("linear")
                    .duration(50)
                    .delay(function(d){return Math.abs(i -previousSegment)*90})
                    .styleTween("fill", function() { return d3.interpolateRgb( getComputedStyle(this).getPropertyValue("fill"),"#2D2D2D"); });

                valueLabel.transition()
                    .ease("linear")
                    .duration(50)
                    .delay(function(d){return Math.abs(i -previousSegment)*90})
                    .text(i==newSegment 1 ? newValue : i*segmentIndex);          

                valueLabel.transition()
                    .ease("linear")
                    .duration(50)
                    .delay(function(d){return Math.abs(i -previousSegment)*90})
                    .attr("transform","translate("   (i * (rectWidth)-(rectWidth))   ","   0   ")")

            }
        }   
     gaugeValue = newValue;

    }


setInterval(function() {
   generate()
}, 6000);
  

Ответ №1:

Если вы хотите, чтобы каждый styleTween получал отдельный i экземпляр, вам придется использовать let , а не var .

Просто измените:

 var temp = colorArray[i];
  

Для:

 let temp = colorArray[i];
  

Вот обновленная скрипка: https://jsfiddle.net/x2mL97x7 /

Комментарии:

1. Еще раз спасибо Джеральдо Фуртадо. Все работает так, как ожидалось. Понятия не имел, что я мог бы использовать let вместо var.