Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
D
drawing-app
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
hlgr
drawing-app
Commits
edfe21b8
Commit
edfe21b8
authored
5 years ago
by
Giovanni Caruso
Browse files
Options
Downloads
Plain Diff
Merge branch 'master' into avatar
parents
e3ee3d0f
188789b4
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/app.js
+33
-108
33 additions, 108 deletions
src/app.js
src/canvas.js
+0
-38
0 additions, 38 deletions
src/canvas.js
src/tool-selection.js
+98
-0
98 additions, 0 deletions
src/tool-selection.js
with
131 additions
and
146 deletions
src/app.js
+
33
−
108
View file @
edfe21b8
// Room connection and synchronisation.
// Room connection and synchronisation.
// Translate local canvas input events to draw messages and send to the room.
// Translate local canvas input events to draw messages in light of current tool
// selections and send to the room.
// Get back room updates and invoke the local canvas renderer.
// Get back room updates and invoke the local canvas renderer.
import
*
as
canvas
from
"
./canvas.js
"
import
*
as
canvas
from
"
./canvas.js
"
import
*
as
HTML
from
"
./elements.js
"
import
*
as
HTML
from
"
./elements.js
"
import
{
connect
}
from
"
./room.js
"
import
{
connect
}
from
"
./room.js
"
import
*
as
toolSelection
from
"
./tool-selection.js
"
const
TEST_ROOM
=
"
imperial
"
const
TEST_ROOM
=
"
imperial
"
const
MIN_PRESSURE_FACTOR
=
0.1
const
MAX_PRESSURE_FACTOR
=
1.5
// This is a quadratic such that:
// - getPressureFactor(0.0) = MIN_PRESSURE_FACTOR
// - getPressureFactor(0.5) = 1.0
// - getPressureFactor(1.0) = MAX_PRESSURE_FACTOR
// For sensible results, maintain that:
// - 0.0 <= MIN_PRESSURE_FACTOR <= 1.0
// - 1.0 <= MAX_PRESSURE_FACTOR
// For intuitive results, maintain that:
// - MAX_PRESSURE_FACTOR <= ~2.0
const
getPressureFactor
=
(
pressure
)
=>
{
const
a
=
2
*
(
MAX_PRESSURE_FACTOR
+
MIN_PRESSURE_FACTOR
)
-
4
const
b
=
-
MAX_PRESSURE_FACTOR
-
3
*
MIN_PRESSURE_FACTOR
+
4
const
c
=
MIN_PRESSURE_FACTOR
return
a
*
pressure
**
2
+
b
*
pressure
+
c
}
let
room
=
null
let
room
=
null
const
onRoomConnect
=
(
room_
)
=>
{
const
onRoomConnect
=
(
room_
)
=>
{
...
@@ -89,102 +110,8 @@ const tryRoomConnect = async (roomID) => {
...
@@ -89,102 +110,8 @@ const tryRoomConnect = async (roomID) => {
.
catch
((
err
)
=>
alert
(
`Error connecting to a room:\n
${
err
}
`
))
.
catch
((
err
)
=>
alert
(
`Error connecting to a room:\n
${
err
}
`
))
}
}
const
ERASER_RADIUS
=
10
const
tools
=
{
PEN
:
Symbol
(
"
pen
"
),
ERASER
:
Symbol
(
"
eraser
"
),
}
let
currentTool
=
tools
.
PEN
const
pathIDsByPointerID
=
new
Map
()
const
pathIDsByPointerID
=
new
Map
()
HTML
.
penButton
.
addEventListener
(
"
click
"
,
()
=>
{
if
(
currentTool
==
tools
.
PEN
)
{
showElement
(
HTML
.
penProperties
)
}
else
{
currentTool
=
tools
.
PEN
HTML
.
penButton
.
classList
.
add
(
"
selected
"
)
HTML
.
eraserButton
.
classList
.
remove
(
"
selected
"
)
}
})
HTML
.
closeButton
.
forEach
((
element
)
=>
{
element
.
addEventListener
(
"
click
"
,
()
=>
{
hideElement
(
element
.
parentNode
.
parentNode
.
parentNode
)
})
})
window
.
addEventListener
(
"
click
"
,
(
event
)
=>
{
if
(
event
.
target
==
HTML
.
penProperties
)
{
hideElement
(
HTML
.
penProperties
)
}
else
if
(
event
.
target
==
HTML
.
palette
)
{
hideElement
(
HTML
.
palette
)
hideElement
(
HTML
.
penProperties
)
}
})
HTML
.
rectangle
.
addEventListener
(
"
click
"
,
()
=>
{
showElement
(
HTML
.
palette
)
})
const
svg
=
HTML
.
wheel
.
children
for
(
let
i
=
1
;
i
<
svg
.
length
;
i
++
)
{
svg
[
i
].
addEventListener
(
"
click
"
,
(
event
)
=>
{
const
paletteColour
=
event
.
target
.
getAttribute
(
"
fill
"
)
HTML
.
rectangle
.
style
.
backgroundColor
=
paletteColour
HTML
.
picker
.
value
=
paletteColour
HTML
.
labelColours
.
style
.
backgroundColor
=
paletteColour
canvas
.
setStrokeColour
(
paletteColour
)
hideElement
(
HTML
.
palette
)
})
}
function
showElement
(
element
)
{
element
.
style
.
display
=
"
block
"
}
function
hideElement
(
element
)
{
element
.
style
.
display
=
"
none
"
}
HTML
.
picker
.
addEventListener
(
"
change
"
,
()
=>
{
const
paletteColour
=
event
.
target
.
value
HTML
.
rectangle
.
style
.
backgroundColor
=
paletteColour
HTML
.
labelColours
.
style
.
backgroundColor
=
paletteColour
canvas
.
setStrokeColour
(
paletteColour
)
})
HTML
.
output
.
innerHTML
=
HTML
.
slider
.
value
HTML
.
slider
.
oninput
=
function
()
{
HTML
.
output
.
innerHTML
=
this
.
value
canvas
.
setStrokeRadius
(
this
.
value
/
10
)
}
const
x
=
window
.
matchMedia
(
"
only screen and (orientation: landscape) and (max-width: 600px)
"
,
)
x
.
addListener
(()
=>
{
if
(
x
.
matches
)
{
HTML
.
wheel
.
setAttribute
(
"
viewBox
"
,
"
-50 10 200 100
"
)
HTML
.
palette
.
setAttribute
(
"
style
"
,
"
padding-top: 50px
"
)
}
else
{
HTML
.
wheel
.
setAttribute
(
"
viewBox
"
,
"
0 10 100 100
"
)
}
})
HTML
.
picker
.
addEventListener
(
"
change
"
,
()
=>
{
const
paletteColour
=
event
.
target
.
value
HTML
.
rectangle
.
style
.
backgroundColor
=
paletteColour
HTML
.
labelColours
.
style
.
backgroundColor
=
paletteColour
canvas
.
setStrokeColour
(
paletteColour
)
})
HTML
.
eraserButton
.
addEventListener
(
"
click
"
,
()
=>
{
currentTool
=
tools
.
ERASER
HTML
.
penButton
.
classList
.
remove
(
"
selected
"
)
HTML
.
eraserButton
.
classList
.
add
(
"
selected
"
)
})
HTML
.
peerButton
.
addEventListener
(
"
click
"
,
()
=>
{
HTML
.
peerButton
.
addEventListener
(
"
click
"
,
()
=>
{
const
peerID
=
HTML
.
peerIDElem
.
value
const
peerID
=
HTML
.
peerIDElem
.
value
if
(
room
==
null
||
peerID
==
""
)
{
if
(
room
==
null
||
peerID
==
""
)
{
...
@@ -293,7 +220,7 @@ const erasePoint = ([x, y]) => {
...
@@ -293,7 +220,7 @@ const erasePoint = ([x, y]) => {
}
}
room
.
getPaths
().
forEach
((
points
,
pathID
)
=>
{
room
.
getPaths
().
forEach
((
points
,
pathID
)
=>
{
points
.
forEach
((
point
,
i
)
=>
{
points
.
forEach
((
point
,
i
)
=>
{
if
(
getDistance
([
x
,
y
],
point
)
<=
ERASER_RADIUS
)
{
if
(
getDistance
([
x
,
y
],
point
)
<=
toolSelection
.
getEraseRadius
()
)
{
room
.
erasePoint
(
pathID
,
i
)
room
.
erasePoint
(
pathID
,
i
)
}
}
})
})
...
@@ -304,19 +231,18 @@ canvas.input.addEventListener("strokestart", ({ detail: e }) => {
...
@@ -304,19 +231,18 @@ canvas.input.addEventListener("strokestart", ({ detail: e }) => {
if
(
room
==
null
)
{
if
(
room
==
null
)
{
return
return
}
}
const
currentTool
=
toolSelection
.
getTool
()
const
mousePos
=
[
e
.
offsetX
,
e
.
offsetY
]
const
mousePos
=
[
e
.
offsetX
,
e
.
offsetY
]
if
(
currentTool
==
toolSelection
.
Tools
.
PEN
)
{
if
(
currentTool
==
tools
.
PEN
)
{
pathIDsByPointerID
.
set
(
pathIDsByPointerID
.
set
(
e
.
pointerId
,
e
.
pointerId
,
room
.
addPath
([
room
.
addPath
([
...
mousePos
,
...
mousePos
,
canvas
.
getStrokeRadius
(
e
.
pressure
),
toolSelection
.
getStrokeRadius
(
)
*
getPressureFactor
(
e
.
pressure
),
canvas
.
getStrokeColour
(),
toolSelection
.
getStrokeColour
(),
]),
]),
)
)
}
else
if
(
currentTool
==
tools
.
ERASER
)
{
}
else
if
(
currentTool
==
tool
Selection
.
Tool
s
.
ERASER
)
{
erasePoint
(
mousePos
)
erasePoint
(
mousePos
)
}
}
})
})
...
@@ -329,16 +255,15 @@ canvas.input.addEventListener("strokemove", ({ detail: e }) => {
...
@@ -329,16 +255,15 @@ canvas.input.addEventListener("strokemove", ({ detail: e }) => {
if
(
room
==
null
)
{
if
(
room
==
null
)
{
return
return
}
}
const
currentTool
=
toolSelection
.
getTool
()
const
mousePos
=
[
e
.
offsetX
,
e
.
offsetY
]
const
mousePos
=
[
e
.
offsetX
,
e
.
offsetY
]
if
(
currentTool
==
toolSelection
.
Tools
.
PEN
)
{
if
(
currentTool
==
tools
.
PEN
)
{
room
.
extendPath
(
pathIDsByPointerID
.
get
(
e
.
pointerId
),
[
room
.
extendPath
(
pathIDsByPointerID
.
get
(
e
.
pointerId
),
[
...
mousePos
,
...
mousePos
,
canvas
.
getStrokeRadius
(
e
.
pressure
),
toolSelection
.
getStrokeRadius
(
)
*
getPressureFactor
(
e
.
pressure
),
canvas
.
getStrokeColour
(),
toolSelection
.
getStrokeColour
(),
])
])
}
else
if
(
currentTool
==
tools
.
ERASER
)
{
}
else
if
(
currentTool
==
tool
Selection
.
Tool
s
.
ERASER
)
{
erasePoint
(
mousePos
)
erasePoint
(
mousePos
)
}
}
})
})
...
...
This diff is collapsed.
Click to expand it.
src/canvas.js
+
0
−
38
View file @
edfe21b8
...
@@ -16,9 +16,6 @@ const lineFn = line()
...
@@ -16,9 +16,6 @@ const lineFn = line()
const
pathGroupElems
=
new
Map
()
const
pathGroupElems
=
new
Map
()
let
strokeColour
=
"
#0000ff
"
let
strokeRadius
=
5
const
MAX_POINT_DISTANCE
=
5
const
MAX_POINT_DISTANCE
=
5
const
MAX_RADIUS_DELTA
=
0.05
const
MAX_RADIUS_DELTA
=
0.05
...
@@ -168,38 +165,3 @@ canvas.addEventListener("pointerup", dispatchPointerEvent("strokeend"))
...
@@ -168,38 +165,3 @@ canvas.addEventListener("pointerup", dispatchPointerEvent("strokeend"))
canvas
.
addEventListener
(
"
pointerleave
"
,
dispatchPointerEvent
(
"
strokeend
"
))
canvas
.
addEventListener
(
"
pointerleave
"
,
dispatchPointerEvent
(
"
strokeend
"
))
canvas
.
addEventListener
(
"
pointermove
"
,
dispatchPointerEvent
(
"
strokemove
"
))
canvas
.
addEventListener
(
"
pointermove
"
,
dispatchPointerEvent
(
"
strokemove
"
))
canvas
.
addEventListener
(
"
touchmove
"
,
(
e
)
=>
e
.
preventDefault
())
canvas
.
addEventListener
(
"
touchmove
"
,
(
e
)
=>
e
.
preventDefault
())
export
function
setStrokeColour
(
colour
)
{
strokeColour
=
colour
}
export
function
getStrokeColour
()
{
return
strokeColour
}
const
MIN_PRESSURE_FACTOR
=
0.1
const
MAX_PRESSURE_FACTOR
=
1.5
// This is a quadratic such that:
// - getPressureFactor(0.0) = MIN_PRESSURE_FACTOR
// - getPressureFactor(0.5) = 1.0
// - getPressureFactor(1.0) = MAX_PRESSURE_FACTOR
// For sensible results, maintain that:
// - 0.0 <= MIN_PRESSURE_FACTOR <= 1.0
// - 1.0 <= MAX_PRESSURE_FACTOR
// For intuitive results, maintain that:
// - MAX_PRESSURE_FACTOR <= ~2.0
const
getPressureFactor
=
(
pressure
)
=>
{
const
a
=
2
*
(
MAX_PRESSURE_FACTOR
+
MIN_PRESSURE_FACTOR
)
-
4
const
b
=
-
MAX_PRESSURE_FACTOR
-
3
*
MIN_PRESSURE_FACTOR
+
4
const
c
=
MIN_PRESSURE_FACTOR
return
a
*
pressure
**
2
+
b
*
pressure
+
c
}
export
function
getStrokeRadius
(
pressure
)
{
return
strokeRadius
*
getPressureFactor
(
pressure
)
}
export
function
setStrokeRadius
(
radius
)
{
strokeRadius
=
radius
}
This diff is collapsed.
Click to expand it.
src/tool-selection.js
0 → 100644
+
98
−
0
View file @
edfe21b8
import
*
as
HTML
from
"
./elements.js
"
export
const
Tools
=
Object
.
freeze
({
PEN
:
Symbol
(
"
pen
"
),
ERASER
:
Symbol
(
"
eraser
"
),
})
let
tool
=
Tools
.
PEN
let
strokeColour
=
"
#0000ff
"
let
strokeRadius
=
5
// TODO: The erase radius should also be selectable.
const
ERASE_RADIUS
=
10
export
const
getTool
=
()
=>
tool
export
const
getStrokeColour
=
()
=>
strokeColour
export
const
getStrokeRadius
=
()
=>
strokeRadius
export
const
getEraseRadius
=
()
=>
ERASE_RADIUS
const
showElement
=
(
element
)
=>
{
element
.
style
.
display
=
"
block
"
}
const
hideElement
=
(
element
)
=>
{
element
.
style
.
display
=
"
none
"
}
HTML
.
penButton
.
addEventListener
(
"
click
"
,
()
=>
{
if
(
tool
==
Tools
.
PEN
)
{
showElement
(
HTML
.
penProperties
)
}
else
{
tool
=
Tools
.
PEN
HTML
.
penButton
.
classList
.
add
(
"
selected
"
)
HTML
.
eraserButton
.
classList
.
remove
(
"
selected
"
)
}
})
HTML
.
eraserButton
.
addEventListener
(
"
click
"
,
()
=>
{
tool
=
Tools
.
ERASER
HTML
.
penButton
.
classList
.
remove
(
"
selected
"
)
HTML
.
eraserButton
.
classList
.
add
(
"
selected
"
)
})
HTML
.
picker
.
addEventListener
(
"
change
"
,
()
=>
{
const
paletteColour
=
event
.
target
.
value
HTML
.
rectangle
.
style
.
backgroundColor
=
paletteColour
HTML
.
labelColours
.
style
.
backgroundColor
=
paletteColour
strokeColour
=
paletteColour
})
HTML
.
slider
.
oninput
=
function
()
{
HTML
.
output
.
innerHTML
=
this
.
value
strokeRadius
=
this
.
value
/
10
}
HTML
.
output
.
innerHTML
=
HTML
.
slider
.
value
const
x
=
window
.
matchMedia
(
"
only screen and (orientation: landscape) and (max-width: 600px)
"
,
)
x
.
addListener
(()
=>
{
if
(
x
.
matches
)
{
HTML
.
wheel
.
setAttribute
(
"
viewBox
"
,
"
-50 10 200 100
"
)
HTML
.
palette
.
setAttribute
(
"
style
"
,
"
padding-top: 50px
"
)
}
else
{
HTML
.
wheel
.
setAttribute
(
"
viewBox
"
,
"
0 10 100 100
"
)
}
})
HTML
.
closeButton
.
forEach
((
element
)
=>
{
element
.
addEventListener
(
"
click
"
,
()
=>
{
hideElement
(
element
.
parentNode
.
parentNode
.
parentNode
)
})
})
window
.
addEventListener
(
"
click
"
,
(
event
)
=>
{
if
(
event
.
target
==
HTML
.
penProperties
)
{
hideElement
(
HTML
.
penProperties
)
}
else
if
(
event
.
target
==
HTML
.
palette
)
{
hideElement
(
HTML
.
palette
)
hideElement
(
HTML
.
penProperties
)
}
})
HTML
.
rectangle
.
addEventListener
(
"
click
"
,
()
=>
{
showElement
(
HTML
.
palette
)
})
const
svg
=
HTML
.
wheel
.
children
for
(
let
i
=
1
;
i
<
svg
.
length
;
i
++
)
{
svg
[
i
].
addEventListener
(
"
click
"
,
(
event
)
=>
{
const
paletteColour
=
event
.
target
.
getAttribute
(
"
fill
"
)
HTML
.
rectangle
.
style
.
backgroundColor
=
paletteColour
HTML
.
picker
.
value
=
paletteColour
HTML
.
labelColours
.
style
.
backgroundColor
=
paletteColour
strokeColour
=
paletteColour
hideElement
(
HTML
.
palette
)
})
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment