Skip to content

Instantly share code, notes, and snippets.

@LemoNode
Last active March 10, 2020 20:08
Show Gist options
  • Save LemoNode/af0bfd0ab976572d947bf789fa43c54d to your computer and use it in GitHub Desktop.
Save LemoNode/af0bfd0ab976572d947bf789fa43c54d to your computer and use it in GitHub Desktop.
calendar with canvas test
<head>
<title>Calendar</title>
<meta charset="utf-8">
<style>
:root {
--nav-height: 120px;
}
body {
margin: auto;
width: 850px;
font: 14px consolas;
}
canvas {
border: 1px solid #333;
}
nav {
width: 100%;
height: 50px;
}
</style>
</head>
<body onload="main();">
<nav>
<h2 style="font-weight: lighter;">Calendar</h2>
</nav>
<canvas width="850"></canvas>
<script>
const server = {
data: {
"vgrid": ["robpe3", "joeda", "novto1"],
"teams": ["team1", "team2", "tean3"],
"dates": [
"2020-06-01,2020-06-02",
"2020-07-02,2020-06-01",
"2020-06-05,2020-06-08"
],
},
col: () => Object.keys(server.data),
len: () => server.data[server.col()[0]].length,
};
const canvas = document.querySelector("canvas");
const rects = {
padding: 20,
compensate: 5,
size: 15,
row: 105,
curr_row: null,
stroke: "#ccc",
color: null,
text: {color: "transparent", marked: false},
month: null,
mark: null,
detected: false,
data: [],
}
const mouse = {
x: null,
y: null,
click: {
x: null,
y: null,
flag: false,
},
};
is_weekend = date => [0, 6].includes(date.getDay()) ? true : false;
new_week = (date, week) => date.getDay() == 0 ? week += 1 : week;
aabb_detect = (a_pos, a_size, b_pos, b_size) => {
let d1x = b_pos.x - (a_pos.x + a_size.x);
let d1y = b_pos.y - (a_pos.y + a_size.y);
let d2x = a_pos.x - (b_pos.x + b_size.x);
let d2y = a_pos.y - (b_pos.y + b_size.y);
if (d1x > 0 || d1y > 0)
return false;
if (d2x > 0 || d2y > 0)
return false;
return true;
}
update_days_rect = (user, x, y, index) => {
if (user.mark[index]) {
rects.mark = true;
} else {
rects.mark = false;
}
if (rects.stroke == "#333") {
rects.color = "#999";
} else if (rects.mark) {
rects.color = "crimson";
} else if (user.month[index] % 2 == 0) {
rects.color = "#f0f0f0";
} else {
rects.color = "#fff";
}
}
update_days_text = (user, x, y, index) => {
rects.text.marked = false;
if (user.dates.includes(user.value[index])) {
rects.text.color = "#fff";
rects.text.marked = true;
} else if (rects.month == user.month[index]) {
rects.text.color = "#333";
} else {
rects.text.color = "transparent";
}
}
update_days_stroke = (user, x, y, index) => {
let mouse_pos = {x: mouse.x, y: mouse.y};
let mouse_size = {x: 1, y: 1};
let rect_pos = {x: x + 1, y: y + 1};
let rect_size = {x: rects.size - 2, y: rects.size - 2};
if (aabb_detect(mouse_pos, mouse_size, rect_pos, rect_size)) {
rects.stroke = "#333";
rects.text.color = "#fff";
rects.month = user.month[index];
} else {
rects.stroke = "#ccc";
}
}
init_data = () => {
let items = server.col();
for (let i = 0; i < server.len(); i++) {
rects.data.push({
vgrid: server.data[items[0]][i],
teams: server.data[items[1]][i],
dates: server.data[items[2]][i].split(","),
x_pos: [],
y_pos: [],
value: [],
month: [],
days: [],
mark: [],
row: rects.row * (i + 1),
});
}
console.log(rects.data[0])
}
init_canvas = () => {
canvas.height = (rects.row * rects.data.length) + rects.padding;
}
init = () => {
init_data();
init_canvas();
}
gen_dates = year => {
let start = new Date(year, 0, 1);
let end = new Date(year + 1, 0, 0);
let arr = [];
for (let date = start; date <= end; date.setDate(date.getDate() + 1)) {
arr.push(new Date(date));
}
return arr;
}
date_to_string = date => {
return date.toLocaleDateString('se-SE', {
year: 'numeric',
month: 'numeric',
day: 'numeric',
});
}
draw_rects = (ctx, x, y, data, index) => {
ctx.strokeStyle = rects.stroke;
ctx.strokeRect(x, y, rects.size, rects.size);
ctx.fillStyle = rects.color;
ctx.fillRect(x, y, rects.size, rects.size);
}
draw_text = (ctx, x, y, text, index) => {
ctx.font = "12px consolas";
ctx.fillStyle = rects.text.color;
ctx.fillText(text, x + 1, y + (rects.size * .75));
}
gen_days = (ctx, dates, index) => {
let week = 0;
let data_index = 0;
for (let i = 0; i < dates.length; i++) {
week = new_week(dates[i], week);
if (!is_weekend(dates[i])) {
let month = +dates[i].toLocaleDateString('se-SE', {
month: 'numeric'
});
let day = dates[i].toLocaleDateString('se-SE', {
day: 'numeric'
});
let value = date_to_string(dates[i]);
let x = (week * rects.size) + (month) + rects.padding;
let y = (dates[i].getDay() * rects.size) + (rects.row * index);
rects.data[index].x_pos.push(x);
rects.data[index].y_pos.push(y);
rects.data[index].value.push(value);
rects.data[index].month.push(month);
rects.data[index].days.push(day);
if (rects.data[index].dates.includes(value)) {
rects.data[index].mark.push(true);
rects.mark = true;
} else {
rects.data[index].mark.push(false);
rects.mark = false;
}
update_days_rect(rects.data[index], x, y, i);
draw_rects(ctx, x, y, rects.data[index], data_index);
data_index++;
}
}
}
gen_calendar = (ctx, dates) => {
for (let i = 0; i < rects.data.length; i++) {
gen_days(ctx, dates, i);
}
}
mouse_move = (ctx, index) => {
let user = rects.data[index];
for (let i = 0; i < user.x_pos.length; i++) {
let x = user.x_pos[i];
let y = user.y_pos[i];
update_days_text(user, x, y, i);
update_days_stroke(user, x, y, i);
update_days_rect(user, x, y, i);
draw_rects(ctx, x, y, user, i);
if (rects.month != null || rects.text.marked) {
let text = user.days[i].length == 1
? 0 + user.days[i]
: user.days[i];
draw_text(ctx, x, y, text, i);
}
}
}
mouse_click = index => {
let user = rects.data[index];
for (let i = 0; i < user.x_pos.length; i++) {
if (user.x_pos[i] > (mouse.click.x - rects.size) &&
user.x_pos[i] < (mouse.click.x + rects.size) &&
user.y_pos[i] > (mouse.click.y - rects.size) &&
user.y_pos[i] < (mouse.click.y + rects.size)) {
user.mark[i] = !user.mark[i];
let flag = user.dates.indexOf(user.value[i]);
if (flag > -1) {
user.dates.splice(flag, 1);
} else {
user.dates.push(user.value[i]);
}
break;
}
}
}
update = (ctx) => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < rects.data.length; i++) {
rects.month = null;
if (mouse.click.flag) {
if (mouse.click.y > rects.data[i].row - rects.row &&
mouse.click.y < rects.data[i].row) {
mouse_click(i);
}
}
mouse_move(ctx, i);
}
mouse.click.flag = false;
}
main = () => {
init();
let year = new Date().getFullYear();
let dates = gen_dates(year);
let ctx = canvas.getContext("2d");
let html = document.querySelector("html");
let calendar = gen_calendar(ctx, dates);
canvas.onmousemove = e => {
mouse.x = e.offsetX;
mouse.y = e.offsetY;
};
canvas.onclick = e => {
mouse.click.x = e.offsetX;
mouse.click.y = e.offsetY;
mouse.click.flag = true;
}
let loop = t => {
update(ctx);
requestAnimationFrame(loop);
}
return requestAnimationFrame(t => loop(t));
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment