fix line bugs (#1936)

closes #1913 

Some lines aren't rendering:
<img width="500" alt="shapes"
src="https://github.com/tldraw/tldraw/assets/98838967/bd01bb0f-a967-46ce-9056-a81421224931">

When we begin drawing a line it's nice for the user to be able to see a
dot, so we put down two points. The end point for a new line was set to
the same position as the first point, which was causing a bunch of
divide by zero errors. Offsetting it slightly fixes that.

Now when two handles are too close together we extend the second one
instead of drawing a third. This will probably only ever happen with the
first two points of a line.

### Change Type

- [x] `patch` — Bug fix
- [ ] `minor` — New feature
- [ ] `major` — Breaking change
- [ ] `dependencies` — Changes to package dependencies[^1]
- [ ] `documentation` — Changes to the documentation only[^2]
- [ ] `tests` — Changes to any test code only[^2]
- [ ] `internal` — Any other changes that don't affect the published
package[^2]
- [ ] I don't know

[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: will not publish a new version

### Test Plan

1. Select the Line tool and set spline to line and dash to draw
2. Click around the canvas
3. You should now be able to actually see a line
4. Now set spline to cubic and dash to solid
5. shift click around the canvas
6. You should be able to see a line!

### Release Notes

- This PR patches a couple of bugs which led to straight draw lines and
beziered dash lines not rendering on the canvas

Before & After:

<image width="250"
src="https://github.com/tldraw/tldraw/assets/98838967/e0ca7d54-506f-4014-b65a-6b61a98e3665"
/>
<image width="250"
src="https://github.com/tldraw/tldraw/assets/98838967/90c9fa12-1bcb-430d-80c7-97e1faacea16"
/>

---------

Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This commit is contained in:
Taha 2023-09-29 16:07:14 +01:00 committed by GitHub
parent a176522c57
commit 73e61727cc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 26 deletions

View file

@ -146,7 +146,7 @@ describe('When extending the line with the shift-key in tool-lock mode', () => {
const line = editor.currentPageShapes[editor.currentPageShapes.length - 1]
assert(editor.isShapeOfType<TLLineShape>(line, 'line'))
const handles = Object.values(line.props.handles)
expect(handles.length).toBe(3)
expect(handles.length).toBe(2)
})
it('extends a line by shift-click dragging', () => {

View file

@ -65,8 +65,8 @@ export class LineShapeUtil extends ShapeUtil<TLLineShape> {
canBind: false,
canSnap: true,
index: 'a2',
x: 0,
y: 0,
x: 0.1,
y: 0.1,
},
},
}
@ -243,11 +243,9 @@ export class LineShapeUtil extends ShapeUtil<TLLineShape> {
)
}
}
// Cubic style spline
if (shape.props.spline === 'cubic') {
const splinePath = getSvgPathForLineGeometry(spline)
if (dash === 'solid') {
return (
<SVGContainer id={shape.id}>

View file

@ -14,6 +14,8 @@ import {
structuredClone,
} from '@tldraw/editor'
const MINIMUM_DISTANCE_BETWEEN_SHIFT_CLICKED_HANDLES = 2
export class Pointing extends StateNode {
static override id = 'pointing'
@ -27,9 +29,11 @@ export class Pointing extends StateNode {
this.markId = undefined
// Previously created line shape that we might be extending
const shape = info.shapeId && this.editor.getShape<TLLineShape>(info.shapeId)
if (shape && inputs.shiftKey) {
// Extending a previous shape
this.markId = `creating:${shape.id}`
this.editor.mark(this.markId)
this.shape = shape
@ -39,6 +43,7 @@ export class Pointing extends StateNode {
const vertexHandles = handles.filter((h) => h.type === 'vertex').sort(sortByIndex)
const endHandle = vertexHandles[vertexHandles.length - 1]
const prevEndHandle = vertexHandles[vertexHandles.length - 2]
const shapePagePoint = Matrix2d.applyToPoint(
this.editor.getShapeParentTransform(this.shape)!,
@ -47,24 +52,31 @@ export class Pointing extends StateNode {
let nextEndHandleIndex: string, nextEndHandleId: string, nextEndHandle: TLHandle
if (vertexHandles.length === 2 && vertexHandles[1].x === 1 && vertexHandles[1].y === 1) {
nextEndHandleIndex = vertexHandles[1].index
nextEndHandleId = vertexHandles[1].id
const nextPoint = Vec2d.Sub(currentPagePoint, shapePagePoint)
if (
Vec2d.Dist(endHandle, prevEndHandle) < MINIMUM_DISTANCE_BETWEEN_SHIFT_CLICKED_HANDLES ||
Vec2d.Dist(nextPoint, endHandle) < MINIMUM_DISTANCE_BETWEEN_SHIFT_CLICKED_HANDLES
) {
// If the end handle is too close to the previous end handle, we'll just extend the previous end handle
nextEndHandleIndex = endHandle.index
nextEndHandleId = endHandle.id
nextEndHandle = {
...vertexHandles[1],
x: currentPagePoint.x - shapePagePoint.x,
y: currentPagePoint.y - shapePagePoint.y,
...endHandle,
x: nextPoint.x + 0.1,
y: nextPoint.y + 0.1,
}
} else {
// Otherwise, we'll create a new end handle
nextEndHandleIndex = getIndexAbove(endHandle.index)
nextEndHandleId = 'handle:' + nextEndHandleIndex
nextEndHandle = {
x: currentPagePoint.x - shapePagePoint.x,
y: currentPagePoint.y - shapePagePoint.y,
index: nextEndHandleIndex,
canBind: false,
type: 'vertex',
id: nextEndHandleId,
type: 'vertex',
index: nextEndHandleIndex,
x: nextPoint.x + 0.1,
y: nextPoint.y + 0.1,
canBind: false,
}
}
@ -106,15 +118,17 @@ export class Pointing extends StateNode {
if (this.editor.inputs.isDragging) {
const handles = this.editor.getShapeHandles(this.shape)
console
if (!handles) {
if (this.markId) this.editor.bailToMark(this.markId)
throw Error('No handles found')
}
const lastHandle = last(handles)!
this.editor.setCurrentTool('select.dragging_handle', {
shape: this.shape,
isCreating: true,
handle: last(handles)!,
// remove the offset that we added to the handle when we created it
handle: { ...lastHandle, x: lastHandle.x - 0.1, y: lastHandle.y - 0.1 },
onInteractionEnd: 'line',
})
}

View file

@ -110,19 +110,21 @@ export const Toolbar = memo(function Toolbar() {
<div className="tlui-toolbar">
<div className="tlui-toolbar__inner">
<div className="tlui-toolbar__left">
{!isReadonly && breakpoint < 6 && !editor.isInAny('hand', 'zoom') && (
{!isReadonly && (
<div
className={classNames('tlui-toolbar__extras', {
'tlui-toolbar__extras__hidden': !showExtraActions,
})}
>
<div className="tlui-toolbar__extras__controls">
<UndoButton />
<RedoButton />
<TrashButton />
<DuplicateButton />
<ActionsMenu />
</div>
{breakpoint < 6 && !editor.isInAny('hand', 'zoom') && (
<div className="tlui-toolbar__extras__controls">
<UndoButton />
<RedoButton />
<TrashButton />
<DuplicateButton />
<ActionsMenu />
</div>
)}
<ToggleToolLockedButton activeToolId={activeToolId} />
</div>
)}