block by shimizu 8e8d0b0f405b12da409d5fa95b950c83

邦画興行収入ツリーマップ

Full Screen

2007年〜2016年までの邦画興行収入ツリーマップ。

データ元

Built with blockbuilder.org

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<title>映画興行収入ツリーマップ</title>
<style>
  html, body {
    margin:0px;
    padding:0px;
  }  
  form {
    margin-left:4px;
  }
text {
  font: 10px sans-serif;
}

tspan:last-child {
  font-size: 9px;
  fill-opacity: 0.8;
}

.node rect {
  shape-rendering: crispEdges;
}

.node--hover rect {
  stroke: #000;
}
.tooltip {
  position: absolute;
  min-width: 150px;
  z-index: 10;
  padding: 0;
  background-color: #ffffff;
  color: #222222;
  font-size: 16px;
  border: 0;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
  -webkit-box-shadow: rgba(0, 0, 0, 0.247059) 0px 1px 3px;
  -moz-box-shadow: rgba(0, 0, 0, 0.247059) 0px 1px 3px;
  -ms-box-shadow: rgba(0, 0, 0, 0.247059) 0px 1px 3px;
  box-shadow: rgba(0, 0, 0, 0.247059) 0px 1px 3px;
  opacity: 1;
  box-sizing: border-box;
  pointer-events: none;
  transform: translate(26px, -5px);
}

.tooltip {
  h4 {
	font-size: 16px;
	font-weight: bold;
	margin: 4px 0 12px 0;
	padding: 0 0 12px 0;
	border-bottom: 1px solid #e8e8e8;
  }
  h5 {
	font-size: 16px;
	margin: 0 0 3px 0;
	padding: 0 0 0 0;
  }
}

.tooltip .tooltip_container {
  padding: 10px;
  background-color: #ffffff;
  text-align: center;
  -webkit-border-radius: 4px;
	   -moz-border-radius: 4px;
				  border-radius: 4px;
  &:after {
	  content: "";
	  position: absolute;
	  bottom: -5px;
	  height: 10px;
	  left: 50%;
	  margin-left: -5px;
	  width: 10px;
	  z-index: -1;
	  right: auto;
	  top: auto;
	  margin-top: auto;
	  background-color: rgb(255, 255, 255);
	  -webkit-box-shadow: rgba(0, 0, 0, 0.247059) 0px 1px 3px;
		   -moz-box-shadow: rgba(0, 0, 0, 0.247059) 0px 1px 3px;
			  -ms-box-shadow: rgba(0, 0, 0, 0.247059) 0px 1px 3px;
					  box-shadow: rgba(0, 0, 0, 0.247059) 0px 1px 3px;
	  -webkit-transform: rotate(45deg) scale(1);
	  -moz-transform: rotate(45deg) scale(1);
	  -ms-transform: rotate(45deg) scale(1);
	  transform: rotate(45deg) scale(1);
  }
}

#contenner {
  width: 960px;
}
#info {
  width: 200px;
  margin: 10px auto;
}

.total {
  font-size: 0.8em;
  opacity: 0.7;
}
.unit {
  font-size: 0.8em;  
}
.count,
.persent {
  font-weight: bold;
  margin-right: 2px;
}


</style>
<div id="contenner">
  <form id="form" name="form" action="">
    <input id="Checkbox1" type="checkbox" value="実写化" data-color="#ffcccc" checked="checked"/><label for="Checkbox1">実写化</label>
    <input id="Checkbox2" type="checkbox" value="アニメ" data-color="#ccffff"  /><label for="Checkbox2">アニメ</label>
    <input id="Checkbox3" type="checkbox" value="特撮" data-color="#ccffcc"  /><label for="Checkbox3">特撮</label>
    <input id="Checkbox4" type="checkbox" value="ドラマ" data-color="#ffccff"  /><label for="Checkbox4">TVドラマ</label>
    <input id="Checkbox5" type="checkbox" value="小説" data-color="#ccccff"  /><label for="Checkbox5">小説原作</label>
    <input id="Checkbox6" type="checkbox" value="その他" data-color="#ffffaf"  /><label for="Checkbox6">その他</label>
    <div id="info"></div>
  </form>
  <svg width="960" height="1060"></svg>
</div>
<script src="//d3js.org/d3.v4.0.0-alpha.35.min.js"></script>
<script>
var total = 0;  
var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height");

var format = d3.format(".1f");

var color = ["#333", "#ccc", "#fff"];

var stratify = d3.stratify()
    .parentId(function(d) { return d.id.substring(0, d.id.lastIndexOf(".")); });

var treemap = d3.treemap()
    .size([width, height])
    .paddingOuter(3)
    .paddingTop(19)
    .paddingInner(1)
    .round(true);

