楽天カードの明細csvを読み込んで当月請求額を基準としたツリーマップを表示します。
csvはアップロードされるわけでは無く、フロントエンド(ブラウザ)上だけで処理されますが、不安な方は自サーバーなどにindex.htmlをアップしてためしてみてください。
なお、Chromeでしか動作確認してません。
<!DOCTYPE html> | |
<meta charset="utf-8" /> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"/> | |
<title>楽天カードツリーマップ</title> | |
<style> | |
body { | |
margin: auto; | |
position: relative; | |
padding: 20px; | |
height: 100%; | |
} | |
form { | |
position: absolute; | |
right: 10px; | |
top: 10px; | |
} | |
.node { | |
border: solid 1px white; | |
line-height: 0.95; | |
overflow: hidden; | |
position: absolute; | |
border-radius: 6px; | |
text-shadow: -1px -1px 2px hsla(0,0%,100%,0.25), | |
-1px -1px 2px hsla(0,0%,100%,0.25), | |
-1px 1px 2px hsla(0,0%,100%,0.25), | |
1px -1px 2px hsla(0,0%,100%,0.25), | |
-1px 0px 2px hsla(0,0%,100%,0.25), | |
1px 0px 2px hsla(0,0%,100%,0.25); | |
} | |
.node div { | |
padding: 6px 4%; | |
} | |
#fileBtn { | |
margin-bottom: 8px; | |
} | |
</style> | |
<body> | |
<input id="fileBtn" type="file"> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> | |
<!-- by http://polygon-planet-log.blogspot.jp/2012/04/javascript.html--> | |
<script src="//cdn.rawgit.com/shimizu/9873aaff4961cf3f149d/raw/da5939d7096addf2379a3c48c6cae5179c9b1686/encoding.min.js"></script> | |
<script> | |
var fileBtn = document.querySelector("#fileBtn"); | |
fileBtn.addEventListener('change', upload, false); | |
function draw(data){ | |
var childrenData = data.map(function(d){ | |
return {name: d['利用店名・商品名'], value: +d['当月請求額']} | |
}); | |
var dataSet = { | |
name: "tree", | |
children: childrenData | |
}; | |
var width = 960-40, | |
height = 500-40, | |
color = d3.scale.category20c(), | |
div = d3.select("body").append("div").style("position", "relative"); | |
var treemap = d3.layout.treemap() | |
.size([width, height]) | |
.sticky(true) | |
.value(function(d) { return d.value; }); | |
var node = div.datum(dataSet).selectAll(".node") | |
.data(treemap.nodes) | |
.enter() | |
.append("div") | |
.attr("class", "node") | |
.call(position) | |
.style("background-color", function(d) { | |
return d.name == 'tree' ? '#fff' : color(d.name); }) | |
.append('div') | |
.style("font-size", function(d) { | |
return Math.max(20, 0.18*Math.sqrt(d.area))+'px'; }) | |
.text(function(d) { return d.children ? null : d.name; }); | |
function position() { | |
this.style("left", function(d) { return d.x + "px"; }) | |
.style("top", function(d) { return d.y + "px"; }) | |
.style("width", function(d) { return Math.max(0, d.dx - 1) + "px"; }) | |
.style("height", function(d) { return Math.max(0, d.dy - 1) + "px"; }); | |
} | |
} | |
function upload(evt) { | |
if (!isFileUpload()) { | |
console.log('お使いのブラウザはファイルAPIがサポートされていません'); | |
} else { | |
var data = null; | |
var file = evt.target.files[0]; | |
var reader = new FileReader(); | |
reader.readAsBinaryString(file); | |
reader.onload = function(event) { | |
var result = event.target.result; | |
var sjisArray = str2Array(result); | |
var uniArray = Encoding.convert(sjisArray, 'UNICODE', 'SJIS'); | |
var csvStr = Encoding.codeToString(uniArray); | |
draw(d3.csv.parse(csvStr)); | |
}; | |
reader.onerror = function() { | |
console.log('ファイルが読み込めませんでした。 ' + file.fileName); | |
}; | |
} | |
} | |
function isFileUpload() { | |
var isCompatible = false; | |
if (window.File && window.FileReader && window.FileList && window.Blob) { | |
isCompatible = true; | |
} | |
return isCompatible; | |
} | |
function str2Array(str) { | |
var array = [],i,il=str.length; | |
for(i=0;i<il;i++) array.push(str.charCodeAt(i)); | |
return array; | |
} | |
</script> |