diff --git a/client/cursor.js b/client/cursor.js index a6ff6f3..4f95804 100644 --- a/client/cursor.js +++ b/client/cursor.js @@ -1,6 +1,5 @@ function on_down(e) { if (e.button === 1) { - elements.cursor.classList.add('dhide'); elements.canvas0.classList.add('moving'); storage.state.moving = true; storage.state.mousedown = true; @@ -76,7 +75,6 @@ async function on_up(e) { if (storage.state.moving && (e.button === 1 || e.button === 0)) { storage.state.mousedown = false; if (!storage.state.spacedown) { - elements.cursor.classList.remove('dhide'); elements.canvas0.classList.remove('moving'); storage.state.moving = false; return; @@ -94,16 +92,21 @@ async function on_up(e) { function on_keydown(e) { if (e.code === 'Space' && !storage.state.drawing) { - elements.cursor.classList.add('dhide'); elements.canvas0.classList.add('moving'); storage.state.moving = true; storage.state.spacedown = true; + return; + } + + if (e.code === 'KeyZ' && e.ctrlKey) { + const event = undo_event(); + queue_event(event); + return; } } function on_keyup(e) { if (e.code === 'Space' && storage.state.moving) { - elements.cursor.classList.remove('dhide'); elements.canvas0.classList.remove('moving'); storage.state.moving = false; storage.state.spacedown = false; @@ -112,7 +115,6 @@ function on_keyup(e) { function on_leave(e) { if (storage.state.moving) { - elements.cursor.classList.remove('dhide'); elements.canvas0.classList.remove('moving'); storage.state.moving = false; storage.state.holding = false; diff --git a/client/default.css b/client/default.css index ea5c4e9..d5614e1 100644 --- a/client/default.css +++ b/client/default.css @@ -13,6 +13,12 @@ html, body { position: absolute; top: 0; left: 0; + opacity: 1; + transition: opacity .2s; +} + +.canvas.white { + opacity: 0; } .canvas.moving { diff --git a/client/draw.js b/client/draw.js index 759d04a..bb7d0c9 100644 --- a/client/draw.js +++ b/client/draw.js @@ -38,4 +38,28 @@ function predraw_user(user_id, event) { storage.ctx1.stroke(); storage.predraw[user_id].push({ 'x': event.x, 'y': event.y }); +} + +function redraw_region(bbox) { + storage.ctx0.save(); + storage.ctx0.clearRect(bbox.xmin, bbox.ymin, bbox.xmax - bbox.xmin, bbox.ymax - bbox.ymin); + + storage.ctx0.beginPath(); + storage.ctx0.rect(bbox.xmin, bbox.ymin, bbox.xmax - bbox.xmin, bbox.ymax - bbox.ymin); + storage.ctx0.clip(); + + for (const event of storage.events) { + if (event.type === EVENT.STROKE && !event.deleted) { + if (stroke_intersects_region(event.points, bbox)) { + draw_stroke(event); + } + } else if (event.type === EVENT.IMAGE && !event.deleted) { + const image_bbox = bitmap_bbox(event); + if (rectangles_intersect(image_bbox, bbox)) { + storage.ctx0.drawImage(event.bitmap, image_bbox.xmin, image_bbox.ymin); + } + } + } + + storage.ctx0.restore(); } \ No newline at end of file diff --git a/client/index.html b/client/index.html index de6b393..d51fe39 100644 --- a/client/index.html +++ b/client/index.html @@ -14,8 +14,7 @@ -
- + diff --git a/client/index.js b/client/index.js index c754f5a..8c695ef 100644 --- a/client/index.js +++ b/client/index.js @@ -141,9 +141,6 @@ function main() { elements.canvas0 = document.getElementById('canvas0'); elements.canvas1 = document.getElementById('canvas1'); - elements.cursor = document.getElementById('cursor'); - elements.cursor.style.width = storage.cursor.width + 'px'; - elements.cursor.style.height = storage.cursor.width + 'px'; storage.canvas.offset_x = window.scrollX; storage.canvas.offset_y = window.scrollY; diff --git a/client/recv.js b/client/recv.js index e18a832..be6ec3c 100644 --- a/client/recv.js +++ b/client/recv.js @@ -86,23 +86,18 @@ function des_event(d) { return event; } -function redraw_region(bbox) { - storage.ctx0.save(); - storage.ctx0.clearRect(bbox.xmin, bbox.ymin, bbox.xmax - bbox.xmin, bbox.ymax - bbox.ymin); - - storage.ctx0.beginPath(); - storage.ctx0.rect(bbox.xmin, bbox.ymin, bbox.xmax - bbox.xmin, bbox.ymax - bbox.ymin); - storage.ctx0.clip(); - - for (const event of storage.events) { - if (event.type === EVENT.STROKE && !event.deleted) { - if (stroke_intersects_region(event.points, bbox)) { - draw_stroke(event); - } - } - } +function bitmap_bbox(event) { + const x = (event.x <= storage.canvas.width ? event.x : event.x - 65536); + const y = (event.y <= storage.canvas.height ? event.y : event.y - 65536); + + const bbox = { + 'xmin': x, + 'xmax': x + event.bitmap.width, + 'ymin': y, + 'ymax': y + event.bitmap.height + }; - storage.ctx0.restore(); + return bbox; } async function handle_event(event) { @@ -123,11 +118,17 @@ async function handle_event(event) { case EVENT.UNDO: { for (let i = storage.events.length - 1; i >=0; --i) { const other_event = storage.events[i]; + if (other_event.type === EVENT.STROKE && other_event.user_id === event.user_id && !other_event.deleted) { other_event.deleted = true; const stats = stroke_stats(other_event.points, storage.cursor.width); redraw_region(stats.bbox); break; + } else if (other_event.type === EVENT.IMAGE && other_event.user_id === event.user_id && !other_event.deleted) { + other_event.deleted = true; + const bbox = bitmap_bbox(other_event); + redraw_region(bbox); + break; } } @@ -139,11 +140,11 @@ async function handle_event(event) { const blob = await r.blob(); const bitmap = await createImageBitmap(blob); + event.bitmap = bitmap; - const x = (event.x <= storage.canvas.width ? event.x : event.x - 65536); - const y = (event.y <= storage.canvas.height ? event.y : event.y - 65536); + const bbox = bitmap_bbox(event); + storage.ctx0.drawImage(bitmap, bbox.xmin, bbox.ymin); - storage.ctx0.drawImage(bitmap, x, y); break; } @@ -176,7 +177,6 @@ async function handle_message(d) { console.debug('init in'); } - const event_count = des_u32(d); console.debug(`${event_count} events in init`); @@ -184,10 +184,12 @@ async function handle_message(d) { for (let i = 0; i < event_count; ++i) { const event = des_event(d); - handle_event(event); + await handle_event(event); storage.events.push(event); } + elements.canvas0.classList.remove('white'); + send_ack(event_count); sync_queue();