cleans up shape utils
This commit is contained in:
parent
9ab86ba9ae
commit
bef35b9207
13 changed files with 134 additions and 415 deletions
|
@ -153,12 +153,6 @@ const arrow = registerShapeUtils<ArrowShape>({
|
|||
)
|
||||
},
|
||||
|
||||
applyStyles(shape, style) {
|
||||
Object.assign(shape.style, style)
|
||||
shape.style.isFilled = false
|
||||
return this
|
||||
},
|
||||
|
||||
getBounds(shape) {
|
||||
if (!this.boundsCache.has(shape)) {
|
||||
this.boundsCache.set(shape, getBoundsFromPoints(shape.points))
|
||||
|
@ -167,15 +161,6 @@ const arrow = registerShapeUtils<ArrowShape>({
|
|||
return translateBounds(this.boundsCache.get(shape), shape.point)
|
||||
},
|
||||
|
||||
getRotatedBounds(shape) {
|
||||
return this.getBounds(shape)
|
||||
},
|
||||
|
||||
getCenter(shape) {
|
||||
const bounds = this.getBounds(shape)
|
||||
return [bounds.minX + bounds.width / 2, bounds.minY + bounds.height / 2]
|
||||
},
|
||||
|
||||
hitTest(shape, point) {
|
||||
const { start, end, bend } = shape.handles
|
||||
if (shape.bend === 0) {
|
||||
|
@ -247,16 +232,6 @@ const arrow = registerShapeUtils<ArrowShape>({
|
|||
return this
|
||||
},
|
||||
|
||||
transformSingle(shape, bounds, info) {
|
||||
this.transform(shape, bounds, info)
|
||||
return this
|
||||
},
|
||||
|
||||
setProperty(shape, prop, value) {
|
||||
shape[prop] = value
|
||||
return this
|
||||
},
|
||||
|
||||
onHandleMove(shape, handles) {
|
||||
for (let id in handles) {
|
||||
const handle = handles[id]
|
||||
|
@ -293,8 +268,12 @@ const arrow = registerShapeUtils<ArrowShape>({
|
|||
return this
|
||||
},
|
||||
|
||||
canTransform: true,
|
||||
canChangeAspectRatio: true,
|
||||
applyStyles(shape, style) {
|
||||
Object.assign(shape.style, style)
|
||||
shape.style.isFilled = false
|
||||
return this
|
||||
},
|
||||
|
||||
canStyleFill: false,
|
||||
})
|
||||
|
||||
|
|
|
@ -43,11 +43,6 @@ const circle = registerShapeUtils<CircleShape>({
|
|||
)
|
||||
},
|
||||
|
||||
applyStyles(shape, style) {
|
||||
Object.assign(shape.style, style)
|
||||
return this
|
||||
},
|
||||
|
||||
getBounds(shape) {
|
||||
if (!this.boundsCache.has(shape)) {
|
||||
const { radius } = shape
|
||||
|
@ -118,14 +113,7 @@ const circle = registerShapeUtils<CircleShape>({
|
|||
return this
|
||||
},
|
||||
|
||||
setProperty(shape, prop, value) {
|
||||
shape[prop] = value
|
||||
return this
|
||||
},
|
||||
|
||||
canTransform: true,
|
||||
canChangeAspectRatio: false,
|
||||
canStyleFill: true,
|
||||
})
|
||||
|
||||
export default circle
|
||||
|
|
|
@ -37,11 +37,6 @@ const dot = registerShapeUtils<DotShape>({
|
|||
return <DotCircle id={id} cx={0} cy={0} r={3} />
|
||||
},
|
||||
|
||||
applyStyles(shape, style) {
|
||||
Object.assign(shape.style, style)
|
||||
return this
|
||||
},
|
||||
|
||||
getBounds(shape) {
|
||||
if (!this.boundsCache.has(shape)) {
|
||||
const bounds = {
|
||||
|
@ -85,19 +80,8 @@ const dot = registerShapeUtils<DotShape>({
|
|||
return this
|
||||
},
|
||||
|
||||
transformSingle(shape, bounds, info) {
|
||||
this.transform(shape, bounds, info)
|
||||
return this
|
||||
},
|
||||
|
||||
setProperty(shape, prop, value) {
|
||||
shape[prop] = value
|
||||
return this
|
||||
},
|
||||
|
||||
canTransform: false,
|
||||
canChangeAspectRatio: false,
|
||||
canStyleFill: true,
|
||||
})
|
||||
|
||||
export default dot
|
||||
|
|
|
@ -70,13 +70,6 @@ const draw = registerShapeUtils<DrawShape>({
|
|||
return <path id={id} d={pathCache.get(points)} fill={styles.stroke} />
|
||||
},
|
||||
|
||||
applyStyles(shape, style) {
|
||||
Object.assign(shape.style, style)
|
||||
shape.style.isFilled = false
|
||||
shape.style.dash = DashStyle.Solid
|
||||
return this
|
||||
},
|
||||
|
||||
getBounds(shape) {
|
||||
if (!this.boundsCache.has(shape)) {
|
||||
const bounds = getBoundsFromPoints(shape.points)
|
||||
|
@ -161,18 +154,13 @@ const draw = registerShapeUtils<DrawShape>({
|
|||
return this
|
||||
},
|
||||
|
||||
transformSingle(shape, bounds, info) {
|
||||
this.transform(shape, bounds, info)
|
||||
applyStyles(shape, style) {
|
||||
Object.assign(shape.style, style)
|
||||
shape.style.isFilled = false
|
||||
shape.style.dash = DashStyle.Solid
|
||||
return this
|
||||
},
|
||||
|
||||
setProperty(shape, prop, value) {
|
||||
shape[prop] = value
|
||||
return this
|
||||
},
|
||||
|
||||
canTransform: true,
|
||||
canChangeAspectRatio: true,
|
||||
canStyleFill: false,
|
||||
})
|
||||
|
||||
|
|
|
@ -49,11 +49,6 @@ const ellipse = registerShapeUtils<EllipseShape>({
|
|||
)
|
||||
},
|
||||
|
||||
applyStyles(shape, style) {
|
||||
Object.assign(shape.style, style)
|
||||
return this
|
||||
},
|
||||
|
||||
getBounds(shape) {
|
||||
if (!this.boundsCache.has(shape)) {
|
||||
const { radiusX, radiusY } = shape
|
||||
|
@ -130,15 +125,6 @@ const ellipse = registerShapeUtils<EllipseShape>({
|
|||
transformSingle(shape, bounds, info) {
|
||||
return this.transform(shape, bounds, info)
|
||||
},
|
||||
|
||||
setProperty(shape, prop, value) {
|
||||
shape[prop] = value
|
||||
return this
|
||||
},
|
||||
|
||||
canTransform: true,
|
||||
canChangeAspectRatio: true,
|
||||
canStyleFill: true,
|
||||
})
|
||||
|
||||
export default ellipse
|
||||
|
|
|
@ -7,7 +7,11 @@ import {
|
|||
ShapeStyles,
|
||||
ShapeHandle,
|
||||
ShapeBinding,
|
||||
BaseShape,
|
||||
ShapeSpecificProps,
|
||||
Mutable,
|
||||
} from 'types'
|
||||
import { v4 as uuid } from 'uuid'
|
||||
import circle from './circle'
|
||||
import dot from './dot'
|
||||
import polyline from './polyline'
|
||||
|
@ -17,6 +21,18 @@ import line from './line'
|
|||
import ray from './ray'
|
||||
import draw from './draw'
|
||||
import arrow from './arrow'
|
||||
import rectangleUtils from '../shapes/Rectangle'
|
||||
import {
|
||||
getBoundsCenter,
|
||||
getBoundsFromPoints,
|
||||
getRotatedCorners,
|
||||
} from 'utils/utils'
|
||||
import shape from 'components/canvas/shape'
|
||||
import {
|
||||
boundsCollidePolygon,
|
||||
boundsContainPolygon,
|
||||
pointInBounds,
|
||||
} from 'utils/bounds'
|
||||
|
||||
/*
|
||||
Shape Utiliies
|
||||
|
@ -47,14 +63,14 @@ export interface ShapeUtility<K extends Shape> {
|
|||
|
||||
applyStyles(
|
||||
this: ShapeUtility<K>,
|
||||
shape: K,
|
||||
shape: Mutable<K>,
|
||||
style: Partial<ShapeStyles>
|
||||
): ShapeUtility<K>
|
||||
|
||||
// Transform to fit a new bounding box when more than one shape is selected.
|
||||
transform(
|
||||
this: ShapeUtility<K>,
|
||||
shape: K,
|
||||
shape: Mutable<K>,
|
||||
bounds: Bounds,
|
||||
info: {
|
||||
type: Edge | Corner
|
||||
|
@ -68,7 +84,7 @@ export interface ShapeUtility<K extends Shape> {
|
|||
// Transform a single shape to fit a new bounding box.
|
||||
transformSingle(
|
||||
this: ShapeUtility<K>,
|
||||
shape: K,
|
||||
shape: Mutable<K>,
|
||||
bounds: Bounds,
|
||||
info: {
|
||||
type: Edge | Corner
|
||||
|
@ -81,7 +97,7 @@ export interface ShapeUtility<K extends Shape> {
|
|||
|
||||
setProperty<P extends keyof K>(
|
||||
this: ShapeUtility<K>,
|
||||
shape: K,
|
||||
shape: Mutable<K>,
|
||||
prop: P,
|
||||
value: K[P]
|
||||
): ShapeUtility<K>
|
||||
|
@ -89,14 +105,14 @@ export interface ShapeUtility<K extends Shape> {
|
|||
// Respond when a user moves one of the shape's bound elements.
|
||||
onBindingMove?(
|
||||
this: ShapeUtility<K>,
|
||||
shape: K,
|
||||
shape: Mutable<K>,
|
||||
bindings: Record<string, ShapeBinding>
|
||||
): ShapeUtility<K>
|
||||
|
||||
// Respond when a user moves one of the shape's handles.
|
||||
onHandleMove?(
|
||||
this: ShapeUtility<K>,
|
||||
shape: K,
|
||||
shape: Mutable<K>,
|
||||
handle: Partial<K['handles']>
|
||||
): ShapeUtility<K>
|
||||
|
||||
|
@ -141,15 +157,109 @@ export function getShapeUtils<T extends Shape>(shape: T): ShapeUtility<T> {
|
|||
return shapeUtilityMap[shape.type] as ShapeUtility<T>
|
||||
}
|
||||
|
||||
function getDefaultShapeUtil<T extends Shape>(): ShapeUtility<T> {
|
||||
return {
|
||||
boundsCache: new WeakMap(),
|
||||
canTransform: true,
|
||||
canChangeAspectRatio: true,
|
||||
canStyleFill: true,
|
||||
|
||||
create(props) {
|
||||
return {
|
||||
id: uuid(),
|
||||
isGenerated: false,
|
||||
point: [0, 0],
|
||||
name: 'Shape',
|
||||
parentId: 'page0',
|
||||
childIndex: 0,
|
||||
rotation: 0,
|
||||
isAspectRatioLocked: false,
|
||||
isLocked: false,
|
||||
isHidden: false,
|
||||
...props,
|
||||
} as T
|
||||
},
|
||||
|
||||
render(shape) {
|
||||
return <circle id={shape.id} />
|
||||
},
|
||||
|
||||
transform(shape, bounds) {
|
||||
shape.point = [bounds.minX, bounds.minY]
|
||||
return this
|
||||
},
|
||||
|
||||
transformSingle(shape, bounds, info) {
|
||||
return this.transform(shape, bounds, info)
|
||||
},
|
||||
|
||||
onBindingMove() {
|
||||
return this
|
||||
},
|
||||
|
||||
onHandleMove() {
|
||||
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
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory of shape utilities, with typing enforced.
|
||||
* @param shape
|
||||
* @returns
|
||||
*/
|
||||
export function registerShapeUtils<T extends Shape>(
|
||||
shape: ShapeUtility<T>
|
||||
): ShapeUtility<T> {
|
||||
return Object.freeze(shape)
|
||||
export function registerShapeUtils<K extends Shape>(
|
||||
shapeUtil: Partial<ShapeUtility<K>>
|
||||
): ShapeUtility<K> {
|
||||
return Object.freeze({ ...getDefaultShapeUtil<K>(), ...shapeUtil })
|
||||
}
|
||||
|
||||
export function createShape<T extends Shape>(
|
||||
|
|
|
@ -47,11 +47,6 @@ const line = registerShapeUtils<LineShape>({
|
|||
)
|
||||
},
|
||||
|
||||
applyStyles(shape, style) {
|
||||
Object.assign(shape.style, style)
|
||||
return this
|
||||
},
|
||||
|
||||
getBounds(shape) {
|
||||
if (!this.boundsCache.has(shape)) {
|
||||
const bounds = {
|
||||
|
@ -99,11 +94,6 @@ const line = registerShapeUtils<LineShape>({
|
|||
return this.transform(shape, bounds, info)
|
||||
},
|
||||
|
||||
setProperty(shape, prop, value) {
|
||||
shape[prop] = value
|
||||
return this
|
||||
},
|
||||
|
||||
canTransform: false,
|
||||
canChangeAspectRatio: false,
|
||||
canStyleFill: false,
|
||||
|
|
|
@ -33,11 +33,6 @@ const polyline = registerShapeUtils<PolylineShape>({
|
|||
return <polyline id={id} points={points.toString()} />
|
||||
},
|
||||
|
||||
applyStyles(shape, style) {
|
||||
Object.assign(shape.style, style)
|
||||
return this
|
||||
},
|
||||
|
||||
getBounds(shape) {
|
||||
if (!this.boundsCache.has(shape)) {
|
||||
this.boundsCache.set(shape, getBoundsFromPoints(shape.points))
|
||||
|
@ -117,11 +112,6 @@ const polyline = registerShapeUtils<PolylineShape>({
|
|||
return this
|
||||
},
|
||||
|
||||
setProperty(shape, prop, value) {
|
||||
shape[prop] = value
|
||||
return this
|
||||
},
|
||||
|
||||
canTransform: true,
|
||||
canChangeAspectRatio: true,
|
||||
canStyleFill: false,
|
||||
|
|
|
@ -45,11 +45,6 @@ const ray = registerShapeUtils<RayShape>({
|
|||
)
|
||||
},
|
||||
|
||||
applyStyles(shape, style) {
|
||||
Object.assign(shape.style, style)
|
||||
return this
|
||||
},
|
||||
|
||||
getRotatedBounds(shape) {
|
||||
return this.getBounds(shape)
|
||||
},
|
||||
|
@ -97,11 +92,6 @@ const ray = registerShapeUtils<RayShape>({
|
|||
return this.transform(shape, bounds, info)
|
||||
},
|
||||
|
||||
setProperty(shape, prop, value) {
|
||||
shape[prop] = value
|
||||
return this
|
||||
},
|
||||
|
||||
canTransform: false,
|
||||
canChangeAspectRatio: false,
|
||||
canStyleFill: false,
|
||||
|
|
|
@ -2,12 +2,7 @@ import { v4 as uuid } from 'uuid'
|
|||
import * as vec from 'utils/vec'
|
||||
import { RectangleShape, ShapeType } from 'types'
|
||||
import { registerShapeUtils } from './index'
|
||||
import { boundsCollidePolygon, boundsContainPolygon } from 'utils/bounds'
|
||||
import {
|
||||
getBoundsFromPoints,
|
||||
getRotatedCorners,
|
||||
translateBounds,
|
||||
} from 'utils/utils'
|
||||
import { translateBounds } from 'utils/utils'
|
||||
import { defaultStyle, getShapeStyle } from 'lib/shape-styles'
|
||||
|
||||
const rectangle = registerShapeUtils<RectangleShape>({
|
||||
|
@ -48,11 +43,6 @@ const rectangle = registerShapeUtils<RectangleShape>({
|
|||
)
|
||||
},
|
||||
|
||||
applyStyles(shape, style) {
|
||||
Object.assign(shape.style, style)
|
||||
return this
|
||||
},
|
||||
|
||||
getBounds(shape) {
|
||||
if (!this.boundsCache.has(shape)) {
|
||||
const [width, height] = shape.size
|
||||
|
@ -71,33 +61,10 @@ const rectangle = registerShapeUtils<RectangleShape>({
|
|||
return translateBounds(this.boundsCache.get(shape), shape.point)
|
||||
},
|
||||
|
||||
getRotatedBounds(shape) {
|
||||
return getBoundsFromPoints(
|
||||
getRotatedCorners(this.getBounds(shape), shape.rotation)
|
||||
)
|
||||
},
|
||||
|
||||
getCenter(shape) {
|
||||
const bounds = this.getRotatedBounds(shape)
|
||||
return [bounds.minX + bounds.width / 2, bounds.minY + bounds.height / 2]
|
||||
},
|
||||
|
||||
hitTest(shape) {
|
||||
hitTest() {
|
||||
return true
|
||||
},
|
||||
|
||||
hitTestBounds(shape, brushBounds) {
|
||||
const rotatedCorners = getRotatedCorners(
|
||||
this.getBounds(shape),
|
||||
shape.rotation
|
||||
)
|
||||
|
||||
return (
|
||||
boundsContainPolygon(brushBounds, rotatedCorners) ||
|
||||
boundsCollidePolygon(brushBounds, rotatedCorners)
|
||||
)
|
||||
},
|
||||
|
||||
transform(shape, bounds, { initialShape, transformOrigin, scaleX, scaleY }) {
|
||||
if (shape.rotation === 0 && !shape.isAspectRatioLocked) {
|
||||
shape.size = [bounds.width, bounds.height]
|
||||
|
@ -131,15 +98,6 @@ const rectangle = registerShapeUtils<RectangleShape>({
|
|||
shape.point = [bounds.minX, bounds.minY]
|
||||
return this
|
||||
},
|
||||
|
||||
setProperty(shape, prop, value) {
|
||||
shape[prop] = value
|
||||
return this
|
||||
},
|
||||
|
||||
canTransform: true,
|
||||
canChangeAspectRatio: true,
|
||||
canStyleFill: true,
|
||||
})
|
||||
|
||||
export default rectangle
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
interface Props {
|
||||
name: string
|
||||
}
|
||||
|
||||
interface Core {
|
||||
id: string
|
||||
}
|
||||
|
||||
interface Instance extends Props, Core {}
|
||||
|
||||
const defaults: Props = {
|
||||
name: 'Spot',
|
||||
}
|
||||
|
||||
const core: Core = {
|
||||
id: '0',
|
||||
}
|
||||
|
||||
class ClassInstance<T extends object = {}> implements Instance {
|
||||
id = '0'
|
||||
name = 'Spot'
|
||||
|
||||
constructor(
|
||||
props: Partial<Props> &
|
||||
{ [K in keyof T]: K extends keyof Core ? never : T[K] }
|
||||
) {
|
||||
Object.assign(this, props)
|
||||
}
|
||||
}
|
||||
|
||||
interface InstanceConstructor {
|
||||
new <T extends object = {}>(
|
||||
props: Partial<Props> &
|
||||
{ [K in keyof T]: K extends keyof Core ? never : T[K] }
|
||||
): Instance
|
||||
}
|
||||
|
||||
function makeInstance<T extends object = {}>(
|
||||
props: Partial<Props> &
|
||||
{ [K in keyof T]: K extends keyof Core ? never : T[K] } &
|
||||
ThisType<ClassInstance>
|
||||
) {
|
||||
return new ClassInstance<T>({ ...defaults, ...props, ...core })
|
||||
}
|
||||
|
||||
function getInstance<T extends object = {}>(
|
||||
props: Partial<Props> &
|
||||
{ [K in keyof T]: K extends keyof Core ? never : T[K] }
|
||||
) {
|
||||
return { ...defaults, ...props, ...core }
|
||||
}
|
||||
|
||||
const instance = getInstance({
|
||||
name: 'Steve',
|
||||
age: 93,
|
||||
wag(this: Instance) {
|
||||
return this.name
|
||||
},
|
||||
})
|
||||
|
||||
interface AnimalProps {
|
||||
name: string
|
||||
greet(this: Animal, name: string): string
|
||||
}
|
||||
|
||||
interface AnimalCore {
|
||||
id: string
|
||||
sleep(this: Animal): void
|
||||
}
|
||||
|
||||
interface Animal extends AnimalProps, AnimalCore {}
|
||||
|
||||
const getAnimal = <T extends object>(
|
||||
props: Partial<AnimalProps> &
|
||||
{ [K in keyof T]: K extends keyof AnimalCore ? never : T[K] }
|
||||
): Animal & T => {
|
||||
return {
|
||||
// Defaults
|
||||
name: 'Animal',
|
||||
greet(name) {
|
||||
return 'Hey ' + name
|
||||
},
|
||||
// Overrides
|
||||
...props,
|
||||
// Core
|
||||
id: 'hi',
|
||||
sleep() {},
|
||||
}
|
||||
}
|
||||
|
||||
const dog = getAnimal({
|
||||
name: 'doggo',
|
||||
greet(name) {
|
||||
return 'Woof ' + this.name
|
||||
},
|
||||
wag() {
|
||||
return 'wagging...'
|
||||
},
|
||||
})
|
||||
|
||||
dog.greet('steve')
|
||||
dog.wag()
|
||||
dog.sleep()
|
||||
|
||||
class ShapeTest {}
|
||||
|
||||
const shapeTest = new ShapeTest()
|
||||
|
||||
export default shapeTest
|
||||
|
||||
type Greet = (name: string) => string
|
||||
|
||||
const greet: Greet = (name: string | number) => {
|
||||
return 'hello ' + name
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
import { defaultStyle } from 'lib/shape-styles'
|
||||
import {
|
||||
Shape,
|
||||
Bounds,
|
||||
BaseShape,
|
||||
ShapeSpecificProps,
|
||||
ShapeType,
|
||||
ShapeStyles,
|
||||
MutableShape,
|
||||
Edge,
|
||||
Corner,
|
||||
ShapeBinding,
|
||||
} from 'types'
|
||||
import { v4 as uuid } from 'uuid'
|
||||
import * as vec from 'utils/vec'
|
||||
import {
|
||||
getBoundsCenter,
|
||||
getRotatedCorners,
|
||||
getBoundsFromPoints,
|
||||
} from 'utils/utils'
|
||||
|
||||
class ShapeUtility<K extends MutableShape> {
|
||||
boundsCache = new WeakMap<K, Bounds>([])
|
||||
canTransform = true
|
||||
canChangeAspectRatio = true
|
||||
canStyleFill = true
|
||||
|
||||
// Create a new shape.
|
||||
create(props: Partial<K> & ShapeSpecificProps<K>): K {
|
||||
return {
|
||||
id: uuid(),
|
||||
isGenerated: false,
|
||||
point: [0, 0],
|
||||
name: 'Shape',
|
||||
parentId: 'page0',
|
||||
childIndex: 0,
|
||||
rotation: 0,
|
||||
isAspectRatioLocked: false,
|
||||
isLocked: false,
|
||||
isHidden: false,
|
||||
...props,
|
||||
} as K
|
||||
}
|
||||
|
||||
applyStyles = (shape: K, style: Partial<ShapeStyles>) => {
|
||||
Object.assign(shape.style, style)
|
||||
return this
|
||||
}
|
||||
|
||||
transform = (
|
||||
shape: K,
|
||||
bounds: Bounds,
|
||||
info: {
|
||||
type: Edge | Corner
|
||||
initialShape: K
|
||||
scaleX: number
|
||||
scaleY: number
|
||||
transformOrigin: number[]
|
||||
}
|
||||
) => {
|
||||
shape.point = [bounds.minX, bounds.minY]
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
transformSingle = (
|
||||
shape: K,
|
||||
bounds: Bounds,
|
||||
info: {
|
||||
type: Edge | Corner
|
||||
initialShape: K
|
||||
scaleX: number
|
||||
scaleY: number
|
||||
transformOrigin: number[]
|
||||
}
|
||||
) => {
|
||||
return this.transform(shape, bounds, info)
|
||||
}
|
||||
|
||||
setProperty = <P extends keyof K>(shape: K, prop: P, value: K[P]) => {
|
||||
shape[prop] = value
|
||||
return this
|
||||
}
|
||||
|
||||
onBindingMove? = (shape: K, bindings: Record<string, ShapeBinding>) => {
|
||||
return this
|
||||
}
|
||||
|
||||
onHandleMove? = (shape: K, handle: Partial<K['handles']>) => {
|
||||
return this
|
||||
}
|
||||
|
||||
render = (shape: K): JSX.Element => {
|
||||
return <circle id={shape.id} />
|
||||
}
|
||||
|
||||
// Get the bounds of the a shape.
|
||||
getBounds = (shape: K): Bounds => {
|
||||
const [x, y] = shape.point
|
||||
return {
|
||||
minX: x,
|
||||
minY: y,
|
||||
maxX: x + 1,
|
||||
maxY: y + 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
}
|
||||
}
|
||||
|
||||
// Get the routated bounds of the a shape.
|
||||
getRotatedBounds = (shape: K): Bounds => {
|
||||
return getBoundsFromPoints(
|
||||
getRotatedCorners(this.getBounds(shape), shape.rotation)
|
||||
)
|
||||
}
|
||||
|
||||
// Get the center of the shape
|
||||
getCenter = (shape: K): number[] => {
|
||||
return getBoundsCenter(this.getBounds(shape))
|
||||
}
|
||||
|
||||
// Test whether a point lies within a shape.
|
||||
hitTest = (shape: K, test: number[]): boolean => {
|
||||
return true
|
||||
}
|
||||
|
||||
// Test whether bounds collide with or contain a shape.
|
||||
hitTestBounds = (shape: K, bounds: Bounds): boolean => {
|
||||
return true
|
||||
}
|
||||
}
|
2
types.ts
2
types.ts
|
@ -395,3 +395,5 @@ export type CodeControl =
|
|||
export type PropsOfType<T extends object, K> = {
|
||||
[K in keyof T]: T[K] extends boolean ? K : never
|
||||
}[keyof T]
|
||||
|
||||
export type Mutable<T extends Shape> = { -readonly [K in keyof T]: T[K] }
|
||||
|
|
Loading…
Reference in a new issue