Fix drawing session, avoids expensive iterations if we can
This commit is contained in:
parent
e7987ca451
commit
9787cafc06
6 changed files with 41 additions and 35 deletions
|
@ -72,7 +72,7 @@ export class Arrow extends TLDrawShapeUtil<ArrowShape, SVGGElement> {
|
||||||
}
|
}
|
||||||
|
|
||||||
render = React.forwardRef<SVGGElement, TLShapeProps<ArrowShape, SVGGElement>>(
|
render = React.forwardRef<SVGGElement, TLShapeProps<ArrowShape, SVGGElement>>(
|
||||||
({ shape, meta, events }) => {
|
({ shape, meta, events }, ref) => {
|
||||||
const {
|
const {
|
||||||
handles: { start, bend, end },
|
handles: { start, bend, end },
|
||||||
decorations = {},
|
decorations = {},
|
||||||
|
@ -220,7 +220,7 @@ export class Arrow extends TLDrawShapeUtil<ArrowShape, SVGGElement> {
|
||||||
const sw = strokeWidth * 1.618
|
const sw = strokeWidth * 1.618
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<g {...events}>
|
<g ref={ref} {...events}>
|
||||||
<g pointerEvents="none">
|
<g pointerEvents="none">
|
||||||
{shaftPath}
|
{shaftPath}
|
||||||
{startArrowHead && (
|
{startArrowHead && (
|
||||||
|
|
|
@ -31,7 +31,7 @@ export class Draw extends TLDrawShapeUtil<DrawShape, SVGGElement> {
|
||||||
}
|
}
|
||||||
|
|
||||||
render = React.forwardRef<SVGGElement, TLShapeProps<DrawShape, SVGGElement>>(
|
render = React.forwardRef<SVGGElement, TLShapeProps<DrawShape, SVGGElement>>(
|
||||||
({ shape, meta, events, isEditing }) => {
|
({ shape, meta, events, isEditing }, ref) => {
|
||||||
const { points, style } = shape
|
const { points, style } = shape
|
||||||
|
|
||||||
const styles = getShapeStyle(style, meta.isDarkMode)
|
const styles = getShapeStyle(style, meta.isDarkMode)
|
||||||
|
@ -47,7 +47,7 @@ export class Draw extends TLDrawShapeUtil<DrawShape, SVGGElement> {
|
||||||
const sw = strokeWidth * 0.618
|
const sw = strokeWidth * 0.618
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<g {...events}>
|
<g ref={ref} {...events}>
|
||||||
<circle
|
<circle
|
||||||
r={strokeWidth * 0.618}
|
r={strokeWidth * 0.618}
|
||||||
fill={styles.stroke}
|
fill={styles.stroke}
|
||||||
|
@ -76,7 +76,7 @@ export class Draw extends TLDrawShapeUtil<DrawShape, SVGGElement> {
|
||||||
: Utils.getFromCache(this.drawPathCache, points, () => getDrawStrokePath(shape, false))
|
: Utils.getFromCache(this.drawPathCache, points, () => getDrawStrokePath(shape, false))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<g {...events}>
|
<g ref={ref} {...events}>
|
||||||
{shouldFill && (
|
{shouldFill && (
|
||||||
<path
|
<path
|
||||||
d={polygonPathData}
|
d={polygonPathData}
|
||||||
|
@ -121,7 +121,7 @@ export class Draw extends TLDrawShapeUtil<DrawShape, SVGGElement> {
|
||||||
const sw = strokeWidth * 1.618
|
const sw = strokeWidth * 1.618
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<g {...events}>
|
<g ref={ref} {...events}>
|
||||||
<path
|
<path
|
||||||
d={path}
|
d={path}
|
||||||
fill={shouldFill ? styles.fill : 'none'}
|
fill={shouldFill ? styles.fill : 'none'}
|
||||||
|
@ -260,19 +260,6 @@ export class Draw extends TLDrawShapeUtil<DrawShape, SVGGElement> {
|
||||||
): Partial<DrawShape> {
|
): Partial<DrawShape> {
|
||||||
return this.transform(shape, bounds, info)
|
return this.transform(shape, bounds, info)
|
||||||
}
|
}
|
||||||
|
|
||||||
onSessionComplete(shape: DrawShape): Partial<DrawShape> {
|
|
||||||
const bounds = this.getBounds(shape)
|
|
||||||
|
|
||||||
const [x1, y1] = Vec.round(Vec.sub([bounds.minX, bounds.minY], shape.point))
|
|
||||||
|
|
||||||
const points = shape.points.map(([x0, y0, p]) => Vec.round([x0 - x1, y0 - y1]).concat(p))
|
|
||||||
|
|
||||||
return {
|
|
||||||
points,
|
|
||||||
point: Vec.add(shape.point, [x1, y1]),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const simulatePressureSettings = {
|
const simulatePressureSettings = {
|
||||||
|
|
|
@ -38,7 +38,7 @@ export class Ellipse extends TLDrawShapeUtil<EllipseShape, SVGGElement> {
|
||||||
}
|
}
|
||||||
|
|
||||||
render = React.forwardRef<SVGGElement, TLShapeProps<EllipseShape, SVGGElement>>(
|
render = React.forwardRef<SVGGElement, TLShapeProps<EllipseShape, SVGGElement>>(
|
||||||
({ shape, meta, isBinding, events }) => {
|
({ shape, meta, isBinding, events }, ref) => {
|
||||||
const {
|
const {
|
||||||
radius: [radiusX, radiusY],
|
radius: [radiusX, radiusY],
|
||||||
style,
|
style,
|
||||||
|
@ -56,7 +56,7 @@ export class Ellipse extends TLDrawShapeUtil<EllipseShape, SVGGElement> {
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<g {...events}>
|
<g ref={ref} {...events}>
|
||||||
{isBinding && (
|
{isBinding && (
|
||||||
<ellipse
|
<ellipse
|
||||||
className="tl-binding-indicator"
|
className="tl-binding-indicator"
|
||||||
|
@ -102,7 +102,7 @@ export class Ellipse extends TLDrawShapeUtil<EllipseShape, SVGGElement> {
|
||||||
const sw = strokeWidth * 1.618
|
const sw = strokeWidth * 1.618
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<g {...events}>
|
<g ref={ref} {...events}>
|
||||||
{isBinding && (
|
{isBinding && (
|
||||||
<ellipse
|
<ellipse
|
||||||
className="tl-binding-indicator"
|
className="tl-binding-indicator"
|
||||||
|
|
|
@ -39,7 +39,7 @@ export class Group extends TLDrawShapeUtil<GroupShape, SVGGElement> {
|
||||||
}
|
}
|
||||||
|
|
||||||
render = React.forwardRef<SVGGElement, TLShapeProps<GroupShape, SVGGElement>>(
|
render = React.forwardRef<SVGGElement, TLShapeProps<GroupShape, SVGGElement>>(
|
||||||
({ shape, isBinding, isHovered, isSelected, events }) => {
|
({ shape, isBinding, isHovered, isSelected, events }, ref) => {
|
||||||
const { id, size } = shape
|
const { id, size } = shape
|
||||||
|
|
||||||
const sw = 2
|
const sw = 2
|
||||||
|
@ -77,7 +77,7 @@ export class Group extends TLDrawShapeUtil<GroupShape, SVGGElement> {
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<g {...events}>
|
<g ref={ref} {...events}>
|
||||||
{isBinding && (
|
{isBinding && (
|
||||||
<rect
|
<rect
|
||||||
className="tl-binding-indicator"
|
className="tl-binding-indicator"
|
||||||
|
|
|
@ -42,10 +42,6 @@ export class Rectangle extends TLDrawShapeUtil<RectangleShape, SVGGElement> {
|
||||||
const styles = getShapeStyle(style, meta.isDarkMode)
|
const styles = getShapeStyle(style, meta.isDarkMode)
|
||||||
const strokeWidth = +styles.strokeWidth
|
const strokeWidth = +styles.strokeWidth
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
console.log(this.refMap.get(shape.id))
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
if (style.dash === DashStyle.Draw) {
|
if (style.dash === DashStyle.Draw) {
|
||||||
const pathData = Utils.getFromCache(this.pathCache, shape.size, () => renderPath(shape))
|
const pathData = Utils.getFromCache(this.pathCache, shape.size, () => renderPath(shape))
|
||||||
|
|
||||||
|
@ -166,7 +162,6 @@ export class Rectangle extends TLDrawShapeUtil<RectangleShape, SVGGElement> {
|
||||||
}
|
}
|
||||||
|
|
||||||
getBounds(shape: RectangleShape) {
|
getBounds(shape: RectangleShape) {
|
||||||
console.log(this.refMap.get(shape.id))
|
|
||||||
const bounds = Utils.getFromCache(this.boundsCache, shape, () => {
|
const bounds = Utils.getFromCache(this.boundsCache, shape, () => {
|
||||||
const [width, height] = shape.size
|
const [width, height] = shape.size
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -8,10 +8,12 @@ import { TLDR } from '~state/tldr'
|
||||||
export class DrawSession implements Session {
|
export class DrawSession implements Session {
|
||||||
id = 'draw'
|
id = 'draw'
|
||||||
status = TLDrawStatus.Creating
|
status = TLDrawStatus.Creating
|
||||||
|
topLeft: number[]
|
||||||
origin: number[]
|
origin: number[]
|
||||||
previous: number[]
|
previous: number[]
|
||||||
last: number[]
|
last: number[]
|
||||||
points: number[][]
|
points: number[][]
|
||||||
|
shiftedPoints: number[][] = []
|
||||||
snapshot: DrawSnapshot
|
snapshot: DrawSnapshot
|
||||||
isLocked?: boolean
|
isLocked?: boolean
|
||||||
lockedDirection?: 'horizontal' | 'vertical'
|
lockedDirection?: 'horizontal' | 'vertical'
|
||||||
|
@ -20,6 +22,7 @@ export class DrawSession implements Session {
|
||||||
this.origin = point
|
this.origin = point
|
||||||
this.previous = point
|
this.previous = point
|
||||||
this.last = point
|
this.last = point
|
||||||
|
this.topLeft = point
|
||||||
|
|
||||||
this.snapshot = getDrawSnapshot(data, id)
|
this.snapshot = getDrawSnapshot(data, id)
|
||||||
|
|
||||||
|
@ -79,6 +82,12 @@ export class DrawSession implements Session {
|
||||||
// The previous input (not adjusted) point
|
// The previous input (not adjusted) point
|
||||||
this.previous = point
|
this.previous = point
|
||||||
|
|
||||||
|
const prevTopLeft = [...this.topLeft]
|
||||||
|
|
||||||
|
this.topLeft = [Math.min(this.topLeft[0], point[0]), Math.min(this.topLeft[1], point[1])]
|
||||||
|
|
||||||
|
const delta = Vec.sub(this.topLeft, this.origin)
|
||||||
|
|
||||||
// The new adjusted point
|
// The new adjusted point
|
||||||
const newPoint = Vec.round(Vec.sub(this.previous, this.origin)).concat(pressure)
|
const newPoint = Vec.round(Vec.sub(this.previous, this.origin)).concat(pressure)
|
||||||
|
|
||||||
|
@ -89,16 +98,35 @@ export class DrawSession implements Session {
|
||||||
// The new adjusted point is now the previous adjusted point.
|
// The new adjusted point is now the previous adjusted point.
|
||||||
this.last = newPoint
|
this.last = newPoint
|
||||||
|
|
||||||
|
let points: number[][]
|
||||||
|
|
||||||
// Add the new adjusted point to the points array
|
// Add the new adjusted point to the points array
|
||||||
this.points.push(newPoint)
|
this.points.push(newPoint)
|
||||||
|
|
||||||
|
// Time to shift some points!
|
||||||
|
|
||||||
|
if (Vec.isEqual(prevTopLeft, this.topLeft)) {
|
||||||
|
// If the new top left is the same as the previous top left,
|
||||||
|
// we don't need to shift anything: we just shift the new point
|
||||||
|
// and add it to the shifted points array.
|
||||||
|
points = [...this.shiftedPoints, Vec.sub(newPoint, delta)]
|
||||||
|
} else {
|
||||||
|
// If we have a new top left, then we need to iterate through
|
||||||
|
// the "unshifted" points array and shift them based on the
|
||||||
|
// offset between the new top left and the original top left.
|
||||||
|
points = this.points.map((pt) => Vec.sub(pt, delta))
|
||||||
|
}
|
||||||
|
|
||||||
|
this.shiftedPoints = points
|
||||||
|
|
||||||
return {
|
return {
|
||||||
document: {
|
document: {
|
||||||
pages: {
|
pages: {
|
||||||
[data.appState.currentPageId]: {
|
[data.appState.currentPageId]: {
|
||||||
shapes: {
|
shapes: {
|
||||||
[snapshot.id]: {
|
[snapshot.id]: {
|
||||||
points: [...this.points], // Set to a new array here
|
point: this.topLeft,
|
||||||
|
points,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -163,11 +191,7 @@ export class DrawSession implements Session {
|
||||||
pages: {
|
pages: {
|
||||||
[pageId]: {
|
[pageId]: {
|
||||||
shapes: {
|
shapes: {
|
||||||
[snapshot.id]: TLDR.onSessionComplete(
|
[snapshot.id]: TLDR.getShape(data, snapshot.id, pageId),
|
||||||
data,
|
|
||||||
{ ...TLDR.getShape(data, snapshot.id, pageId), points: [...this.points] },
|
|
||||||
pageId
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue