block by vicapow 5778069

5778069

Full Screen

index.html

<html>
  <head>
    <style type="text/css">

      body {
        font: 10px sans-serif;
      }

      .ball{
        fill: steelblue;
        opacity: 1;
        box-shadow: -5px -5px 5px #888;
        -webkit-box-shadow: -5px -5px 5px #888;
        stroke: #fff;
        opacity: 1;
      }

      .ball.mean{
        fill: #ff6d00;
        fill: #ffb958;
      }

      .bar text {
        fill: #fff;
      }

      .axis path, .axis line {
        fill: none;
        stroke: #000;
        shape-rendering: crispEdges;
      }

      .triangle{
        stroke-linejoin: round;
        stroke: black;
        fill: black;
        stroke-width: 4;
      }

      .ball-group .btn-close .btn-bg{
        fill: black;
        opacity: 1;
      }
      .ball-group .btn-close text{
        fill: white;
      }

      .ball-group .btn-close{
        opacity: 0;
        transition: all 0.1s;
      }

      .ball-group:hover .btn-close{
        opacity: 1;
        cursor: pointer;
      }

      .ball-group:active .btn-close{
        display: none;
        opacity: 0;
      }
      .ball-group:active .btn-close:active{
        display: block;
        opacity: 1;
      }
    </style>
  </head>
  <body>
    <button id="add-ball"> add ball </button>
    <button id="remove-all"> remove all but one </button>
    <script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
    <script type="application/javascript">
      var w = 800
        , margin = { left : 10, right : 10 }
        , h = 100
        
        , svg = d3.select('body').append('svg')
          .append('g')
            .attr('transform'
            , 'translate(' + margin.left + ',' + margin.right + ')')
        
        , x = d3.scale.linear().domain([0, 100]).range([0, w])
        , y = d3.scale.linear().domain([10, 0]).range([0, h])
        , r = 20
        , data = d3.range(0, 4).map(function(d){ return { x : 20 + d * 20, y: 2} })
      
        , drag = d3.behavior.drag()
          .on('drag', dragmove)
          .on('dragend', dragend)
      
        , circles = svg.selectAll('.ball-group')
      
        , meanball = svg.append('circle')
          .attr('class', 'ball mean')
          .attr('r', r * 2)
          .attr('cx', function(d){ return x(100) })
          .attr('cy', function(d){ return y(2) })
      
      function setupCircles(){
        d3.selectAll('.ball-group').remove()
        var d = circles.data(data)
        d.exit().remove()
        var g = d.enter()
            .append('g')
            .attr('class', 'ball-group')
            .attr('transform', function(d){
              return 'translate(' + x(d.x) + ',' + y(d.y) + ')'
            })
            .call(drag)
        g.append('circle')
          .attr('class', 'ball')
          .attr('r', r)
        var btn = g.append('g')
          .attr('class', 'btn-close')
          .attr('transform', 'translate(15,-15)')
        var bg = btn.append('circle')
          .attr('class', 'btn-bg')
          .attr('r', '10')
        btn.append('text')
            .text('x')
            .attr('font-size', '2em')
            .attr('font-family', 'helvetica')
            .attr('x', -5)
            .attr('y', 5)
        btn.on('click', function(d){
          if(data.length <= 1) return
          data.splice(data.indexOf(d),1)
          setupCircles()
          updateMean()
        })
      }
      
      setupCircles()
      
      function dragmove(d){
        d.x += x.invert(d3.event.dx)
        if(d.x > x.invert(w)) d.x = x.invert(w)
        if(d.x < x.invert(0)) d.x = x.invert(0)
        d3.select(this)
          .attr('transform', function(d){
            return 'translate(' + x(d.x) + ',' + y(d.y) + ')'
          })
        updateMean()
      }
      
      function dragend(d){
        d.x = Math.round(d.x)
        d3.select(this)
          .attr('cx', x(d.x))
        updateMean()
      }
      
      var axis = d3.svg.axis().scale(x).orient("bottom")
      svg.append('g')
        .attr('class', 'x axis')
        .attr('transform', 'translate(0,' + h + ')')
        .call(axis)
      
      function updateMean(){
        var set = data.map( function(d){ return d.x } )
        meanball.attr('cx', Math.round( x( d3.mean( set ) ) ) )
      }
      
      updateMean()
      
      document.getElementById('add-ball').onclick = function(){
        data.push({ x : Math.random() * x.invert(w), y : 2})
        setupCircles()
        updateMean()
      }
      document.getElementById('remove-all').onclick = function(){
        data = [{ x : 50 , y : 2 }]
        setupCircles()
        updateMean()
      }
    </script>
  </body>
</html>