Created
January 26, 2016 17:39
-
-
Save snaka/f88d0540c46d50cf3eaf to your computer and use it in GitHub Desktop.
Qiitaへの投稿アクティビティをGithubのように表示
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
フォームの入力内容を元にAPIに問い合わせ | |
*/ | |
$("#form").on("submit", function(e) { | |
$("#btn-submit").prop("disabled", true); | |
var user_id = $("#user_id").val() | |
$.ajax({ | |
type: "GET", | |
url: "http://qiita.com/api/v2/users/" + user_id + "/items?page=1&per_page=100", | |
success: onSucceed | |
}); | |
e.preventDefault(); | |
}); | |
// 日付のフォーマット | |
var format = d3.time.format("%Y-%m-%d"); | |
/* | |
APIから受け取った情報を元にカレンダー描画 | |
*/ | |
function onSucceed(data) { | |
var item_dates = {}; | |
$.each(data, function(idx, val) { | |
var created_at = format(d3.time.day.floor(new Date(val['created_at']))); | |
if (created_at in item_dates) | |
item_dates[created_at]++; | |
else | |
item_dates[created_at] = 1; | |
}); | |
drawCalendar(item_dates); | |
$("#btn-submit").prop("disabled", false); | |
} | |
/* | |
カレンダーの描画 | |
*/ | |
var drawCalendar = (function() { | |
// セルの1辺のサイズ | |
var CELL_SIZE = 15; | |
// カレンダ表示のマージン | |
var MARGIN_LEFT = 25; | |
var MARGIN_TOP = 15; | |
var dataset = null; | |
var color = null; | |
var countScale = null; | |
// 日付の計算 | |
var addDays = function(sourceDate, days) { | |
result = new Date(sourceDate); | |
result.setDate(sourceDate.getDate() + days); | |
return result; | |
}; | |
// 表示する日付の範囲(過去1年間) | |
var rangeBegin = addDays(new Date, -365); | |
var rangeEnd = new Date; | |
var dateRange = d3.time.days(rangeBegin, rangeEnd); | |
var monthRange = d3.time.months(rangeBegin, rangeEnd); | |
// カレンダのオフセット値を算出する関数 | |
var createOffsetFunc = function() { | |
var firstYearOffset = d3.time.weekOfYear(rangeBegin) * -1; | |
var bounderyDate = d3.time.years(rangeBegin, rangeEnd)[0]; | |
var lastDayOfFirstYear = addDays(bounderyDate, -1); | |
var lastWeekOfFirstYear = d3.time.weekOfYear(lastDayOfFirstYear); | |
var lastYearOffset = d3.time.weekOfYear(lastDayOfFirstYear) + firstYearOffset; | |
return function(sourceDate) { | |
if (sourceDate.getFullYear() == rangeBegin.getFullYear()) | |
return firstYearOffset; | |
return lastYearOffset; | |
} | |
}; | |
// メイン処理:カレンダー描画 | |
return function(dataset) { | |
// 件数を3段階に分類 | |
var countScale = d3.scale.linear() | |
.domain([1, d3.max(d3.values(dataset))]) | |
.rangeRound([1, 3]) // 3段階で色分け | |
.clamp(true); | |
// 分類ごとに色分け | |
var colorScale = d3.scale.ordinal() | |
.domain([1, 2, 3]) | |
.range(["#f7fcb9","#addd8e","#31a354"]); | |
// 上記をまとめるスケール関数 | |
var color = function(f) { | |
return colorScale(countScale(f)); | |
}; | |
// svg要素の作成 | |
var svg = d3.select(".weed"); | |
svg.selectAll("*").remove(); | |
svg.append("g"); | |
// 日毎の矩形を生成 | |
var offset = createOffsetFunc(); | |
var rect = svg.selectAll(".day") | |
.data(dateRange) | |
.enter() | |
.append("rect") | |
.attr("class", "day") | |
.attr("width", CELL_SIZE - 1) | |
.attr("height", CELL_SIZE - 1) | |
.attr("x", function(d){ return (d3.time.weekOfYear(d) + offset(d)) * CELL_SIZE + MARGIN_LEFT; }) | |
.attr("y", function(d){ return d.getDay() * CELL_SIZE + MARGIN_TOP; }) | |
.attr("fill", "rgb(230,230,230)") | |
.datum(format); | |
// ツールチップ設定 | |
rect.append("title") | |
.text(function(d){ return d; }); | |
// 投稿のあった日のツールチップと背景色を設定 | |
rect.filter(function(d){ return d in dataset; }) | |
.attr("fill", function(d){ return color(dataset[d]); }) | |
.select("title") | |
.text(function(d){ return d + " (投稿:" + dataset[d] + "件)"; }); | |
// 曜日のラベル | |
dayLabels = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] | |
svg.selectAll(".dayLabel") | |
.data([0, 1, 2, 3, 4, 5, 6]) | |
.enter() | |
.append("text") | |
.attr("class", "dayLabel") | |
.attr("x", 0) | |
.attr("y", function(d){ return d * CELL_SIZE + 11 + MARGIN_TOP; }) | |
.attr("font-size", 11) | |
.attr("fill", "gray") | |
.text(function(d){ return dayLabels[d]; }); | |
// 月のラベル | |
monthLabels = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] | |
svg.selectAll(".monthLabel") | |
.data(monthRange) | |
.enter() | |
.append("text") | |
.attr("class", "monthLabel") | |
.attr("x", function(d){ return (d3.time.weekOfYear(d) + offset(d)) * CELL_SIZE + MARGIN_LEFT; }) | |
.attr("y", 11) | |
.attr("font-size", 11) | |
.attr("fill", "gray") | |
.text(function(d){ return monthLabels[d.getMonth()]; }); | |
} // return function | |
})(); // drawCalendar |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment