代码之家  ›  专栏  ›  技术社区  ›  MagTun

基于for循环的索引查找十进制指数

  •  2
  • MagTun  · 技术社区  · 6 年前

    用户选择一个数字,然后选择d3。js应该显示尽可能多的圆。 我有一个数组,用于为圆指定颜色:

    var color =["red","blue", "yellow", "orange",....., ] 
    

    如果用户选择593,则前500个圆圈应为红色( color[0] ),下一个90应为蓝色( color[1] )最后3个( color[2] )应为黄色,因为

    593= 500+90+3 = 5*10^2+9*10^1+3*10^0 
    

    或 具有

    var number = 593
    var number_as_array = number.toString().split(''); 
    

    然后

    593 = 5*number_as_array[0]*10^number_as_array.length-0-1 + 9*number_as_array[1]*10^number_as_array.length-1-1+ 3*number_as_array[2]*10^number_as_array.length-2-1
    

    如果用户选择4168,则前4000个圆圈应为红色,下100个应为蓝色,下60个为黄色,最后8个为橙色

    为了给每个圆指定颜色,我使用它创建了一个带有for循环的JS对象构建数组

    var data=[]
    for (index =0; index< number; index++){
    circle= {};
            circle.cx = circle_x;
            circle.cy = circle_y;
            circle.color = color[????]
            data.push(circle);
    

    如何将颜色指定给 circle.color 基于上述情况?

    4 回复  |  直到 6 年前
        1
  •  2
  •   Andrew Reid    6 年前

    为了不削弱另一个答案,这里有一个替代方法。

    取一个给定的总圆圈数,它会检查总圆圈数中需要多少有效数字(向下舍入),以便任何给定的索引都小于四舍五入的总数。

    我不确定这是否完全有意义,因此我将使用一个示例:

    如果总共有132个圆:

    • 索引0到99将小于100(132向下舍入一个有效数字)。

    • 索引100到129将小于130(132用两个有效数字向下舍入)。

    • 索引130和131将小于132(132包含所有有效数字)。

    下面是一个快速演示(行是50个圆圈):

    var svg = d3.select("body")
      .append("svg")
      .attr("width",510)
      .attr("height",510);
      
    var n = 377;
    
    var color = d3.scaleOrdinal()
    .range(["steelblue","orange","crimson","lawngreen","pink"])
    
    var digits = Math.floor(Math.log10(n));
    
    var circles = svg.selectAll("circle")
      .data(d3.range(n))
      .enter()
      .append("circle")
      .attr("cx",function(d,i) { return i%50 * 10 + 5 })
      .attr("cy",function(d,i) { return Math.floor(i/50) * 10 + 5 })
      .attr("r",5)
      .attr("fill", function(d,i) {
        var exp = digits;
        while (i < Math.floor(n/Math.pow(10,digits-exp))*Math.pow(10,digits-exp)) {
          exp--;
        }
        return color(exp);
      })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
        2
  •  2
  •   bcr666    6 年前
    var color = ["red","orange", "yellow", "green", "blue", "indigo", "violet"];
    var circleCount = "4192"; // use string
    var length = circleCount.length;
    var counter = [];
    for (var i = 0; i < length; i++) {
        var digit = circleCount.substring(i, i+1);
        var exponent = length - i - 1;
        var number = digit * Math.pow(10, exponent);
        counter.push(number); // might have to use .unshift instead of .push
    }
    console.log(counter);
    for (var i = 0; i < counter.length; i++) {
        for (var j = 0; j < counter[i]; j++) {
            drawCircle(color[i]);
        }
    }
    
        3
  •  2
  •   SteveR    6 年前

    这是使用D3的完美案例 Threshold Scales :在需要颜色之间的分隔处为其指定N个数字,并为任何输入值返回N+1个颜色。以下是文档中的示例:

    var color = d3.scaleThreshold()
        .domain([0, 1])
        .range(["red", "white", "green"]);
    
    color(-1);   // "red"
    color(0);    // "white"
    color(0.5);  // "white"
    color(1);    // "green"
    color(1000); // "green"
    

    因此,您的案例面临的挑战是如何(例如)将示例输入593转换为两个数字的数组[500590]:

    var sinput = 593 + ""; // make the input a string
    var digits = sinput.split("").slice(0, -1); // use all digits but the last one
    var breaks = digits.map((d, i, a) =>
        +(a.slice(0, i+1).join("")) * Math.pow(10, a.length-i)
    );
    
    var colors = ["red", "blue", "yellow", "orange"];
    var tScale = d3.scaleThreshold()
        .domain(breaks)
        .range(colors);
    

    任何内容(<500张地图变为“红色”,从500-589张地图变为“蓝色”,以及≥ 590映射为“黄色”。除非使用4位数字作为输入,否则不使用附加范围颜色(“橙色”)。

    注:此逻辑假定输入编号至少有2位数字。

    现在,您可以在创建圆时指定颜色,而不是在数据数组中预先填充它,使用如下语法 .attr("color", (d, i) => tScale(i))

        4
  •  1
  •   RobG    6 年前

    其他方法似乎过于复杂。您可以将数字拆分为数字,然后根据索引创建所需的带颜色的10^digitIndex圆。我加了一行代码来检查数字是否太大。

    function mapColors(num) {
      var color =['red','blue', 'yellow', 'orange'];
      
      // If the number is longer than the color array, return undefined
      if ((''+num).length > color.length) return;
      
      return (''+num).split('').reduce(function (acc, n, i, arr) {
        for (var j=n*Math.pow(10, arr.length-i-1); j; --j) {
          acc.push({'color':color[i]});
          // Add more circle properties here
        }
        return acc;
      }, []);
    }
    
    console.log(mapColors(23));