add corner radius for regular polygon

This commit is contained in:
CadenH 2025-06-30 01:24:21 -07:00
parent 27fc1b1ba5
commit 5155a240a3
3 changed files with 110 additions and 5 deletions

View File

@ -1042,4 +1042,46 @@ export const Util = {
context.lineTo(0, topLeft);
context.arc(topLeft, topLeft, topLeft, Math.PI, (Math.PI * 3) / 2, false);
},
drawRoundedPolygonPath(
context: Context,
points: Vector2d[],
sides: number,
radius: number,
cornerRadius: number | number[]
) {
for (let i = 0; i < sides; i++) {
const prev = points[(i - 1 + sides) % sides];
const curr = points[i];
const next = points[(i + 1) % sides];
const vec1 = {x: curr.x - prev.x, y: curr.y - prev.y};
const vec2 = {x: next.x - curr.x, y: next.y - curr.y};
const len1 = Math.hypot(vec1.x, vec1.y);
const len2 = Math.hypot(vec2.x, vec2.y);
let currCornerRadius;
if (typeof cornerRadius === 'number') {
currCornerRadius = cornerRadius;
} else {
currCornerRadius = i < cornerRadius.length ? cornerRadius[i] : 0;
}
const maxCornerRadius = radius * Math.cos(Math.PI / sides);
// cornerRadius creates perfect circle at 1/2 radius
currCornerRadius = maxCornerRadius * Math.min(1, (currCornerRadius / radius) * 2);
const normalVec1 = {x: vec1.x / len1, y: vec1.y / len1};
const normalVec2 = {x: vec2.x / len2, y: vec2.y / len2};
const p1 = {
x: curr.x - normalVec1.x * currCornerRadius,
y: curr.y - normalVec1.y * currCornerRadius,
};
const p2 = {
x: curr.x + normalVec2.x * currCornerRadius,
y: curr.y + normalVec2.y * currCornerRadius,
};
if (i === 0) {
context.moveTo(p1.x, p1.y);
} else {
context.lineTo(p1.x, p1.y);
}
context.arcTo(curr.x, curr.y, p2.x, p2.y, currCornerRadius);
}
}
};

View File

@ -1,13 +1,15 @@
import { Factory } from '../Factory';
import { Shape, ShapeConfig } from '../Shape';
import { GetSet, Vector2d } from '../types';
import { getNumberValidator } from '../Validators';
import { getNumberOrArrayOfNumbersValidator, getNumberValidator } from '../Validators';
import { _registerNode } from '../Global';
import { Context } from '../Context';
import { Util } from '../Util';
export interface RegularPolygonConfig extends ShapeConfig {
sides: number;
radius: number;
cornerRadius?: number | number[];
}
/**
* RegularPolygon constructor. Examples include triangles, squares, pentagons, hexagons, etc.
@ -15,6 +17,7 @@ export interface RegularPolygonConfig extends ShapeConfig {
* @memberof Konva
* @augments Konva.Shape
* @param {Object} config
* @param {Number} [config.cornerRadius]
* @param {Number} config.sides
* @param {Number} config.radius
* @@shapeParams
@ -32,13 +35,20 @@ export interface RegularPolygonConfig extends ShapeConfig {
*/
export class RegularPolygon extends Shape<RegularPolygonConfig> {
_sceneFunc(context: Context) {
const points = this._getPoints();
const points = this._getPoints(),
radius = this.radius(),
sides = this.sides(),
cornerRadius = this.cornerRadius();
context.beginPath();
context.moveTo(points[0].x, points[0].y);
for (let n = 1; n < points.length; n++) {
context.lineTo(points[n].x, points[n].y);
if (!cornerRadius) {
context.moveTo(points[0].x, points[0].y);
for (let n = 1; n < points.length; n++) {
context.lineTo(points[n].x, points[n].y);
}
} else {
Util.drawRoundedPolygonPath(context, points, sides, radius, cornerRadius);
}
context.closePath();
@ -91,6 +101,7 @@ export class RegularPolygon extends Shape<RegularPolygonConfig> {
radius: GetSet<number, this>;
sides: GetSet<number, this>;
cornerRadius: GetSet<number | number[], this>;
}
RegularPolygon.prototype.className = 'RegularPolygon';
@ -127,3 +138,27 @@ Factory.addGetterSetter(RegularPolygon, 'radius', 0, getNumberValidator());
* shape.sides(10);
*/
Factory.addGetterSetter(RegularPolygon, 'sides', 0, getNumberValidator());
/**
* get/set corner radius
* @method
* @name Konva.RegularPolygon#cornerRadius
* @param {Number} cornerRadius
* @returns {Number}
* @example
* // get corner radius
* var cornerRadius = rect.cornerRadius();
*
* // set corner radius
* rect.cornerRadius(10);
*
* // set different corner radius values
* // top-left, top-right, bottom-right, bottom-left
* rect.cornerRadius([0, 10, 20, 30]);
*/
Factory.addGetterSetter(
RegularPolygon,
'cornerRadius',
0,
getNumberOrArrayOfNumbersValidator(4)
);

View File

@ -5,6 +5,8 @@ import {
Konva,
cloneAndCompareLayer,
assertAlmostEqual,
createCanvas,
compareLayerAndCanvas,
} from './test-utils';
describe('RegularPolygon', function () {
@ -206,4 +208,30 @@ describe('RegularPolygon', function () {
assertAlmostEqual(box.width, 91.60254037844388);
assertAlmostEqual(box.height, 80.00000000000003);
});
// ======================================================
it('limit corner radius', function () {
var stage = addStage();
var layer = new Konva.Layer();
var poly = new Konva.RegularPolygon({
x: 50,
y: 50,
sides: 5,
radius: 50,
fill: 'black',
cornerRadius: 25,
});
layer.add(poly);
stage.add(layer);
// corner radius creates perfect circle at 1/2 radius
var canvas = createCanvas();
var context = canvas.getContext('2d');
context.beginPath();
context.arc(100, 100, 50, 0, Math.PI * 2);
context.fillStyle = 'black';
context.fill();
compareLayerAndCanvas(layer, canvas, 100);
});
});