block by sxywu 2f31dcdf781e3715aba6b4cd773e7058

Film Flowers, Full Complete

Full Screen

Built with blockbuilder.org

forked from sxywu‘s block: DS July: Code 1

forked from sxywu‘s block: DS July: Code 2

forked from sxywu‘s block: DS July: Code 3

forked from sxywu‘s block: DS July: Code 4

forked from sxywu‘s block: DS July: Code 5

forked from sxywu‘s block: DS July: Code 6

forked from sxywu‘s block: DS July: Code 7

forked from sxywu‘s block: Film Flowers, All

forked from anonymous‘s block: Film Flowers, Refactored

forked from sxywu‘s block: Film Flowers, Single Complete

index.html

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.js'></script>
  <link href='https://fonts.googleapis.com/css?family=Libre+Baskerville:400,700' rel='stylesheet' type='text/css'>
  
  <style>
    svg {
      width: 500px;
      height: 500px;
    }
  </style>
</head>

<body>
  <svg></svg>
  
  <script>
    const width = 600;
    const height = 600;
    
    const petalPaths = [[
    	'M0,0',
      'C50,40 50,70 20,100',
      'L0,85',
      'L-20,100',
      'C-50,70 -50,40 0,0'
    ],
                        [
			'M-35,0',
      'C-25,25 25,25 35,0',
      'C50,25 25,75 0,100',
      'C-25,75 -50,25 -35,0'
    ],
    [
      'M0,0',
      'C50,40 50,70 20,100',
      'L0,85',
      'L-20,100',
      'C-50,70 -50,40 0,0'
    ],
    [
      'M0,0',
      'C50,25 50,75 0,100',
      'C-50,75 -50,25 0,0'
    ]
    	// ADD 3 MORE PETAL PATHS                   
    ];
    
    // instantiate scales and petal path lookup
    const sizeScale = d3.scaleLinear()
    	.range([0.1, 1]);
   	const numPetalsScale = d3.scaleQuantize()
    	.range(_.range(5, 10));
    const pathLookup = {
      G: petalPaths[0],
      PG: petalPaths[1],
      'PG-13': petalPaths[2],
      R: petalPaths[3],
    };
    
    // grab svg
    const svg = d3.select(' svg');
    
    /*****************************************************
    ** get movie data
    ******************************************************/
    
    d3.json('movies.json', function(movies) {
      movies = _.map(movies, movie => {
        return {
          rating: ++movie.imdbRating,
          votes: parseInt(movie.imdbVotes.replace(/\,/g, '')),
          year: ++movie.Year,
          title: movie.Title,
          pg: movie.Rated,
        }
      });
      
      // 1. set domain for scales
      // size scale = rating
      // number of petals scale = number of votes
      const sizeExtent = d3.extent(movies, d => d.rating);
      const numPetalsExtent = d3.extent(movies, d => d.votes);
      // set domain on scales
      sizeScale.domain(sizeExtent);
      numPetalsScale.domain(numPetalsExtent);
      
      function drawFlowers(movies) {
        // create data
      const perRow = 3;
      const flowerData = _.map(movies, (d, i) => {
        // flower: translate and scale
        // petal: path and rotate
        const x = (Math.floor(i % perRow) + 0.5) * 150;
        const y = (Math.floor(i / perRow) + 0.5) * 150;
        const numPetals = numPetalsScale(d.votes);
        const petals = _.times(numPetals, i => {
          return {
            path: pathLookup[d.pg].join(' '),
            rotate: i * (360 / numPetals),
            numPetals,
          }
        });
        
        return {
          title: d.title,
          translate: [x, y],
          scale: sizeScale(d.rating),
          petals
        }
      });

      const t = d3.transition().duration(500);
      // 2. create a <g> for each flower
      // and translate+scale the whole flower
      // instead of individual petals
      let flowers = svg.selectAll('g').data(flowerData);
      
      flowers.exit().transition(t)
      	.attr('transform', d => `translate(${d.translate})scale(0)`)
        .remove();
      
      const enter = flowers.enter().append('g');
      	
      enter.append('text')
      	.attr('text-anchor', 'middle');
      
      // enter + update
      flowers = enter
      	.attr('transform', d => `translate(${d.translate})scale(0)`)
        .merge(flowers)
      flowers.transition(t)
      	.attr('transform', d => `translate(${d.translate})scale(${d.scale})`);
      
      // update text
     flowers.select('text')
      .text(d => d.title)
       
      // draw petals 
      const petals = flowers.selectAll('path')
      	.data(d => d.petals);
      
      petals.exit().remove();
      
      // enter + update petals
      petals.enter().insert('path', 'text')
      	.merge(petals)
      	.transition(t)
      	.attr('d', d => d.path)
      	.attr('transform', d => `rotate(${d.rotate})`)
      	.attr('fill', (d, i) => d3.interpolateRainbow(i / d.numPetals))
      }
      
      let i = 0;
     	setInterval(() => {
        i += 1;
        if (i === movies.length) {
          i = 0;
        }
        drawFlowers(_.slice(movies, i, i + 9));
      }, 1000)
    });
    
  </script>
</body>