diff --git a/README.md b/README.md index 27d8497..39782fd 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,9 @@ Release: + Pretty player pointers + Player list + Follow player + + Color picker (or at the very least an Open Color color pallete) - Eraser - Line drawing - - Color picker (or at the very least an Open Color color pallete) - Undo/redo - Dynamic svg cursor to represent the brush * Polish diff --git a/client/client_recv.js b/client/client_recv.js index a8d87f4..4fecb09 100644 --- a/client/client_recv.js +++ b/client/client_recv.js @@ -397,9 +397,8 @@ async function handle_message(state, context, d) { init_player_defaults(state, state.me); - const color_code = color_from_u32(color).substring(1); + set_color_u32(state, color); - switch_color(state, document.querySelector(`.color[data-color="${color_code}"]`)); document.querySelector('#stroke-width').value = width; fire_event(state, width_event(width)); diff --git a/client/default.css b/client/default.css index 5cf06a9..d79886d 100644 --- a/client/default.css +++ b/client/default.css @@ -4,7 +4,7 @@ --radius: 5px; --hgap: 5px; --gap: 10px; - --transform-amimate: transform .1s ease-in-out; + --transform-amimate: transform .1s ease-out; } html, body { @@ -137,16 +137,16 @@ canvas.mousemoving { } .pallete { - pointer-events: all; + pointer-events: none; display: grid; flex-direction: column; align-items: center; - background: var(--dark-blue); border-top-right-radius: var(--radius); border-bottom-right-radius: var(--radius); /* border-bottom-left-radius: var(--radius);*/ padding-top: var(--gap); padding-bottom: var(--gap); + overflow: hidden; } .pallete-wrapper.hidden { @@ -157,25 +157,37 @@ canvas.mousemoving { transform: translateY(-125%); } -.pallete .color { - padding: var(--gap); - cursor: pointer; +.pallete .color-major { + pointer-events: all; background: var(--dark-blue); + display: flex; transition: var(--transform-amimate); + transform: translateX(calc(-100% + 2 * var(--gap) + 24px)); + cursor: pointer; + overflow: hidden; } -.pallete .color:hover { - background: var(--dark-hover); +.pallete .color-major.extended { + transform: translateX(0px); + border-top-right-radius: var(--radius); + border-bottom-right-radius: var(--radius); } -.pallete .color.active { - transform: translateX(10px); +.pallete .color-major.active { + transform: translateX(calc(-100% + 3 * var(--gap) + 24px)); border-top-right-radius: var(--radius); border-bottom-right-radius: var(--radius); } -.pallete .color.active:hover { - background: var(--dark-blue); +.pallete .color-minor { + padding: var(--gap); + display: flex; + justify-content: center; + align-items: center; +} + +.pallete .color-major:not(.active) .color-minor:hover { + background: var(--dark-hover); } .pallete .color-pane { @@ -184,6 +196,14 @@ canvas.mousemoving { box-sizing: border-box; border-radius: var(--radius); } +.pallete .color .color-pane:hover { + background: var(--dark-hover); +} + + +.pallete .color.active:hover { + background: var(--dark-blue); +} .tools, .sizer { diff --git a/client/index.html b/client/index.html index e02d380..5f4e2c9 100644 --- a/client/index.html +++ b/client/index.html @@ -62,15 +62,165 @@
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/index.js b/client/index.js index e033c99..5d17f7e 100644 --- a/client/index.js +++ b/client/index.js @@ -204,6 +204,7 @@ function main() { 'colors': { 'active_element': null, + 'extended_element': null, }, 'timers': { diff --git a/client/tools.js b/client/tools.js index d0f00c6..ddaf2ff 100644 --- a/client/tools.js +++ b/client/tools.js @@ -14,21 +14,64 @@ function switch_tool(state, item) { state.tools.active_element.classList.add('active'); } -function switch_color(state, item) { - const color = item.getAttribute('data-color'); - +function select_color(state, item, color_u32) { if (state.colors.active_element) { state.colors.active_element.classList.remove('active'); } - if (state.me in state.players) { - const color_u32 = color_to_u32(color); - state.players[state.me].color = color_u32 - fire_event(state, color_event(color_u32)); + if (state.colors.extended_element) { + state.colors.extended_element.classList.remove('extended'); + state.colors.extended_element = null; } + const last_minor = item.lastElementChild; + const color_css = color_from_u32(color_u32); + + + last_minor.setAttribute('data-color', color_css.substring(1)); + last_minor.querySelector('.color-pane').style.background = color_css; + state.colors.active_element = item; - state.colors.active_element.classList.add('active'); + item.classList.add('active'); +} + +function extend_major_color(state, item) { + if (state.colors.active_element) { + state.colors.active_element.classList.remove('active'); + } + + if (state.colors.extended_element) { + state.colors.extended_element.classList.remove('extended'); + } + + const last_minor = item.lastElementChild; + + // Restore last pane color in case it was overwritten by active color + last_minor.querySelector('.color-pane').style.background = '#' + item.getAttribute('data-last-color'); + last_minor.setAttribute('data-color', item.getAttribute('data-last-color')); + + state.colors.extended_element = item; + item.classList.add('extended'); +} + +function set_color_u32(state, color_u32) { + if (color_u32 === state.players[state.me].color) { + return; + } + + const color_css = color_from_u32(color_u32).substring(1); + const color_minor = document.querySelector(`.color-minor[data-color="${color_css}"]`); + + if (!color_minor) { + set_color_u32(state, 0); + return; + } + + const major_color = color_minor.parentElement; + select_color(state, major_color, color_u32); + + state.players[state.me].color = color_u32 + fire_event(state, color_event(color_u32)); } function show_stroke_preview(state, size) { @@ -67,14 +110,32 @@ function broadcast_stroke_width(e, state) { function init_tools(state) { const tools = document.querySelectorAll('.tools .tool'); - const colors = document.querySelectorAll('.pallete .color'); + const color_groups = document.querySelectorAll('.pallete .color-major'); tools.forEach((item) => { item.addEventListener('click', () => switch_tool(state, item)); }); - colors.forEach((item) => { item.addEventListener('click', () => switch_color(state, item)); }); + color_groups.forEach((item) => { + item.setAttribute('data-last-color', item.lastElementChild.getAttribute('data-color')); + item.addEventListener('click', (e) => { + if (e.ctrlKey) { + extend_major_color(state, item); + return; + } + + let color_element = e.target; + let target = e.target; + + while (!target.classList.contains('color-minor')) { + target = target.parentElement; + } + + const color_str = target.getAttribute('data-color'); + const color_u32 = color_to_u32(color_str); + + set_color_u32(state, color_u32); + }) + }); - // TODO: from localstorage switch_tool(state, document.querySelector('.tool[data-tool="pencil"]')); - switch_color(state, document.querySelector('.color[data-color="000000"]')); const slider = document.querySelector('#stroke-width'); @@ -83,4 +144,4 @@ function init_tools(state) { slider.addEventListener('change', (e) => broadcast_stroke_width(e, state)); document.querySelector('.phone-extra-controls').addEventListener('click', zenmode); -} \ No newline at end of file +}