Browse Source

Brush width control. Phone "zen mode" button

infinite
A.Olokhtonov 2 years ago
parent
commit
45c3af9c67
  1. 118
      client/default.css
  2. 59
      client/icons/cheeseburga.svg
  3. 46
      client/index.html
  4. 9
      client/tools.js
  5. 2
      client/webgl.js
  6. 3
      client/webgl_geometry.js
  7. 10
      client/webgl_listeners.js

118
client/default.css

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
--radius: 5px;
--hgap: 5px;
--gap: 10px;
--transform-amimate: transform .1s ease-in-out;
}
html, body {
@ -40,7 +41,8 @@ canvas.movemode.moving { @@ -40,7 +41,8 @@ canvas.movemode.moving {
pointer-events: none;
}
.pallete-wrapper {
.pallete-wrapper,
.sizer-wrapper {
position: fixed;
top: 0;
left: 0;
@ -49,6 +51,13 @@ canvas.movemode.moving { @@ -49,6 +51,13 @@ canvas.movemode.moving {
display: flex;
flex-direction: column;
justify-content: center;
transition: var(--transform-amimate);
}
.sizer-wrapper {
height: unset;
width: 100%;
flex-direction: row;
}
.pallete {
@ -64,11 +73,19 @@ canvas.movemode.moving { @@ -64,11 +73,19 @@ canvas.movemode.moving {
padding-bottom: var(--gap);
}
.pallete-wrapper.hidden {
transform: translateX(-125%); /* to account for a selected color, which is also offset to the right */
}
.sizer-wrapper.hidden {
transform: translateY(-125%);
}
.pallete .color {
padding: var(--gap);
cursor: pointer;
background: var(--dark-blue);
transition: transform .1s ease-in-out;
transition: var(--transform-amimate);
}
.pallete .color:hover {
@ -92,7 +109,8 @@ canvas.movemode.moving { @@ -92,7 +109,8 @@ canvas.movemode.moving {
border-radius: var(--radius);
}
.tools {
.tools,
.sizer {
pointer-events: all;
display: flex;
align-items: center;
@ -106,6 +124,12 @@ canvas.movemode.moving { @@ -106,6 +124,12 @@ canvas.movemode.moving {
padding-right: var(--gap);
}
.sizer {
border-radius: 0;
border-bottom-right-radius: var(--radius);
border-bottom-left-radius: var(--radius);
}
.tool {
cursor: pointer;
padding-left: var(--gap);
@ -114,7 +138,7 @@ canvas.movemode.moving { @@ -114,7 +138,7 @@ canvas.movemode.moving {
display: flex;
align-items: center;
background: var(--dark-blue);
transition: transform .1s ease-in-out;
transition: var(--transform-amimate);
user-select: none;
}
@ -133,4 +157,90 @@ canvas.movemode.moving { @@ -133,4 +157,90 @@ canvas.movemode.moving {
height: 24px;
width: 24px;
filter: invert(100%);
}
input[type=range] {
-webkit-appearance: none;
width: 200px;
background: transparent;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
border: none;
background: white;
height: 20px;
width: 20px;
border-radius: 50%;
cursor: pointer;
border: 2px solid var(--dark-blue);
margin-top: -6px; /* You need to specify a margin in Chrome, but in Firefox and IE it is automatic */
}
input[type=range]::-moz-range-thumb {
border: none;
background: white;
height: 16px;
width: 16px;
border-radius: 50%;
cursor: pointer;
border: 2px solid var(--dark-blue);
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 8px;
cursor: pointer;
background: white;
border-radius: 2px;
border: none;
}
input[type=range]:focus::-webkit-slider-runnable-track {
width: 100%;
height: 8px;
cursor: pointer;
background: white;
border-radius: 2px;
border: none;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 8px;
cursor: pointer;
background: white;
border-radius: 2px;
border: none;
}
.phone-extra-controls {
display: none;
cursor: pointer; /* for click events on mobile */
pointer-events: all;
position: absolute;
right: 0;
background: var(--dark-blue);
height: 42px;
justify-content: center;
align-items: center;
padding-left: var(--gap);
padding-right: var(--gap);
border-top-left-radius: var(--radius);
}
.phone-extra-controls img {
height: 24px;
width: 24px;
filter: invert(100%);
}
@media (hover: none) and (pointer: coarse) {
.phone-extra-controls {
display: flex;
}
}

59
client/icons/cheeseburga.svg

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="7.9173102mm"
height="6.8706498mm"
viewBox="0 0 7.9173102 6.8706498"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="cheeseburga.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="19.02887"
inkscape:cx="12.586139"
inkscape:cy="19.654346"
inkscape:window-width="2558"
inkscape:window-height="1412"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-130.27075,-83.242635)">
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="m 130.77075,83.742635 h 6.91731"
id="path242"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="m 130.77075,89.613285 h 6.91731"
id="path242-3"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="m 130.77075,86.67796 h 6.91731"
id="path242-6"
sodipodi:nodetypes="cc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

46
client/index.html

@ -6,33 +6,39 @@ @@ -6,33 +6,39 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="shortcut icon" href="icons/favicon.svg" id="favicon">
<link rel="stylesheet" type="text/css" href="default.css?v=7">
<link rel="stylesheet" type="text/css" href="default.css?v=8">
<script type="text/javascript" src="math.js?v=6"></script>
<script type="text/javascript" src="aux.js?v=6"></script>
<script type="text/javascript" src="tools.js?v=6"></script>
<script type="text/javascript" src="webgl_geometry.js?v=6"></script>
<script type="text/javascript" src="webgl_shaders.js?v=6"></script>
<script type="text/javascript" src="webgl_listeners.js?v=6"></script>
<script type="text/javascript" src="webgl.js?v=6"></script>
<script type="text/javascript" src="math.js?v=8"></script>
<script type="text/javascript" src="aux.js?v=8"></script>
<script type="text/javascript" src="tools.js?v=8"></script>
<script type="text/javascript" src="webgl_geometry.js?v=8"></script>
<script type="text/javascript" src="webgl_shaders.js?v=8"></script>
<script type="text/javascript" src="webgl_listeners.js?v=8"></script>
<script type="text/javascript" src="webgl.js?v=8"></script>
<script type="text/javascript" src="client_send.js?v=7"></script>
<script type="text/javascript" src="client_recv.js?v=7"></script>
<script type="text/javascript" src="websocket.js?v=7"></script>
<script type="text/javascript" src="client_send.js?v=8"></script>
<script type="text/javascript" src="client_recv.js?v=8"></script>
<script type="text/javascript" src="websocket.js?v=8"></script>
</head>
<body>
<canvas id="c"></canvas>
<div class="sizer-wrapper">
<div class="sizer">
<input type="range" class="slider" id="stroke-width" min="1" max="64">
</div>
</div>
<div class="pallete-wrapper">
<div class="pallete">
<div class="color active" data-color="000000"><div class="color-pane" style="background: #000000;"></div></div>
<div class="color" data-color="ffffff" ><div class="color-pane" style="background: #ffffff;"></div></div>
<div class="color" data-color="d65c5c" ><div class="color-pane" style="background: #d65c5c;"></div></div>
<div class="color" data-color="d6835c" ><div class="color-pane" style="background: #d6835c;"></div></div>
<div class="color" data-color="72d65c" ><div class="color-pane" style="background: #72d65c;"></div></div>
<div class="color" data-color="5cd6ce" ><div class="color-pane" style="background: #5cd6ce;"></div></div>
<div class="color" data-color="5c89d6" ><div class="color-pane" style="background: #5c89d6;"></div></div>
<div class="color" data-color="6e5cd6" ><div class="color-pane" style="background: #6e5cd6;"></div></div>
<div class="color" data-color="ffffff"><div class="color-pane" style="background: #ffffff;"></div></div>
<div class="color" data-color="d65c5c"><div class="color-pane" style="background: #d65c5c;"></div></div>
<div class="color" data-color="d6835c"><div class="color-pane" style="background: #d6835c;"></div></div>
<div class="color" data-color="72d65c"><div class="color-pane" style="background: #72d65c;"></div></div>
<div class="color" data-color="5cd6ce"><div class="color-pane" style="background: #5cd6ce;"></div></div>
<div class="color" data-color="5c89d6"><div class="color-pane" style="background: #5c89d6;"></div></div>
<div class="color" data-color="6e5cd6"><div class="color-pane" style="background: #6e5cd6;"></div></div>
</div>
</div>
@ -44,6 +50,10 @@ @@ -44,6 +50,10 @@
<div class="tool" data-tool="undo"><img draggable="false" src="icons/undo.svg"></div>
<!-- <div class="tool" data-tool="redo"><img draggable="false" src="icons/redo.svg"></div> -->
</div>
<div class="phone-extra-controls">
<img draggable="false" src="icons/cheeseburga.svg">
</div>
</div>
</body>
</html>

9
client/tools.js

@ -22,6 +22,11 @@ function switch_color(state, item) { @@ -22,6 +22,11 @@ function switch_color(state, item) {
state.colors.active_element.classList.add('active');
}
function switch_stroke_width(e, state) {
const value = e.target.value;
state.stroke_width = value;
}
function init_tools(state) {
const tools = document.querySelectorAll('.tools .tool');
const colors = document.querySelectorAll('.pallete .color');
@ -32,4 +37,8 @@ function init_tools(state) { @@ -32,4 +37,8 @@ function init_tools(state) {
// TODO: from localstorage
switch_tool(state, document.querySelector('.tool[data-tool="pencil"]'));
switch_color(state, document.querySelector('.color[data-color="000000"]'));
document.querySelector('#stroke-width').value = state.stroke_width;
document.querySelector('#stroke-width').addEventListener('input', (e) => switch_stroke_width(e, state));
document.querySelector('.phone-extra-controls').addEventListener('click', zenmode);
}

2
client/webgl.js

@ -180,8 +180,6 @@ function main() { @@ -180,8 +180,6 @@ function main() {
'drawing': false,
'spacedown': false,
'stroke_width': 8,
'current_strokes': {},
'queue': [],

3
client/webgl_geometry.js

@ -169,7 +169,7 @@ function update_dynamic_stroke(state, context, player_id, point) { @@ -169,7 +169,7 @@ function update_dynamic_stroke(state, context, player_id, point) {
if (!(player_id in state.current_strokes)) {
state.current_strokes[player_id] = {
'points': [],
'width': 8, // TODO
'width': state.stroke_width,
'color': state.colors.active,
};
@ -191,6 +191,7 @@ function clear_dynamic_stroke(state, context, player_id) { @@ -191,6 +191,7 @@ function clear_dynamic_stroke(state, context, player_id) {
if (player_id in state.current_strokes) {
state.current_strokes[player_id].points.length = 0;
state.current_strokes[player_id].color = state.colors.active;
state.current_strokes[player_id].width = state.stroke_width;
context.dynamic_positions[player_id].length = 0;
recompute_dynamic_data(state, context);
}

10
client/webgl_listeners.js

@ -22,12 +22,18 @@ function cancel(e) { @@ -22,12 +22,18 @@ function cancel(e) {
return false;
}
function zenmode() {
document.querySelector('.pallete-wrapper').classList.toggle('hidden');
document.querySelector('.sizer-wrapper').classList.toggle('hidden');
}
function keydown(e, state, context) {
if (e.code === 'Space' && !state.drawing) {
state.spacedown = true;
context.canvas.classList.add('movemode');
} else if (e.code === 'KeyD') {
} else if (e.code === 'Tab') {
e.preventDefault();
zenmode();
}
}

Loading…
Cancel
Save