feat: The Image adds rounded corner support

This commit is contained in:
iaosee
2022-12-19 23:46:01 +08:00
parent 3a40917e32
commit 2d8e30085c
5 changed files with 134 additions and 57 deletions

View File

@@ -1,4 +1,5 @@
import { Konva } from './Global';
import { Context } from './Context';
import { IRect, RGB, RGBA, Vector2d } from './types';
/*
@@ -988,5 +989,53 @@ export const Util = {
c.width = 0;
c.height = 0;
})
},
drawRoundedRectPath(context: Context, width: number, height: number, cornerRadius: number | number[]) {
let topLeft = 0;
let topRight = 0;
let bottomLeft = 0;
let bottomRight = 0;
if (typeof cornerRadius === 'number') {
topLeft = topRight = bottomLeft = bottomRight = Math.min(
cornerRadius,
width / 2,
height / 2
);
} else {
topLeft = Math.min(cornerRadius[0] || 0, width / 2, height / 2);
topRight = Math.min(cornerRadius[1] || 0, width / 2, height / 2);
bottomRight = Math.min(cornerRadius[2] || 0, width / 2, height / 2);
bottomLeft = Math.min(cornerRadius[3] || 0, width / 2, height / 2);
}
context.moveTo(topLeft, 0);
context.lineTo(width - topRight, 0);
context.arc(
width - topRight,
topRight,
topRight,
(Math.PI * 3) / 2,
0,
false
);
context.lineTo(width, height - bottomRight);
context.arc(
width - bottomRight,
height - bottomRight,
bottomRight,
0,
Math.PI / 2,
false
);
context.lineTo(bottomLeft, height);
context.arc(
bottomLeft,
height - bottomLeft,
bottomLeft,
Math.PI / 2,
Math.PI,
false
);
context.lineTo(0, topLeft);
context.arc(topLeft, topLeft, topLeft, Math.PI, (Math.PI * 3) / 2, false);
}
};

View File

@@ -1,8 +1,8 @@
import { Util } from '../Util';
import { Factory } from '../Factory';
import { Shape, ShapeConfig } from '../Shape';
import { getNumberValidator } from '../Validators';
import { _registerNode } from '../Global';
import { getNumberOrArrayOfNumbersValidator, getNumberValidator } from '../Validators';
import { GetSet, IRect } from '../types';
import { Context } from '../Context';
@@ -10,6 +10,7 @@ import { Context } from '../Context';
export interface ImageConfig extends ShapeConfig {
image: CanvasImageSource | undefined;
crop?: IRect;
cornerRadius?: number | number[];
}
/**
@@ -66,6 +67,7 @@ export class Image extends Shape<ImageConfig> {
_sceneFunc(context: Context) {
const width = this.getWidth();
const height = this.getHeight();
const cornerRadius = this.cornerRadius();
const image = this.attrs.image;
let params;
@@ -89,23 +91,32 @@ export class Image extends Shape<ImageConfig> {
}
}
if (this.hasFill() || this.hasStroke()) {
context.beginPath();
context.beginPath();
if (!cornerRadius) {
context.rect(0, 0, width, height);
context.closePath();
context.fillStrokeShape(this);
} else {
Util.drawRoundedRectPath(context, width, height, cornerRadius);
}
if (image) {
context.save();
cornerRadius && context.clip();
context.drawImage.apply(context, params);
context.restore();
}
context.closePath();
context.fillStrokeShape(this);
}
_hitFunc(context) {
var width = this.width(),
height = this.height();
height = this.height(),
cornerRadius = this.cornerRadius();
context.beginPath();
context.rect(0, 0, width, height);
if (!cornerRadius) {
context.rect(0, 0, width, height);
} else {
Util.drawRoundedRectPath(context, width, height, cornerRadius);
}
context.closePath();
context.fillStrokeShape(this);
}
@@ -149,10 +160,36 @@ export class Image extends Shape<ImageConfig> {
cropY: GetSet<number, this>;
cropWidth: GetSet<number, this>;
cropHeight: GetSet<number, this>;
cornerRadius: GetSet<number | number[], this>;
}
Image.prototype.className = 'Image';
_registerNode(Image);
/**
* get/set corner radius
* @method
* @name Konva.Image#cornerRadius
* @param {Number} cornerRadius
* @returns {Number}
* @example
* // get corner radius
* var cornerRadius = image.cornerRadius();
*
* // set corner radius
* image.cornerRadius(10);
*
* // set different corner radius values
* // top-left, top-right, bottom-right, bottom-left
* image.cornerRadius([0, 10, 20, 30]);
*/
Factory.addGetterSetter(
Image,
'cornerRadius',
0,
getNumberOrArrayOfNumbersValidator(4)
);
/**
* get/set image source. It can be image, canvas or video element
* @name Konva.Image#image

View File

@@ -2,8 +2,11 @@ import { Factory } from '../Factory';
import { Shape, ShapeConfig } from '../Shape';
import { _registerNode } from '../Global';
import { Util } from '../Util';
import { GetSet } from '../types';
import { Context } from '../Context';
import { getNumberOrArrayOfNumbersValidator } from '../Validators';
export interface RectConfig extends ShapeConfig {
cornerRadius?: number | number[];
}
@@ -27,7 +30,7 @@ export interface RectConfig extends ShapeConfig {
* });
*/
export class Rect extends Shape<RectConfig> {
_sceneFunc(context) {
_sceneFunc(context: Context) {
var cornerRadius = this.cornerRadius(),
width = this.width(),
height = this.height();
@@ -38,52 +41,7 @@ export class Rect extends Shape<RectConfig> {
// simple rect - don't bother doing all that complicated maths stuff.
context.rect(0, 0, width, height);
} else {
let topLeft = 0;
let topRight = 0;
let bottomLeft = 0;
let bottomRight = 0;
if (typeof cornerRadius === 'number') {
topLeft = topRight = bottomLeft = bottomRight = Math.min(
cornerRadius,
width / 2,
height / 2
);
} else {
topLeft = Math.min(cornerRadius[0] || 0, width / 2, height / 2);
topRight = Math.min(cornerRadius[1] || 0, width / 2, height / 2);
bottomRight = Math.min(cornerRadius[2] || 0, width / 2, height / 2);
bottomLeft = Math.min(cornerRadius[3] || 0, width / 2, height / 2);
}
context.moveTo(topLeft, 0);
context.lineTo(width - topRight, 0);
context.arc(
width - topRight,
topRight,
topRight,
(Math.PI * 3) / 2,
0,
false
);
context.lineTo(width, height - bottomRight);
context.arc(
width - bottomRight,
height - bottomRight,
bottomRight,
0,
Math.PI / 2,
false
);
context.lineTo(bottomLeft, height);
context.arc(
bottomLeft,
height - bottomLeft,
bottomLeft,
Math.PI / 2,
Math.PI,
false
);
context.lineTo(0, topLeft);
context.arc(topLeft, topLeft, topLeft, Math.PI, (Math.PI * 3) / 2, false);
Util.drawRoundedRectPath(context, width, height, cornerRadius);
}
context.closePath();
context.fillStrokeShape(this);