1
0
Fork 0

[client] Create skeleton for new eraser.

Also, send the actual absolute cursor position instead of the cursor
position in screen space.
master
Starbeamrainbowlabs 5 years ago
parent 64667dcc10
commit d5f6407cf5
Signed by: sbrl
GPG Key ID: 1BE5172E637709C2
  1. 2
      Nibriboard/ClientFiles/BoardWindow.js
  2. 22
      Nibriboard/ClientFiles/Chunk.js
  3. 26
      Nibriboard/ClientFiles/CursorSyncer.js
  4. 16
      Nibriboard/ClientFiles/Pencil.js
  5. BIN
      Nibriboard/ClientFiles/images/icons/eraser.png
  6. 1
      Nibriboard/ClientFiles/index.html
  7. 2
      README.md

@ -185,7 +185,7 @@ class BoardWindow extends EventEmitter
}).bind(this))
// 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

@ -1,5 +1,7 @@
"use strict";
import { point_line_distance_multi } from 'line-distance-calculator';
/**
* Represents a single chunk on a plane.
* Note that this is the client's representation of the chunk, so it's likely
@ -14,8 +16,11 @@ class Chunk
*/
constructor(inChunkRef, inSize)
{
/** @type {ChunkReference} */
this.chunkRef = inChunkRef;
/** @type {number} */
this.size = inSize;
/** @type {[ { Points: [Vector], Width: number, Color: string }] */
this.lines = [];
}
@ -62,6 +67,23 @@ class Chunk
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)
{

@ -1,11 +1,14 @@
"use strict";
import Vector from './Utilities/Vector.js';
class CursorSyncer
{
constructor(inRippleLink, syncFrequency)
constructor(inBoardWindow, syncFrequency)
{
this.boardWindow = inBoardWindow
// 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.
this.cursorUpdateFrequency = syncFrequency;
@ -13,7 +16,10 @@ class CursorSyncer
// link connects
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()
@ -22,10 +28,11 @@ class CursorSyncer
this.lastCursorUpdate = 0;
document.addEventListener("mousemove", (function(event) {
this.cursorPosition = {
X: event.clientX,
Y: event.clientY
};
this.cursorPosition.x = event.clientX;
this.cursorPosition.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() {
// 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
this.rippleLink.send({
"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 { simplify_line } from "visvalingam-simplifier";
import ChunkReference from './ChunkReference.js';
import Vector from './Utilities/Vector';
import Mouse from './Utilities/Mouse';
@ -129,6 +130,21 @@ class Pencil
this.sendUnsent();
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":
// handled by BoardWindow.handleCanvasMovement(event)
break;

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

@ -21,6 +21,7 @@
<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="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="pointer" title="Point at things, but don't change them."><img src="images/icons/point.png" aria-hidden="true" /></span>
</section>

@ -47,7 +47,7 @@ Note that if you're intending to use Nibriboard over the internet or an untruste
- Images:
- [Transparent Square Tiles](https://www.toptal.com/designers/subtlepatterns/transparent-square-tiles/) from [subtlepatterns.com](https://subtlepatterns.com/)
- 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
- [Paper.js](http://paperjs.org/) - Client-side rendering
- [IotWeb](http://sensaura.org/pages/tools/iotweb/) - Underlying HTTP / WebSocket server

Loading…
Cancel
Save