|
1 | 1 | import { COLOR } from "./state/constants.mjs"; |
2 | | -import { getCursorCanvas } from "./dom.mjs"; |
| 2 | +import { getCursorCanvas, getCanvas } from "./dom.mjs"; |
| 3 | +import { getPanel } from "./dom.mjs"; |
| 4 | +import { isCursorWithinPanelBounds } from "./ui-utils.mjs"; |
3 | 5 |
|
4 | 6 | const ctx = getCursorCanvas().getContext("2d"); |
5 | | -const CURSOR_SIZE = 20; |
| 7 | +const canvasCtx = getCanvas().getContext("2d"); |
| 8 | +const CURSOR_SIZE = 10; |
| 9 | +const CURSOR_PART_SIZE = CURSOR_SIZE / 2; |
| 10 | +const GAP = CURSOR_SIZE / 2; |
| 11 | +const LINE_WIDTH = 5; |
| 12 | + |
| 13 | +/** |
| 14 | + * Inverts color to avoid invisible cursor. |
| 15 | + * |
| 16 | + * @param {number} r - Red color. |
| 17 | + * @param {number} g - Green color. |
| 18 | + * @param {number} b - Blue color. |
| 19 | + * |
| 20 | + * @returns {number[]} - Inverted color in r, g,b order. |
| 21 | + */ |
| 22 | +function invertColor(r, g, b, a) { |
| 23 | + const rgb = [r, g, b, a]; |
| 24 | + for (var i = 0; i < rgb.length; i++) rgb[i] = (i === 3 ? 1 : 255) - rgb[i]; |
| 25 | + return rgb; |
| 26 | +} |
| 27 | + |
| 28 | +/** |
| 29 | + * Returns color on given canvas area in RGBA format. |
| 30 | + * |
| 31 | + * @param {number} x - X coordinate. |
| 32 | + * @param {number} y - Y coordinate. |
| 33 | + * |
| 34 | + * @returns {string} - RGBA color. |
| 35 | + */ |
| 36 | +function getPixelRGBAColor(x, y) { |
| 37 | + const panel = getPanel(); |
| 38 | + const rect = panel.getBoundingClientRect(); |
| 39 | + |
| 40 | + if (isCursorWithinPanelBounds(x, y, rect)) { |
| 41 | + return COLOR.BLACK; |
| 42 | + } |
| 43 | + |
| 44 | + const pixel = canvasCtx.getImageData(x, y, GAP, GAP); |
| 45 | + const [r, g, b, a] = invertColor(...pixel.data); |
| 46 | + |
| 47 | + return `rgb(${r}, ${g}, ${b}, ${Math.abs(a)})`; |
| 48 | +} |
6 | 49 |
|
7 | 50 | export function drawCursor(x, y) { |
8 | 51 | ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); |
9 | | - const half = CURSOR_SIZE / 2; |
10 | | - |
11 | | - ctx.lineWidth = 5; |
| 52 | + ctx.lineWidth = LINE_WIDTH; |
12 | 53 | ctx.lineCap = "round"; |
13 | | - ctx.strokeStyle = COLOR.BLACK; |
| 54 | + ctx.strokeStyle = getPixelRGBAColor(x, y); |
14 | 55 |
|
| 56 | + /* --- Cursor --- */ |
| 57 | + // Draw top line |
15 | 58 | ctx.beginPath(); |
16 | | - ctx.moveTo(x, y); |
17 | | - ctx.lineTo(x + CURSOR_SIZE, y); |
| 59 | + ctx.moveTo(x, y - GAP); |
| 60 | + ctx.lineTo(x, y - CURSOR_PART_SIZE - GAP - CURSOR_SIZE); |
18 | 61 | ctx.stroke(); |
19 | 62 |
|
| 63 | + // Draw bottom line |
20 | 64 | ctx.beginPath(); |
21 | | - ctx.moveTo(x + half, y - half); |
22 | | - ctx.lineTo(x + half, y + half); |
| 65 | + ctx.moveTo(x, y + GAP); |
| 66 | + ctx.lineTo(x, y + CURSOR_PART_SIZE + GAP + CURSOR_SIZE); |
23 | 67 | ctx.stroke(); |
24 | 68 |
|
25 | | - ctx.closePath(); |
| 69 | + // Draw left line |
| 70 | + ctx.beginPath(); |
| 71 | + ctx.moveTo(x - GAP, y); |
| 72 | + ctx.lineTo(x - CURSOR_PART_SIZE - GAP - CURSOR_SIZE, y); |
| 73 | + ctx.stroke(); |
26 | 74 |
|
27 | | - ctx.moveTo(x + half, y + half); |
28 | | - ctx.strokeStyle = COLOR.WHITE; |
29 | | - ctx.fillStyle = COLOR.WHITE; |
| 75 | + // Draw right line |
30 | 76 | ctx.beginPath(); |
31 | | - ctx.arc(x + half, y, 3, 0, Math.PI * 2); |
32 | | - ctx.fill(); |
| 77 | + ctx.moveTo(x + GAP, y); |
| 78 | + ctx.lineTo(x + CURSOR_PART_SIZE + GAP + CURSOR_SIZE, y); |
| 79 | + ctx.stroke(); |
| 80 | + |
| 81 | + ctx.closePath(); |
33 | 82 | } |
0 commit comments