mirror of
https://github.com/sbrl/Nibriboard.git
synced 2018-01-10 21:33:49 +00:00
[client] Create skeleton for new eraser.
Also, send the actual absolute cursor position instead of the cursor position in screen space.
This commit is contained in:
parent
64667dcc10
commit
d5f6407cf5
7 changed files with 59 additions and 10 deletions
|
@ -185,7 +185,7 @@ class BoardWindow extends EventEmitter
|
||||||
}).bind(this))
|
}).bind(this))
|
||||||
|
|
||||||
// Keep the server up to date on our viewport and cursor position
|
// Keep the server up to date on our viewport and cursor position
|
||||||
this.cursorSyncer = new CursorSyncer(this.rippleLink, this.cursorUpdateFrequency)
|
this.cursorSyncer = new CursorSyncer(this, this.cursorUpdateFrequency)
|
||||||
|
|
||||||
// RippleLink message bindings
|
// RippleLink message bindings
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
import { point_line_distance_multi } from 'line-distance-calculator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a single chunk on a plane.
|
* Represents a single chunk on a plane.
|
||||||
* Note that this is the client's representation of the chunk, so it's likely
|
* Note that this is the client's representation of the chunk, so it's likely
|
||||||
|
@ -14,8 +16,11 @@ class Chunk
|
||||||
*/
|
*/
|
||||||
constructor(inChunkRef, inSize)
|
constructor(inChunkRef, inSize)
|
||||||
{
|
{
|
||||||
|
/** @type {ChunkReference} */
|
||||||
this.chunkRef = inChunkRef;
|
this.chunkRef = inChunkRef;
|
||||||
|
/** @type {number} */
|
||||||
this.size = inSize;
|
this.size = inSize;
|
||||||
|
/** @type {[ { Points: [Vector], Width: number, Color: string }] */
|
||||||
this.lines = [];
|
this.lines = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +67,23 @@ class Chunk
|
||||||
return area.overlaps(area);
|
return area.overlaps(area);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the last line segment that lies underneath the specified point.
|
||||||
|
* Prefers lines drawn later to lines drawn earlier.
|
||||||
|
* @param {Vector} point The point to find the line underneath.
|
||||||
|
* @return {object|null} The first line (segment) that lies underneath the specified point, or null if one couldn't be found.
|
||||||
|
*/
|
||||||
|
getLineUnderPoint(point)
|
||||||
|
{
|
||||||
|
// Prefer lines that have been drawn later (i.e. on top)
|
||||||
|
for (let i = this.lines.length - 1; i > 0; i--) {
|
||||||
|
// If our distance to the line is less than half the width (i.e.
|
||||||
|
// the radius), then we must be inside it
|
||||||
|
if(point_line_distance_multi(point, this.lines[i].Points) <= this.lines[i].Width / 2)
|
||||||
|
return this.lines[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
update(dt)
|
update(dt)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
import Vector from './Utilities/Vector.js';
|
||||||
|
|
||||||
class CursorSyncer
|
class CursorSyncer
|
||||||
{
|
{
|
||||||
constructor(inRippleLink, syncFrequency)
|
constructor(inBoardWindow, syncFrequency)
|
||||||
{
|
{
|
||||||
|
this.boardWindow = inBoardWindow
|
||||||
// The ripple link we should send the cursor updates down
|
// The ripple link we should send the cursor updates down
|
||||||
this.rippleLink = inRippleLink;
|
this.rippleLink = this.boardWindow.rippleLink;
|
||||||
// The target frequency in fps at we should send cursor updates.
|
// The target frequency in fps at we should send cursor updates.
|
||||||
this.cursorUpdateFrequency = syncFrequency;
|
this.cursorUpdateFrequency = syncFrequency;
|
||||||
|
|
||||||
|
@ -13,7 +16,10 @@ class CursorSyncer
|
||||||
// link connects
|
// link connects
|
||||||
this.rippleLink.on("connect", this.setup.bind(this));
|
this.rippleLink.on("connect", this.setup.bind(this));
|
||||||
|
|
||||||
this.cursorPosition = { X: 0, Y: 0 };
|
/** The current cursor position in screen-space. @type {Vector} */
|
||||||
|
this.cursorPosition = new Vector(0, 0);
|
||||||
|
/** The current cursor position in plane-space. @type {Vector} */
|
||||||
|
this.absCursorPosition = new Vector(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
setup()
|
setup()
|
||||||
|
@ -22,10 +28,11 @@ class CursorSyncer
|
||||||
this.lastCursorUpdate = 0;
|
this.lastCursorUpdate = 0;
|
||||||
|
|
||||||
document.addEventListener("mousemove", (function(event) {
|
document.addEventListener("mousemove", (function(event) {
|
||||||
this.cursorPosition = {
|
this.cursorPosition.x = event.clientX;
|
||||||
X: event.clientX,
|
this.cursorPosition.y = event.clientY;
|
||||||
Y: event.clientY
|
|
||||||
};
|
this.absCursorPosition.x = this.boardWindow.viewport.x + this.cursorPosition.x;
|
||||||
|
this.absCursorPosition.y = this.boardWindow.viewport.y + this.cursorPosition.y;
|
||||||
|
|
||||||
setTimeout((function() {
|
setTimeout((function() {
|
||||||
// Throttle the cursor updates we send to the server - a high
|
// Throttle the cursor updates we send to the server - a high
|
||||||
|
@ -50,7 +57,10 @@ class CursorSyncer
|
||||||
// Update the server on the mouse's position
|
// Update the server on the mouse's position
|
||||||
this.rippleLink.send({
|
this.rippleLink.send({
|
||||||
"Event": "CursorPosition",
|
"Event": "CursorPosition",
|
||||||
"AbsCursorPosition": this.cursorPosition
|
"AbsCursorPosition": {
|
||||||
|
X: Math.floor(this.absCursorPosition.x),
|
||||||
|
Y: Math.floor(this.absCursorPosition.y)
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import cuid from "cuid";
|
import cuid from "cuid";
|
||||||
import { simplify_line } from "visvalingam-simplifier";
|
import { simplify_line } from "visvalingam-simplifier";
|
||||||
|
|
||||||
|
import ChunkReference from './ChunkReference.js';
|
||||||
import Vector from './Utilities/Vector';
|
import Vector from './Utilities/Vector';
|
||||||
import Mouse from './Utilities/Mouse';
|
import Mouse from './Utilities/Mouse';
|
||||||
|
|
||||||
|
@ -129,6 +130,21 @@ class Pencil
|
||||||
this.sendUnsent();
|
this.sendUnsent();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "eraser":
|
||||||
|
let locRef = this.boardWin.cursorSyncer.absCursorPosition;
|
||||||
|
let hoverChunkRef = new ChunkReference(
|
||||||
|
this.boardWindow.currentPlaneName,
|
||||||
|
Math.floor((this.boardWindow.viewport.x + this.mouse.position.x) / this.boardWindow.gridSize),
|
||||||
|
Math.floor((this.boardWindow.viewport.y + this.mouse.position.y) / this.boardWindow.gridSize)
|
||||||
|
);
|
||||||
|
|
||||||
|
let hoverChunk = this.boardWindow.chunkCache.fetchChunk(hoverChunk);
|
||||||
|
if(hoverChunk == null)
|
||||||
|
break; // If it's null, then we haven't received it yet from the server
|
||||||
|
|
||||||
|
let lineToErase = hoverChunk.getLineUnderPoint()
|
||||||
|
break;
|
||||||
|
|
||||||
case "pan":
|
case "pan":
|
||||||
// handled by BoardWindow.handleCanvasMovement(event)
|
// handled by BoardWindow.handleCanvasMovement(event)
|
||||||
break;
|
break;
|
||||||
|
|
BIN
Nibriboard/ClientFiles/images/icons/eraser.png
Normal file
BIN
Nibriboard/ClientFiles/images/icons/eraser.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 489 B |
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
<section class="tools">
|
<section class="tools">
|
||||||
<span class="tool-selector" data-tool-name="brush" title="Draw lines with a brush." data-selected><img src="images/icons/brush.png" aria-hidden="true" /></span>
|
<span class="tool-selector" data-tool-name="brush" title="Draw lines with a brush." data-selected><img src="images/icons/brush.png" aria-hidden="true" /></span>
|
||||||
|
<span class="tool-selector" data-tool-name="eraser" title="Erase lines. Remember that you can't undo/redo yet!"><img src="images/icons/eraser.png" aria-hidden="true" /></span>
|
||||||
<span class="tool-selector" data-tool-name="pan" title="Pan around the plane."><img src="images/icons/pan.png" aria-hidden="true" /></span>
|
<span class="tool-selector" data-tool-name="pan" title="Pan around the plane."><img src="images/icons/pan.png" aria-hidden="true" /></span>
|
||||||
<span class="tool-selector" data-tool-name="pointer" title="Point at things, but don't change them."><img src="images/icons/point.png" aria-hidden="true" /></span>
|
<span class="tool-selector" data-tool-name="pointer" title="Point at things, but don't change them."><img src="images/icons/point.png" aria-hidden="true" /></span>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -47,7 +47,7 @@ Note that if you're intending to use Nibriboard over the internet or an untruste
|
||||||
- Images:
|
- Images:
|
||||||
- [Transparent Square Tiles](https://www.toptal.com/designers/subtlepatterns/transparent-square-tiles/) from [subtlepatterns.com](https://subtlepatterns.com/)
|
- [Transparent Square Tiles](https://www.toptal.com/designers/subtlepatterns/transparent-square-tiles/) from [subtlepatterns.com](https://subtlepatterns.com/)
|
||||||
- Icons:
|
- Icons:
|
||||||
- [OpenIconic](https://useiconic.com/open) - brush, move -> pan, sun -> point
|
- [OpenIconic](https://useiconic.com/open) - brush, move -> pan, sun -> point, eraser -> delete
|
||||||
- Future reference: Libraries I am considering
|
- Future reference: Libraries I am considering
|
||||||
- [Paper.js](http://paperjs.org/) - Client-side rendering
|
- [Paper.js](http://paperjs.org/) - Client-side rendering
|
||||||
- [IotWeb](http://sensaura.org/pages/tools/iotweb/) - Underlying HTTP / WebSocket server
|
- [IotWeb](http://sensaura.org/pages/tools/iotweb/) - Underlying HTTP / WebSocket server
|
||||||
|
|
Loading…
Reference in a new issue