814 lines
19 KiB
TypeScript
814 lines
19 KiB
TypeScript
import { Gesture } from "@/gestures"
|
|
import { Editor, TLDrawShape, TLShape, VecLike, createShapeId } from "tldraw"
|
|
|
|
const getShapesUnderGesture = (editor: Editor, gesture: TLDrawShape) => {
|
|
const bounds = editor.getShapePageBounds(gesture.id)
|
|
return editor.getShapesAtPoint(bounds?.center!, {
|
|
margin: (bounds?.width! + bounds?.height!) / 4,
|
|
}).filter((shape) => shape.id !== gesture.id)
|
|
}
|
|
|
|
/** Returns shapes arranged in a circle around the given origin */
|
|
const circleDistribution = (editor: Editor, shapes: TLShape[], origin: VecLike, radius: number): TLShape[] => {
|
|
const angleStep = (2 * Math.PI) / shapes.length;
|
|
return shapes.map((shape, index) => {
|
|
const { w, h } = editor.getShapeGeometry(shape.id).bounds
|
|
const angle = index * angleStep;
|
|
const pointOnCircle = {
|
|
x: origin.x + radius * Math.cos(angle),
|
|
y: origin.y + radius * Math.sin(angle),
|
|
};
|
|
const shapeAngle = angle + Math.PI / 2;
|
|
const pos = posFromRotatedCenter(pointOnCircle, w, h, shapeAngle);
|
|
return {
|
|
...shape,
|
|
x: pos.x,
|
|
y: pos.y,
|
|
rotation: shapeAngle,
|
|
};
|
|
});
|
|
}
|
|
|
|
/** Returns shapes arranged in a triangle around the given origin */
|
|
const triangleDistribution = (editor: Editor, shapes: TLShape[], origin: VecLike, radius: number): TLShape[] => {
|
|
const vertices = [
|
|
{ x: origin.x - radius, y: origin.y + radius }, // Bottom left
|
|
{ x: origin.x + radius, y: origin.y + radius }, // Bottom right
|
|
{ x: origin.x, y: origin.y - radius }, // Top middle
|
|
];
|
|
|
|
const totalShapes = shapes.length;
|
|
const shapesPerEdge = Math.ceil(totalShapes / 3);
|
|
|
|
return shapes.map((shape, index) => {
|
|
const edgeIndex = Math.floor(index / shapesPerEdge);
|
|
const edgeStart = vertices[edgeIndex];
|
|
const edgeEnd = vertices[(edgeIndex + 1) % 3];
|
|
|
|
const t = (index % shapesPerEdge) / shapesPerEdge;
|
|
const pointOnEdge = {
|
|
x: edgeStart.x + t * (edgeEnd.x - edgeStart.x),
|
|
y: edgeStart.y + t * (edgeEnd.y - edgeStart.y),
|
|
};
|
|
|
|
let shapeAngle;
|
|
if (index % shapesPerEdge === 0) {
|
|
// Shape is at a vertex, adjust angle to face away from the triangle
|
|
const vertex = vertices[edgeIndex];
|
|
shapeAngle = Math.atan2(vertex.y - origin.y, vertex.x - origin.x);
|
|
} else {
|
|
// Shape is on an edge
|
|
shapeAngle = Math.atan2(edgeEnd.y - edgeStart.y, edgeEnd.x - edgeStart.x);
|
|
}
|
|
|
|
const { w, h } = editor.getShapeGeometry(shape.id).bounds;
|
|
const pos = posFromRotatedCenter(pointOnEdge, w, h, shapeAngle);
|
|
|
|
return {
|
|
...shape,
|
|
x: pos.x,
|
|
y: pos.y,
|
|
rotation: shapeAngle,
|
|
};
|
|
});
|
|
}
|
|
|
|
/** Calculates the top-left position of a shape given a center point, width, height, and rotation (radians) */
|
|
/** its origin x/y and rotation are around the top-left corner of the shape */
|
|
const posFromRotatedCenter = (center: VecLike, w: number, h: number, rotation: number): VecLike => {
|
|
const halfWidth = w / 2;
|
|
const halfHeight = h / 2;
|
|
|
|
const cosTheta = Math.cos(rotation);
|
|
const sinTheta = Math.sin(rotation);
|
|
|
|
const topLeftX = center.x - (halfWidth * cosTheta - halfHeight * sinTheta);
|
|
const topLeftY = center.y - (halfWidth * sinTheta + halfHeight * cosTheta);
|
|
|
|
return { x: topLeftX, y: topLeftY };
|
|
}
|
|
|
|
export const DEFAULT_GESTURES: Gesture[] = [
|
|
{
|
|
name: "x",
|
|
onComplete(editor) {
|
|
editor.deleteShapes(editor.getSelectedShapes())
|
|
},
|
|
points: [
|
|
{ x: 87, y: 142 },
|
|
{ x: 89, y: 145 },
|
|
{ x: 91, y: 148 },
|
|
{ x: 93, y: 151 },
|
|
{ x: 96, y: 155 },
|
|
{ x: 98, y: 157 },
|
|
{ x: 100, y: 160 },
|
|
{ x: 102, y: 162 },
|
|
{ x: 106, y: 167 },
|
|
{ x: 108, y: 169 },
|
|
{ x: 110, y: 171 },
|
|
{ x: 115, y: 177 },
|
|
{ x: 119, y: 183 },
|
|
{ x: 123, y: 189 },
|
|
{ x: 127, y: 193 },
|
|
{ x: 129, y: 196 },
|
|
{ x: 133, y: 200 },
|
|
{ x: 137, y: 206 },
|
|
{ x: 140, y: 209 },
|
|
{ x: 143, y: 212 },
|
|
{ x: 146, y: 215 },
|
|
{ x: 151, y: 220 },
|
|
{ x: 153, y: 222 },
|
|
{ x: 155, y: 223 },
|
|
{ x: 157, y: 225 },
|
|
{ x: 158, y: 223 },
|
|
{ x: 157, y: 218 },
|
|
{ x: 155, y: 211 },
|
|
{ x: 154, y: 208 },
|
|
{ x: 152, y: 200 },
|
|
{ x: 150, y: 189 },
|
|
{ x: 148, y: 179 },
|
|
{ x: 147, y: 170 },
|
|
{ x: 147, y: 158 },
|
|
{ x: 147, y: 148 },
|
|
{ x: 147, y: 141 },
|
|
{ x: 147, y: 136 },
|
|
{ x: 144, y: 135 },
|
|
{ x: 142, y: 137 },
|
|
{ x: 140, y: 139 },
|
|
{ x: 135, y: 145 },
|
|
{ x: 131, y: 152 },
|
|
{ x: 124, y: 163 },
|
|
{ x: 116, y: 177 },
|
|
{ x: 108, y: 191 },
|
|
{ x: 100, y: 206 },
|
|
{ x: 94, y: 217 },
|
|
{ x: 91, y: 222 },
|
|
{ x: 89, y: 225 },
|
|
{ x: 87, y: 226 },
|
|
{ x: 87, y: 224 },
|
|
],
|
|
},
|
|
{
|
|
name: "rectangle",
|
|
onComplete(editor, gesture?: TLDrawShape) {
|
|
const bounds = editor.getShapePageBounds(gesture?.id!)
|
|
const { w, h, center } = bounds!
|
|
editor.createShape({
|
|
id: createShapeId(),
|
|
type: "geo",
|
|
x: center?.x! - w / 2,
|
|
y: center?.y! - h / 2,
|
|
isLocked: false,
|
|
props: {
|
|
fill: "solid",
|
|
w: w,
|
|
h: h,
|
|
geo: "rectangle",
|
|
dash: "draw",
|
|
size: "m",
|
|
font: "draw",
|
|
align: "middle",
|
|
verticalAlign: "middle",
|
|
growY: 0,
|
|
url: "",
|
|
scale: 1,
|
|
labelColor: "black",
|
|
richText: [] as any
|
|
},
|
|
})
|
|
},
|
|
points: [
|
|
{ x: 78, y: 149 },
|
|
{ x: 78, y: 153 },
|
|
{ x: 78, y: 157 },
|
|
{ x: 78, y: 160 },
|
|
{ x: 79, y: 162 },
|
|
{ x: 79, y: 164 },
|
|
{ x: 79, y: 167 },
|
|
{ x: 79, y: 169 },
|
|
{ x: 79, y: 173 },
|
|
{ x: 79, y: 178 },
|
|
{ x: 79, y: 183 },
|
|
{ x: 80, y: 189 },
|
|
{ x: 80, y: 193 },
|
|
{ x: 80, y: 198 },
|
|
{ x: 80, y: 202 },
|
|
{ x: 81, y: 208 },
|
|
{ x: 81, y: 210 },
|
|
{ x: 81, y: 216 },
|
|
{ x: 82, y: 222 },
|
|
{ x: 82, y: 224 },
|
|
{ x: 82, y: 227 },
|
|
{ x: 83, y: 229 },
|
|
{ x: 83, y: 231 },
|
|
{ x: 85, y: 230 },
|
|
{ x: 88, y: 232 },
|
|
{ x: 90, y: 233 },
|
|
{ x: 92, y: 232 },
|
|
{ x: 94, y: 233 },
|
|
{ x: 99, y: 232 },
|
|
{ x: 102, y: 233 },
|
|
{ x: 106, y: 233 },
|
|
{ x: 109, y: 234 },
|
|
{ x: 117, y: 235 },
|
|
{ x: 123, y: 236 },
|
|
{ x: 126, y: 236 },
|
|
{ x: 135, y: 237 },
|
|
{ x: 142, y: 238 },
|
|
{ x: 145, y: 238 },
|
|
{ x: 152, y: 238 },
|
|
{ x: 154, y: 239 },
|
|
{ x: 165, y: 238 },
|
|
{ x: 174, y: 237 },
|
|
{ x: 179, y: 236 },
|
|
{ x: 186, y: 235 },
|
|
{ x: 191, y: 235 },
|
|
{ x: 195, y: 233 },
|
|
{ x: 197, y: 233 },
|
|
{ x: 200, y: 233 },
|
|
{ x: 201, y: 235 },
|
|
{ x: 201, y: 233 },
|
|
{ x: 199, y: 231 },
|
|
{ x: 198, y: 226 },
|
|
{ x: 198, y: 220 },
|
|
{ x: 196, y: 207 },
|
|
{ x: 195, y: 195 },
|
|
{ x: 195, y: 181 },
|
|
{ x: 195, y: 173 },
|
|
{ x: 195, y: 163 },
|
|
{ x: 194, y: 155 },
|
|
{ x: 192, y: 145 },
|
|
{ x: 192, y: 143 },
|
|
{ x: 192, y: 138 },
|
|
{ x: 191, y: 135 },
|
|
{ x: 191, y: 133 },
|
|
{ x: 191, y: 130 },
|
|
{ x: 190, y: 128 },
|
|
{ x: 188, y: 129 },
|
|
{ x: 186, y: 129 },
|
|
{ x: 181, y: 132 },
|
|
{ x: 173, y: 131 },
|
|
{ x: 162, y: 131 },
|
|
{ x: 151, y: 132 },
|
|
{ x: 149, y: 132 },
|
|
{ x: 138, y: 132 },
|
|
{ x: 136, y: 132 },
|
|
{ x: 122, y: 131 },
|
|
{ x: 120, y: 131 },
|
|
{ x: 109, y: 130 },
|
|
{ x: 107, y: 130 },
|
|
{ x: 90, y: 132 },
|
|
{ x: 81, y: 133 },
|
|
{ x: 76, y: 133 },
|
|
],
|
|
},
|
|
{
|
|
name: "circle",
|
|
onComplete(editor, gesture?: TLDrawShape) {
|
|
const selection = getShapesUnderGesture(editor, gesture!)
|
|
editor.setSelectedShapes(selection)
|
|
editor.setHintingShapes(selection)
|
|
},
|
|
points: [
|
|
{ x: 127, y: 141 },
|
|
{ x: 124, y: 140 },
|
|
{ x: 120, y: 139 },
|
|
{ x: 118, y: 139 },
|
|
{ x: 116, y: 139 },
|
|
{ x: 111, y: 140 },
|
|
{ x: 109, y: 141 },
|
|
{ x: 104, y: 144 },
|
|
{ x: 100, y: 147 },
|
|
{ x: 96, y: 152 },
|
|
{ x: 93, y: 157 },
|
|
{ x: 90, y: 163 },
|
|
{ x: 87, y: 169 },
|
|
{ x: 85, y: 175 },
|
|
{ x: 83, y: 181 },
|
|
{ x: 82, y: 190 },
|
|
{ x: 82, y: 195 },
|
|
{ x: 83, y: 200 },
|
|
{ x: 84, y: 205 },
|
|
{ x: 88, y: 213 },
|
|
{ x: 91, y: 216 },
|
|
{ x: 96, y: 219 },
|
|
{ x: 103, y: 222 },
|
|
{ x: 108, y: 224 },
|
|
{ x: 111, y: 224 },
|
|
{ x: 120, y: 224 },
|
|
{ x: 133, y: 223 },
|
|
{ x: 142, y: 222 },
|
|
{ x: 152, y: 218 },
|
|
{ x: 160, y: 214 },
|
|
{ x: 167, y: 210 },
|
|
{ x: 173, y: 204 },
|
|
{ x: 178, y: 198 },
|
|
{ x: 179, y: 196 },
|
|
{ x: 182, y: 188 },
|
|
{ x: 182, y: 177 },
|
|
{ x: 178, y: 167 },
|
|
{ x: 170, y: 150 },
|
|
{ x: 163, y: 138 },
|
|
{ x: 152, y: 130 },
|
|
{ x: 143, y: 129 },
|
|
{ x: 140, y: 131 },
|
|
{ x: 129, y: 136 },
|
|
{ x: 126, y: 139 },
|
|
],
|
|
},
|
|
{
|
|
name: "check",
|
|
onComplete(editor, gesture?: TLDrawShape) {
|
|
const originPoint = { x: gesture?.x!, y: gesture?.y! }
|
|
const shapeAtOrigin = editor.getShapesAtPoint(originPoint, {
|
|
hitInside: true,
|
|
margin: 10,
|
|
})
|
|
for (const shape of shapeAtOrigin) {
|
|
if (shape.id === gesture?.id) continue
|
|
editor.updateShape({
|
|
...shape,
|
|
props: {
|
|
...shape.props,
|
|
color: "green",
|
|
},
|
|
})
|
|
}
|
|
},
|
|
points: [
|
|
{ x: 91, y: 185 },
|
|
{ x: 93, y: 185 },
|
|
{ x: 95, y: 185 },
|
|
{ x: 97, y: 185 },
|
|
{ x: 100, y: 188 },
|
|
{ x: 102, y: 189 },
|
|
{ x: 104, y: 190 },
|
|
{ x: 106, y: 193 },
|
|
{ x: 108, y: 195 },
|
|
{ x: 110, y: 198 },
|
|
{ x: 112, y: 201 },
|
|
{ x: 114, y: 204 },
|
|
{ x: 115, y: 207 },
|
|
{ x: 117, y: 210 },
|
|
{ x: 118, y: 212 },
|
|
{ x: 120, y: 214 },
|
|
{ x: 121, y: 217 },
|
|
{ x: 122, y: 219 },
|
|
{ x: 123, y: 222 },
|
|
{ x: 124, y: 224 },
|
|
{ x: 126, y: 226 },
|
|
{ x: 127, y: 229 },
|
|
{ x: 129, y: 231 },
|
|
{ x: 130, y: 233 },
|
|
{ x: 129, y: 231 },
|
|
{ x: 129, y: 228 },
|
|
{ x: 129, y: 226 },
|
|
{ x: 129, y: 224 },
|
|
{ x: 129, y: 221 },
|
|
{ x: 129, y: 218 },
|
|
{ x: 129, y: 212 },
|
|
{ x: 129, y: 208 },
|
|
{ x: 130, y: 198 },
|
|
{ x: 132, y: 189 },
|
|
{ x: 134, y: 182 },
|
|
{ x: 137, y: 173 },
|
|
{ x: 143, y: 164 },
|
|
{ x: 147, y: 157 },
|
|
{ x: 151, y: 151 },
|
|
{ x: 155, y: 144 },
|
|
{ x: 161, y: 137 },
|
|
{ x: 165, y: 131 },
|
|
{ x: 171, y: 122 },
|
|
{ x: 174, y: 118 },
|
|
{ x: 176, y: 114 },
|
|
{ x: 177, y: 112 },
|
|
{ x: 177, y: 114 },
|
|
{ x: 175, y: 116 },
|
|
{ x: 173, y: 118 },
|
|
],
|
|
},
|
|
{
|
|
name: "caret",
|
|
onComplete(editor) {
|
|
editor.alignShapes(editor.getSelectedShapes(), "top")
|
|
},
|
|
points: [
|
|
{ x: 79, y: 245 },
|
|
{ x: 79, y: 242 },
|
|
{ x: 79, y: 239 },
|
|
{ x: 80, y: 237 },
|
|
{ x: 80, y: 234 },
|
|
{ x: 81, y: 232 },
|
|
{ x: 82, y: 230 },
|
|
{ x: 84, y: 224 },
|
|
{ x: 86, y: 220 },
|
|
{ x: 86, y: 218 },
|
|
{ x: 87, y: 216 },
|
|
{ x: 88, y: 213 },
|
|
{ x: 90, y: 207 },
|
|
{ x: 91, y: 202 },
|
|
{ x: 92, y: 200 },
|
|
{ x: 93, y: 194 },
|
|
{ x: 94, y: 192 },
|
|
{ x: 96, y: 189 },
|
|
{ x: 97, y: 186 },
|
|
{ x: 100, y: 179 },
|
|
{ x: 102, y: 173 },
|
|
{ x: 105, y: 165 },
|
|
{ x: 107, y: 160 },
|
|
{ x: 109, y: 158 },
|
|
{ x: 112, y: 151 },
|
|
{ x: 115, y: 144 },
|
|
{ x: 117, y: 139 },
|
|
{ x: 119, y: 136 },
|
|
{ x: 119, y: 134 },
|
|
{ x: 120, y: 132 },
|
|
{ x: 121, y: 129 },
|
|
{ x: 122, y: 127 },
|
|
{ x: 124, y: 125 },
|
|
{ x: 126, y: 124 },
|
|
{ x: 129, y: 125 },
|
|
{ x: 131, y: 127 },
|
|
{ x: 132, y: 130 },
|
|
{ x: 136, y: 139 },
|
|
{ x: 141, y: 154 },
|
|
{ x: 145, y: 166 },
|
|
{ x: 151, y: 182 },
|
|
{ x: 156, y: 193 },
|
|
{ x: 157, y: 196 },
|
|
{ x: 161, y: 209 },
|
|
{ x: 162, y: 211 },
|
|
{ x: 167, y: 223 },
|
|
{ x: 169, y: 229 },
|
|
{ x: 170, y: 231 },
|
|
{ x: 173, y: 237 },
|
|
{ x: 176, y: 242 },
|
|
{ x: 177, y: 244 },
|
|
{ x: 179, y: 250 },
|
|
{ x: 181, y: 255 },
|
|
{ x: 182, y: 257 },
|
|
],
|
|
},
|
|
// {
|
|
// name: "zig-zag",
|
|
// points: [
|
|
// { x: 307, y: 216 },
|
|
// { x: 333, y: 186 },
|
|
// { x: 356, y: 215 },
|
|
// { x: 375, y: 186 },
|
|
// { x: 399, y: 216 },
|
|
// { x: 418, y: 186 },
|
|
// ],
|
|
// },
|
|
{
|
|
name: "v",
|
|
onComplete(editor) {
|
|
editor.alignShapes(editor.getSelectedShapes(), "bottom")
|
|
},
|
|
points: [
|
|
{ x: 89, y: 164 },
|
|
{ x: 90, y: 162 },
|
|
{ x: 92, y: 162 },
|
|
{ x: 94, y: 164 },
|
|
{ x: 95, y: 166 },
|
|
{ x: 96, y: 169 },
|
|
{ x: 97, y: 171 },
|
|
{ x: 99, y: 175 },
|
|
{ x: 101, y: 178 },
|
|
{ x: 103, y: 182 },
|
|
{ x: 106, y: 189 },
|
|
{ x: 108, y: 194 },
|
|
{ x: 111, y: 199 },
|
|
{ x: 114, y: 204 },
|
|
{ x: 117, y: 209 },
|
|
{ x: 119, y: 214 },
|
|
{ x: 122, y: 218 },
|
|
{ x: 124, y: 222 },
|
|
{ x: 126, y: 225 },
|
|
{ x: 128, y: 228 },
|
|
{ x: 130, y: 229 },
|
|
{ x: 133, y: 233 },
|
|
{ x: 134, y: 236 },
|
|
{ x: 136, y: 239 },
|
|
{ x: 138, y: 240 },
|
|
{ x: 139, y: 242 },
|
|
{ x: 140, y: 244 },
|
|
{ x: 142, y: 242 },
|
|
{ x: 142, y: 240 },
|
|
{ x: 142, y: 237 },
|
|
{ x: 143, y: 235 },
|
|
{ x: 143, y: 233 },
|
|
{ x: 145, y: 229 },
|
|
{ x: 146, y: 226 },
|
|
{ x: 148, y: 217 },
|
|
{ x: 149, y: 208 },
|
|
{ x: 149, y: 205 },
|
|
{ x: 151, y: 196 },
|
|
{ x: 151, y: 193 },
|
|
{ x: 153, y: 182 },
|
|
{ x: 155, y: 172 },
|
|
{ x: 157, y: 165 },
|
|
{ x: 159, y: 160 },
|
|
{ x: 162, y: 155 },
|
|
{ x: 164, y: 150 },
|
|
{ x: 165, y: 148 },
|
|
{ x: 166, y: 146 },
|
|
],
|
|
},
|
|
{
|
|
name: "delete",
|
|
onComplete(editor) {
|
|
editor.deleteShapes(editor.getSelectedShapes())
|
|
},
|
|
points: [
|
|
{ x: 123, y: 129 },
|
|
{ x: 123, y: 131 },
|
|
{ x: 124, y: 133 },
|
|
{ x: 125, y: 136 },
|
|
{ x: 127, y: 140 },
|
|
{ x: 129, y: 142 },
|
|
{ x: 133, y: 148 },
|
|
{ x: 137, y: 154 },
|
|
{ x: 143, y: 158 },
|
|
{ x: 145, y: 161 },
|
|
{ x: 148, y: 164 },
|
|
{ x: 153, y: 170 },
|
|
{ x: 158, y: 176 },
|
|
{ x: 160, y: 178 },
|
|
{ x: 164, y: 183 },
|
|
{ x: 168, y: 188 },
|
|
{ x: 171, y: 191 },
|
|
{ x: 175, y: 196 },
|
|
{ x: 178, y: 200 },
|
|
{ x: 180, y: 202 },
|
|
{ x: 181, y: 205 },
|
|
{ x: 184, y: 208 },
|
|
{ x: 186, y: 210 },
|
|
{ x: 187, y: 213 },
|
|
{ x: 188, y: 215 },
|
|
{ x: 186, y: 212 },
|
|
{ x: 183, y: 211 },
|
|
{ x: 177, y: 208 },
|
|
{ x: 169, y: 206 },
|
|
{ x: 162, y: 205 },
|
|
{ x: 154, y: 207 },
|
|
{ x: 145, y: 209 },
|
|
{ x: 137, y: 210 },
|
|
{ x: 129, y: 214 },
|
|
{ x: 122, y: 217 },
|
|
{ x: 118, y: 218 },
|
|
{ x: 111, y: 221 },
|
|
{ x: 109, y: 222 },
|
|
{ x: 110, y: 219 },
|
|
{ x: 112, y: 217 },
|
|
{ x: 118, y: 209 },
|
|
{ x: 120, y: 207 },
|
|
{ x: 128, y: 196 },
|
|
{ x: 135, y: 187 },
|
|
{ x: 138, y: 183 },
|
|
{ x: 148, y: 167 },
|
|
{ x: 157, y: 153 },
|
|
{ x: 163, y: 145 },
|
|
{ x: 165, y: 142 },
|
|
{ x: 172, y: 133 },
|
|
{ x: 177, y: 127 },
|
|
{ x: 179, y: 127 },
|
|
{ x: 180, y: 125 },
|
|
],
|
|
},
|
|
{
|
|
name: "pigtail",
|
|
onComplete(editor, gesture?: TLDrawShape) {
|
|
const shapes = getShapesUnderGesture(editor, gesture!)
|
|
editor.setSelectedShapes(shapes)
|
|
editor.setHintingShapes(shapes)
|
|
editor.animateShapes(shapes.map((shape) => ({
|
|
...shape,
|
|
rotation: shape.rotation + (Math.PI / -2),
|
|
})),
|
|
{
|
|
animation: {
|
|
duration: 600,
|
|
easing: (t) => t * t * (3 - 2 * t),
|
|
},
|
|
},
|
|
)
|
|
},
|
|
points: [
|
|
{ x: 81, y: 219 },
|
|
{ x: 84, y: 218 },
|
|
{ x: 86, y: 220 },
|
|
{ x: 88, y: 220 },
|
|
{ x: 90, y: 220 },
|
|
{ x: 92, y: 219 },
|
|
{ x: 95, y: 220 },
|
|
{ x: 97, y: 219 },
|
|
{ x: 99, y: 220 },
|
|
{ x: 102, y: 218 },
|
|
{ x: 105, y: 217 },
|
|
{ x: 107, y: 216 },
|
|
{ x: 110, y: 216 },
|
|
{ x: 113, y: 214 },
|
|
{ x: 116, y: 212 },
|
|
{ x: 118, y: 210 },
|
|
{ x: 121, y: 208 },
|
|
{ x: 124, y: 205 },
|
|
{ x: 126, y: 202 },
|
|
{ x: 129, y: 199 },
|
|
{ x: 132, y: 196 },
|
|
{ x: 136, y: 191 },
|
|
{ x: 139, y: 187 },
|
|
{ x: 142, y: 182 },
|
|
{ x: 144, y: 179 },
|
|
{ x: 146, y: 174 },
|
|
{ x: 148, y: 170 },
|
|
{ x: 149, y: 168 },
|
|
{ x: 151, y: 162 },
|
|
{ x: 152, y: 160 },
|
|
{ x: 152, y: 157 },
|
|
{ x: 152, y: 155 },
|
|
{ x: 152, y: 151 },
|
|
{ x: 152, y: 149 },
|
|
{ x: 152, y: 146 },
|
|
{ x: 149, y: 142 },
|
|
{ x: 148, y: 139 },
|
|
{ x: 145, y: 137 },
|
|
{ x: 141, y: 135 },
|
|
{ x: 139, y: 135 },
|
|
{ x: 134, y: 136 },
|
|
{ x: 130, y: 140 },
|
|
{ x: 128, y: 142 },
|
|
{ x: 126, y: 145 },
|
|
{ x: 122, y: 150 },
|
|
{ x: 119, y: 158 },
|
|
{ x: 117, y: 163 },
|
|
{ x: 115, y: 170 },
|
|
{ x: 114, y: 175 },
|
|
{ x: 117, y: 184 },
|
|
{ x: 120, y: 190 },
|
|
{ x: 125, y: 199 },
|
|
{ x: 129, y: 203 },
|
|
{ x: 133, y: 208 },
|
|
{ x: 138, y: 213 },
|
|
{ x: 145, y: 215 },
|
|
{ x: 155, y: 218 },
|
|
{ x: 164, y: 219 },
|
|
{ x: 166, y: 219 },
|
|
{ x: 177, y: 219 },
|
|
{ x: 182, y: 218 },
|
|
{ x: 192, y: 216 },
|
|
{ x: 196, y: 213 },
|
|
{ x: 199, y: 212 },
|
|
{ x: 201, y: 211 },
|
|
],
|
|
},
|
|
]
|
|
|
|
export const ALT_GESTURES: Gesture[] = [
|
|
{
|
|
name: "circle layout",
|
|
onComplete(editor, gesture?: TLDrawShape) {
|
|
const bounds = editor.getShapePageBounds(gesture?.id!)
|
|
const center = bounds?.center
|
|
const radius = Math.max(bounds?.width || 0, bounds?.height || 0) / 2
|
|
const selected = editor.getSelectedShapes()
|
|
const radialShapes = circleDistribution(editor, selected, center!, radius)
|
|
editor.animateShapes(radialShapes, {
|
|
animation: {
|
|
duration: 600,
|
|
easing: (t) => t * t * (3 - 2 * t),
|
|
},
|
|
})
|
|
},
|
|
points: [
|
|
{ x: 127, y: 141 },
|
|
{ x: 124, y: 140 },
|
|
{ x: 120, y: 139 },
|
|
{ x: 118, y: 139 },
|
|
{ x: 116, y: 139 },
|
|
{ x: 111, y: 140 },
|
|
{ x: 109, y: 141 },
|
|
{ x: 104, y: 144 },
|
|
{ x: 100, y: 147 },
|
|
{ x: 96, y: 152 },
|
|
{ x: 93, y: 157 },
|
|
{ x: 90, y: 163 },
|
|
{ x: 87, y: 169 },
|
|
{ x: 85, y: 175 },
|
|
{ x: 83, y: 181 },
|
|
{ x: 82, y: 190 },
|
|
{ x: 82, y: 195 },
|
|
{ x: 83, y: 200 },
|
|
{ x: 84, y: 205 },
|
|
{ x: 88, y: 213 },
|
|
{ x: 91, y: 216 },
|
|
{ x: 96, y: 219 },
|
|
{ x: 103, y: 222 },
|
|
{ x: 108, y: 224 },
|
|
{ x: 111, y: 224 },
|
|
{ x: 120, y: 224 },
|
|
{ x: 133, y: 223 },
|
|
{ x: 142, y: 222 },
|
|
{ x: 152, y: 218 },
|
|
{ x: 160, y: 214 },
|
|
{ x: 167, y: 210 },
|
|
{ x: 173, y: 204 },
|
|
{ x: 178, y: 198 },
|
|
{ x: 179, y: 196 },
|
|
{ x: 182, y: 188 },
|
|
{ x: 182, y: 177 },
|
|
{ x: 178, y: 167 },
|
|
{ x: 170, y: 150 },
|
|
{ x: 163, y: 138 },
|
|
{ x: 152, y: 130 },
|
|
{ x: 143, y: 129 },
|
|
{ x: 140, y: 131 },
|
|
{ x: 129, y: 136 },
|
|
{ x: 126, y: 139 },
|
|
],
|
|
},
|
|
{
|
|
name: "triangle layout",
|
|
onComplete(editor, gesture?: TLDrawShape) {
|
|
const bounds = editor.getShapePageBounds(gesture?.id!)
|
|
const center = bounds?.center
|
|
const radius = Math.max(bounds?.width || 0, bounds?.height || 0) / 2
|
|
const selected = editor.getSelectedShapes()
|
|
const radialShapes = triangleDistribution(editor, selected, center!, radius)
|
|
editor.animateShapes(radialShapes, {
|
|
animation: {
|
|
duration: 600,
|
|
easing: (t) => t * t * (3 - 2 * t),
|
|
},
|
|
})
|
|
},
|
|
points: [
|
|
{ x: 137, y: 139 },
|
|
{ x: 135, y: 141 },
|
|
{ x: 133, y: 144 },
|
|
{ x: 132, y: 146 },
|
|
{ x: 130, y: 149 },
|
|
{ x: 128, y: 151 },
|
|
{ x: 126, y: 155 },
|
|
{ x: 123, y: 160 },
|
|
{ x: 120, y: 166 },
|
|
{ x: 116, y: 171 },
|
|
{ x: 112, y: 177 },
|
|
{ x: 107, y: 183 },
|
|
{ x: 102, y: 188 },
|
|
{ x: 100, y: 191 },
|
|
{ x: 95, y: 195 },
|
|
{ x: 90, y: 199 },
|
|
{ x: 86, y: 203 },
|
|
{ x: 82, y: 206 },
|
|
{ x: 80, y: 209 },
|
|
{ x: 75, y: 213 },
|
|
{ x: 73, y: 213 },
|
|
{ x: 70, y: 216 },
|
|
{ x: 67, y: 219 },
|
|
{ x: 64, y: 221 },
|
|
{ x: 61, y: 223 },
|
|
{ x: 60, y: 225 },
|
|
{ x: 62, y: 226 },
|
|
{ x: 65, y: 225 },
|
|
{ x: 67, y: 226 },
|
|
{ x: 74, y: 226 },
|
|
{ x: 77, y: 227 },
|
|
{ x: 85, y: 229 },
|
|
{ x: 91, y: 230 },
|
|
{ x: 99, y: 231 },
|
|
{ x: 108, y: 232 },
|
|
{ x: 116, y: 233 },
|
|
{ x: 125, y: 233 },
|
|
{ x: 134, y: 234 },
|
|
{ x: 145, y: 233 },
|
|
{ x: 153, y: 232 },
|
|
{ x: 160, y: 233 },
|
|
{ x: 170, y: 234 },
|
|
{ x: 177, y: 235 },
|
|
{ x: 179, y: 236 },
|
|
{ x: 186, y: 237 },
|
|
{ x: 193, y: 238 },
|
|
{ x: 198, y: 239 },
|
|
{ x: 200, y: 237 },
|
|
{ x: 202, y: 239 },
|
|
{ x: 204, y: 238 },
|
|
{ x: 206, y: 234 },
|
|
{ x: 205, y: 230 },
|
|
{ x: 202, y: 222 },
|
|
{ x: 197, y: 216 },
|
|
{ x: 192, y: 207 },
|
|
{ x: 186, y: 198 },
|
|
{ x: 179, y: 189 },
|
|
{ x: 174, y: 183 },
|
|
{ x: 170, y: 178 },
|
|
{ x: 164, y: 171 },
|
|
{ x: 161, y: 168 },
|
|
{ x: 154, y: 160 },
|
|
{ x: 148, y: 155 },
|
|
{ x: 143, y: 150 },
|
|
{ x: 138, y: 148 },
|
|
{ x: 136, y: 148 },
|
|
],
|
|
},
|
|
] |