block by sxywu 368e4dba64c7b861481a332dc374c4c1

film flowers washi tape

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

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>
  </style>
</head>

<body>
  <svg></svg>
  
  <script>
    const width = 4134;
    const height = 213;
    var strokeColor = '#444';
    var flowerSize = 160;
    
    var svg = d3.select('svg');
    
		var petalPaths = [[
    	'M0 0',
      "C50 50 50 100 0 100",
      "C-50 100 -50 50 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'
    ]];
    var leaf = [
      'M0 15',
      'C15 40 15 60 0 75',
      'C-15 60 -15 40 0 15'
    ];
    const moviesToDraw = [
      'Straight Outta Compton',
      'Finding Dory',
      'Despicable Me 2',
      'Brave',
      'The Dark Knight Rises',
      'Harry Potter and the Deathly Hallows: Part 2',
      'Inception',
      'Despicable Me',
      'Spider-Man 2',
      'Batman Begins',
      'Toy Story 3',
      'Lilo & Stitch',
      'Rush Hour 2',
      // 'X-Men',
      // 'The Sixth Sense',
      'Saving Private Ryan',
      // 'The Rock',
      // 'Pocahontas',
      'Forrest Gump',
      'Slumdog Millionaire',
      'The Dark Knight',
      'WALL·E',
      'Harry Potter and the Half-Blood Prince',
      'Ratatouille',
      'Harry Potter and the Order of the Phoenix',
      'Mr. & Mrs. Smith',
      "Pirates of the Caribbean: Dead Man's Chest",
      'Pirates of the Caribbean: The Curse of the Black Pearl'
    ]

    const simulation = d3.forceSimulation()
      .force('collide', d3.forceCollide().radius(d => d.radius + 40))
      .force('center', d3.forceCenter(width / 2, height / 2))
      .force('charge', d3.forceManyBody(-240));
    const numPetalScale = d3.scaleQuantize()
      .range(_.range(5, 15));
    const flowerSizeScale = d3.scaleLinear()
      .range([.05 * flowerSize, .5 * flowerSize]);
    const petalScale = d3.scaleOrdinal()
      .domain(['G', 'PG', 'PG-13', 'R'])
      .range(_.range(4));
    const petalColors = d3.scaleOrdinal()
      .range(['#FFB09E', '#CBF2BD', '#AFE9FF', '#FFC8F0', '#FFF2B4']);

    const defs = d3.select('svg')
      .style('isolation', 'isolate')
    	.attr('width', width)
      .attr('height', height)
      .append("defs");
    defs.append("filter")
      .attr("id", "motionFilter") 	//Give it a unique ID
      .attr("width", "300%")		//Increase the width of the filter region to remove blur "boundary"
      .attr("x", "-100%") 			//Make sure the center of the "width" lies in the middle of the element
      .append("feGaussianBlur")	//Append a filter technique
      .attr("in", "SourceGraphic")	//Perform the blur on the applied element
      .attr("stdDeviation", "8 8");	//Do a blur of 8 standard deviations in the horizontal and vertical direction
  
    d3.json('movies.json', function(movies) {
      movies = _.chain(movies)
        .map(function(movie) {
          movie.year = parseInt(movie.Year);
          movie.genres = movie.Genre.split(', ');
          movie.rating = parseFloat(movie.imdbRating);
          movie.votes = parseInt(movie.imdbVotes.replace(/\,/g, ''));

          return movie;
        }).value()

      // number of petals depending on number of rating votes
      const votesExtent = d3.extent(movies, function(d) {return d.votes})
      numPetalScale.domain(votesExtent)
      // overall flower size from rating
      const ratingExtent = d3.extent(movies, function(d) {return d.rating})
      flowerSizeScale.domain(ratingExtent)
      // get the top 4 genres by count
      const topGenres = _.chain(movies)
        .map('genres').flatten()
        .countBy().toPairs()
        .sortBy(1).map(0)
        .takeRight(4)
        .value();
      topGenres.push('Other');
      petalColors.domain(topGenres);

      // calculate movie data with each of the petals as well as 
      movies = _.chain(movies)
        .filter(movie => _.includes(moviesToDraw, movie.Title))
        .map(d => {
          const radius = flowerSizeScale(d.rating);
          const scale = radius / 100;
          const rotate = _.random(240, 360);
          const numPetals = numPetalScale(d.votes);
          const petals = _.times(numPetals, i => {
            return {
              scale,
              rotate: (i / numPetals) * 360,
              path: petalPaths[petalScale(d.Rated)],
            }
          });
          // if there's only one genre, center the circle
          const cy = d.genres.length === 1 ? 0 : -0.14 * flowerSize;
          const colors = _.map(d.genres, function(genre, i) {
            genre = _.includes(topGenres, genre) ? genre : 'Other';
            return {
              cy,
              scale,
              angle: (360/d.genres.length) * i,
              fill: petalColors(genre),
            }
          });
          return {radius, petals, colors, scale, rotate};
        }).shuffle().value();

      // use force simulation to calculate positions
      simulation.nodes(movies);
      _.times(10000, i => {
        simulation.tick();
        // make sure it's within bounds
        _.each(movies, d => {
          if (0 > d.x - d.radius) {
            d.x = d.radius + 5;
          } else if (d.x + d.radius >= width) {
            d.x = width - d.radius - 5;
          }
          if (0 > d.y - d.radius) {
            d.y = _.random(0.5 * d.radius, 1 * d.radius);
            // d.y = d.radius - 5;
          } else if (d.y + d.radius >= height) {
            d.y = height - _.random(0.5 * d.radius, 1 * d.radius);
            // d.y = height - d.radius + 5;
          }
        });
      });

      console.log(JSON.stringify(movies))
      const flowers = d3.select('svg').selectAll('g.flower')
        .data(_.values(movies)).enter().append('g')
        .classed('flower', true)
        .attr('transform', d => `translate(${d.x}, ${d.y})rotate(${d.rotate})scale(${d.scale})`);

      // colors
      flowers.selectAll('circle')
        .data(d => d.colors).enter().append('circle')
        .attr('cy', d => d.cy)
        .attr('r', 0.45 * flowerSize)
        .attr('fill', d => d.fill)
        .attr('transform', d => `rotate(${d.angle})`)
        .style("filter", "url(#motionFilter)")
        .style('mix-blend-mode', 'multiply');

      // petals
      flowers.selectAll('path')
        .data(d => d.petals).enter().append('path')
        .attr('transform', d => `rotate(${d.rotate})`)
        .attr('d', d => d.path)
        .attr('stroke', strokeColor)
        .attr('stroke-width', d => 2.5 / d.scale)
        .attr('fill', 'none');
    });
    
  </script>
</body>