0

I'm getting an error message after a while, when using a blink function in D3

.transition()
                                .duration(250)
                                .delay( 0)
                                .each(blink);

function blink() {

                        var line = d3.select(this);
                        (function repeat() {
                        line = line.transition()
                        .style("opacity", function(d) { return(1);})
                        .transition()
                        .style("opacity", function(d) { return(0);})
                        .each("end", repeat);})();
            }

enter image description here

Robert Rieser
  • 63
  • 1
  • 7
  • what is your error ? – thatOneGuy Feb 23 '16 at 14:23
  • are you running this in browser ? Could you set up a JSFiddle with the bare amount of code to show us your problem. Also when you put .style("opacity",function(d){return(1);{), you can just put .style("opacity",1). Also, maybe put a slight delay after the transition, otherwise your browser may get over cluttered – thatOneGuy Feb 23 '16 at 15:09
  • 1
    You've created a nested transition, every 17ms, you are **creating** another transition which in turn fires every 17ms.... What are you really trying to do here, just blink a line every 250ms? – Mark Feb 23 '16 at 16:28

1 Answers1

2

As I said in my comment:

You've created a nested transition, every 17ms, you are creating another transition which in turn fires every 17ms...

To fix this, remove the nesting:

<!DOCTYPE html>
<html>

  <head>
    <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
  </head>

  <body>
    <script>
      
      var svg = d3.select('body')
        .append('svg')
        .attr('width', 300)
        .attr('height', 300);
        
      svg
        .append('line')
        .attr('y1', 150)
        .attr('y2', 150)
        .attr('x1', 0)
        .attr('x2', 300)
        .style('fill', 'none')
        .style('stroke', 'steelblue');
        
      svg.selectAll("line")
        .each(blink);
        
      function blink(){
        var self = d3.select(this);
        self
          .transition()
          .duration(250)
          .style("opacity", function(d) { 
            return self.style("opacity") === "1" ? "0" : "1";
          })
          .each("end", blink);
      }
      
    </script>
  </body>

</html>

Of course, if you just want something to blink you can do this with straight css:

<!DOCTYPE html>
<html>

  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
    <style>
.blink {
  animation: blink-animation 1s steps(5, start) infinite;
  -webkit-animation: blink-animation 1s steps(5, start) infinite;
}
@keyframes blink-animation {
  to {
    visibility: hidden;
  }
}
@-webkit-keyframes blink-animation {
  to {
    visibility: hidden;
  }
}
    </style>
    
  </head>

  <body>
    <script>
      
      var svg = d3.select('body')
        .append('svg')
        .attr('width', 300)
        .attr('height', 300);
        
      svg
        .append('line')
        .attr('class', 'blink')
        .attr('y1', 150)
        .attr('y2', 150)
        .attr('x1', 0)
        .attr('x2', 300)
        .style('fill', 'none')
        .style('stroke', 'steelblue');       

    </script>
  </body>

</html>
Community
  • 1
  • 1
Mark
  • 106,305
  • 20
  • 172
  • 230
  • thank you very much, I hope this will fix my problem – Robert Rieser Feb 24 '16 at 09:45
  • I have something like this setInterval(vmhvlan,30000); function vmhvlan() {var svg = d3.select('body') .append('svg') .attr('width', 300) .attr('height', 300); svg .append('line') .attr('y1', 150) .attr('y2', 150) .attr('x1', 0) .attr('x2', 300) .style('fill', 'none') .style('stroke', 'steelblue'); svg.selectAll("line") .each(blink);} function blink(){ .... } could this be the problem? – Robert Rieser Feb 26 '16 at 09:30
  • @DeGoya, you still get an unresponsive message? Why are you re-appending a new svg, line, etc... every 30s? – Mark Feb 26 '16 at 13:45
  • because my data changes consistently and I have to make a connection every 30 seconds to my server to get the updated Data. In the beginning of the method, I have something like this "d3.select('#content').html("");" and then I re-appending every DOM element. I have the feeling, that for every new generated blink call, the old one is still running, although the old one isn't existing anymore. – Robert Rieser Feb 29 '16 at 11:43
  • @DeGoya, tough to answer without being able to reproduce it. When you say `although the old one isn't existing anymore` do you `.remove()` from the SVG? Make sure you cancel any transitions on it before you remove. **And** don't remove with a transition. `svg.selectAll('line').transition().remove()` is **bad**, `svg.selectAll('line').transition(); svg.selectAll('line').remove(); ` – Mark Feb 29 '16 at 14:11
  • @DeGoya, I let [this example run](http://plnkr.co/edit/mjTvkZQipUsofXUcmOpC?p=preview) for a good long while and haven't seen any issues. – Mark Feb 29 '16 at 14:11
  • your example has the same problem as mine, it hangs for me. I remove everything like this d3.select('#body').html(""); – Robert Rieser Mar 01 '16 at 09:12
  • 1
    @DeGoya, you are correct. I didn't let it run long enough to see the issue. The memory usage is ever increasing. How about [this version](http://plnkr.co/edit/cVaCTgdmxTWO5HZEZZVG?p=preview); the memory usage stays flat. – Mark Mar 01 '16 at 16:17