mirror of
https://github.com/motion-canvas/motion-canvas.git
synced 2026-01-12 07:18:01 -05:00
feat(2d): improve Rect corner radius (#120)
The corner radius of a Rect is now declared using the Spacing type. It allows specifying each radius individually similar to CSS.
This commit is contained in:
@@ -1,17 +1,16 @@
|
||||
import {Signal, SignalValue} from '@motion-canvas/core/lib/utils';
|
||||
import {Rect as RectType} from '@motion-canvas/core/lib/types';
|
||||
import {SignalValue} from '@motion-canvas/core/lib/utils';
|
||||
import {PossibleSpacing, Rect as RectType} from '@motion-canvas/core/lib/types';
|
||||
import {Shape, ShapeProps} from './Shape';
|
||||
import {initial, property} from '../decorators';
|
||||
import {drawRoundRect} from '../utils';
|
||||
import {spacingProperty, SpacingProperty} from '../decorators/spacingProperty';
|
||||
|
||||
export interface RectProps extends ShapeProps {
|
||||
radius?: SignalValue<number>;
|
||||
radius?: SignalValue<PossibleSpacing>;
|
||||
}
|
||||
|
||||
export class Rect extends Shape {
|
||||
@initial(0)
|
||||
@property()
|
||||
public declare readonly radius: Signal<number, this>;
|
||||
@spacingProperty('radius')
|
||||
public declare readonly radius: SpacingProperty<this>;
|
||||
|
||||
public constructor(props: RectProps) {
|
||||
super(props);
|
||||
@@ -33,7 +32,7 @@ export class Rect extends Shape {
|
||||
protected override getRipplePath(): Path2D {
|
||||
const path = new Path2D();
|
||||
const rippleSize = this.rippleSize();
|
||||
const radius = this.radius() + rippleSize;
|
||||
const radius = this.radius().addScalar(rippleSize);
|
||||
const rect = RectType.fromSizeCentered(this.size()).expand(rippleSize);
|
||||
drawRoundRect(path, rect, radius);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {CanvasStyle, Gradient, Pattern, PossibleCanvasStyle} from '../partials';
|
||||
import {Color, Rect, Vector2} from '@motion-canvas/core/lib/types';
|
||||
import {Color, Rect, Spacing, Vector2} from '@motion-canvas/core/lib/types';
|
||||
|
||||
export function canvasStyleParser(style: PossibleCanvasStyle) {
|
||||
if (style === null) {
|
||||
@@ -38,18 +38,36 @@ export function resolveCanvasStyle(
|
||||
export function drawRoundRect(
|
||||
context: CanvasRenderingContext2D | Path2D,
|
||||
rect: Rect,
|
||||
radius: number,
|
||||
radius: Spacing,
|
||||
) {
|
||||
if (radius > 0) {
|
||||
const maxRadius = Math.min(rect.width / 2, rect.height / 2, radius);
|
||||
context.moveTo(rect.left + maxRadius, rect.top);
|
||||
context.arcTo(rect.right, rect.top, rect.right, rect.bottom, maxRadius);
|
||||
context.arcTo(rect.right, rect.bottom, rect.left, rect.bottom, maxRadius);
|
||||
context.arcTo(rect.left, rect.bottom, rect.left, rect.top, maxRadius);
|
||||
context.arcTo(rect.left, rect.top, rect.right, rect.top, maxRadius);
|
||||
} else {
|
||||
if (
|
||||
radius.top === 0 &&
|
||||
radius.bottom === 0 &&
|
||||
radius.left === 0 &&
|
||||
radius.right === 0
|
||||
) {
|
||||
drawRect(context, rect);
|
||||
return;
|
||||
}
|
||||
|
||||
const topLeft = Math.min(rect.width, rect.height, radius.top);
|
||||
const topRight = Math.min(rect.width - topLeft, rect.height, radius.right);
|
||||
const bottomRight = Math.min(
|
||||
rect.width,
|
||||
rect.height - topRight,
|
||||
radius.bottom,
|
||||
);
|
||||
const bottomLeft = Math.min(
|
||||
rect.width - topLeft,
|
||||
rect.height - bottomRight,
|
||||
radius.left,
|
||||
);
|
||||
|
||||
context.moveTo(rect.left + topLeft, rect.top);
|
||||
context.arcTo(rect.right, rect.top, rect.right, rect.bottom, topRight);
|
||||
context.arcTo(rect.right, rect.bottom, rect.left, rect.bottom, bottomRight);
|
||||
context.arcTo(rect.left, rect.bottom, rect.left, rect.top, bottomLeft);
|
||||
context.arcTo(rect.left, rect.top, rect.right, rect.top, topLeft);
|
||||
}
|
||||
|
||||
export function drawRect(
|
||||
|
||||
@@ -92,6 +92,15 @@ export class Spacing implements Type {
|
||||
);
|
||||
}
|
||||
|
||||
public addScalar(value: number): Spacing {
|
||||
return new Spacing(
|
||||
this.top + value,
|
||||
this.right + value,
|
||||
this.bottom + value,
|
||||
this.left + value,
|
||||
);
|
||||
}
|
||||
|
||||
public toSymbol(): symbol {
|
||||
return Spacing.symbol;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user