annotate onthecanvas example (#2459)
I've changed this example a little bit to add some hints to the user, similar to the only-editor example. I also removed snaplines: null from the components object because it seemed a bit unnecessary. ### Change Type - [ ] `patch` — Bug fix - [ ] `minor` — New feature - [ ] `major` — Breaking change - [ ] `dependencies` — Changes to package dependencies[^1] - [x] `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. Add a step-by-step description of how to test your PR here. 2. - [ ] Unit Tests - [ ] End to end tests ### Release Notes - annotate onthecanvas example
This commit is contained in:
parent
6fdd0987b0
commit
1cf6b4ff51
1 changed files with 58 additions and 13 deletions
|
@ -9,7 +9,9 @@ import {
|
|||
import '@tldraw/tldraw/tldraw.css'
|
||||
import { useState } from 'react'
|
||||
|
||||
// The "OnTheCanvas" component is rendered on top of the canvas, but behind the UI.
|
||||
// There's a guide at the bottom of this file!
|
||||
|
||||
// [1]
|
||||
function MyComponent() {
|
||||
const [state, setState] = useState(0)
|
||||
|
||||
|
@ -20,46 +22,49 @@ function MyComponent() {
|
|||
position: 'absolute',
|
||||
top: 50,
|
||||
left: 50,
|
||||
width: 'fit-content',
|
||||
width: 200,
|
||||
padding: 12,
|
||||
borderRadius: 8,
|
||||
backgroundColor: 'goldenrod',
|
||||
zIndex: 0,
|
||||
pointerEvents: 'all',
|
||||
userSelect: 'unset',
|
||||
boxShadow: '0 0 0 1px rgba(0,0,0,0.1), 0 4px 8px rgba(0,0,0,0.1)',
|
||||
}}
|
||||
onPointerDown={stopEventPropagation}
|
||||
onPointerMove={stopEventPropagation}
|
||||
>
|
||||
The count is {state}! <button onClick={() => setState((s) => s - 1)}>-1</button>
|
||||
<p>The count is {state}! </p>
|
||||
<button onClick={() => setState((s) => s - 1)}>-1</button>
|
||||
<p>These components are on the canvas. They will scale with camera zoom like shapes.</p>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 150,
|
||||
top: 210,
|
||||
left: 150,
|
||||
width: 128,
|
||||
width: 200,
|
||||
padding: 12,
|
||||
borderRadius: 8,
|
||||
backgroundColor: 'pink',
|
||||
zIndex: 99999999,
|
||||
pointerEvents: 'all',
|
||||
userSelect: 'unset',
|
||||
boxShadow: '0 0 0 1px rgba(0,0,0,0.1), 0 4px 8px rgba(0,0,0,0.1)',
|
||||
}}
|
||||
onPointerDown={stopEventPropagation}
|
||||
onPointerMove={stopEventPropagation}
|
||||
>
|
||||
The count is {state}! <button onClick={() => setState((s) => s + 1)}>+1</button>
|
||||
<p>The count is {state}! </p>
|
||||
<button onClick={() => setState((s) => s + 1)}>+1</button>
|
||||
<p>Create and select a shape to see the in front of the canvas component</p>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
// The "InFrontOfTheCanvas" component is rendered on top of the canvas, but behind the UI.
|
||||
//[2]
|
||||
const MyComponentInFront = track(() => {
|
||||
const editor = useEditor()
|
||||
const selectionRotatedPageBounds = editor.getSelectionRotatedPageBounds()
|
||||
|
||||
if (!selectionRotatedPageBounds) return null
|
||||
|
||||
const pageCoordinates = Vec.Sub(
|
||||
|
@ -73,21 +78,25 @@ const MyComponentInFront = track(() => {
|
|||
position: 'absolute',
|
||||
top: Math.max(64, pageCoordinates.y - 64),
|
||||
left: Math.max(64, pageCoordinates.x),
|
||||
padding: 12,
|
||||
borderRadius: 8,
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10,
|
||||
background: '#efefef',
|
||||
boxShadow: '0 0 0 1px rgba(0,0,0,0.1), 0 4px 8px rgba(0,0,0,0.1)',
|
||||
}}
|
||||
>
|
||||
This does not scale with the zoom
|
||||
<p>This won't scale with zoom.</p>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
// [3]
|
||||
const components: TLEditorComponents = {
|
||||
OnTheCanvas: MyComponent,
|
||||
InFrontOfTheCanvas: MyComponentInFront,
|
||||
SnapLine: null,
|
||||
}
|
||||
|
||||
// [4]
|
||||
export default function OnTheCanvasExample() {
|
||||
return (
|
||||
<div className="tldraw__editor">
|
||||
|
@ -95,3 +104,39 @@ export default function OnTheCanvasExample() {
|
|||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
This example shows how you can use the onTheCanvas and inFrontOfTheCanvas components.
|
||||
onTheCanvas components will behave similarly to shapes, they will scale with the zoom
|
||||
and move when the page is panned. inFrontOfTheCanvas components don't scale with the
|
||||
zoom, but still move when the page is panned.
|
||||
|
||||
For another example that shows how to customize components, check out the custom
|
||||
components example.
|
||||
|
||||
To have a component that ignores the camera entirely, you should check out the custom
|
||||
UI example.
|
||||
|
||||
|
||||
[1]
|
||||
This is our onTheCanvas component. We also stop event propagation on the pointer events
|
||||
so that we don't accidentally select shapes when interacting with the component.
|
||||
|
||||
[2]
|
||||
This is our inFrontOfTheCanvas component. We want to render this next to a selected shape,
|
||||
so we need to make sure it's reactive to changes in the editor. We use the track function
|
||||
to make sure the component is re-rendered whenever the selection changes. Check out the
|
||||
Signia docs for more info: https://signia.tldraw.dev/docs/API/signia_react/functions/track
|
||||
|
||||
Using the editor instance we can get the bounds of the selection box and convert them to
|
||||
screen coordinates. We then render the component at those coordinates.
|
||||
|
||||
|
||||
[3]
|
||||
This is where we define the object that will be passed to the Tldraw component prop.
|
||||
|
||||
[4]
|
||||
This is where we render the Tldraw component. Let's pass the components object to the
|
||||
components prop.
|
||||
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue