diff --git a/src/app.js b/src/app.js index c50df89efff35421e32548074b9a3b1df098f261..62626b62832d8be6b263f7489d3858eeaf8fea11 100644 --- a/src/app.js +++ b/src/app.js @@ -145,7 +145,7 @@ const onRoomConnect = (room_) => { }) room.addEventListener("addOrUpdatePath", ({ detail: { id, points } }) => { - canvas.renderPath(id, points, room.erasureIntervals) + canvas.renderPath(id, points, room.erasureIntervals[id] || []) }) room.addEventListener( @@ -155,7 +155,7 @@ const onRoomConnect = (room_) => { room.erasureIntervals[id] || {}, intervals, ) - canvas.renderPath(id, points, room.erasureIntervals) + canvas.renderPath(id, points, room.erasureIntervals[id] || []) }, ) } diff --git a/src/canvas.js b/src/canvas.js index 6aeaecccfe4fc74c5b90daac239efaa9a5d2d4e7..26c9c758c5892be1a128bc2832f4bb8f081610c4 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -75,22 +75,12 @@ export const input = new EventTarget() const createSvgElem = (tagName) => document.createElementNS(SVG_URL, tagName) -const erasurePoints = (point0, point1, [start, fin]) => { - if (start >= fin) return - if (start <= 0) start = 0 - if (fin >= 1) fin = 1 - - const dx = point1[0] - point0[0] - const dy = point1[1] - point0[1] - const dw = point1[2] - point0[2] - - return [start, fin].map((fraction) => [ - point0[0] + fraction * dx, - point0[1] + fraction * dy, - point0[2] + fraction * dw, - point0[3], - ]) -} +const interpolate = (point0, point1, fraction) => [ + point0[0] + fraction * (point1[0] - point0[0]), + point0[1] + fraction * (point1[1] - point0[1]), + point0[2] + fraction * (point1[2] - point0[2]), + point0[3], +] const ensurePathGroupElem = (id) => { let groupElem = pathGroupElems.get(id) @@ -138,45 +128,31 @@ const isValidPoint = (point) => { return point != null && point[0] != null } -const getEraseIntervalsForPointInPath = (intervals, pathID, pointID) => { - if (!intervals) return undefined - const eraseIntervalsForPath = intervals[pathID] - if (!eraseIntervalsForPath) return undefined - return eraseIntervalsForPath[pointID] -} - const POINT_ERASE_LIMIT = 0.0001 -const pointWasErased = (eraseIntervals) => { +const pointWasErased = (pointEraseIntervals) => { return ( - eraseIntervals.length && - eraseIntervals[0] && - eraseIntervals[0][0] <= POINT_ERASE_LIMIT + pointEraseIntervals.length > 0 && + pointEraseIntervals[0][0] <= POINT_ERASE_LIMIT ) } -const needToDrawLastPoint = (points, pathID, eraseIntervals) => { +const needToDrawLastPoint = (points, pathEraseIntervals) => { if (points.length < 2) return true const penultimatePointIndex = points.length - 2 - const penPointEraseIntervals = getEraseIntervalsForPointInPath( - eraseIntervals, - pathID, - penultimatePointIndex, - ) + const pointEraseIntervals = pathEraseIntervals[penultimatePointIndex] || null if ( - penPointEraseIntervals && - penPointEraseIntervals.length && - penPointEraseIntervals.some( - (interval) => interval[1] >= 1 - POINT_ERASE_LIMIT, - ) + pointEraseIntervals != null && + pointEraseIntervals.length > 0 && + pointEraseIntervals.some((interval) => interval[1] >= 1 - POINT_ERASE_LIMIT) ) { return false } return true } -const applyErasureIntervals = (pathID, points, erasureIntervals) => { +const applyErasureIntervals = (points, pathEraseIntervals) => { if (points.length == 0) { return [] } @@ -191,42 +167,33 @@ const applyErasureIntervals = (pathID, points, erasureIntervals) => { } const nextPoint = points[i + 1] - const eraseIntervals = getEraseIntervalsForPointInPath( - erasureIntervals, - pathID, - i, - ) + const pointEraseIntervals = pathEraseIntervals[i] || null - if (!eraseIntervals) { + if (pointEraseIntervals == null) { subpath.push(point) continue - } else if (nextPoint === undefined) { - if (JSON.stringify(eraseIntervals) != "[[0,0]]") subpath.push(point) + } else if (nextPoint == null) { + if (JSON.stringify(pointEraseIntervals) != "[[0,0]]") subpath.push(point) continue } - if (!pointWasErased(eraseIntervals) || subpath.length) { + if (!pointWasErased(pointEraseIntervals) || subpath.length) { subpath.push(point) } - for (const eraseInterval of eraseIntervals) { - if (!eraseInterval) continue - - const erasedIntervalBounds = erasurePoints( - point, - nextPoint, - eraseInterval, + for (const pointEraseInterval of pointEraseIntervals) { + const eraseIntervalBounds = pointEraseInterval.map((f) => + interpolate(point, nextPoint, f), ) - if (!(erasedIntervalBounds && erasedIntervalBounds.length)) continue - const [endOfDrawnSegment, startOfNewSegment] = erasedIntervalBounds + const [endOfDrawnSegment, startOfNewSegment] = eraseIntervalBounds - if (eraseInterval[0] > POINT_ERASE_LIMIT) { + if (pointEraseInterval[0] > POINT_ERASE_LIMIT) { subpath.push(endOfDrawnSegment) } subpaths.push(subpath.slice()) - if (eraseInterval[1] < 1 - POINT_ERASE_LIMIT) { + if (pointEraseInterval[1] < 1 - POINT_ERASE_LIMIT) { subpath = [startOfNewSegment] } else { subpath = [] @@ -234,7 +201,7 @@ const applyErasureIntervals = (pathID, points, erasureIntervals) => { } } - if (needToDrawLastPoint(points, pathID, erasureIntervals)) { + if (needToDrawLastPoint(points, pathEraseIntervals)) { subpaths.push(subpath.slice()) } @@ -255,8 +222,8 @@ export const splitOnPressures = ([...path]) => { return subpaths } -export const renderPath = (id, points, erasureIntervals) => { - let subpaths = applyErasureIntervals(id, points, erasureIntervals) +export const renderPath = (id, points, pathEraseIntervals) => { + let subpaths = applyErasureIntervals(points, pathEraseIntervals) subpaths = subpaths.map(smoothPath) subpaths = subpaths.flatMap(splitOnPressures) const subpathElems = subpaths.map((subpath) => renderSubpath(subpath))