Skip to content

Instantly share code, notes, and snippets.

@shimizu
Last active April 12, 2016 03:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shimizu/11bc492af4498c76aa7f to your computer and use it in GitHub Desktop.
Save shimizu/11bc492af4498c76aa7f to your computer and use it in GitHub Desktop.
楽天カード明細ツリーマップ

楽天カードの明細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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment