mirror of
https://github.com/konvajs/konva.git
synced 2025-04-05 20:48:28 +08:00
Merge branch 'iaosee-image-corner-radius' into master
This commit is contained in:
commit
6ca59aace1
49
src/Util.ts
49
src/Util.ts
@ -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);
|
||||
}
|
||||
};
|
||||
|
@ -1,8 +1,11 @@
|
||||
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 +13,7 @@ import { Context } from '../Context';
|
||||
export interface ImageConfig extends ShapeConfig {
|
||||
image: CanvasImageSource | undefined;
|
||||
crop?: IRect;
|
||||
cornerRadius?: number | number[];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,6 +70,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 +94,34 @@ export class Image extends Shape<ImageConfig> {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.hasFill() || this.hasStroke()) {
|
||||
if (this.hasFill() || this.hasStroke() || cornerRadius) {
|
||||
context.beginPath();
|
||||
context.rect(0, 0, width, height);
|
||||
cornerRadius
|
||||
? Util.drawRoundedRectPath(context, width, height, cornerRadius)
|
||||
: context.rect(0, 0, width, height);
|
||||
context.closePath();
|
||||
context.fillStrokeShape(this);
|
||||
}
|
||||
|
||||
if (image) {
|
||||
if (cornerRadius) {
|
||||
context.clip();
|
||||
}
|
||||
context.drawImage.apply(context, params);
|
||||
}
|
||||
// If you need to draw later, you need to execute save/restore
|
||||
}
|
||||
_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 +165,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
|
||||
|
@ -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);
|
||||
|
@ -52,6 +52,38 @@
|
||||
stage.on('contextmenu', (e) => {
|
||||
console.log('click');
|
||||
});
|
||||
|
||||
var imageObj = new Image();
|
||||
imageObj.onload = function () {
|
||||
var yoda = new Konva.Image({
|
||||
x: 150,
|
||||
y: 50,
|
||||
image: imageObj,
|
||||
width: 200,
|
||||
height: 200,
|
||||
draggable: true,
|
||||
strokeWidth: 4,
|
||||
stroke: 'blue',
|
||||
cornerRadius: [10, 20, 30, 40],
|
||||
});
|
||||
layer.add(yoda);
|
||||
};
|
||||
imageObj.src = 'https://konvajs.org/assets/yoda.jpg';
|
||||
|
||||
Konva.Image.fromURL('https://konvajs.org/assets/darth-vader.jpg', function (darthNode) {
|
||||
darthNode.setAttrs({
|
||||
x: 300,
|
||||
y: 50,
|
||||
// scaleX: 0.5,
|
||||
// scaleY: 0.5,
|
||||
draggable: true,
|
||||
strokeEnabled: true,
|
||||
stroke: 'green',
|
||||
strokeWidth: 2,
|
||||
cornerRadius: 30,
|
||||
});
|
||||
layer.add(darthNode);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -44,8 +44,7 @@ describe('Image', function () {
|
||||
assert.equal(darth.offset().x, 50);
|
||||
assert.equal(darth.offset().y, 30);
|
||||
|
||||
var crop = null;
|
||||
crop = darth.crop();
|
||||
var crop = darth.crop();
|
||||
|
||||
assert.equal(crop.x, 135);
|
||||
assert.equal(crop.y, 7);
|
||||
@ -168,6 +167,7 @@ describe('Image', function () {
|
||||
crop: { x: 186, y: 211, width: 106, height: 74 },
|
||||
draggable: true,
|
||||
scale: { x: 0.5, y: 0.5 },
|
||||
cornerRadius: 15,
|
||||
});
|
||||
|
||||
layer.add(darth);
|
||||
@ -209,6 +209,7 @@ describe('Image', function () {
|
||||
assert.equal(darth.cropY(), 6);
|
||||
assert.equal(darth.cropWidth(), 7);
|
||||
assert.equal(darth.cropHeight(), 8);
|
||||
assert.equal(darth.cornerRadius(), 15);
|
||||
|
||||
done();
|
||||
});
|
||||
@ -384,4 +385,32 @@ describe('Image', function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('corner radius', function (done) {
|
||||
loadImage('darth-vader.jpg', (imageObj) => {
|
||||
var stage = addStage();
|
||||
|
||||
var layer = new Konva.Layer();
|
||||
var darth = new Konva.Image({
|
||||
x: 20,
|
||||
y: 20,
|
||||
image: imageObj,
|
||||
cornerRadius: 10,
|
||||
draggable: true,
|
||||
stroke: 'red',
|
||||
strokeWidth: 100,
|
||||
strokeEnabled: false,
|
||||
});
|
||||
|
||||
layer.add(darth);
|
||||
stage.add(layer);
|
||||
|
||||
assert.equal(
|
||||
layer.getContext().getTrace(true),
|
||||
'clearRect();save();transform();beginPath();moveTo();lineTo();arc();lineTo();arc();lineTo();arc();lineTo();arc();closePath();clip();drawImage();restore();'
|
||||
);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user