Merge branch 'zarv1k-release-canvas' into master

This commit is contained in:
Anton Lavrenov 2022-11-09 13:27:05 -05:00
commit 4a273df683
12 changed files with 89 additions and 11 deletions

View File

@ -8,7 +8,7 @@
* Konva JavaScript Framework v8.3.13
* http://konvajs.org/
* Licensed under the MIT
* Date: Mon Oct 03 2022
* Date: Wed Nov 09 2022
*
* Original work Copyright (C) 2011 - 2013 by Eric Rowell (KineticJS)
* Modified work Copyright (C) 2014 - present by Anton Lavrenov (Konva)
@ -157,6 +157,17 @@
isDragReady() {
return !!Konva$2['DD'].node;
},
/**
* Should Konva release canvas elements on destroy. Default is true.
* Useful to avoid memory leak issues in Safari on macOS/iOS.
* @property releaseCanvasOnDestroy
* @default true
* @name releaseCanvasOnDestroy
* @memberof Konva
* @example
* Konva.releaseCanvasOnDestroy = true;
*/
releaseCanvasOnDestroy: true,
// user agent
document: glob.document,
// insert Konva into global namespace (window)
@ -1071,6 +1082,14 @@
return evt.changedTouches[0].identifier;
}
},
releaseCanvas(...canvases) {
if (!Konva$2.releaseCanvasOnDestroy)
return;
canvases.forEach(c => {
c.width = 0;
c.height = 0;
});
}
};
function _formatValue(val) {
@ -2164,6 +2183,7 @@
1;
return devicePixelRatio / backingStoreRatio;
})();
Util.releaseCanvas(canvas);
return _pixelRatio;
}
/**
@ -2556,7 +2576,11 @@
* node.clearCache();
*/
clearCache() {
this._cache.delete(CANVAS);
if (this._cache.has(CANVAS)) {
const { scene, filter, hit } = this._cache.get(CANVAS);
Util.releaseCanvas(scene, filter, hit);
this._cache.delete(CANVAS);
}
this._clearSelfAndDescendantCache();
this._requestDraw();
return this;
@ -3042,6 +3066,7 @@
*/
destroy() {
this.remove();
this.clearCache();
return this;
}
/**
@ -5997,6 +6022,7 @@
if (index > -1) {
stages.splice(index, 1);
}
Util.releaseCanvas(this.bufferCanvas._canvas, this.bufferHitCanvas._canvas);
return this;
}
/**
@ -8620,6 +8646,10 @@
parent.content.appendChild(this.hitCanvas._canvas);
}
}
destroy() {
Util.releaseCanvas(this.getNativeCanvasElement(), this.getHitCanvas()._canvas);
return super.destroy();
}
}
Layer.prototype.nodeType = 'Layer';
_registerNode(Layer);
@ -14407,6 +14437,10 @@
height: maxY - minY + fontSize,
};
}
destroy() {
Util.releaseCanvas(this.dummyCanvas);
return super.destroy();
}
}
TextPath.prototype._fillFunc = _fillFunc;
TextPath.prototype._strokeFunc = _strokeFunc;
@ -17593,6 +17627,7 @@
var scratchData = tempCanvas
.getContext('2d')
.getImageData(0, 0, xSize, ySize);
Util.releaseCanvas(tempCanvas);
// Convert thhe original to polar coordinates
ToPolar(imageData, scratchData, {
polarCenterX: xSize / 2,

4
konva.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -23,6 +23,7 @@ function getDevicePixelRatio() {
1;
return devicePixelRatio / backingStoreRatio;
})();
Util.releaseCanvas(canvas);
return _pixelRatio;
}

View File

@ -86,7 +86,7 @@ var CONTEXT_PROPERTIES = [
'globalAlpha',
'globalCompositeOperation',
'imageSmoothingEnabled',
];
] as const;
const traceArrMax = 100;
/**
@ -701,6 +701,11 @@ export class Context {
}
}
// supported context properties
type CanvasContextProps = Pick<CanvasRenderingContext2D, typeof CONTEXT_PROPERTIES[number]>;
export interface Context extends CanvasContextProps {};
CONTEXT_PROPERTIES.forEach(function (prop) {
Object.defineProperty(Context.prototype, prop, {
get() {

View File

@ -164,6 +164,17 @@ export const Konva = {
isDragReady() {
return !!Konva['DD'].node;
},
/**
* Should Konva release canvas elements on destroy. Default is true.
* Useful to avoid memory leak issues in Safari on macOS/iOS.
* @property releaseCanvasOnDestroy
* @default true
* @name releaseCanvasOnDestroy
* @memberof Konva
* @example
* Konva.releaseCanvasOnDestroy = true;
*/
releaseCanvasOnDestroy: true,
// user agent
document: glob.document,
// insert Konva into global namespace (window)

View File

@ -468,6 +468,11 @@ export class Layer extends Container<Group | Shape> {
}
}
destroy(): this {
Util.releaseCanvas(this.getNativeCanvasElement(), this.getHitCanvas()._canvas);
return super.destroy();
}
hitGraphEnabled: GetSet<boolean, this>;
clearBeforeDraw: GetSet<boolean, this>;

View File

@ -243,7 +243,12 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
* node.clearCache();
*/
clearCache() {
this._cache.delete(CANVAS);
if (this._cache.has(CANVAS)) {
const { scene, filter, hit } = this._cache.get(CANVAS);
Util.releaseCanvas(scene, filter, hit);
this._cache.delete(CANVAS);
}
this._clearSelfAndDescendantCache();
this._requestDraw();
return this;
@ -853,6 +858,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
*/
destroy() {
this.remove();
this.clearCache();
return this;
}
/**

View File

@ -278,6 +278,9 @@ export class Stage extends Container<Layer> {
if (index > -1) {
stages.splice(index, 1);
}
Util.releaseCanvas(this.bufferCanvas._canvas, this.bufferHitCanvas._canvas)
return this;
}
/**

View File

@ -957,4 +957,12 @@ export const Util = {
return evt.changedTouches[0].identifier;
}
},
releaseCanvas(...canvases: HTMLCanvasElement[]) {
if (!Konva.releaseCanvasOnDestroy) return;
canvases.forEach(c => {
c.width = 0;
c.height = 0;
})
}
};

View File

@ -197,7 +197,7 @@ export const Kaleidoscope: Filter = function (imageData) {
var scratchData = tempCanvas
.getContext('2d')
.getImageData(0, 0, xSize, ySize);
Util.releaseCanvas(tempCanvas);
// Convert thhe original to polar coordinates
ToPolar(imageData, scratchData, {
polarCenterX: xSize / 2,

View File

@ -533,6 +533,10 @@ export class TextPath extends Shape<TextPathConfig> {
height: maxY - minY + fontSize,
};
}
destroy(): this {
Util.releaseCanvas(this.dummyCanvas);
return super.destroy();
}
fontFamily: GetSet<string, this>;
fontSize: GetSet<number, this>;

View File

@ -57,7 +57,7 @@ describe('Context', function () {
'textBaseline',
'globalAlpha',
'globalCompositeOperation',
];
] as const;
it('context wrapper should work like native context', function () {
var stage = addStage();
@ -108,10 +108,10 @@ describe('Context', function () {
// test get
nativeContext.fillStyle = '#ff0000';
assert.equal(context['fillStyle'], '#ff0000');
assert.equal(context.fillStyle, '#ff0000');
// test set
context['globalAlpha'] = 0.5;
assert.equal(context['globalAlpha'], 0.5);
context.globalAlpha = 0.5;
assert.equal(context.globalAlpha, 0.5);
});
});