d3.js反向转换不起作用

时间:2016-10-07 15:45:46

标签: javascript html d3.js transform

我正在处理水平段条形图。我想这样做,条形图将根据每隔几秒随机生成的值为各个段之间的颜色过渡设置动画。

我还有一个文本框,现在说"你好"并且它与过渡同时移动。它仅从左到右在一个方向上起作用。 我不能在段之间进行颜色转换并从左到右翻译文本框。从左到右我的意思是上次生成的数字大于当前生成的数字。条形图应该从右到左关闭段。但它从左到右也是这样做的,当涉及到反向翻译时,文本框也很奇怪。

我也遇到了这个错误:g属性转换:预期的转换函数," null"。在我的代码中,我想在我的valueLabel上进行转换,我认为我使用的方式不正确。尽管出现此错误,代码仍会执行。 我的小提琴代码是here

非常感谢您的建议

var configObject = {

    svgWidth : 1000,
    svgHeight : 1000,


    minValue : 1,
    maxValue : 100,

    midRange : 50,
    highRange : 75,

    numberOfSegments : 50
};
//define variables
var newValue;
var gaugeValue = configObject.minValue - 1;
var mySegmentMappingScale;
var rectArray=[];


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

//var myG=svg.append('g');
var valueLabel= svg.append("text")
    .attr('x',0)
    .attr('y', (configObject.svgHeight/13)+15)
    .text("hello");

var backgroundRect=svg.append("rect")
    .attr("fill", "black")
    .attr("x",0) 
    .attr("y", 0)
    .attr("width", (configObject.svgWidth/3))
    .attr("height",  configObject.svgHeight/13);

for(i = 0; i <= configObject.numberOfSegments; i++){
    var myRect=svg.append("rect")
        .attr("fill", "#2D2D2D")
        .attr("x",i * ((configObject.svgWidth/3)/configObject.numberOfSegments)) 
        .attr("y", 0)
        .attr("id","rect"+i)
        .attr("width", ((configObject.svgWidth/3)/configObject.numberOfSegments)-3)
        .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);

    }

//generate random number
function generate(){
    var randomNumber = Math.random() * (configObject.maxValue - configObject.minValue) + configObject.minValue;     
    newValue = Math.floor(randomNumber);
    setmySegmentMappingScale(); 
    animateSVG();
}     
function animateSVG(){

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

    if(previousSegment <= -1 && newSegment > -1){
        for(i = 0; i <= newSegment; i++){ 

            rectArray[i].transition()
                .ease("linear")
                .duration(50)
                .delay(function(d){return i * 90})
                .styleTween("fill", function() { return d3.interpolate( "#2D2D2D","red"); });

                valueLabel
                .transition().ease("linear")
                .duration(50)
                .delay(function(d){return i * 90})
                .attr("transform","translate(" + (i * ((configObject.svgWidth/3)/configObject.numberOfSegments)+((configObject.svgWidth/3)/configObject.numberOfSegments)) + "," + 0 + ")")


        }
    }
    else if(newSegment > previousSegment){

        for(i = previousSegment; i <= newSegment; i++){
            rectArray[i].transition()
                        .ease("linear")
                        .duration(50)
                        .delay(function(d){return i * 90})
                         .styleTween("fill", function() { return d3.interpolate( "#2D2D2D","red"); });
            //console.log(temp);
            valueLabel
            .transition()
            .ease("linear")
            .duration(50)
            .delay(function(d){return i * 90})
            .attr("transform","translate(" + (i * ((configObject.svgWidth/3)/configObject.numberOfSegments)+((configObject.svgWidth/3)/configObject.numberOfSegments)) + "," + 0 + ")")




        }
    }
    else if(newSegment < previousSegment){

        for(i = previousSegment; i > newSegment; i--){

            rectArray[i].transition()
                        .ease("linear")
                        .duration(50)
                        .delay(function(d){return i * 90})
                        .styleTween("fill", function() { return d3.interpolate( "red","#2D2D2D"); });


                        valueLabel
                        .transition()
                        .ease("linear")
                        .duration(50)
                        .delay(function(d){return i * 90})
                        .attr("transform","translate(" + (i * ((configObject.svgWidth/3)/configObject.numberOfSegments)-((configObject.svgWidth/3)/configObject.numberOfSegments)) + "," + 0 + ")")

        }
    }   
     gaugeValue = newValue;

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

1 个答案:

答案 0 :(得分:0)

问题只是delay

newSegment > previousSegment时,您可以设置延迟:

.delay(function(d){return i * 90})

这是有道理的,因为i是一个不断增加的变量。但是,当newSegment < previousSegment相同的数学不再有效时:i是一个递减变量,延迟必须随i 减少而增加,不是相反。

这就是你需要的:

.delay(function(d){return Math.abs(i -previousSegment)*90})

这是您更新的小提琴:https://jsfiddle.net/b7usw2nr/