Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 173 additions & 23 deletions factors/smooth-corners.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,173 @@
class SmoothCorners {
static get inputProperties() {
return ['--smooth-radius'];
}

paint(ctx, geom, properties) {
const radius = parseFloat(properties.get('--smooth-radius')) || 20;
const width = geom.width;
const height = geom.height;

ctx.fillStyle = 'black';
ctx.beginPath();
ctx.moveTo(radius, 0);
ctx.arcTo(width, 0, width, height, radius);
ctx.arcTo(width, height, 0, height, radius);
ctx.arcTo(0, height, 0, 0, radius);
ctx.arcTo(0, 0, width, 0, radius);
ctx.closePath();
ctx.fill();
}
}

registerPaint('smooth-corners', SmoothCorners);

const drawSquircle = (ctx, geom, corners, radius, smooth, lineWidth, color) => {
const defaultFill = color;
const lineWidthOffset = lineWidth / 2;

// OPEN LEFT-TOP CORNER
ctx.beginPath();
// ctx.lineTo(radius, lineWidthOffset);

// TOP-RIGHT CORNER
if (corners.has('top-right')) {
ctx.lineTo(geom.width - radius, lineWidthOffset);
ctx.bezierCurveTo(
geom.width - radius / smooth,
lineWidthOffset, // first bezier point
geom.width - lineWidthOffset,
radius / smooth, // second bezier point
geom.width - lineWidthOffset,
radius // last connect point
);
} else {
ctx.lineTo(geom.width - lineWidthOffset, lineWidthOffset);
}

// BOTTOM-RIGHT CORNER
if (corners.has('bottom-right')) {
ctx.lineTo(geom.width - lineWidthOffset, geom.height - radius);
ctx.bezierCurveTo(
geom.width - lineWidthOffset,
geom.height - radius / smooth, // first bezier point
geom.width - radius / smooth,
geom.height - lineWidthOffset, // second bezier point
geom.width - radius,
geom.height - lineWidthOffset // last connect point
);
} else {
ctx.lineTo(geom.width - lineWidthOffset, geom.height - lineWidthOffset);
}

// BOTTOM-LEFT CORNER
if (corners.has('bottom-left')) {
ctx.lineTo(radius, geom.height - lineWidthOffset);
ctx.bezierCurveTo(
radius / smooth,
geom.height - lineWidthOffset, // first bezier point
lineWidthOffset,
geom.height - radius / smooth, // second bezier point
lineWidthOffset,
geom.height - radius // last connect point
);
} else {
ctx.lineTo(lineWidthOffset, geom.height - lineWidthOffset);
}

// CLOSE LEFT-TOP CORNER
if (corners.has('top-left')) {
ctx.lineTo(lineWidthOffset, radius);
ctx.bezierCurveTo(
lineWidthOffset,
radius / smooth, // first bezier point
radius / smooth,
lineWidthOffset, // second bezier point
radius,
lineWidthOffset // last connect point
);
} else {
ctx.lineTo(lineWidthOffset, lineWidthOffset);
}

ctx.closePath();

if (lineWidth) {
ctx.strokeStyle = defaultFill;
ctx.lineWidth = lineWidth;
ctx.stroke();
} else {
ctx.fillStyle = defaultFill;
ctx.fill();
}
};

if (typeof registerPaint !== "undefined") {
class SquirclePainter {
static get contextOptions() {
return { alpha: true };
}
static get inputProperties() {
return [
"--squircle-radius",
"--squircle-smooth",
"--squircle-outline",
"--squircle-fill",
"--squircle-ratio",
"--squircle-corners",
];
}

paint(ctx, geom, properties) {
const customRatio = properties.get("--squircle-ratio");
const smoothRatio = 10;
const distanceRatio = parseFloat(customRatio)
? parseFloat(customRatio)
: 1.8;
const squircleSmooth = parseFloat(
properties.get("--squircle-smooth") * smoothRatio
);
const squircleRadius =
parseInt(properties.get("--squircle-radius"), 10) * distanceRatio;
const squrcleOutline = parseFloat(
properties.get("--squircle-outline"),
10
);
const squircleColor = properties
.get("--squircle-fill")
.toString()
.replace(/s/g, "");

const isSmooth = () => {
if (typeof properties.get("--squircle-smooth")[0] !== "undefined") {
if (squircleSmooth === 0) {
return 1;
}
return squircleSmooth;
} else {
return 10;
}
};

const isOutline = () => {
if (squrcleOutline) {
return squrcleOutline;
} else {
return 0;
}
};

const isColor = () => {
if (squircleColor) {
return squircleColor;
} else {
return "#2f2f2f";
}
};

const corners = new Set(properties.get('--squircle-corners')?.[0]?.split(' '));

if (squircleRadius < geom.width / 2 && squircleRadius < geom.height / 2) {
drawSquircle(
ctx,
geom,
corners,
squircleRadius,
isSmooth(),
isOutline(),
isColor()
);
} else {
drawSquircle(
ctx,
geom,
corners,
Math.min(geom.width / 2, geom.height / 2),
isSmooth(),
isOutline(),
isColor()
);
}
}
}

registerPaint("squircle", SquirclePainter);
}