turnip
turnip

Reputation: 2346

Horizontal fade-in transition from side to side using d3?

I know how to do a normal fade in transition using the opacity attribute, but how would I go about making the transition start from one end of the element and gradually complete itself horizontally?

Something like this:

enter image description here

I am trying to do this for some text:

text = svg.selectAll(".myText")
          .data(myData)
          .enter()
          .append("text")
          .attr("class", "myText")
          .attr("text-anchor", "start")
          .attr("fill-opacity", 0)
          .text(function (d)
          {
              return d.message
          });

text.transition()
    .delay(500)
    .duration(1000)
    .attr("fill-opacity", 1)

Upvotes: 3

Views: 1394

Answers (2)

Mark
Mark

Reputation: 108567

Cool question. How about this craziness:

<!DOCTYPE html>
<html>

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

  <body>
    <script>
    
      var str = "This is a long string.",
          i = 0;
    
      var svg = d3.select("body")
        .append("svg")
        .attr("width", 500)
        .attr("height", 300);
        
      var text = svg.append("text")
        .style("fill", "black")
        .style("font-size", "30pt")
        .style("font-family", "arial")
        .attr("transform", "translate(10,50)");
        
      fadeLeftToRight();
        
      function fadeLeftToRight(){
        i++;
        if (i >= str.length) return;
        
        var char = str.substring(i-1,i);
        text
          .append("tspan")
          .style("opacity", 0)
          .text(char)
          .transition()
          .delay(100)
          .duration(char === " " ? 0 : 500)
          .style("opacity", 1)
          .each("start", function(d){
            fadeLeftToRight();
          })
      }
      
    </script>
  </body>

</html>

Upvotes: 1

Steve Ladavich
Steve Ladavich

Reputation: 3562

Pure CSS Answer

You can see how to do this with pure CSS here: CSS fade left to right

D3 Approach

Below is the same approach given in the linked answer just applying it with D3...

The gist is to place a box over the text and use transitions to modify the box width (from completely covering the text to completely revealing it).

  • To prevent the box edges from being visible and too harsh a gradient is applied.

  • To make sure the box nicely covers the text, the covering rect uses parameters from the text's bounding box using the function getBBox()

var height = 25,
    width = 100;

d3.select('div').append('svg')
        .attr('width', '100%')
        .attr('viewBox', "0 0 " + width + " " + height)
        .attr('style', 'border: solid 1px green')
        .append('g')
        .attr('transform','translate('+ width/2 +','+ height/2 +')')
        .attr('id', 'main');

var text = d3.select('#main').append('text')
             .attr('class', 'myText')
             .attr('text-anchor', 'middle')
             .attr('alignment-baseline','middle') 
             .text('My Message');

bbox = text[0][0].getBBox();

var gradient = d3.select('svg').append("defs")
  .append("linearGradient")
    .attr("id", "gradient")
    .attr("x1", "0%")
    .attr("x2", "0%")
    .attr("spreadMethod", "pad");

gradient.append("stop")
    .attr("offset", "0%")
    .attr("stop-color", "#fff")
    .attr("stop-opacity", 1);

gradient.append("stop")
    .attr("offset", "100%")
    .attr("stop-color", "#fff")
    .attr("stop-opacity", 0);

fadeBox = d3.select('#main').append('rect')
  .attr('x', bbox.x)
  .attr('y', bbox.y)
  .attr('width', bbox.width)
  .attr('height', bbox.height)
  .style("fill", "url(#gradient)");



fadeBox.transition()
  .delay(500)
  .duration(2000)
  .attr('width', 0)
  .attr('x', bbox.width)


gradient.transition()
  .delay('500')
  .duration('2000')
  .attr('x1','100%')
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

<div>

</div>

Upvotes: 5

Related Questions