mirror of
https://github.com/konvajs/konva.git
synced 2025-09-18 18:27:58 +08:00
feat: add support for miter-limit
This commit is contained in:
@@ -304,6 +304,12 @@ export class Context {
|
|||||||
this.setAttr('lineJoin', lineJoin);
|
this.setAttr('lineJoin', lineJoin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_applyMiterLimit(shape: Shape) {
|
||||||
|
const miterLimit = shape.attrs.miterLimit;
|
||||||
|
if (miterLimit != null) {
|
||||||
|
this.setAttr('miterLimit', miterLimit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setAttr(attr: string, val) {
|
setAttr(attr: string, val) {
|
||||||
this._context[attr] = val;
|
this._context[attr] = val;
|
||||||
|
21
src/Shape.ts
21
src/Shape.ts
@@ -66,6 +66,7 @@ export interface ShapeConfig extends NodeConfig {
|
|||||||
strokeEnabled?: boolean;
|
strokeEnabled?: boolean;
|
||||||
lineJoin?: LineJoin;
|
lineJoin?: LineJoin;
|
||||||
lineCap?: LineCap;
|
lineCap?: LineCap;
|
||||||
|
miterLimit?: number;
|
||||||
sceneFunc?: (con: Context, shape: Shape) => void;
|
sceneFunc?: (con: Context, shape: Shape) => void;
|
||||||
hitFunc?: (con: Context, shape: Shape) => void;
|
hitFunc?: (con: Context, shape: Shape) => void;
|
||||||
shadowColor?: string;
|
shadowColor?: string;
|
||||||
@@ -637,6 +638,7 @@ export class Shape<
|
|||||||
bufferContext.clear();
|
bufferContext.clear();
|
||||||
bufferContext.save();
|
bufferContext.save();
|
||||||
bufferContext._applyLineJoin(this);
|
bufferContext._applyLineJoin(this);
|
||||||
|
bufferContext._applyMiterLimit(this);
|
||||||
// layer might be undefined if we are using cache before adding to layer
|
// layer might be undefined if we are using cache before adding to layer
|
||||||
const o = this.getAbsoluteTransform(top).getMatrix();
|
const o = this.getAbsoluteTransform(top).getMatrix();
|
||||||
bufferContext.transform(o[0], o[1], o[2], o[3], o[4], o[5]);
|
bufferContext.transform(o[0], o[1], o[2], o[3], o[4], o[5]);
|
||||||
@@ -660,6 +662,7 @@ export class Shape<
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
context._applyLineJoin(this);
|
context._applyLineJoin(this);
|
||||||
|
context._applyMiterLimit(this);
|
||||||
|
|
||||||
if (!cachingSelf) {
|
if (!cachingSelf) {
|
||||||
const o = this.getAbsoluteTransform(top).getMatrix();
|
const o = this.getAbsoluteTransform(top).getMatrix();
|
||||||
@@ -710,6 +713,7 @@ export class Shape<
|
|||||||
}
|
}
|
||||||
context.save();
|
context.save();
|
||||||
context._applyLineJoin(this);
|
context._applyLineJoin(this);
|
||||||
|
context._applyMiterLimit(this);
|
||||||
|
|
||||||
const selfCache = this === top;
|
const selfCache = this === top;
|
||||||
if (!selfCache) {
|
if (!selfCache) {
|
||||||
@@ -828,6 +832,7 @@ export class Shape<
|
|||||||
hitFunc: GetSet<ShapeConfigHandler<this>, this>;
|
hitFunc: GetSet<ShapeConfigHandler<this>, this>;
|
||||||
lineCap: GetSet<LineCap, this>;
|
lineCap: GetSet<LineCap, this>;
|
||||||
lineJoin: GetSet<LineJoin, this>;
|
lineJoin: GetSet<LineJoin, this>;
|
||||||
|
miterLimit: GetSet<number, this>;
|
||||||
perfectDrawEnabled: GetSet<boolean, this>;
|
perfectDrawEnabled: GetSet<boolean, this>;
|
||||||
sceneFunc: GetSet<ShapeConfigHandler<this>, this>;
|
sceneFunc: GetSet<ShapeConfigHandler<this>, this>;
|
||||||
shadowColor: GetSet<string, this>;
|
shadowColor: GetSet<string, this>;
|
||||||
@@ -1084,6 +1089,22 @@ Factory.addGetterSetter(Shape, 'lineCap');
|
|||||||
* shape.lineCap('round');
|
* shape.lineCap('round');
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
Factory.addGetterSetter(Shape, 'miterLimit');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get/set miterLimit.
|
||||||
|
* @name Konva.Shape#miterLimit
|
||||||
|
* @method
|
||||||
|
* @param {Number} miterLimit
|
||||||
|
* @returns {Number}
|
||||||
|
* @example
|
||||||
|
* // get miter limit
|
||||||
|
* var miterLimit = shape.miterLimit();
|
||||||
|
*
|
||||||
|
* // set miter limit
|
||||||
|
* shape.miterLimit(10);
|
||||||
|
*/
|
||||||
|
|
||||||
Factory.addGetterSetter(Shape, 'sceneFunc');
|
Factory.addGetterSetter(Shape, 'sceneFunc');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -971,6 +971,9 @@ describe('Shape', function () {
|
|||||||
rect.strokeWidth(8);
|
rect.strokeWidth(8);
|
||||||
assert.equal(rect.strokeWidth(), 8);
|
assert.equal(rect.strokeWidth(), 8);
|
||||||
|
|
||||||
|
rect.miterLimit(5);
|
||||||
|
assert.equal(rect.miterLimit(), 5);
|
||||||
|
|
||||||
const f = () => {};
|
const f = () => {};
|
||||||
rect.sceneFunc(f);
|
rect.sceneFunc(f);
|
||||||
assert.equal(rect.sceneFunc(), f);
|
assert.equal(rect.sceneFunc(), f);
|
||||||
@@ -2408,4 +2411,59 @@ describe('Shape', function () {
|
|||||||
const hitShape = layer.getIntersection({ x: 150, y: 150 });
|
const hitShape = layer.getIntersection({ x: 150, y: 150 });
|
||||||
assert.equal(hitShape, null);
|
assert.equal(hitShape, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('miterLimit with buffer canvas', function () {
|
||||||
|
var stage = addStage();
|
||||||
|
var layer = new Konva.Layer();
|
||||||
|
|
||||||
|
// Sharp triangle with opacity to force buffer canvas usage
|
||||||
|
var triangle = new Konva.Shape({
|
||||||
|
x: 100,
|
||||||
|
y: 50,
|
||||||
|
sceneFunc: function (ctx, shape) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(140, 5);
|
||||||
|
ctx.lineTo(0, 70);
|
||||||
|
ctx.lineTo(220, 70);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.fillStrokeShape(shape);
|
||||||
|
},
|
||||||
|
fill: 'yellow',
|
||||||
|
stroke: 'orange',
|
||||||
|
strokeWidth: 10,
|
||||||
|
lineJoin: 'miter',
|
||||||
|
miterLimit: 3,
|
||||||
|
opacity: 0.7, // Forces buffer canvas usage
|
||||||
|
});
|
||||||
|
|
||||||
|
layer.add(triangle);
|
||||||
|
stage.add(layer);
|
||||||
|
|
||||||
|
// Create expected result using native canvas with buffer approach
|
||||||
|
var canvas = createCanvas();
|
||||||
|
var context = canvas.getContext('2d');
|
||||||
|
|
||||||
|
// Draw on buffer first
|
||||||
|
context.beginPath();
|
||||||
|
context.translate(100, 50);
|
||||||
|
context.moveTo(140, 5);
|
||||||
|
context.lineTo(0, 70);
|
||||||
|
context.lineTo(220, 70);
|
||||||
|
context.closePath();
|
||||||
|
context.fillStyle = 'yellow';
|
||||||
|
context.strokeStyle = 'orange';
|
||||||
|
context.lineWidth = 10;
|
||||||
|
context.lineJoin = 'miter';
|
||||||
|
context.miterLimit = 3;
|
||||||
|
context.fill();
|
||||||
|
context.stroke();
|
||||||
|
|
||||||
|
// Apply opacity by drawing to final canvas
|
||||||
|
var finalCanvas = createCanvas();
|
||||||
|
var finalContext = finalCanvas.getContext('2d');
|
||||||
|
finalContext.globalAlpha = 0.7;
|
||||||
|
finalContext.drawImage(canvas, 0, 0);
|
||||||
|
|
||||||
|
compareLayerAndCanvas(layer, finalCanvas, 200);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user