Skip to content

Commit fc22743

Browse files
committed
feat: add support for miter-limit
1 parent c621b39 commit fc22743

File tree

3 files changed

+87
-2
lines changed

3 files changed

+87
-2
lines changed

src/Context.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,12 @@ export class Context {
304304
this.setAttr('lineJoin', lineJoin);
305305
}
306306
}
307+
_applyMiterLimit(shape: Shape) {
308+
const miterLimit = shape.attrs.miterLimit;
309+
if (miterLimit != null) {
310+
this.setAttr('miterLimit', miterLimit);
311+
}
312+
}
307313

308314
setAttr(attr: string, val) {
309315
this._context[attr] = val;

src/Shape.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export interface ShapeConfig extends NodeConfig {
6666
strokeEnabled?: boolean;
6767
lineJoin?: LineJoin;
6868
lineCap?: LineCap;
69+
miterLimit?: number;
6970
sceneFunc?: (con: Context, shape: Shape) => void;
7071
hitFunc?: (con: Context, shape: Shape) => void;
7172
shadowColor?: string;
@@ -214,14 +215,14 @@ export class Shape<
214215
}
215216

216217
/**
217-
* @deprecated
218+
* @deprecated
218219
*/
219220
getContext() {
220221
Util.warn('shape.getContext() method is deprecated. Please do not use it.');
221222
return this.getLayer()!.getContext();
222223
}
223224
/**
224-
* @deprecated
225+
* @deprecated
225226
*/
226227
getCanvas() {
227228
Util.warn('shape.getCanvas() method is deprecated. Please do not use it.');
@@ -637,6 +638,7 @@ export class Shape<
637638
bufferContext.clear();
638639
bufferContext.save();
639640
bufferContext._applyLineJoin(this);
641+
bufferContext._applyMiterLimit(this);
640642
// layer might be undefined if we are using cache before adding to layer
641643
const o = this.getAbsoluteTransform(top).getMatrix();
642644
bufferContext.transform(o[0], o[1], o[2], o[3], o[4], o[5]);
@@ -660,6 +662,7 @@ export class Shape<
660662
);
661663
} else {
662664
context._applyLineJoin(this);
665+
context._applyMiterLimit(this);
663666

664667
if (!cachingSelf) {
665668
const o = this.getAbsoluteTransform(top).getMatrix();
@@ -710,6 +713,7 @@ export class Shape<
710713
}
711714
context.save();
712715
context._applyLineJoin(this);
716+
context._applyMiterLimit(this);
713717

714718
const selfCache = this === top;
715719
if (!selfCache) {
@@ -828,6 +832,7 @@ export class Shape<
828832
hitFunc: GetSet<ShapeConfigHandler<this>, this>;
829833
lineCap: GetSet<LineCap, this>;
830834
lineJoin: GetSet<LineJoin, this>;
835+
miterLimit: GetSet<number, this>;
831836
perfectDrawEnabled: GetSet<boolean, this>;
832837
sceneFunc: GetSet<ShapeConfigHandler<this>, this>;
833838
shadowColor: GetSet<string, this>;
@@ -1084,6 +1089,22 @@ Factory.addGetterSetter(Shape, 'lineCap');
10841089
* shape.lineCap('round');
10851090
*/
10861091

1092+
Factory.addGetterSetter(Shape, 'miterLimit');
1093+
1094+
/**
1095+
* get/set miterLimit.
1096+
* @name Konva.Shape#miterLimit
1097+
* @method
1098+
* @param {Number} miterLimit
1099+
* @returns {Number}
1100+
* @example
1101+
* // get miter limit
1102+
* var miterLimit = shape.miterLimit();
1103+
*
1104+
* // set miter limit
1105+
* shape.miterLimit(10);
1106+
*/
1107+
10871108
Factory.addGetterSetter(Shape, 'sceneFunc');
10881109

10891110
/**

test/unit/Shape-test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,9 @@ describe('Shape', function () {
971971
rect.strokeWidth(8);
972972
assert.equal(rect.strokeWidth(), 8);
973973

974+
rect.miterLimit(5);
975+
assert.equal(rect.miterLimit(), 5);
976+
974977
const f = () => {};
975978
rect.sceneFunc(f);
976979
assert.equal(rect.sceneFunc(), f);
@@ -2408,4 +2411,59 @@ describe('Shape', function () {
24082411
const hitShape = layer.getIntersection({ x: 150, y: 150 });
24092412
assert.equal(hitShape, null);
24102413
});
2414+
2415+
it('miterLimit with buffer canvas', function () {
2416+
var stage = addStage();
2417+
var layer = new Konva.Layer();
2418+
2419+
// Sharp triangle with opacity to force buffer canvas usage
2420+
var triangle = new Konva.Shape({
2421+
x: 100,
2422+
y: 50,
2423+
sceneFunc: function (ctx, shape) {
2424+
ctx.beginPath();
2425+
ctx.moveTo(140, 5);
2426+
ctx.lineTo(0, 70);
2427+
ctx.lineTo(220, 70);
2428+
ctx.closePath();
2429+
ctx.fillStrokeShape(shape);
2430+
},
2431+
fill: 'yellow',
2432+
stroke: 'orange',
2433+
strokeWidth: 10,
2434+
lineJoin: 'miter',
2435+
miterLimit: 3,
2436+
opacity: 0.7, // Forces buffer canvas usage
2437+
});
2438+
2439+
layer.add(triangle);
2440+
stage.add(layer);
2441+
2442+
// Create expected result using native canvas with buffer approach
2443+
var canvas = createCanvas();
2444+
var context = canvas.getContext('2d');
2445+
2446+
// Draw on buffer first
2447+
context.beginPath();
2448+
context.translate(100, 50);
2449+
context.moveTo(140, 5);
2450+
context.lineTo(0, 70);
2451+
context.lineTo(220, 70);
2452+
context.closePath();
2453+
context.fillStyle = 'yellow';
2454+
context.strokeStyle = 'orange';
2455+
context.lineWidth = 10;
2456+
context.lineJoin = 'miter';
2457+
context.miterLimit = 3;
2458+
context.fill();
2459+
context.stroke();
2460+
2461+
// Apply opacity by drawing to final canvas
2462+
var finalCanvas = createCanvas();
2463+
var finalContext = finalCanvas.getContext('2d');
2464+
finalContext.globalAlpha = 0.7;
2465+
finalContext.drawImage(canvas, 0, 0);
2466+
2467+
compareLayerAndCanvas(layer, finalCanvas, 200);
2468+
});
24112469
});

0 commit comments

Comments
 (0)