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

进度条:如何根据进度进行颜色转换?

  •  3
  • SkyWalker  · 技术社区  · 6 年前

    我一直在寻找一个d3 js进度条,这是我找到的最佳匹配: https://bl.ocks.org/sarahob/1e291c95c4169ddabb77bbd10b6a7ef7

    然而,这是一个具有三种状态的有序域,很难在实际应用程序中重用。我想以一种方式改变它,不管我把它增加到多少个任意的百分比;说黄色到绿色之间的颜色将根据新的进展/高度成比例地改变。怎么能做到?

    2 回复  |  直到 6 年前
        1
  •  3
  •   Gerardo Furtado    6 年前

    d3有一系列非常有用的颜色方法(你可以 see here )和配色方案(你可以 see here )

    但是,您所要求的可以用一个简单的线性比例来实现,如(d3 v3,如您的示例中所示):

    var colorScale = d3.scale.linear()
        .range(['yellow', 'limegreen']);
    

    因为我们没有设置域名 [0, 1] 默认情况下,这很方便,因为我们的进度从0%到100%。

    您还可以使用三种颜色,相应地设置域:

    var colorScale = d3.scale.linear()
        .domain([0, 0.5, 1])
        .range(['yellow', 'orange', 'limegreen']);
    

    下面是演示:

    var svg = d3.select('body')
      .append('svg')
      .attr('height', 100)
      .attr('width', 500);
    
    var segmentWidth = 300;
    
    var colorScale = d3.scale.linear()
      .domain([0, 0.5, 1])
      .range(['yellow', 'orange', 'limegreen']);
    
    svg.append('rect')
      .attr('class', 'bg-rect')
      .attr('rx', 10)
      .attr('ry', 10)
      .attr('fill', 'gray')
      .attr('height', 15)
      .attr('width', segmentWidth)
      .attr('x', 0);
    
    var progress = svg.append('rect')
      .attr('class', 'progress-rect')
      .attr('fill', colorScale(0))
      .attr('height', 15)
      .attr('width', 0)
      .attr('rx', 10)
      .attr('ry', 10)
      .attr('x', 0);
    
    progress.transition()
      .duration(5000)
      .attr('width', segmentWidth)
      .attrTween("fill", function() {
        return function(t) {
          return colorScale(t)
        }
      });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
        2
  •  1
  •   Danziger    6 年前

    你可以用两个重叠的元素来代替一个,一个在后面是黄色,另一个在前面是绿色 opacity .

    或者更好的是,您可以将颜色设置为 hls 而不是 rgb 并且改变 hue lightness 随着进度的增加或减少:

    const progressBar = document.getElementById('progressBar');
    const range = document.getElementById('slider');
    
    const hueStart = 60;
    const hueEnd = 120;
    const hueRange = hueEnd - hueStart;
    const lStart = 50;
    const lEnd = 32;
    const lRange = lEnd - lStart;
    
    range.oninput = () => {
      const percent = range.value;
      const alpha = percent / 100;
      const hue = hueStart + hueRange * alpha;
      const lightness = lStart + lRange * alpha;
      
      requestAnimationFrame(() => {
        progressBar.style.width = `${ percent }%`;
        progressBar.style.backgroundColor = `hsl(${ hue }, 100%, ${ lightness }%)`;
      });
    };
    body {
      text-align: center;
    }
    
    .progressBar__base {
      position: relative;
      height: 32px;
      border: 3px solid black;
      margin: 0 0 32px;
    }
    
    .progressBar__progress {
      position: absolute;
      top: 0;
      left: 0;
      height: 100%;
      background: yellow;
    }
    <div class="progressBar__base">
      <div class="progressBar__progress" id="progressBar"></div>
    </div>
    
    <input type="range" min="0" max="100" value="0" id="slider">