Here are a couple line/rect helpers that you can use to do fancy stuff in a bit of a more straightfoward way when determining where to draw lines using Motion Canvas.
- Figure out how to get this to work nicely with corner radius.
import { Line, Rect } from "@motion-canvas/2d/lib/components"; | |
import { Reference } from "@motion-canvas/core/lib/utils"; | |
import { getRectPoint, RectPosition } from "./rectpoint"; | |
export function lineBetween( | |
line: Reference<Line>, | |
rect1: Reference<Rect>, | |
rect2: Reference<Rect>, | |
side1: { x: number; y: number } = RectPosition.Bottom, | |
side2: { x: number; y: number } = RectPosition.Top, | |
): void { | |
line().points([ | |
getRectPoint(rect1, side1), | |
getRectPoint(rect2, side2) | |
]); | |
} |
import { Rect } from "@motion-canvas/2d/lib/components"; | |
import { Vector2 } from "@motion-canvas/core/lib/types"; | |
import { Reference } from "@motion-canvas/core/lib/utils"; | |
export type RectOffset = { x: number, y: number }; | |
export const RectPosition: Record<string, RectOffset> = { | |
TopLeft: { | |
x: 0.5, | |
y: 0.5, | |
}, | |
Top: { | |
x: 0, | |
y: 0.5, | |
}, | |
TopRight: { | |
x: -0.5, | |
y: 0.5, | |
}, | |
Left: { | |
x: 0.5, | |
y: 0, | |
}, | |
Center: { | |
x: 0, | |
y: 0, | |
}, | |
Right: { | |
x: -0.5, | |
y: 0, | |
}, | |
BottomLeft: { | |
x: 0.5, | |
y: -0.5, | |
}, | |
Bottom: { | |
x: 0, | |
y: -0.5, | |
}, | |
BottomRight: { | |
x: -0.5, | |
y: -0.5, | |
}, | |
}; | |
export function getRectPoint( | |
rect: Reference<Rect>, | |
point: RectOffset, | |
) { | |
return new Vector2( | |
rect().position.x() + rect().size.x() * point.x, | |
rect().position.y() + rect().size.y() * point.y | |
) | |
} |
import { Line, Rect } from "@motion-canvas/2d/lib/components"; | |
import { makeScene2D } from "@motion-canvas/2d/lib/scenes"; | |
import { waitFor } from "@motion-canvas/core/lib/flow"; | |
import { tween } from "@motion-canvas/core/lib/tweening"; | |
import { createRef } from "@motion-canvas/core/lib/utils"; | |
import { lineBetween } from "../util/linebetween"; | |
import { getRectPoint, RectPosition } from "../util/rectpoint"; | |
export default makeScene2D(function* (view) { | |
const rect1 = createRef<Rect>(); | |
view.add( | |
<Rect | |
ref={rect1} | |
fill="#fab000" | |
position={[100, 200]} | |
width={50} | |
height={50} | |
></Rect> | |
); | |
const rect2 = createRef<Rect>(); | |
view.add( | |
<Rect | |
ref={rect2} | |
fill="#fab000" | |
position={[0, -200]} | |
width={50} | |
height={50} | |
></Rect> | |
); | |
const line = createRef<Line>(); | |
view.add( | |
<Line | |
ref={line} | |
stroke={"white"} | |
lineWidth={2} | |
points={[ | |
[0, 0], | |
[0, 0], | |
]} | |
></Line> | |
); | |
lineBetween(line, rect1, rect2, RectPosition.Right, RectPosition.Left); | |
yield* line().points( | |
[ | |
getRectPoint(rect1, RectPosition.Bottom), | |
getRectPoint(rect2, RectPosition.Top), | |
], | |
0.5 | |
); | |
yield* waitFor(1); | |
yield* tween(0.5, (value) => { | |
rect2().position.x(-200 * value); | |
lineBetween(line, rect1, rect2); | |
}); | |
yield* waitFor(1); | |
}); |