最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Color transition in d3 using time elapsed - Stack Overflow

programmeradmin5浏览0评论

I've been having a hard time wrapping my head around some D3 concepts (it does not help that I am relatively new to javascript). What I am trying to do is have a status indicator that begins green, slowly turning yellow, and then slowly turning red. If some event occurs (button press, message received, whatever), I want the indicator to return to green, restarting the transition.

Here's a simple example (in jQuery) showing the basic visual effect (without the ability to reset) /

In D3, my idea was to map the background color to the number of milliseconds passed. I tried to create a scale like this:

//10 sec is yellow, 30 sec is red
d3.scale.linear().domain([0, 10000, 30000]).range(["#00ff00", "#ffff00", "#ff0000"]);

But now I'm a bit lost. I have been playing with combinations of transitions, tweens, and interpolators, but I don't seem to be getting anywhere. Here's some pathetic attempts to get it working /

My issues:

  • I don't know how to associate the elapsed millis of a transition to my scale, and then set the background color
  • My transition seems to run when I create it, instead of when I call it, and it operates on the wrong element.
  • I'm not positive how to reset the transition to keep it green once I've conquered my other problems.

One other note, I could be happy using an svg circle or something like that instead, but I have had just as poor luck manipulating an svg fill attribute as I have an html background attribute.

Thank you

I've been having a hard time wrapping my head around some D3 concepts (it does not help that I am relatively new to javascript). What I am trying to do is have a status indicator that begins green, slowly turning yellow, and then slowly turning red. If some event occurs (button press, message received, whatever), I want the indicator to return to green, restarting the transition.

Here's a simple example (in jQuery) showing the basic visual effect (without the ability to reset) http://jsfiddle.net/N4APE/

In D3, my idea was to map the background color to the number of milliseconds passed. I tried to create a scale like this:

//10 sec is yellow, 30 sec is red
d3.scale.linear().domain([0, 10000, 30000]).range(["#00ff00", "#ffff00", "#ff0000"]);

But now I'm a bit lost. I have been playing with combinations of transitions, tweens, and interpolators, but I don't seem to be getting anywhere. Here's some pathetic attempts to get it working http://jsfiddle.net/Ebuwa/

My issues:

  • I don't know how to associate the elapsed millis of a transition to my scale, and then set the background color
  • My transition seems to run when I create it, instead of when I call it, and it operates on the wrong element.
  • I'm not positive how to reset the transition to keep it green once I've conquered my other problems.

One other note, I could be happy using an svg circle or something like that instead, but I have had just as poor luck manipulating an svg fill attribute as I have an html background attribute.

Thank you

Share Improve this question asked Jul 3, 2013 at 1:37 DenialDenial 3731 gold badge5 silver badges12 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 17

You don't really need to do any work with scales, .transition() will take care of the hard work behind the scenes:

function changeElementColor(d3Element){
    d3Element
    .transition().duration(0)
      .style("background", "green")
    .transition().duration(1000)
      .style("background", "yellow")
    .transition().delay(1000).duration(5000)
      .style("background", "red");
}
changeElementColor(d3.select("#d3Color"));

To reset the transition, just add an onclick event to the element:

d3.select("#d3Color")
  .on("click", function(){ changeElementColor(d3.select(this)) });

http://jsfiddle.net/N4APE/2/

I've also included a colored svg circle. I'm guessing you were trying to use .style("color", "red") to change its color; you need to use .attr("fill", "red") for non CSS properties.

I had the same question but wanted to change the text colour as well to provide more contrast toward the end. Mine also updates the message with the elapsed seconds (to see how long slow queries take)

var duration = 30 * 1000;

// background color progression is smooth from lime to orange to red
var colorScale = d3.scale.linear().clamp(true)
    .domain([0, duration / 2, duration])
    .range(['lime', 'orange', 'red']);

// text color is mostly black but switches to yellow when there is good contrast
var textScale = d3.scale.quantile()
    .domain([0, 0.85 * duration, duration])
    .range(['black', 'yellow', 'yellow']);

var start = new Date();
var counterId = setInterval(function () {
    console.log("setInterval ID: " + counterId);
    var now = new Date();
    var elapsed = Math.round((now - start) / 1000);
    var message = "Querying... " + (elapsed) + " s";
    elapsed = 1000 * elapsed;
    d3.select('#progress')
    .style("color", textScale(elapsed))
        .style("background", colorScale(elapsed))
        .html(message)
    ;
}, 1000);

Working Example Here:

http://jsfiddle.net/SKLUn/5/

I think I may have been overthinking things. It occurred to me I can just use my D3 scale with setInterval. Something like this:

var step = 100;

var scale = d3.scale.linear()
                .domain([0, msToYellow, msToRed])
                .range([green, yellow, red]);

setInterval(function(){
    elapsed += step;     
    update(elapsed);    
}, step);

function update(e){
    d3.select("input")
        .style("background", scale(e));
}

Full working example here : http://jsfiddle.net/WBAuT/1/

发布评论

评论列表(0)

  1. 暂无评论