mirror of
https://github.com/konvajs/konva.git
synced 2025-11-24 16:53:06 +08:00
Merge branch 'master' of github.com:konvajs/konva
This commit is contained in:
43
src/Util.ts
43
src/Util.ts
@@ -1076,4 +1076,47 @@ export const Util = {
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
drawRoundedPolygonPath(
|
||||||
|
context: Context,
|
||||||
|
points: Vector2d[],
|
||||||
|
sides: number,
|
||||||
|
radius: number,
|
||||||
|
cornerRadius: number | number[]
|
||||||
|
) {
|
||||||
|
radius = Math.abs(radius);
|
||||||
|
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 { Factory } from '../Factory';
|
||||||
import { Shape, ShapeConfig } from '../Shape';
|
import { Shape, ShapeConfig } from '../Shape';
|
||||||
import { GetSet, Vector2d } from '../types';
|
import { GetSet, Vector2d } from '../types';
|
||||||
import { getNumberValidator } from '../Validators';
|
import { getNumberOrArrayOfNumbersValidator, getNumberValidator } from '../Validators';
|
||||||
import { _registerNode } from '../Global';
|
import { _registerNode } from '../Global';
|
||||||
import { Context } from '../Context';
|
import { Context } from '../Context';
|
||||||
|
import { Util } from '../Util';
|
||||||
|
|
||||||
export interface RegularPolygonConfig extends ShapeConfig {
|
export interface RegularPolygonConfig extends ShapeConfig {
|
||||||
sides: number;
|
sides: number;
|
||||||
radius: number;
|
radius: number;
|
||||||
|
cornerRadius?: number | number[];
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* RegularPolygon constructor. Examples include triangles, squares, pentagons, hexagons, etc.
|
* RegularPolygon constructor. Examples include triangles, squares, pentagons, hexagons, etc.
|
||||||
@@ -15,6 +17,7 @@ export interface RegularPolygonConfig extends ShapeConfig {
|
|||||||
* @memberof Konva
|
* @memberof Konva
|
||||||
* @augments Konva.Shape
|
* @augments Konva.Shape
|
||||||
* @param {Object} config
|
* @param {Object} config
|
||||||
|
* @param {Number} [config.cornerRadius]
|
||||||
* @param {Number} config.sides
|
* @param {Number} config.sides
|
||||||
* @param {Number} config.radius
|
* @param {Number} config.radius
|
||||||
* @@shapeParams
|
* @@shapeParams
|
||||||
@@ -32,13 +35,20 @@ export interface RegularPolygonConfig extends ShapeConfig {
|
|||||||
*/
|
*/
|
||||||
export class RegularPolygon extends Shape<RegularPolygonConfig> {
|
export class RegularPolygon extends Shape<RegularPolygonConfig> {
|
||||||
_sceneFunc(context: Context) {
|
_sceneFunc(context: Context) {
|
||||||
const points = this._getPoints();
|
const points = this._getPoints(),
|
||||||
|
radius = this.radius(),
|
||||||
|
sides = this.sides(),
|
||||||
|
cornerRadius = this.cornerRadius();
|
||||||
|
|
||||||
context.beginPath();
|
context.beginPath();
|
||||||
context.moveTo(points[0].x, points[0].y);
|
|
||||||
|
|
||||||
for (let n = 1; n < points.length; n++) {
|
if (!cornerRadius) {
|
||||||
context.lineTo(points[n].x, points[n].y);
|
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();
|
context.closePath();
|
||||||
@@ -91,6 +101,7 @@ export class RegularPolygon extends Shape<RegularPolygonConfig> {
|
|||||||
|
|
||||||
radius: GetSet<number, this>;
|
radius: GetSet<number, this>;
|
||||||
sides: GetSet<number, this>;
|
sides: GetSet<number, this>;
|
||||||
|
cornerRadius: GetSet<number | number[], this>;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegularPolygon.prototype.className = 'RegularPolygon';
|
RegularPolygon.prototype.className = 'RegularPolygon';
|
||||||
@@ -127,3 +138,26 @@ Factory.addGetterSetter(RegularPolygon, 'radius', 0, getNumberValidator());
|
|||||||
* shape.sides(10);
|
* shape.sides(10);
|
||||||
*/
|
*/
|
||||||
Factory.addGetterSetter(RegularPolygon, 'sides', 0, getNumberValidator());
|
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 = poly.cornerRadius();
|
||||||
|
*
|
||||||
|
* // set corner radius
|
||||||
|
* poly.cornerRadius(10);
|
||||||
|
*
|
||||||
|
* // set different corner radius values (pentagon)
|
||||||
|
* poly.cornerRadius([0, 10, 20, 30, 40]);
|
||||||
|
*/
|
||||||
|
Factory.addGetterSetter(
|
||||||
|
RegularPolygon,
|
||||||
|
'cornerRadius',
|
||||||
|
0,
|
||||||
|
getNumberOrArrayOfNumbersValidator(4)
|
||||||
|
);
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import {
|
|||||||
Konva,
|
Konva,
|
||||||
cloneAndCompareLayer,
|
cloneAndCompareLayer,
|
||||||
assertAlmostEqual,
|
assertAlmostEqual,
|
||||||
|
createCanvas,
|
||||||
|
compareLayerAndCanvas,
|
||||||
} from './test-utils';
|
} from './test-utils';
|
||||||
|
|
||||||
describe('RegularPolygon', function () {
|
describe('RegularPolygon', function () {
|
||||||
@@ -206,4 +208,59 @@ describe('RegularPolygon', function () {
|
|||||||
assertAlmostEqual(box.width, 91.60254037844388);
|
assertAlmostEqual(box.width, 91.60254037844388);
|
||||||
assertAlmostEqual(box.height, 80.00000000000003);
|
assertAlmostEqual(box.height, 80.00000000000003);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ======================================================
|
||||||
|
it('limit corner radius', function () {
|
||||||
|
var stage = addStage();
|
||||||
|
var layer = new Konva.Layer();
|
||||||
|
var sides = 5;
|
||||||
|
var radius = 50;
|
||||||
|
|
||||||
|
var poly = new Konva.RegularPolygon({
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
sides: sides,
|
||||||
|
radius: radius,
|
||||||
|
fill: 'black',
|
||||||
|
cornerRadius: 25,
|
||||||
|
});
|
||||||
|
var resultCircleRadius = radius * Math.cos(Math.PI / sides);
|
||||||
|
|
||||||
|
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, resultCircleRadius, 0, Math.PI * 2);
|
||||||
|
context.fillStyle = 'black';
|
||||||
|
context.fill();
|
||||||
|
compareLayerAndCanvas(layer, canvas, 200);
|
||||||
|
});
|
||||||
|
|
||||||
|
// ======================================================
|
||||||
|
it('negative polygon radius with cornerRadius', function () {
|
||||||
|
var stage = addStage();
|
||||||
|
var layer = new Konva.Layer();
|
||||||
|
|
||||||
|
var poly = new Konva.RegularPolygon({
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
sides: 5,
|
||||||
|
radius: -100,
|
||||||
|
fill: 'black',
|
||||||
|
cornerRadius: 20,
|
||||||
|
});
|
||||||
|
|
||||||
|
layer.add(poly);
|
||||||
|
stage.add(layer);
|
||||||
|
layer.draw();
|
||||||
|
|
||||||
|
var trace = layer.getContext().getTrace();
|
||||||
|
assert.equal(
|
||||||
|
trace,
|
||||||
|
'clearRect(0,0,578,200);save();transform(1,0,0,1,100,100);beginPath();moveTo(26.18,80.979);arcTo(0,100,-26.18,80.979,32.361);lineTo(-68.925,49.923);arcTo(-95.106,30.902,-85.106,0.125,32.361);lineTo(-68.779,-50.125);arcTo(-58.779,-80.902,-26.418,-80.902,32.361);lineTo(26.418,-80.902);arcTo(58.779,-80.902,68.779,-50.125,32.361);lineTo(85.106,0.125);arcTo(95.106,30.902,68.925,49.923,32.361);closePath();fillStyle=black;fill();restore();clearRect(0,0,578,200);save();transform(1,0,0,1,100,100);beginPath();moveTo(26.18,80.979);arcTo(0,100,-26.18,80.979,32.361);lineTo(-68.925,49.923);arcTo(-95.106,30.902,-85.106,0.125,32.361);lineTo(-68.779,-50.125);arcTo(-58.779,-80.902,-26.418,-80.902,32.361);lineTo(26.418,-80.902);arcTo(58.779,-80.902,68.779,-50.125,32.361);lineTo(85.106,0.125);arcTo(95.106,30.902,68.925,49.923,32.361);closePath();fillStyle=black;fill();restore();'
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user