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>>(
|
||||
({ shape, meta, events }) => {
|
||||
({ shape, meta, events }, ref) => {
|
||||
const {
|
||||
handles: { start, bend, end },
|
||||
decorations = {},
|
||||
|
@ -220,7 +220,7 @@ export class Arrow extends TLDrawShapeUtil<ArrowShape, SVGGElement> {
|
|||
const sw = strokeWidth * 1.618
|
||||
|
||||
return (
|
||||
<g {...events}>
|
||||
<g ref={ref} {...events}>
|
||||
<g pointerEvents="none">
|
||||
{shaftPath}
|
||||
{startArrowHead && (
|
||||
|
|
|
@ -31,7 +31,7 @@ export class Draw extends TLDrawShapeUtil<DrawShape, SVGGElement> {
|
|||
}
|
||||
|
||||
render = React.forwardRef<SVGGElement, TLShapeProps<DrawShape, SVGGElement>>(
|
||||
({ shape, meta, events, isEditing }) => {
|
||||
({ shape, meta, events, isEditing }, ref) => {
|
||||
const { points, style } = shape
|
||||
|
||||
const styles = getShapeStyle(style, meta.isDarkMode)
|
||||
|
@ -47,7 +47,7 @@ export class Draw extends TLDrawShapeUtil<DrawShape, SVGGElement> {
|
|||
const sw = strokeWidth * 0.618
|
||||
|
||||
return (
|
||||
<g {...events}>
|
||||
<g ref={ref} {...events}>
|
||||
<circle
|
||||
r={strokeWidth * 0.618}
|
||||
fill={styles.stroke}
|
||||
|
@ -76,7 +76,7 @@ export class Draw extends TLDrawShapeUtil<DrawShape, SVGGElement> {
|
|||
: Utils.getFromCache(this.drawPathCache, points, () => getDrawStrokePath(shape, false))
|
||||
|
||||
return (
|
||||
<g {...events}>
|
||||
<g ref={ref} {...events}>
|
||||
{shouldFill && (
|
||||
<path
|
||||
d={polygonPathData}
|
||||
|
@ -121,7 +121,7 @@ export class Draw extends TLDrawShapeUtil<DrawShape, SVGGElement> {
|
|||
const sw = strokeWidth * 1.618
|
||||
|
||||
return (
|
||||
<g {...events}>
|
||||
<g ref={ref} {...events}>
|
||||
<path
|
||||
d={path}
|
||||
fill={shouldFill ? styles.fill : 'none'}
|
||||
|
@ -260,19 +260,6 @@ export class Draw extends TLDrawShapeUtil<DrawShape, SVGGElement> {
|
|||
): Partial<DrawShape> {
|
||||
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 = {
|
||||
|
|
|
@ -38,7 +38,7 @@ export class Ellipse extends TLDrawShapeUtil<EllipseShape, SVGGElement> {
|
|||
}
|
||||
|
||||
render = React.forwardRef<SVGGElement, TLShapeProps<EllipseShape, SVGGElement>>(
|
||||
({ shape, meta, isBinding, events }) => {
|
||||
({ shape, meta, isBinding, events }, ref) => {
|
||||
const {
|
||||
radius: [radiusX, radiusY],
|
||||
style,
|
||||
|
@ -56,7 +56,7 @@ export class Ellipse extends TLDrawShapeUtil<EllipseShape, SVGGElement> {
|
|||
)
|
||||
|
||||
return (
|
||||
<g {...events}>
|
||||
<g ref={ref} {...events}>
|
||||
{isBinding && (
|
||||
<ellipse
|
||||
className="tl-binding-indicator"
|
||||
|
@ -102,7 +102,7 @@ export class Ellipse extends TLDrawShapeUtil<EllipseShape, SVGGElement> {
|
|||
const sw = strokeWidth * 1.618
|
||||
|
||||
return (
|
||||
<g {...events}>
|
||||
<g ref={ref} {...events}>
|
||||
{isBinding && (
|
||||
<ellipse
|
||||
className="tl-binding-indicator"
|
||||
|
|
|
@ -39,7 +39,7 @@ export class Group extends TLDrawShapeUtil<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 sw = 2
|
||||
|
@ -77,7 +77,7 @@ export class Group extends TLDrawShapeUtil<GroupShape, SVGGElement> {
|
|||
})
|
||||
|
||||
return (
|
||||
<g {...events}>
|
||||
<g ref={ref} {...events}>
|
||||
{isBinding && (
|
||||
<rect
|
||||
className="tl-binding-indicator"
|
||||
|
|
|
@ -42,10 +42,6 @@ export class Rectangle extends TLDrawShapeUtil<RectangleShape, SVGGElement> {
|
|||
const styles = getShapeStyle(style, meta.isDarkMode)
|
||||
const strokeWidth = +styles.strokeWidth
|
||||
|
||||
React.useEffect(() => {
|
||||
console.log(this.refMap.get(shape.id))
|
||||
}, [])
|
||||
|
||||
if (style.dash === DashStyle.Draw) {
|
||||
const pathData = Utils.getFromCache(this.pathCache, shape.size, () => renderPath(shape))
|
||||
|
||||
|
@ -166,7 +162,6 @@ export class Rectangle extends TLDrawShapeUtil<RectangleShape, SVGGElement> {
|
|||
}
|
||||
|
||||
getBounds(shape: RectangleShape) {
|
||||
console.log(this.refMap.get(shape.id))
|
||||
const bounds = Utils.getFromCache(this.boundsCache, shape, () => {
|
||||
const [width, height] = shape.size
|
||||
return {
|
||||
|
|
|
@ -8,10 +8,12 @@ import { TLDR } from '~state/tldr'
|
|||
export class DrawSession implements Session {
|
||||
id = 'draw'
|
||||
status = TLDrawStatus.Creating
|
||||
topLeft: number[]
|
||||
origin: number[]
|
||||
previous: number[]
|
||||
last: number[]
|
||||
points: number[][]
|
||||
shiftedPoints: number[][] = []
|
||||
snapshot: DrawSnapshot
|
||||
isLocked?: boolean
|
||||
lockedDirection?: 'horizontal' | 'vertical'
|
||||
|
@ -20,6 +22,7 @@ export class DrawSession implements Session {
|
|||
this.origin = point
|
||||
this.previous = point
|
||||
this.last = point
|
||||
this.topLeft = point
|
||||
|
||||
this.snapshot = getDrawSnapshot(data, id)
|
||||
|
||||
|
@ -79,6 +82,12 @@ export class DrawSession implements Session {
|
|||
// The previous input (not adjusted) 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
|
||||
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.
|
||||
this.last = newPoint
|
||||
|
||||
let points: number[][]
|
||||
|
||||
// Add the new adjusted point to the points array
|
||||
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 {
|
||||
document: {
|
||||
pages: {
|
||||
[data.appState.currentPageId]: {
|
||||
shapes: {
|
||||
[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: {
|
||||
[pageId]: {
|
||||
shapes: {
|
||||
[snapshot.id]: TLDR.onSessionComplete(
|
||||
data,
|
||||
{ ...TLDR.getShape(data, snapshot.id, pageId), points: [...this.points] },
|
||||
pageId
|
||||
),
|
||||
[snapshot.id]: TLDR.getShape(data, snapshot.id, pageId),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue