进度条:如何根据进度进行颜色过渡?

时间:2019-01-20 21:21:03

标签: javascript d3.js

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

但是,这是一个具有三个状态的序数域,在现实生活中几乎不可重用。我想以某种方式更改它,无论我将其增加到多少百分比;黄色到绿色之间的颜色将按比例更改为新的进度/高度。该怎么办?

2 个答案:

答案 0 :(得分:3)

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>

答案 1 :(得分:1)

您可以使用两个重叠的元素代替一个,黄色的后面是一个元素,绿色的前面是一个opacity

甚至更好的是,您可以在hls中设置颜色,而不是rgb,并随着进度的增加或减少而更改huelightness的分量:

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">