var cast = function(d){
    Object.keys(d).forEach(function(key){
        d[key] = d[key].trim();
        if (d[key] && !isNaN(+d[key])) d[key] = +d[key];
    });
    return d;
};
    
    
d3.tsv("movie.tsv", cast, function(error, data) {
  if (error) throw error;

  var nested = d3.nest()
  .rollup(function(d){ return d[0]; })
  .key(function(d){ return d.uid ;})
  .map(data);
  
  
  var root = stratify(data)
      .sum(function(d) { return d["興収(単位:億円)"] ; })
      .sort(function(a, b) { return  b["興収(単位:億円)"] - a["興収(単位:億円)"]; });

  treemap(root);

  var cell = svg
    .selectAll(".node")
    .data(root.descendants())
    .enter().append("g")
      .attr("transform", function(d) { return "translate(" + d.x0 + "," + d.y0 + ")"; })
      .attr("class", "node")
      .each(function(d) { d.node = this; })
      .on("mouseover", hovered(true))
      .on("mouseout", hovered(false));

  cell.append("rect")
      .attr("id", function(d) { return "rect-" + d.id; })
      .attr("width", function(d) { return d.x1 - d.x0; })
      .attr("height", function(d) { return d.y1 - d.y0; })
      .attr("fill", function(d) { return color[d.depth]; })
      .attr("class",function(d){
        if (d.depth < 2) return ;
        return "cell " + d.data["タイプ"]
      })
      .call(bindTooltip)
      ;
      
  total = d3.selectAll(".cell").nodes().length;
  var count = fillCeckedCell();
  output(count, total);
  
  cell.append("clipPath")
      .attr("id", function(d) { return "clip-" + d.id; })
    .append("use")
      .attr("xlink:href", function(d) { return "#rect-" + d.id + ""; });

  var label = cell.append("text")
      .attr("clip-path", function(d) { return "url(#clip-" + d.id + ")"; });

  label
    .filter(function(d) { return d.children; })
    .selectAll("tspan")
      .data(function(d) { return d.id.substring(d.id.lastIndexOf(".") + 1).split(/(?=[A-Z][^A-Z])/g); })
    .enter().append("tspan")
      .attr("x", function(d, i) { return i ? null : 4; })
      .attr("y", 13)
	  .attr("fill", function(d){ return (d !="root") ? "black" : "white"; })
      .text(function(d) { return (d !="root") ? d : "邦画10億円以上作品 2007-2016" ; });

  label
    .filter(function(d) { return !d.children; })
    .selectAll("tspan")
      .data(function(d) { return d.id.substring(d.id.lastIndexOf(".") + 1).split(/(?=[A-Z][^A-Z])/g); })
    .enter().append("tspan")
      .attr("x", 4)
      .attr("y", function(d, i) { return 13 + i * 10; })
      .text(function(id) {var data = nested.get(id); return data["タイトル"]; });

});

function hovered(hover) {
  return function(d) {
    d3.selectAll(d.ancestors().map(function(d) { return d.node; }))
        .classed("node--hover", hover)
      .select("rect")
        .attr("width", function(d) { return d.x1 - d.x0 - hover; })
        .attr("height", function(d) { return d.y1 - d.y0 - hover; });
  };
}

var tooltip = d3.select("body")
  .append("div")
  .attr("class", "tooltip")
  .style("visibility", "hidden");
	
  
  
function bindTooltip(selector) {
  selector.on("mouseover", function(d) {
	  if (!d.data["タイトル"]) return ;
	  d3.select(this).classed("selected", true);
	  tooltip.style("visibility", "visible");
	})
	.on("mouseout", function(d) {
	  selector.classed("selected", false);
	  tooltip.style("visibility", "hidden");
	})
	.on("mousemove", function(d){
	  var data = d.data;
	  var content = [
		  '<div class="tooltip_container">',
		  '<h4>', data['タイトル'], '</h4>',
		  '<h5>興収:', data['興収(単位:億円)'], '億円</h5>',
		  "</div>"].join("");
		
	  tooltip
		  .style("top", (d3.event.pageY-100)+"px")
		  .style("left",(d3.event.pageX-100)+"px")
		  .html(content);
	});

}  
  
d3.select("#form").on("change", function(){
  d3.selectAll(".cell").attr("fill", "#fff");
  var count = fillCeckedCell();
  output(count, total);  
});


function output(count, total) {
  d3.select("#info").html('<span class="count">'+count + '</span><span class="unit">作品</span>/<span class="total">' + total + '</span> <span class="persent">' +format((count/total)*100)+'</span><span class="unit">%</span>')    
}


function fillCeckedCell() {
  var checked = d3.select("#form").selectAll("input:checked");
  var count = 0;
  checked.each(function(){    
	var selector = d3.selectAll("."+this.value).attr("fill", this.dataset.color);
	count += selector.nodes().length;    
  });
  
  return count;
}
</script>