kopia lustrzana https://github.com/Tldraw/Tldraw
174 wiersze
3.3 KiB
TypeScript
174 wiersze
3.3 KiB
TypeScript
import React from 'react'
|
|
import {
|
|
vec,
|
|
pointInBounds,
|
|
getBoundsCenter,
|
|
getBoundsFromPoints,
|
|
getRotatedCorners,
|
|
boundsCollidePolygon,
|
|
boundsContainPolygon,
|
|
} from 'utils'
|
|
import { Shape, ShapeUtility } from 'types'
|
|
|
|
function getDefaultShapeUtil<T extends Shape>(): ShapeUtility<T> {
|
|
return {
|
|
boundsCache: new WeakMap(),
|
|
canTransform: true,
|
|
canChangeAspectRatio: true,
|
|
canStyleFill: true,
|
|
canEdit: false,
|
|
isShy: false,
|
|
isParent: false,
|
|
isForeignObject: false,
|
|
|
|
defaultProps: {} as T,
|
|
|
|
create(props) {
|
|
return {
|
|
...this.defaultProps,
|
|
...props,
|
|
style: {
|
|
...this.defaultProps.style,
|
|
...props.style,
|
|
isFilled: this.canStyleFill
|
|
? props.style?.isFilled || this.defaultProps.style.isFilled
|
|
: false,
|
|
},
|
|
} as T
|
|
},
|
|
|
|
render(shape) {
|
|
return <circle id={shape.id} />
|
|
},
|
|
|
|
translateBy(shape, delta) {
|
|
shape.point = vec.round(vec.add(shape.point, delta))
|
|
return this
|
|
},
|
|
|
|
translateTo(shape, point) {
|
|
shape.point = vec.round(point)
|
|
return this
|
|
},
|
|
|
|
rotateTo(shape, rotation) {
|
|
shape.rotation = rotation
|
|
return this
|
|
},
|
|
|
|
rotateBy(shape, rotation) {
|
|
shape.rotation += rotation
|
|
return this
|
|
},
|
|
|
|
transform(shape, bounds) {
|
|
shape.point = [bounds.minX, bounds.minY]
|
|
return this
|
|
},
|
|
|
|
transformSingle(shape, bounds, info) {
|
|
return this.transform(shape, bounds, info)
|
|
},
|
|
|
|
onChildrenChange() {
|
|
return this
|
|
},
|
|
|
|
onBindingChange() {
|
|
return this
|
|
},
|
|
|
|
onHandleChange() {
|
|
return this
|
|
},
|
|
|
|
onDoublePointHandle() {
|
|
return this
|
|
},
|
|
|
|
onDoubleFocus() {
|
|
return this
|
|
},
|
|
|
|
onBoundsReset() {
|
|
return this
|
|
},
|
|
|
|
onSessionComplete() {
|
|
return this
|
|
},
|
|
|
|
getBounds(shape) {
|
|
const [x, y] = shape.point
|
|
return {
|
|
minX: x,
|
|
minY: y,
|
|
maxX: x + 1,
|
|
maxY: y + 1,
|
|
width: 1,
|
|
height: 1,
|
|
}
|
|
},
|
|
|
|
getRotatedBounds(shape) {
|
|
return getBoundsFromPoints(
|
|
getRotatedCorners(this.getBounds(shape), shape.rotation)
|
|
)
|
|
},
|
|
|
|
getCenter(shape) {
|
|
return getBoundsCenter(this.getBounds(shape))
|
|
},
|
|
|
|
hitTest(shape, point) {
|
|
return pointInBounds(point, this.getBounds(shape))
|
|
},
|
|
|
|
hitTestBounds(shape, brushBounds) {
|
|
const rotatedCorners = getRotatedCorners(
|
|
this.getBounds(shape),
|
|
shape.rotation
|
|
)
|
|
|
|
return (
|
|
boundsContainPolygon(brushBounds, rotatedCorners) ||
|
|
boundsCollidePolygon(brushBounds, rotatedCorners)
|
|
)
|
|
},
|
|
|
|
setProperty(shape, prop, value) {
|
|
shape[prop] = value
|
|
return this
|
|
},
|
|
|
|
applyStyles(shape, style) {
|
|
Object.assign(shape.style, style)
|
|
return this
|
|
},
|
|
|
|
shouldDelete() {
|
|
return false
|
|
},
|
|
|
|
invalidate(shape) {
|
|
this.boundsCache.delete(shape)
|
|
return this
|
|
},
|
|
|
|
shouldRender() {
|
|
return true
|
|
},
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A factory of shape utilities, with typing enforced.
|
|
* @param shape
|
|
* @returns
|
|
*/
|
|
export function registerShapeUtils<K extends Shape>(
|
|
shapeUtil: Partial<ShapeUtility<K>>
|
|
): ShapeUtility<K> {
|
|
return Object.freeze({ ...getDefaultShapeUtil<K>(), ...shapeUtil })
|
|
}
|