Javascript d3 热图日历,如何追加月份的日期?
Javascript d3 heatmap calendar, how to append day of the month?
我有一个 d3 日历,灵感来自:
http://bl.ocks.org/KathyZ/c2d4694c953419e0509b
现在可以正常工作,但我不知道在哪里或如何添加文本来显示月份中的第几天,意思是数字(1、2、... 31 等)每一天。我必须以某种方式将文本元素附加到日期矩形,但我不知道该怎么做。
function normal_cal(dom, data, clk_fn, scp){
var width = 900,
height = 259,
cellSize = 12; // cell size
var no_months_in_a_row = Math.floor(width / (cellSize * 7 + 50));
var shift_up = cellSize * 1;
var day = d3.time.format("%w"), // day of the week
day_of_month = d3.time.format("%e") // day of the month
day_of_year = d3.time.format("%j")
week = d3.time.format("%U"), // week number of the year
month = d3.time.format("%m"), // month number
year = d3.time.format("%Y"),
percent = d3.format(".1%"),
format = d3.time.format("%Y-%m-%d"),
parseDate = d3.time.format("%Y-%m-%d").parse,
year_getter = d3.time.format("%Y%"),
day_getter=d3.time.format("%a, %e");
var color = d3.scale.quantize()
.domain([-.05, .05])
.range(d3.range(11).map(function(d) { return "q" + d + "-11"; }));
// range?
var years = [d3.extent(data, function(d) { return year_getter(parseDate(d.Date)); })];
var start_year = parseInt(years[0][0]);
var end_year = parseInt(years[0][1]);
var svg = d3.select(dom.get(0)).selectAll("svg")
.data(d3.range(start_year, end_year + 1))
.enter().append("svg")
.attr("width", width)
.attr("height", height)
.attr("class", "RdYlGn")
.append("g")
var rect = svg.selectAll(".day")
.data(function(d) {
return d3.time.days(new Date(d, 0, 1), new Date(d + 1, 0, 1));
})
.enter().append("rect")
.attr("class", "day")
.attr("width", cellSize)
.attr("height", cellSize)
.attr("x", function(d) {
var month_padding = 1.2 * cellSize*7 * ((month(d)-1) % (no_months_in_a_row));
return day(d) * cellSize + month_padding;
})
.attr("y", function(d) {
var week_diff = week(d) - week(new Date(year(d), month(d)-1, 1) );
var row_level = Math.ceil(month(d) / (no_months_in_a_row));
return (week_diff*cellSize) + row_level*cellSize*8 - cellSize/2 - shift_up;
})
.datum(format);
var month_titles = svg.selectAll(".month-title") // Jan, Feb, Mar and the whatnot
.data(function(d) {
return d3.time.months(new Date(d, 0, 1), new Date(d + 1, 0, 1)); })
.enter().append("text")
.text(monthTitle)
.attr("x", function(d, i) {
var month_padding = 1.2 * cellSize*7* ((month(d)-1) % (no_months_in_a_row));
return month_padding;
})
.attr("y", function(d, i) {
var week_diff = week(d) - week(new Date(year(d), month(d)-1, 1) );
var row_level = Math.ceil(month(d) / (no_months_in_a_row));
return (week_diff*cellSize) + row_level*cellSize*8 - cellSize - shift_up;
})
.attr("class", "month-title")
.attr("d", monthTitle);
var year_titles = svg.selectAll(".year-title") // Jan, Feb, Mar and the whatnot
.data(function(d) {
return d3.time.years(new Date(d, 0, 1), new Date(d + 1, 0, 1)); })
.enter().append("text")
.text(yearTitle)
.attr("x", function(d, i) { return width/2 - 100; })
.attr("y", function(d, i) { return cellSize*3 - shift_up; })
.attr("class", "year-title")
.attr("d", yearTitle);
// Tooltip Object
var tooltip = d3.select("body")
.append("div").attr("id", "tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("a simple tooltip");
//==================================================================================PROCESS DATA
//==================================================================================PROCESS DATA
//==================================================================================PROCESS DATA
var data = d3.nest()
.key(function(d) { return d.Date; })
.rollup(function(d) {
return {"value": -5,
"comment": d[0].comment,
"key": d[0].key
};
})
.map(data);
rect.filter(function(d) { return d in data; })
.attr("class", function(d) { return "day " + color(data[d].value); })
.select("title")
.text(function(d) {
return d + ": " +data[d].comment;
});
// Tooltip
rect.on("mouseover", mouseover);
rect.on("mouseout", mouseout);
rect.on("click", function(d){
clk_fn(d, data, scp);
});
function mouseover(d) {
console.log(data[d]);
tooltip.style("visibility", "visible");
var purchase_text = (data[d] !== undefined) ? day_getter(parseDate(d)) + " : " + data[d].comment : day_getter(parseDate(d));
tooltip.transition()
.duration(200)
.style("opacity", .9);
tooltip.html(purchase_text)
.style("left", (d3.event.pageX)+30 + "px")
.style("top", (d3.event.pageY) + "px");
}
function mouseout (d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
var $tooltip = $("#tooltip");
$tooltip.empty();
}
function dayTitle (t0) {
return t0.toString().split(" ")[2];
}
function monthTitle (t0) {
return t0.toLocaleString("en-us", { month: "long" });
}
function yearTitle (t0) {
return t0.toString().split(" ")[3];
}
//});
}
如何在方块上附加月中的第几天(数字)?
根据您提供的link:
http://bl.ocks.org/KathyZ/c2d4694c953419e0509b
我已经以这种方式修改了 rect
定义(只需将定义 rect (var rect = svg.selectAll(".day")...)
的块替换为以下内容来尝试):
var rectContainer = svg.selectAll(".day")
.data(function(d) {
return d3.time.days(new Date(d, 0, 1), new Date(d + 1, 0, 1));
})
.enter().append("g")
.attr("transform", function(d) {
var month_padding = 1.2 * cellSize*7 * ((month(d)-1) % (no_months_in_a_row));
var x = day(d) * cellSize + month_padding;
var week_diff = week(d) - week(new Date(year(d), month(d)-1, 1) );
var row_level = Math.ceil(month(d) / (no_months_in_a_row));
var y = (week_diff*cellSize) + row_level*cellSize*8 - cellSize/2 - shift_up;
return "translate(" + x + "," + y + ")";
});
var rect = rectContainer.append("rect")
.attr("class", "day")
.attr("width", cellSize)
.attr("height", cellSize)
.datum(format);
rectContainer.append("text")
.attr("x", cellSize / 2)
.attr("y", cellSize / 2)
.attr("dy", ".35em")
.text(function(d) {
return day_of_month(d);
})
.style("font-size", "10px");
由于无法在 rect
中添加 text
(详细信息 here),因此您必须创建一个 容器 它将包含 rect 和 text.
由于矩形的位置现在由容器的位置处理,因此必须设置容器的坐标。这是使用 transform
属性通过翻译容器而不是设置矩形的 x 和 y 来完成的。
day_of_month() 格式化程序定义在 Kathy Zhou 代码中 link 的顶部。
我会让你管理样式(字体大小,将文本恰好放在中心,...)
我有一个 d3 日历,灵感来自:
http://bl.ocks.org/KathyZ/c2d4694c953419e0509b
现在可以正常工作,但我不知道在哪里或如何添加文本来显示月份中的第几天,意思是数字(1、2、... 31 等)每一天。我必须以某种方式将文本元素附加到日期矩形,但我不知道该怎么做。
function normal_cal(dom, data, clk_fn, scp){
var width = 900,
height = 259,
cellSize = 12; // cell size
var no_months_in_a_row = Math.floor(width / (cellSize * 7 + 50));
var shift_up = cellSize * 1;
var day = d3.time.format("%w"), // day of the week
day_of_month = d3.time.format("%e") // day of the month
day_of_year = d3.time.format("%j")
week = d3.time.format("%U"), // week number of the year
month = d3.time.format("%m"), // month number
year = d3.time.format("%Y"),
percent = d3.format(".1%"),
format = d3.time.format("%Y-%m-%d"),
parseDate = d3.time.format("%Y-%m-%d").parse,
year_getter = d3.time.format("%Y%"),
day_getter=d3.time.format("%a, %e");
var color = d3.scale.quantize()
.domain([-.05, .05])
.range(d3.range(11).map(function(d) { return "q" + d + "-11"; }));
// range?
var years = [d3.extent(data, function(d) { return year_getter(parseDate(d.Date)); })];
var start_year = parseInt(years[0][0]);
var end_year = parseInt(years[0][1]);
var svg = d3.select(dom.get(0)).selectAll("svg")
.data(d3.range(start_year, end_year + 1))
.enter().append("svg")
.attr("width", width)
.attr("height", height)
.attr("class", "RdYlGn")
.append("g")
var rect = svg.selectAll(".day")
.data(function(d) {
return d3.time.days(new Date(d, 0, 1), new Date(d + 1, 0, 1));
})
.enter().append("rect")
.attr("class", "day")
.attr("width", cellSize)
.attr("height", cellSize)
.attr("x", function(d) {
var month_padding = 1.2 * cellSize*7 * ((month(d)-1) % (no_months_in_a_row));
return day(d) * cellSize + month_padding;
})
.attr("y", function(d) {
var week_diff = week(d) - week(new Date(year(d), month(d)-1, 1) );
var row_level = Math.ceil(month(d) / (no_months_in_a_row));
return (week_diff*cellSize) + row_level*cellSize*8 - cellSize/2 - shift_up;
})
.datum(format);
var month_titles = svg.selectAll(".month-title") // Jan, Feb, Mar and the whatnot
.data(function(d) {
return d3.time.months(new Date(d, 0, 1), new Date(d + 1, 0, 1)); })
.enter().append("text")
.text(monthTitle)
.attr("x", function(d, i) {
var month_padding = 1.2 * cellSize*7* ((month(d)-1) % (no_months_in_a_row));
return month_padding;
})
.attr("y", function(d, i) {
var week_diff = week(d) - week(new Date(year(d), month(d)-1, 1) );
var row_level = Math.ceil(month(d) / (no_months_in_a_row));
return (week_diff*cellSize) + row_level*cellSize*8 - cellSize - shift_up;
})
.attr("class", "month-title")
.attr("d", monthTitle);
var year_titles = svg.selectAll(".year-title") // Jan, Feb, Mar and the whatnot
.data(function(d) {
return d3.time.years(new Date(d, 0, 1), new Date(d + 1, 0, 1)); })
.enter().append("text")
.text(yearTitle)
.attr("x", function(d, i) { return width/2 - 100; })
.attr("y", function(d, i) { return cellSize*3 - shift_up; })
.attr("class", "year-title")
.attr("d", yearTitle);
// Tooltip Object
var tooltip = d3.select("body")
.append("div").attr("id", "tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("a simple tooltip");
//==================================================================================PROCESS DATA
//==================================================================================PROCESS DATA
//==================================================================================PROCESS DATA
var data = d3.nest()
.key(function(d) { return d.Date; })
.rollup(function(d) {
return {"value": -5,
"comment": d[0].comment,
"key": d[0].key
};
})
.map(data);
rect.filter(function(d) { return d in data; })
.attr("class", function(d) { return "day " + color(data[d].value); })
.select("title")
.text(function(d) {
return d + ": " +data[d].comment;
});
// Tooltip
rect.on("mouseover", mouseover);
rect.on("mouseout", mouseout);
rect.on("click", function(d){
clk_fn(d, data, scp);
});
function mouseover(d) {
console.log(data[d]);
tooltip.style("visibility", "visible");
var purchase_text = (data[d] !== undefined) ? day_getter(parseDate(d)) + " : " + data[d].comment : day_getter(parseDate(d));
tooltip.transition()
.duration(200)
.style("opacity", .9);
tooltip.html(purchase_text)
.style("left", (d3.event.pageX)+30 + "px")
.style("top", (d3.event.pageY) + "px");
}
function mouseout (d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
var $tooltip = $("#tooltip");
$tooltip.empty();
}
function dayTitle (t0) {
return t0.toString().split(" ")[2];
}
function monthTitle (t0) {
return t0.toLocaleString("en-us", { month: "long" });
}
function yearTitle (t0) {
return t0.toString().split(" ")[3];
}
//});
}
如何在方块上附加月中的第几天(数字)?
根据您提供的link:
http://bl.ocks.org/KathyZ/c2d4694c953419e0509b
我已经以这种方式修改了 rect
定义(只需将定义 rect (var rect = svg.selectAll(".day")...)
的块替换为以下内容来尝试):
var rectContainer = svg.selectAll(".day")
.data(function(d) {
return d3.time.days(new Date(d, 0, 1), new Date(d + 1, 0, 1));
})
.enter().append("g")
.attr("transform", function(d) {
var month_padding = 1.2 * cellSize*7 * ((month(d)-1) % (no_months_in_a_row));
var x = day(d) * cellSize + month_padding;
var week_diff = week(d) - week(new Date(year(d), month(d)-1, 1) );
var row_level = Math.ceil(month(d) / (no_months_in_a_row));
var y = (week_diff*cellSize) + row_level*cellSize*8 - cellSize/2 - shift_up;
return "translate(" + x + "," + y + ")";
});
var rect = rectContainer.append("rect")
.attr("class", "day")
.attr("width", cellSize)
.attr("height", cellSize)
.datum(format);
rectContainer.append("text")
.attr("x", cellSize / 2)
.attr("y", cellSize / 2)
.attr("dy", ".35em")
.text(function(d) {
return day_of_month(d);
})
.style("font-size", "10px");
由于无法在 rect
中添加 text
(详细信息 here),因此您必须创建一个 容器 它将包含 rect 和 text.
由于矩形的位置现在由容器的位置处理,因此必须设置容器的坐标。这是使用 transform
属性通过翻译容器而不是设置矩形的 x 和 y 来完成的。
day_of_month() 格式化程序定义在 Kathy Zhou 代码中 link 的顶部。
我会让你管理样式(字体大小,将文本恰好放在中心,...)