00dri
00dri

Reputation: 85

Move divs along a circular path on scroll

I have a circular container div with multiple divs with text along its circumference. I need to move the text divs in and out of view along the circumference in either direction on scroll.

I selected and styled the circular container div with d3.js and put it inside a smaller wrapper div with overflow-y set to auto.

<div id="circle-out-container-wrapper"><div id="circle-out-container"></div></div>

var radius = Math.floor(document.documentElement.clientHeight * 1.5);
d3.select('#circle-out-container-wrapper')
  .style('overflow-y', 'auto')
  .style('overflow-x', 'hidden')
  .style('width', '80%')
  .style('height', '400px')
  .style('left', '0')
  .style('top', '0')
  .style('position', 'absolute');

d3.select('#circle-out-container')
  .style('background-color', 'transparent')
  .style('position', 'absolute')
  .style('box-sizing', 'border-box')
  .style('display', 'block')
  .style('border', '1px solid #bce8f1')
  .style('border-radius', '50%')
  .style('width', (radius * 2) + "px")
  .style('height', (radius * 2) + "px")
  .style('left', Math.floor(-(radius * 5) / 3) + "px")
  .style('top', Math.floor(-(radius * 2) / 3) + "px");

Then I add the text divs and position them with transform.

var params = [];
for (var i = 30; i >= 0; i--) {
  params.push(i);
}

var nums = d3.select("#circle-out-container")
  .selectAll("div.nums")
  .data(params)
  .enter()
  .append("div")
  .attr("class", "circle")
  .style("transform", function(d, i) {
    var angle = 20 - (i + 1) * (70 / (params.length + 1));
    return "rotate(" + angle + "deg) translate(" + radius  + "px, 0) rotate(" + -angle + "deg)";
  })
  .text(function(d) { return d });

This is how I scroll the text divs:

$('#circle-out-container-wrapper').scroll(function() {   
  b.style("transform", function(d, i) {
    var scroll = $('#circle-out-container-wrapper').scrollTop();
    var angle = scroll - (i + 1) * (40 / (params.length + 1));
    return "rotate(" + angle + "deg) translate(" + radius  + "px, 0) rotate(" + -angle + "deg)";
  })
});

The container circle has to be static with only about half of it showing. At the moment when scrolling the text divs move but you also scroll down on the circular container div and the displayed arc changes. How do I keep everything in place and move only the text divs along the circular path when I scroll?

Here's a fiddle: http://jsfiddle.net/00drii/etnkLkL3/3/ The circle is inside the modal.

Upvotes: 6

Views: 1858

Answers (1)

ElChiniNet
ElChiniNet

Reputation: 2902

I've never worked with d3.js but you need to put the div that contains the numbers outside the container that you need to scroll.

<div id="app">
    <!-- container -->
    <div id="scroll-container">
        <!-- content of the scroll -->
        <div class="content"></div>
    </div>

    <!-- the numbers should be inside this div -->
    <div id="canvas">
    </div>
</div>

Here you have an example. Adapt it to your needs.

$(function () {

  var radius = 200;
  var cant = 36;
  var i;
  var $circle;
  var $scrollcont = $("#scroll-container");
  var $canvas = $("#canvas");

  //---Create circles
  for(i = 0; i < cant; i++){

      $circle = $("<div/>");
      $circle.attr("data-index", i).addClass("circle").text(i + 1);

      $canvas.append($circle);

  }

  var $circles = $canvas.find(".circle");

  //---Update circles position
  function updateCirclesPosition(){

      //---Scroll value
      var scroll = $scrollcont.scrollTop();

      //---Vars
      var index;
      var radian;
      var posx;
      var posy;

      $circles.each(function(){

          index = Number( $(this).attr("data-index") );
          radian = ((index * 10 + scroll / 10) * Math.PI) / 180;
          posx = Math.cos( radian ) * radius;
          posy = Math.sin( radian ) * radius + radius;

          $(this).css("transform", "translate(" + posx + "px, " + posy + "px)");

      });  

  }

  //---On scroll event
  $("#scroll-container").on("scroll", updateCirclesPosition);

  updateCirclesPosition();

});
#app, #scroll-container, #canvas{
    height: 400px;
    width: 400px;
}
#app{
    position: relative;
}
#scroll-container{
    overflow-y: scroll;
    position: relative;
    z-index: 1;
}

#scroll-container .content{
    height: 5000px;
}

#canvas{
    position: absolute;
    left: 0;
    top: 0;
    z-index: 0;
}

#canvas .circle{
    background: #666;
    border-radius: 50%;
    -moz-border-radius: 50%;
    color: #FFF;
    font-family: Arial;
    font-size: 10px;
    height: 20px;
    line-height: 20px;
    position: absolute;
    text-align: center;
    width: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

<div id="app">
    <div id="scroll-container">
        <div class="content"></div>
    </div>
    <div id="canvas">
    </div>
</div>

JSFiddle

Upvotes: 2

Related Questions