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
+}