** 第一次写文章 不喜欢请喷我 您的支持是我最大的动力 **
<meta charset="utf-8">
<html>
<head>
<style>
body {
font: 1.1em sans-serif;
background-color: #255;
}
#chart{
width: 800px;
margin: 0 auto;
}
.background {
fill: #eee;
}
.day {
fill: none;
stroke: #fff;
}
/* hover info */
#tooltip {
background-color: #fff;
border: 2px solid #ccc;
padding: 10px;
}
style>
head>
<body>
<div id="chart" class="clearfix">div>
<script src="d3.v3.js">script>
<script src="jquery.min.js" type="text/javascript">script>
<script>
//颜色其实就是根据该天的空气质量大小去判断 严不严重的颜色
var width = 500,//画布宽度
height = 500,//画布高度
cellSize = 25; //一格占用大小
var date = new Date();//该实例为当前时间
var yearDate = 2019;//date.getYear()+1900;//当前年份
var monthNo =1;//date.getMonth()+1;//当前月份
var dayDate = 12;//date.getDate();//当前月的第几天
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");
//用于将每一个日期文字 和 背景 拼接成7×6
var countDay = 0;
var c = 0;
var countDayFun = function(i){
if(i==6 && c==0){
c++;
}else{
if(i==0){
countDay++;
}
}
};
var color = d3.scale.quantize()
.domain([-.05, .05])
.range(d3.range(11).map(function(d) { return "q" + d + "-11"; }));
//创建画布
var svg = d3.select("#chart").selectAll("svg")
.data(d3.range(yearDate, yearDate+1))
.enter().append("svg")
.attr("width", width)
.attr("height", height)
.append("g");
// 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");
//获取当前月的最后一天
function getCurrentMonthLast(date){
var currentMonth=date.getMonth();
var nextMonth=++currentMonth;
var nextMonthFirstDay=new Date(date.getFullYear(),nextMonth,1);
var oneDay=1000*60*60*24;
return new Date(nextMonthFirstDay-oneDay);
}
//获取当前月的第一天是周几
function getCurrentOneDay(){
var date=new Date(yearDate,monthNo-1);
date.setDate(1);
return date.getDay();
}
//发送请求 返回数据拼接 其实逻辑挺复杂的 拼接按实际来吧
var heatmapChart = function (url) {
d3.json(
url,
function (data) {
var calendar = [];
//拼接示例 var calendar = [{day:该天数是周几,hour:这个月的第几周,value:值用于获取背景指定Colors的背景色渲染}];
//该拼接只提供参考 因为每个人写的返回数据都会不一样
for (var i = 0; i < data.length; i++) {
var datum = data[i];
var timeStrs = datum.time.split('-');
var date = new Date(datum.time);
if((date.getMonth()+1) == monthNo){
//获取上个月的最后一天是周几
var lastDay = getCurrentMonthLast(new Date(yearDate,monthNo-2)).getDay();
//获取数据的今天本月的第几周
var weekDate = Math.ceil((date.getDate()+6-date.getDay())/7);
if(lastDay==6){//判断如果上个月的最后一天是周六
//本月周+1 防止背景色渲染出现问题 这里是个坑 可能出现上个月的30号正好是
//周六 本月1号在第二行 渲染在第一行
weekDate = Math.ceil((date.getDate()+6-date.getDay())/7)+1;
}
calendar.push({
day: date.getDay(),
hour: weekDate,//parseInt(timeStrs[2]),
value: datum.AQI
});
}
}
//拼接完成后 执行该函数
drawCalendar(calendar);
});
};
var data = [
{
day: 2,
hour: 1,
value: 132.9583
},
{
day: 3,
hour: 1,
value: 183.0417
},
{
day: 4,
hour: 1,
value: 212.7083
},
{
day: 5,
hour: 1,
value: 213.2273
},
{
day: 6,
hour: 1,
value: 75
},
{
day: 0,
hour: 2,
value: 142.75
},
{
day: 1,
hour: 2,
value: 254.375
},
{
day: 2,
hour: 2,
value: 81.5833
},
{
day: 3,
hour: 2,
value: 54.7083
},
{
day: 4,
hour: 2,
value: 109.75
},
{
day: 5,
hour: 2,
value: 126.0833
},
{
day: 6,
hour: 2,
value: 197.4
}
];
//==执行可测试绘制日历 此处乃重中之重了 核心代码
drawCalendar(data);
//该函数接收data数据
function drawCalendar(data) {
//背景颜色
var colors =["rgba(109,204,38,1)","rgba(251,209,63,1)","rgba(252,136,35,1)","rgba(251,13,28,1)","rgba(149,12,82,1)","rgba(96,2,26,1)","rgba(13,13,13,1)"];
var colorScale = function (aqi) {
var result = colors[0];
if (aqi >= 500) { // '爆表'
result = colors[6];
} else if (aqi < 500 && aqi >= 300) { // '严重污染'
result = colors[5];
} else if (aqi < 300 && aqi >= 200) { // '重度污染'
result = colors[4];
} else if (aqi < 200 && aqi >= 150) { // '中度污染'
result = colors[3];
} else if (aqi < 150 && aqi >= 100) { // '轻度污染'
result = colors[2];
} else if (aqi < 100 && aqi >= 50) { // '良'
result = colors[1];
} else if (aqi < 50 && aqi >= 0) { // '优'
result = colors[0];
}
return result;
};
//绘制背景色
countDay=1;c=0;
var cards = svg.selectAll(".hour")
.data(data, function (d) { return d.day + ':' + d.hour; });
cards.append("title");
cards.enter().append("rect")
.attr("x", function (d) { return (d.day) * cellSize *2; })//x位置
.attr("y", function (d) { //y位置
countDayFun(d.day);
return countDay * cellSize *2;
})
.attr("rx", 4)//背景边框圆滑度
.attr("ry", 4)//背景边框圆滑度
.attr("class", "hour bordered")
.attr("width", cellSize)//背景单格宽度
.attr("height", cellSize)//背景单格高度
.style("fill", colors[0]);
cards.transition().duration(1000)
.style("fill", function (d) { return colorScale(d.value); });//return 执行value大小获取的背景颜色值
cards.select("title").text(function (d) { return d.value; });
cards.exit().remove();
//创建天数 字 必须在背景颜色添加之后 不然会形成覆盖
countDay=0,c=0;
var texts = svg.selectAll("text")
.data(function(d) {
//获取上个月最后一天是周几
var pre = getCurrentMonthLast( new Date(new Date(yearDate,monthNo-1).setMonth(new Date(yearDate,monthNo-1).getMonth()-1))).getDay();
//有必要说一下 返回的类型为Date类型的数组形式
//总共返回的是本月之前的补全时间也就是7×6格的第一格到本月之后的补全时间
//只不过我获取的时间从本月之前的几天到下个月低 截取到42个时间点,正好到本月之后的几天
return d3.time.days(new Date(yearDate,monthNo-1,-(pre)), new Date(d,monthNo+1,0)).slice(0,42);
})
.enter().append("text")
.attr("class", "day")
.attr("width", cellSize)
.attr("height", cellSize)
.attr("x", function(d) {
return (day(d)) * cellSize *2 +13;
})
.attr("y", function(d,i) {
countDayFun(day(d));
return countDay*cellSize *2 +18;
})
.attr("text-anchor","middle")
.style("fill","none")
.style("stroke", function(d){
if((d.getMonth()+1)==monthNo){//判断如果该天是本月的 文本颜色为白色 否则是蓝色的
return "#fff";
}else{
return "#00569f";
}
})
.text(function(d){
return d.getDate();//返回文本内容 42个时间点的某一天
})
.style({"font-size":"15px","z-index":"999"});
//这个没什么可说的 就是日期周标注而已 写死的
var legend = svg.selectAll(".legend")
.data(["日", "一", "二", "三", "四", "五", "六"], function (d) { return d; });
legend.enter().append("g")
.attr("class", "legend")
.append("text")
.attr("class", "mono")
.text(function (d) { return d; })
.attr("x", function (d, i) { return cellSize * i * 2 +4; })
.attr("y", cellSize)
.style("fill","#fff");
};
script>
body>
html>