Skip to content

Instantly share code, notes, and snippets.

@mootari
Last active March 8, 2025 16:50
Show Gist options
  • Save mootari/724d4b70ad07b3aa95e9d6bcc212ce51 to your computer and use it in GitHub Desktop.
Save mootari/724d4b70ad07b3aa95e9d6bcc212ce51 to your computer and use it in GitHub Desktop.
TLDraw - arrow label as range slider
import { createBindingId, createShapeId, Editor, TLArrowShape, Tldraw, UnknownRecord } from 'tldraw'
function updateText(editor: Editor, shape: TLArrowShape) {
const clamp = (a: number, b: number, v: number) => v <= a ? a : v >= b ? b : v;
const rescale = (a: number, b: number, t: number) => (t - a) / (b - a);
const t = shape.props.labelPosition;
const text = (clamp(0, 1, rescale(.1, .9, t)) * 100).toFixed(0) + "%";
editor.updateShape({id: shape.id, type: shape.type, props: {text}});
}
function isArrowShape(o: UnknownRecord): o is TLArrowShape {
return o.typeName === "shape" && "type" in o && o.type === "arrow";
}
function App() {
return (
<div style={{ position: 'fixed', inset: 0 }}>
<Tldraw onMount={editor => {
editor.store.listen(e => {
console.log("event", e);
for(const o of Object.values(e.changes.added)) if(isArrowShape(o)) updateText(editor, o);
for(const [, o] of Object.values(e.changes.updated)) if(isArrowShape(o)) updateText(editor, o);
}, {source: "user", scope: "document"});
const r1 = createShapeId("r1");
const r2 = createShapeId("r2");
const arr = createShapeId("arr");
editor.createShapes([
{type: "geo", id: r1, x: 200, y: 220, props: { geo: "rectangle", w: 100, h: 50 }},
{type: "geo", id: r2, x: 600, y: 320, props: { geo: "rectangle", w: 100, h: 50 }},
{type: "arrow", id: arr}
]);
editor.createBindings([
{type: "arrow", id: createBindingId(`${arr}-${r1}`), fromId: arr, toId: r1, props: {terminal: "start"}},
{type: "arrow", id: createBindingId(`${arr}-${r2}`), fromId: arr, toId: r2, props: {terminal: "end"}},
])
}} />
</div>
)
}
export default App
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment