mirror of
https://github.com/konvajs/konva.git
synced 2025-08-20 07:04:20 +08:00
add corner radius for regular polygon
This commit is contained in:
parent
27fc1b1ba5
commit
5155a240a3
42
src/Util.ts
42
src/Util.ts
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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)
|
||||
);
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user