Working streams
This commit is contained in:
@@ -11,6 +11,7 @@ node_modules
|
|||||||
dist
|
dist
|
||||||
dist-ssr
|
dist-ssr
|
||||||
*.local
|
*.local
|
||||||
|
circles-pictures
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
import { Stroke } from "./canvas-state";
|
import { Stroke } from "./canvas-state";
|
||||||
|
|
||||||
export type ListenCallbackParam = { strokeId: number, stroke: Stroke }
|
export type StrokeStreamElement = { strokeId: number, stroke: Stroke }
|
||||||
|
|
||||||
|
export type OnStrokeCallback = (state: StrokeStreamElement) => void
|
||||||
@@ -29,23 +29,19 @@ export class ClientDrawService {
|
|||||||
private readonly drawer = document.getElementById('drawer')!,
|
private readonly drawer = document.getElementById('drawer')!,
|
||||||
private readonly closeButton = document.getElementById('closeButton')!,
|
private readonly closeButton = document.getElementById('closeButton')!,
|
||||||
) {
|
) {
|
||||||
this.resizeCanvas()
|
|
||||||
this.setupCanvasEvents()
|
this.setupCanvasEvents()
|
||||||
window.addEventListener("resize", () => this.resizeCanvas());
|
|
||||||
this.cctx = canvas.getContext("2d")!
|
|
||||||
this.currentColor = colorPicker!.getAttribute('value')!
|
this.currentColor = colorPicker!.getAttribute('value')!
|
||||||
this.currentDensity = Number(densitySlider!.getAttribute('value'))!
|
this.currentDensity = Number(densitySlider!.getAttribute('value'))!
|
||||||
this.currentWidth = Number(widthSlider!.getAttribute('value'))!
|
this.currentWidth = Number(widthSlider!.getAttribute('value'))!
|
||||||
|
|
||||||
|
this.cctx = canvas.getContext("2d")!
|
||||||
}
|
}
|
||||||
|
|
||||||
draw() {
|
draw() {
|
||||||
|
|
||||||
console.log("drawing")
|
|
||||||
const strokes: Stroke[] = this.stateService.getStrokes()
|
const strokes: Stroke[] = this.stateService.getStrokes()
|
||||||
|
|
||||||
this.cctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
this.cctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||||
|
|
||||||
this.cctx.globalAlpha = 1;
|
|
||||||
strokes.forEach(stroke => {
|
strokes.forEach(stroke => {
|
||||||
this.cctx.fillStyle = stroke.color;
|
this.cctx.fillStyle = stroke.color;
|
||||||
this.drawCurve(stroke.points, stroke.density, stroke.width)
|
this.drawCurve(stroke.points, stroke.density, stroke.width)
|
||||||
@@ -122,7 +118,7 @@ export class ClientDrawService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener('click', (e) => {
|
document.addEventListener('click', (e) => {
|
||||||
if(!e.target){
|
if (!e.target) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!this.drawer.contains(e.target as Node) && !this.menuButton.contains(e.target as Node)) {
|
if (!this.drawer.contains(e.target as Node) && !this.menuButton.contains(e.target as Node)) {
|
||||||
@@ -132,12 +128,6 @@ export class ClientDrawService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private resizeCanvas() {
|
|
||||||
const size = Math.min(window.innerWidth, window.innerHeight) * 0.9;
|
|
||||||
this.canvas.width = size;
|
|
||||||
this.canvas.height = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
private drawCurve(points: Point[], density: number, width: number) {
|
private drawCurve(points: Point[], density: number, width: number) {
|
||||||
if (points.length < 2) return;
|
if (points.length < 2) return;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { RPCSocket } from "../../../../node_modules/rpclibrary/js/Index";
|
import { RPCSocket } from "../../../../node_modules/rpclibrary/js/Index";
|
||||||
import { CanvasState, Point, Stroke } from "../../model/canvas-state";
|
import { CanvasState, Point, Stroke } from "../../model/canvas-state";
|
||||||
import { ListenCallbackParam } from "../../model/rpc-callbacks";
|
import { StrokeStreamElement } from "../../model/rpc-callbacks";
|
||||||
import { ClientDrawService } from "../draw/draw.client-service";
|
import { ClientDrawService } from "../draw/draw.client-service";
|
||||||
|
|
||||||
|
|
||||||
@@ -14,11 +14,11 @@ export class ClientStateService {
|
|||||||
const sock = await new RPCSocket(8080, 'localhost').connect();
|
const sock = await new RPCSocket(8080, 'localhost').connect();
|
||||||
this.remoteService = sock['StateService']
|
this.remoteService = sock['StateService']
|
||||||
this.canvasState = await this.getState()
|
this.canvasState = await this.getState()
|
||||||
await this.remoteService.listen((listenDto: ListenCallbackParam) => {
|
await this.remoteService.onStroke((s: StrokeStreamElement) => {
|
||||||
if(!this.canvasState.strokes[listenDto.strokeId]){
|
if(!this.canvasState.strokes[s.strokeId]){
|
||||||
this.canvasState.strokes[listenDto.strokeId] = listenDto.stroke
|
this.canvasState.strokes[s.strokeId] = s.stroke
|
||||||
}else{
|
}else{
|
||||||
this.canvasState.strokes[listenDto.strokeId].points = [...this.canvasState.strokes[listenDto.strokeId].points, ...listenDto.stroke.points]
|
this.canvasState.strokes[s.strokeId].points = [...this.canvasState.strokes[s.strokeId].points, ...s.stroke.points]
|
||||||
}
|
}
|
||||||
drawService.draw()
|
drawService.draw()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ export class ExpressService implements Initializable {
|
|||||||
@Inject(StateService)
|
@Inject(StateService)
|
||||||
private stateService: StateService;
|
private stateService: StateService;
|
||||||
|
|
||||||
|
private connectionCount = 0;
|
||||||
|
|
||||||
initialize() {
|
initialize() {
|
||||||
const app = express();
|
const app = express();
|
||||||
const PORT = 8080;
|
const PORT = 8080;
|
||||||
@@ -28,7 +30,15 @@ export class ExpressService implements Initializable {
|
|||||||
const rpcServer = new RPCServer([
|
const rpcServer = new RPCServer([
|
||||||
this.stateService,
|
this.stateService,
|
||||||
|
|
||||||
])
|
], {
|
||||||
|
closeHandler: (socket) => {
|
||||||
|
this.connectionCount -= 1
|
||||||
|
if(this.connectionCount === 0){
|
||||||
|
this.stateService.finalizePicture()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
connectionHandler: (socket) => { this.connectionCount += 1 },
|
||||||
|
})
|
||||||
rpcServer.attach(httpServer)
|
rpcServer.attach(httpServer)
|
||||||
rpcServer.listen(PORT)
|
rpcServer.listen(PORT)
|
||||||
|
|
||||||
|
|||||||
@@ -1,43 +1,59 @@
|
|||||||
import { Singleton, Initializable } from "depents";
|
import { Singleton, Initializable } from "depents";
|
||||||
import { RPCExporter } from "rpclibrary";
|
import { RPCExporter } from "rpclibrary";
|
||||||
import { CanvasState, Point, Stroke } from "../../../client/model/canvas-state";
|
import { CanvasState, Point, Stroke } from "../../../client/model/canvas-state";
|
||||||
import { ListenCallbackParam } from "../../../client/model/rpc-callbacks";
|
import { OnStrokeCallback } from "../../../client/model/rpc-callbacks";
|
||||||
|
import * as fs from "fs";
|
||||||
|
import * as path from "path";
|
||||||
|
|
||||||
@Singleton()
|
@Singleton()
|
||||||
export class StateService implements Initializable, RPCExporter {
|
export class StateService implements Initializable, RPCExporter {
|
||||||
name = 'StateService' as const
|
name = 'StateService' as const
|
||||||
|
|
||||||
private canvasState: CanvasState = { strokes: [] }
|
private canvasState: CanvasState = { strokes: [] }
|
||||||
private clients: Array<(param: ListenCallbackParam) => void> = []
|
private onStrokeCallbacks: Array<OnStrokeCallback> = []
|
||||||
|
|
||||||
initialize() {
|
initialize() {
|
||||||
this.canvasState = { strokes: [] }
|
this.canvasState = { strokes: [] }
|
||||||
this.clients = []
|
this.onStrokeCallbacks = []
|
||||||
};
|
};
|
||||||
|
|
||||||
beginStroke = async (stroke: Stroke) => {
|
beginStroke = async (stroke: Stroke) => {
|
||||||
const strokeId = this.canvasState.strokes.length
|
const strokeId = this.canvasState.strokes.length
|
||||||
this.canvasState.strokes.push(stroke)
|
this.canvasState.strokes.push(stroke)
|
||||||
this.updateclients(strokeId, stroke)
|
this.updateStrokeListeners(strokeId, stroke)
|
||||||
return strokeId
|
return strokeId
|
||||||
}
|
}
|
||||||
|
|
||||||
addPoint = async (strokeId: number, point: Point) => {
|
addPoint = async (strokeId: number, point: Point) => {
|
||||||
this.canvasState.strokes[strokeId].points.push(point)
|
this.canvasState.strokes[strokeId].points.push(point)
|
||||||
this.updateclients(strokeId, { ...this.canvasState.strokes[strokeId], points: [point] })
|
this.updateStrokeListeners(strokeId, { ...this.canvasState.strokes[strokeId], points: [point] })
|
||||||
}
|
}
|
||||||
|
|
||||||
listen = async (callback: (state: any) => Promise<void>) => {
|
onStroke = async (callback: OnStrokeCallback) => {
|
||||||
this.clients = [...this.clients, callback]
|
this.onStrokeCallbacks = [...this.onStrokeCallbacks, callback]
|
||||||
return this.canvasState
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
getState = async (): Promise<CanvasState> => {
|
getState = async (): Promise<CanvasState> => {
|
||||||
return this.canvasState
|
return this.canvasState
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateclients = (strokeId: number, stroke: Stroke) => {
|
finalizePicture = () => {
|
||||||
this.clients.forEach((client) => {
|
const finalState = { ...this.canvasState }
|
||||||
|
this.canvasState = { strokes: [] }
|
||||||
|
|
||||||
|
const picturedir = path.join(__dirname, `../../../../circles-pictures/`);
|
||||||
|
|
||||||
|
if (!fs.existsSync(picturedir)) {
|
||||||
|
fs.mkdirSync(picturedir);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(path.join(picturedir, `${Date.now()}.json`), JSON.stringify(finalState))
|
||||||
|
console.log(finalState)
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateStrokeListeners = (strokeId: number, stroke: Stroke) => {
|
||||||
|
this.onStrokeCallbacks.forEach((client) => {
|
||||||
client({ strokeId, stroke })
|
client({ strokeId, stroke })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -47,8 +63,8 @@ export class StateService implements Initializable, RPCExporter {
|
|||||||
this.addPoint,
|
this.addPoint,
|
||||||
this.getState,
|
this.getState,
|
||||||
{
|
{
|
||||||
name: 'listen' as const,
|
name: 'onStroke' as const,
|
||||||
hook: (cb: any) => { this.listen(cb) }
|
hook: this.onStroke,
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user