HeatMapCalendar 라는 이름은 그냥 내 마음대로 붙여봤음...
2012 년 예제
1년치 달력을 가로축을 월(month), 세로축을 주(week)로 배열하여 한 눈에 볼 수 있게 해주는 달력.
각 날짜마다 데이터가 있고, 해당 데이터를 색값으로 계산하여 여러 형태로 보여줄 수 있음.
원래라면 좀 더 예쁘게 나왔어야 하는건데,
예를 들면 여름은 빨갛고 겨울은 파랗다거나...-_-;
참조: http://mbostock.github.com/d3/ex/calendar.html
참조링크의 원본은 그림을 그리는 스타일이나, 간단하게 테이블로 가능할 것 같아서 만들어 봤음.
핵심은 아래와 같음.
- 1년치 날짜정보를 배열로 가져와 pivot 처리.
- 날짜정보를 인덱스로 가지는 배열과 맵핑하여 색값 계산.
색값은 참조링크처럼 말 그대로 HeatMap 처럼 나타낼 수도 있고, 데이터의 성격에 따라서 여러가지 응용이 가능할 것으로 보여짐.
<!DOCTYPE HTML>
<html>
<head>
<style>
.tbl_cal { border: 0px; border-collapse: collapse; border-spacing: 0px; }
.tbl_cal td { width: 10px; height: 10px; border: 1px solid
#CDCDCD; }
.tbl_cal .no_date { border: 0px; }
.tbl_cal .sunday { border-top: 2px solid black; }
.tbl_cal .saturday { border-bottom: 2px solid black; }
.tbl_cal .first_day_of_month { border-top: 2px solid black; }
.tbl_cal .first_week_of_month { border-left: 2px solid black; }
.tbl_cal .last_week { border-right: 2px solid black; }
.tbl_cal .last_day_of_year { border-bottom: 2px solid black; }
</style>
<script>
$(document).ready(
function
(){
// 년도 지정
var
year =
new
Date().getFullYear();
// 시작일, 종료일
var
iStart =
new
Date(year, 0, 1, 0, 0, 0).getTime();
var
iEnd =
new
Date(year, 11, 31, 0, 0, 0).getTime();
// 날짜 데이터를 저장할 배열
var
aDate = [[]];
// 시작 빈칸 채우기
var
iStartPos =
new
Date(year,0,1,0,0,0).getDay();
for
(
var
i=0; i<iStartPos; i++) {
aDate[0][i] =
null
;
}
// 날짜 데이터 채우기 (+임시 데이터 만들기)
var
aTmpData = {};
i = iStart;
var
iWeek = 0;
var
j = iStartPos;
while
(i <= iEnd) {
var
iPos = (
new
Date(i)).getDay();
if
(!aDate[iWeek]) aDate.push([]);
var
oDate = getDate(i);
aDate[iWeek][iPos] = {
date: oDate
};
// 임시 데이터 만들기
aTmpData[oDate.year+oDate.month+oDate.day] = Math.floor(Math.random() * 255) + 1;
i += 86400000;
++j;
if
(j > 6) {
j = 0;
++iWeek;
}
}
// 마지막 빈칸 채우기
iEndPos =
new
Date(i).getDay();
if
(iEndPos > 0) {
for
(i=iEndPos; i<7; i++) {
aDate[iWeek][i] =
null
;
}
}
// pivot
var
aDatePivot = [[], [], [], [], [], [], []];
for
(i=0; i<aDate.length; i++) {
for
(j=0; j<aDate[i].length; j++) {
aDatePivot[j].push(aDate[i][j]);
}
}
// 테이블 만들기
var
sMonth =
''
;
var
iTotalWeeks = aDatePivot[0].length;
var
sCalendarTable =
''
;
sCalendarTable +=
'<table id="tbl_cal" class="tbl_cal">'
;
for
(i=0; i<aDatePivot.length; i++) {
sCalendarTable +=
'<tr>'
;
for
(j=0; j<iTotalWeeks; j++) {
var
aClass = [];
var
bgColor =
''
;
var
sId =
''
;
if
(aDatePivot[i][j] ==
null
) aClass.push(
'no_date'
);
else
{
var
d = aDatePivot[i][j].date;
sId =
' id="tbl_cal_'
+d.year+d.month+d.day+
'"'
;
// 테이블 상단,하단
if
(i == 0) aClass.push(
'sunday'
);
else
if
(i == 6) aClass.push(
'saturday'
);
// 월의 첫날, 마지막 날
if
(d.day ==
'01'
) {
aClass.push(
'first_day_of_month'
);
}
// 월간 분리
if
(d.month != sMonth) {
sMonth = d.month;
aClass.push(
'first_week_of_month'
);
}
// 테이블 마지막
if
(j == iTotalWeeks-1) {
aClass.push(
'last_week'
);
if
(d.month==12 && d.day==31 && i<6) aClass.push(
'last_day_of_year'
);
}
else
if
(j == iTotalWeeks-2) {
if
(aDatePivot[i][j+1] ==
null
) aClass.push(
'last_week'
);
}
// 색상 지정 (with 임시데이터)
var
RGB =
''
;
RGB = (255 - aTmpData[d.year+d.month+d.day]).toString(16);
if
(RGB.length < 2) RGB =
'0'
+RGB;
RGB =
'#FF'
+RGB+RGB;
bgColor =
' style="background-color:'
+RGB+
';"'
;
}
sCalendarTable +=
'<td'
+sId+
' class="'
+aClass.join(
' '
)+
'"'
+bgColor+
'></td>'
;
}
sCalendarTable +=
'</tr>'
;
}
sCalendarTable +=
'</table>'
;
var
sInfoLayer =
'<div id="info" style="display:none;"></div>'
;
// 붙이기 + 이벤트 걸기
$(
'body'
).append(sCalendarTable+sInfoLayer)
.find(
'[id="tbl_cal"] td'
)
.mouseover(
function
(){
if
(!$(
this
).attr(
'id'
))
return
;
$(
'#info'
).show();
})
.mousemove(
function
(e){
if
(!$(
this
).attr(
'id'
))
return
;
var
d = $(
this
).attr(
'id'
).replace(/tbl_cal_/,
''
);
var
info = d+
'<br />'
+aTmpData[d];
$(
'#info'
).html(info);
console.log();
$(
'#info'
)
.css(
'border'
,
'1px solid black'
).css(
'background-color'
,
'yellow'
)
.css(
'left'
, e.pageX - (parseInt($(
'#info'
).css(
'width'
))/2))
.css(
'top'
, e.pageY - (parseInt($(
'#info'
).css(
'height'
))) - 5)
.css(
'z-index'
, 999).css(
'position'
,
'absolute'
).css(
'display'
,
''
);
})
.mouseout(
function
(){
if
(!$(
this
).attr(
'id'
))
return
;
$(
'#info'
).hide();
});
// 타임스탬프를 받아서 Ymd 값 반환
function
getDate(timestamp)
{
var
zeroPad =
function
(digit, len){
var
i = digit.toString().length;
while
(i < len) {
digit =
'0'
+digit;
++i;
}
return
digit;
};
var
aResult = {
'year'
:
null
,
'month'
:
null
,
'day'
:
null
};
var
d =
new
Date(timestamp);
aResult.year = d.getFullYear()+
''
;
aResult.month = zeroPad(d.getMonth()+1, 2)+
''
;
aResult.day = zeroPad(d.getDate(), 2)+
''
;
return
aResult;
}
});
</script>
</head>
<body>
</body>
</html>
'JavaScript' 카테고리의 다른 글
[JavaScript] object 키로 정렬 (object sort by key name) (0) | 2013.01.21 |
---|---|
[JavaScript] 표현가능한 최고 숫자 (Number.MAX_VALUE) (0) | 2012.11.22 |
[JavaScript] 한줄짜리 thousand separate (number_format) (0) | 2012.05.04 |
[jQuery] iframe의 body select (마우스 드래그로 움직이기) (0) | 2011.10.11 |
[JavaScript] HTML Element의 위치, 크기 절대값 (0) | 2011.01.26 |