From bc1218acd75b6d0594e568e07892f9f9bbb53d7a Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Wed, 28 Aug 2019 10:29:13 +0200 Subject: Use canvas for drawing the schedules. --- public/app.css | 4 ++ public/index.html | 5 +- public/js/app.js | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 170 insertions(+), 8 deletions(-) diff --git a/public/app.css b/public/app.css index 28ffb34..752e9ac 100644 --- a/public/app.css +++ b/public/app.css @@ -8,3 +8,7 @@ body { color: #ccc; font-size: 10pt; } + +canvas { + background-color: white; +} diff --git a/public/index.html b/public/index.html index 6e6333f..22b9fc3 100644 --- a/public/index.html +++ b/public/index.html @@ -7,9 +7,6 @@

Ramaskrik 2019

-
- -
-
+
diff --git a/public/js/app.js b/public/js/app.js index c6899a7..e219af4 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -49,14 +49,174 @@ function log_film(film) { + ")") } +function date_f(d) { + let opts = { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' } + return new Intl.DateTimeFormat('nb-NO', opts).format(d) +} + window.addEventListener("load", function() { + let screenings_by_date = new Map() + + function _add(screening) { + let d = Date.parse(screening.date) + if (!screenings_by_date.has(d)) + screenings_by_date.set(d, new Array()) + + let s = screenings_by_date.get(d) + s.push(screening) + }; + + function _end_time(screening) { + if (screening.end_time < screening.start_time) { + return screening.end_time + .split(':') + // Add 24 to the hour component of the time string + .map( (v, i) => i == 0 ? (parseInt(v) + 24).toString() : v) + .join(':') + } + else { + return screening.end_time + } + } + + function _time_to_sec(t) { + let expl = t.split(':').map( v => parseInt(v) ) + return expl[0] * 3600 + expl[1] * 60 + expl[2] + } + + function _sec_to_time(v) { + let hour = Math.floor(v / 3600) + v = v % 3600 + let min = Math.floor(v / 60) + let f = Intl.NumberFormat('nb-NO', { minimumIntegerDigits: 2 }) + return [ f.format(hour), f.format(min) ].join(':') + } + + function break_text(c, text, x, y, width) { + let len = c.measureText(text).width + if (len < width) { + c.fillText(text, x, y) + return + } + + let expl = text.split(' ') + let space = c.measureText(' ').width + let llen = 0 + let lpos = 0 + + for (let frag of expl) { + flen = c.measureText(frag).width + llen += flen + if (llen > width) { + llen = 0 + lpos = 0 + y += 15 + } + c.fillText(frag, x + lpos, y) + lpos += flen + space + } + } + + function center_text(c, text, x, y, width) { + let len = c.measureText(text).width + let xpos = Math.ceil((width - len) / 2) + c.fillText(text, x + xpos, y) + } + + let margin = 30; + let xmargin = 50; + + function draw_timescale(c, start, end) { + let dur = Math.ceil((end - start) / 30) + + c.font = '10px Helvetica' + c.lineWidth = 'thin' + c.strokeStyle = '#ccc' + + for (let y = 0; y <= dur; y += 30) { + let ypos = y + margin; + c.beginPath() + c.moveTo(35, ypos) + c.lineTo(510, ypos) + c.stroke() + c.fillText(_sec_to_time(y * 30 + start + margin), 5, ypos + 3) + } + } + + function draw_room_headers(c, rooms) { + let x = 0; + c.font = '15px sans-serif' + + for (let r of [...rooms]) { + center_text(c, r, 50 + x, 15, 100) + x += 150 + } + } + + function draw_screenings(c, screenings, start_time, rooms) { + let r = [...rooms] + + c.strokeStyle = '#000' + + for (let s of screenings) { + let ystart = Math.ceil((_time_to_sec(s.start_time) - start_time) / 30) + margin; + let height = Math.ceil((_time_to_sec(_end_time(s)) - start_time ) / 30) + margin - ystart; + let ri = s.room.id - 1 + let xstart = xmargin + ri * 150 + + c.fillStyle = '#ec9' + c.fillRect(xstart, ystart, 100, height) + c.strokeRect(xstart, ystart, 100, height) + + c.fillStyle = '#000' + break_text(c, s.film.title, xstart + 5, ystart + 15, 90) + } + } + load_screenings(function() { - console.log(this.response) - this.response.forEach(function(screening) { - console.log(screening.film.title + "@" + screening.room.name + ": " + screening.date) - }) + this.response.forEach(_add) + + console.log("Screenings in " + screenings_by_date.size + " days: ") + for (let date of screenings_by_date.keys()) { + let date_str = date_f(date) + console.log(date_str) + + let s = screenings_by_date.get(date) + let start_time = s + .map( el => _time_to_sec(el.start_time) ) + .reduce( (acc, cur) => cur < acc ? cur : acc, _time_to_sec('23:59:59') ) + let end_time = s + .map( el => _time_to_sec(_end_time(el))) + .reduce( (acc, cur) => cur > acc ? cur : acc, 0 ) + + console.log(" Start time: " + _sec_to_time(start_time)) + console.log(" End time : " + _sec_to_time(end_time)) + + let dur = end_time - start_time + console.log(" Duration : " + _sec_to_time(dur)) + + // Each line in the canvas equals half a minute + let canvas_height = Math.ceil(dur / 30) + 60 + + let p = document.querySelector('#program') + let day = document.createElement('section') + day.id = "program-" + date_str + day.innerHTML = '

' + date_str + '

' + + '' + + '' + p.appendChild(day) + + let canvas = document.getElementById('canvas-' + date_str) + let c = canvas.getContext('2d'); + let rooms = new Set(s.map( el => el.room.name )) + draw_room_headers(c, rooms) + draw_timescale(c, start_time, end_time) + draw_screenings(c, s, start_time, rooms) + } + }) + /* fetch_rooms(function() { let table = document.getElementById("screening-table") let row = document.createElement("tr") @@ -69,5 +229,6 @@ window.addEventListener("load", function() { row.appendChild(item) }) }) + */ console.log("Holahey!") }) -- cgit v1.2.3