fix types in tests, add skia backend

This commit is contained in:
Anton Lavrevov 2025-08-10 22:10:55 +09:00
parent d2ecf2064e
commit 8f22d97937
31 changed files with 271 additions and 257 deletions

View File

@ -1,3 +0,0 @@
import tseslint from 'typescript-eslint';
export default tseslint.config(...tseslint.configs.recommended);

View File

@ -1,77 +0,0 @@
import fs from 'fs';
// relative path here
// but you will need just require('konva-node');
import Konva from '../';
// Create stage. Container parameter is not required in NodeJS.
var stage = new Konva.Stage({
width: 100,
height: 100,
});
var layer = new Konva.Layer();
stage.add(layer);
var rect = new Konva.Rect({
width: 100,
height: 100,
x: 50,
y: 50,
fill: 'white',
});
var text = new Konva.Text({
text: 'Generated inside node js',
x: 20,
y: 20,
fill: 'black',
});
layer.add(rect).add(text);
layer.draw();
stage.setSize({
width: 200,
height: 200,
});
// check tween works
var tween = new Konva.Tween({
node: rect,
duration: 1,
x: -50,
});
tween.play();
// After tween we want to convert stage to dataURL
setTimeout(function () {
stage.toDataURL({
callback: function (data) {
// Then add result to stage
var img = new Konva.window.Image();
img.onload = function () {
var image = new Konva.Image({
image: img,
x: 10,
y: 50,
});
layer.add(image);
layer.draw();
// save stage image as file
stage.toDataURL({
callback: function (data) {
var base64Data = data.replace(/^data:image\/png;base64,/, '');
fs.writeFile('./out.png', base64Data, 'base64', function (err) {
err && console.log(err);
console.log('See out.png');
});
// now try to create image from url
Konva.Image.fromURL(data, () => {
console.log('image loaded');
// shoul'd throw
});
},
});
};
img.src = data;
},
});
}, 1050);

View File

@ -1,39 +0,0 @@
var Konva = require('konva');
var canvas = require('canvas');
// mock window
Konva.window = {
Image: canvas.Image,
devicePixelRatio: 1,
};
// mock document
Konva.document = {
createElement: function () {},
documentElement: {
addEventListener: function () {},
},
};
// make some global injections
global.requestAnimationFrame = (cb) => {
setImmediate(cb);
};
// create canvas in Node env
Konva.Util.createCanvasElement = () => {
const node = new canvas.Canvas();
node.style = {};
return node;
};
// create image in Node env
Konva.Util.createImageElement = () => {
const node = new canvas.Image();
node.style = {};
return node;
};
// _checkVisibility use dom element, in node we can skip it
Konva.Stage.prototype._checkVisibility = () => {};
module.exports = Konva;

View File

@ -1,32 +0,0 @@
{
"name": "konva-node",
"version": "0.11.2",
"description": "Konva framework for NodeJS env",
"main": "index.js",
"files": [
"index.js"
],
"type": "module",
"typings": "./node_modules/konva/konva.d.ts",
"scripts": {},
"keywords": [
"canvas",
"animations",
"graphic",
"html5"
],
"author": "Anton Lavrenov",
"bugs": {
"url": "https://github.com/konvajs/konva/issues"
},
"homepage": "http://konvajs.org/",
"repository": {
"type": "git",
"url": "git://github.com/konvajs/konva.git"
},
"license": "MIT",
"dependencies": {
"canvas": "^2.5.0",
"konva": "^7"
}
}

View File

@ -3,16 +3,23 @@
"version": "9.3.22",
"description": "HTML5 2d canvas library.",
"author": "Anton Lavrenov",
"type": "module",
"files": [
"README.md",
"konva.js",
"konva.min.js",
"lib",
"cmj"
"lib"
],
"main": "./lib/index-node.js",
"browser": "./lib/index.js",
"typings": "./lib/index-types.d.ts",
"exports": {
".": {
"default": "./lib/index.js"
},
"./setup-node-canvas": {
"default": "./lib/setup-node-canvas.js"
}
},
"main": "./lib/index.js",
"types": "./lib/index-types.d.ts",
"scripts": {
"start": "npm run test:watch",
"compile": "npm run clean && npm run tsc && cp ./src/index-types.d.ts ./lib/index-types.d.ts && npm run rollup",
@ -22,10 +29,12 @@
"test:build": "PARCEL_WORKER_BACKEND=process parcel build ./test/unit-tests.html --dist-dir ./test-build --target none --public-url ./ --no-source-maps",
"test:browser": "npm run test:build && mocha-headless-chrome -f ./test-build/unit-tests.html -a disable-web-security -a no-sandbox -a disable-setuid-sandbox",
"test:watch": "rm -rf ./.parcel-cache && PARCEL_WORKERS=0 parcel serve ./test/unit-tests.html ./test/manual-tests.html ./test/sandbox.html ./test/text-paths.html ./test/bunnies.html",
"test:node:compiled": "rm -rf ./.test-temp && mkdir ./.test-temp && (tsc -p ./test/tsconfig.json --outDir ./.test-temp || true) && mocha './.test-temp/test/unit/**/*.js' -r ./test/node-global-setup.mjs --exit && rm -rf ./.test-temp && npm run test:import",
"test:node": "npm run test:node:compiled",
"test:node:canvas": "rm -rf ./.test-temp && mkdir ./.test-temp && (tsc -p ./test/tsconfig.json --outDir ./.test-temp || true) && node ./rename-imports-test.mjs && mocha './.test-temp/test/unit/**/*.js' -r ./test/node-canvas-global-setup.mjs --exit && rm -rf ./.test-temp && npm run test:import",
"test:node:skia": "rm -rf ./.test-temp && mkdir ./.test-temp && (tsc -p ./test/tsconfig.json --outDir ./.test-temp || true) && node ./rename-imports-test.mjs && mocha './.test-temp/test/unit/**/*.js' -r ./test/node-skia-global-setup.mjs --exit && rm -rf ./.test-temp && npm run test:import",
"test:node": "npm run test:node:canvas && npm run test:node:skia",
"tsc": "tsc --removeComments",
"rollup": "rollup -c --bundleConfigAsCjs",
"rollup": "rollup -c",
"clean": "rm -rf ./lib && rm -rf ./types && rm -rf ./cmj && rm -rf ./test-build",
"watch": "rollup -c -w",
"size": "size-limit"
@ -61,18 +70,18 @@
}
],
"devDependencies": {
"@parcel/transformer-image": "2.13.2",
"@size-limit/preset-big-lib": "^11.1.6",
"@parcel/transformer-image": "2.15.4",
"@size-limit/preset-big-lib": "^11.2.0",
"@types/mocha": "^10.0.10",
"canvas": "^3.1.0",
"chai": "5.1.2",
"canvas": "^3.1.2",
"chai": "5.2.1",
"filehound": "^1.17.6",
"gulp": "^5.0.0",
"gulp": "^5.0.1",
"gulp-concat": "^2.6.1",
"gulp-connect": "^5.7.0",
"gulp-exec": "^5.0.0",
"gulp-jsdoc3": "^3.0.0",
"gulp-rename": "^2.0.0",
"gulp-rename": "^2.1.0",
"gulp-replace": "^1.1.4",
"gulp-typescript": "^5.0.1",
"gulp-uglify": "^3.0.2",
@ -82,12 +91,13 @@
"mocha-headless-chrome": "^4.0.0",
"parcel": "2.13.3",
"process": "^0.11.10",
"rollup": "^4.31.0",
"rollup": "^4.46.2",
"rollup-plugin-typescript2": "^0.36.0",
"size-limit": "^11.1.6",
"ts-mocha": "^10.0.0",
"size-limit": "^11.2.0",
"skia-canvas": "^2.0.2",
"ts-mocha": "^11.1.0",
"ts-node": "^10.9.2",
"typescript": "^5.7.3"
"typescript": "^5.9.2"
},
"keywords": [
"canvas",

36
rename-imports-test.mjs Normal file
View File

@ -0,0 +1,36 @@
import FileHound from 'filehound';
import fs from 'fs';
const files = FileHound.create().paths('./.test-temp').ext(['js', 'ts']).find();
files.then((filePaths) => {
filePaths.forEach((filepath) => {
fs.readFile(filepath, 'utf8', (err, text) => {
if (!text.match(/import .* from/g)) {
return;
}
text = text.replace(/(import .* from\s+['"])(.*)(?=['"])/g, '$1$2.js');
if (text.match(/export .* from/g)) {
text = text.replace(/(export .* from\s+['"])(.*)(?=['"])/g, '$1$2.js');
}
if (err) throw err;
// stupid replacement back
text = text.replace("from 'canvas.js';", "from 'canvas';");
text = text.replace("from 'chai.js';", "from 'chai';");
text = text.replace("from 'skia-canvas.js';", "from 'skia-canvas';");
// Handle import("./x/y/z") syntax.
text = text.replace(/(import\s*\(\s*['"])(.*)(?=['"])/g, '$1$2.js');
fs.writeFile(filepath, text, function (err) {
if (err) {
throw err;
}
});
});
});
});
// Removed CommonJS export rewriting to keep ESM output intact

View File

@ -34,14 +34,4 @@ files.then((filePaths) => {
});
});
const indexFiles = ['lib/index.js', 'lib/index-node.js', 'lib/Core.js'];
indexFiles.forEach((filepath) => {
fs.readFile(filepath, 'utf8', (err, text) => {
text = text.replace('exports.default =', 'module.exports =');
fs.writeFile(filepath, text, function (err) {
if (err) {
throw err;
}
});
});
});
// Removed CommonJS export rewriting to keep ESM output intact

View File

@ -11,16 +11,12 @@ export default {
sourcemap: false,
freeze: false,
},
// { file: pkg.module, format: 'es', sourcemap: true }
],
// Indicate here external modules you don't wanna include in your bundle (i.e.: 'lodash')
external: [],
watch: {
include: 'src/**',
},
plugins: [
// Allow json resolution
// json(),
// Compile TypeScript files
typescript({
useTsconfigDeclarationDir: true,
@ -32,14 +28,5 @@ export default {
},
},
}),
// // Allow bundling cjs modules (unlike webpack, rollup doesn't understand cjs)
// commonjs(),
// // Allow node_modules resolution, so you can use 'external' to control
// // which external modules to include in the bundle
// // https://github.com/rollup/rollup-plugin-node-resolve#usage
// resolve(),
// Resolve source maps to the original source
// sourceMaps()
],
};

View File

@ -184,6 +184,11 @@ export const Konva = {
// insert Konva into global namespace (window)
// it is required for npm packages
_injectGlobal(Konva) {
if (typeof glob.Konva !== 'undefined') {
console.error(
'Severa Konva instances detected. It is not recommended to use multiple Konva instances in the same environment.'
);
}
glob.Konva = Konva;
},
};

View File

@ -2,6 +2,14 @@ import { Konva } from './Global';
import { Context } from './Context';
import { IRect, RGB, Vector2d } from './types';
const ensureBrowser = () => {
if (typeof document === 'undefined') {
throw new Error(
'document is undefined, this is not a browser environment. For node.js env add `import "konva/register-node"`'
);
}
};
/*
* Last updated November 2011
* By Simon Sarris
@ -424,7 +432,7 @@ const OBJECT_ARRAY = '[object Array]',
yellowgreen: [154, 205, 5],
},
RGB_REGEX = /rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/;
let animQueue: Array<Function> = [];
let animQueue: Array<Function> = [];
const req =
(typeof requestAnimationFrame !== 'undefined' && requestAnimationFrame) ||
@ -505,6 +513,7 @@ export const Util = {
}
},
createCanvasElement() {
ensureBrowser();
const canvas = document.createElement('canvas');
// on some environments canvas.style is readonly
try {
@ -513,6 +522,7 @@ export const Util = {
return canvas;
},
createImageElement() {
ensureBrowser();
return document.createElement('img');
},
_isInDocument(el: any) {

30
src/setup-node-canvas.ts Normal file
View File

@ -0,0 +1,30 @@
import { Konva } from './_FullInternals';
import * as Canvas from 'canvas';
const canvas = Canvas['default'] || Canvas;
global.DOMMatrix = canvas.DOMMatrix;
const isNode = typeof global.document === 'undefined';
if (isNode) {
Konva.Util['createCanvasElement'] = () => {
const node = canvas.createCanvas(300, 300) as any;
if (!node['style']) {
node['style'] = {};
}
return node;
};
// create image in Node env
Konva.Util.createImageElement = () => {
const node = new canvas.Image() as any;
return node;
};
// this line is not part of the public API
// but will be used in tests
Konva.Util['Canvas'] = Canvas;
}
export default Konva;

40
src/setup-node-skia.ts Normal file
View File

@ -0,0 +1,40 @@
import { Konva } from './_FullInternals';
import { Canvas, DOMMatrix, Image } from 'skia-canvas';
global.DOMMatrix = DOMMatrix as any;
const isNode = typeof global.document === 'undefined';
if (isNode) {
// @ts-ignore
Canvas.prototype.toDataURL = Canvas.prototype.toDataURLSync;
Konva.Util['createCanvasElement'] = () => {
const node = new Canvas(300, 300) as any;
if (!node['style']) {
node['style'] = {};
}
node.toString = () => '[object HTMLCanvasElement]';
const ctx = node.getContext('2d');
// Override the getter to return the canvas node directly
// because in skia-canvas canvas is using weak ref to the canvas node
// and somehow on many tests it fails to get the canvas node
Object.defineProperty(ctx, 'canvas', {
get: () => node,
});
return node;
};
// create image in Node env
Konva.Util.createImageElement = () => {
const node = new Image() as any;
node.toString = () => '[object HTMLImageElement]';
return node;
};
// this line is not part of the public API
// but will be used in tests
Konva.Util['isSkia'] = true;
}
export default Konva;

View File

@ -1,5 +1,6 @@
// try to import only core
const Konva = require('../');
const Konva = require('../').default;
require('../lib/setup-node-canvas');
// just do a simple action
const stage = new Konva.Stage();

View File

@ -4,15 +4,15 @@ function equal(val1, val2, message) {
}
}
// try to import only core
// try to import only core from built lib
import Konva from '../lib/Core.js';
import '../lib/setup-node-canvas.js';
import { Rect } from '../lib/shapes/Rect.js';
import '../lib/index-node.js';
equal(Rect !== undefined, true, 'Rect is defined');
equal(Konva.Rect, Rect, 'Rect is injected');
// // just do a simple action
// just do a simple action
const stage = new Konva.Stage();
stage.toDataURL();

View File

@ -1,6 +1,6 @@
import { assert } from 'chai';
import { addStage, Konva, loadImage } from '../unit/test-utils';
import { addStage, Konva, loadImage, showHit } from '../unit/test-utils';
describe('Manual', function () {
// ======================================================

View File

@ -0,0 +1,21 @@
export async function mochaGlobalSetup() {
// Load node-canvas polyfills on the compiled test output
// Path from this file (test/) to compiled file (.test-temp/src/...)
try {
await import(
new URL('../.test-temp/src/setup-node-canvas.js', import.meta.url)
);
} catch (e) {
// If not compiled yet or path missing, keep going; tests that need it will fail clearly
}
globalThis.Path2D ??= class Path2D {
constructor(path) {
this.path = path;
}
get [Symbol.toStringTag]() {
return `Path2D`;
}
};
}

View File

@ -1,11 +0,0 @@
export function mochaGlobalSetup() {
globalThis.Path2D ??= class Path2D {
constructor(path) {
this.path = path
}
get [Symbol.toStringTag]() {
return `Path2D`;
}
}
}

View File

@ -0,0 +1,15 @@
export async function mochaGlobalSetup() {
await import(
new URL('../.test-temp/src/setup-node-skia.js', import.meta.url)
);
globalThis.Path2D ??= class Path2D {
constructor(path) {
this.path = path;
}
get [Symbol.toStringTag]() {
return `Path2D`;
}
};
}

View File

@ -4,7 +4,7 @@
"noEmitOnError": false,
"moduleResolution": "node",
"lib": ["ES2015", "dom"],
"module": "CommonJS",
"module": "ESNext",
"skipLibCheck": true,
"noImplicitAny": false,
"allowJs": true,

View File

@ -86,8 +86,6 @@ describe('Group', function () {
const trace = layer.getContext().getTrace();
console.log(trace);
assert.equal(
trace,
'clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);beginPath();rect(0,0,0,0);clip();transform(1,0,0,1,0,0);restore();'

View File

@ -327,7 +327,7 @@ describe('Image', function () {
layer.add(image);
layer.draw();
assert.equal(image instanceof Konva.Image, true);
var nativeImg = image.image();
var nativeImg = image.image() as HTMLImageElement;
assert.equal(nativeImg instanceof Image, true);
assert.equal(nativeImg.src.indexOf(src) !== -1, true);
assert.equal(nativeImg.complete, true);

View File

@ -366,7 +366,7 @@ describe('Label', function () {
layer.add(label);
assert.equal(counter, 4);
tag.pointerDirection('bottom');
tag.pointerDirection('down');
assert.equal(counter, 5);
tag.pointerWidth(30);
assert.equal(counter, 6);

View File

@ -2068,7 +2068,7 @@ describe('MouseEvents', function () {
type: 'mouseenter',
};
stage._pointerenter(evt);
stage._pointerenter(evt as PointerEvent);
assert.equal(mouseenterCount, 1, 'mouseenterCount should be 1');
});
@ -2268,7 +2268,7 @@ describe('MouseEvents', function () {
type: 'mouseenter',
};
stage._pointerenter(evt);
stage._pointerenter(evt as PointerEvent);
simulateMouseMove(stage, {
x: 10,

View File

@ -2552,11 +2552,18 @@ describe('Node', function () {
});
it('make sure we can create non existing node type', function () {
const oldWarn = console.warn;
let called = false;
console.warn = function () {
called = true;
};
var json =
'{"attrs":{},"className":"Layer","children":[{"attrs":{},"className":"Group","children":[{"attrs":{"x":289,"y":100,"radius":70,"fill":"green","stroke":"black","strokeWidth":4,"name":"myCircle","draggable":true},"className":"WeirdShape"}]}]}';
var layer = Konva.Node.create(json);
assert.deepEqual(layer.find('Shape').length, 1);
console.warn = oldWarn;
assert.equal(called, true);
});
// ======================================================
@ -3478,6 +3485,7 @@ describe('Node', function () {
assert.equal(rect.findAncestor('#group'), group);
assert.equal(rect.findAncestor('Group'), group);
// @ts-expect-error - test for no selector
assert.equal(rect.findAncestor(), null, 'return null if no selector');
});

View File

@ -1160,6 +1160,8 @@ describe('Shape', function () {
// no we should hit the rect
assert.equal(stage.getIntersection({ x: 5, y: 5 }), rect);
const oldWarn = console.warn;
console.warn = function () {};
rect.strokeHitEnabled(false);
assert.equal(rect.hitStrokeWidth(), 0);
@ -1171,15 +1173,7 @@ describe('Shape', function () {
rect.hitStrokeWidth(0);
assert.equal(rect.strokeHitEnabled(), false);
// var trace = layer
// .getHitCanvas()
// .getContext()
// .getTrace(true);
// assert.equal(
// trace,
// 'clearRect();save();transform();beginPath();rect();closePath();save();fillStyle;fill();restore();restore();'
// );
console.warn = oldWarn;
});
it('enable hitStrokeWidth even if we have no stroke on scene', function () {

View File

@ -551,6 +551,11 @@ describe('Stage', function () {
// ======================================================
it('Should not throw on clip for stage', function () {
// no asserts, because we check throw
const oldWarn = console.warn;
let called = false;
console.warn = function () {
called = true;
};
var stage = addStage({
clipFunc: function () {},
});
@ -566,6 +571,8 @@ describe('Stage', function () {
layer.add(text);
stage.add(layer);
console.warn = oldWarn;
assert.equal(called, true);
});
// ======================================================

View File

@ -1780,10 +1780,15 @@ describe('Text', function () {
layer.draw();
Konva._fixTextRendering = false;
const trace =
'clearRect(0,0,578,200);clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);font=normal normal 100px Arial;textBaseline=alphabetic;textAlign=left;translate(0,0);save();fillStyle=black;fillText(hello,0,85);restore();restore();';
assert.equal(layer.getContext().getTrace(), trace);
if (Konva.Util['isSkia']) {
const trace =
'clearRect(0,0,578,200);clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);font=normal normal 100px Arial;textBaseline=alphabetic;textAlign=left;translate(0,0);save();fillStyle=black;fillText(hello,0,84.668);restore();restore();';
assert.equal(layer.getContext().getTrace(), trace);
} else {
const trace =
'clearRect(0,0,578,200);clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);font=normal normal 100px Arial;textBaseline=alphabetic;textAlign=left;translate(0,0);save();fillStyle=black;fillText(hello,0,85);restore();restore();';
assert.equal(layer.getContext().getTrace(), trace);
}
});
it('charRenderFunc draws per character and can mutate context', function () {

View File

@ -877,7 +877,7 @@ describe('TextPath', function () {
var rect = textpath.getClientRect();
assert.equal(Math.round(rect.width), 299);
assert.equal(Math.round(rect.height), 171);
assert.equal(Math.abs(Math.round(rect.height) - 171) < 2, true);
});
it.skip('check vertical text path', function () {

View File

@ -1,5 +1,6 @@
import { assert } from 'chai';
import { Transformer } from '../../src/shapes/Transformer';
import type { Rect } from '../../src/shapes/Rect';
import {
addStage,
@ -4842,8 +4843,15 @@ describe('Transformer', function () {
const tr = new Konva.Transformer();
layer.add(tr);
const oldError = console.error;
let called = false;
console.error = function () {
called = true;
};
tr.nodes([layer]);
assert.equal(tr.nodes().length, 0);
console.error = oldError;
assert.equal(called, true);
});
it('anchorStyleFunc', function () {
@ -4866,7 +4874,7 @@ describe('Transformer', function () {
});
layer.add(tr);
// manual check of correct position of node
var handler = tr.findOne<Konva.Rect>('.bottom-right');
var handler = tr.findOne<Rect>('.bottom-right');
assert.equal(handler.fill(), 'white');
tr.anchorStyleFunc((anchor) => {

View File

@ -1,4 +1,5 @@
import { createCanvas, Canvas } from 'canvas';
import KonvaModule from '../../src/index';
export const Konva = KonvaModule;
var TYPE_ARRAY = /\[object Array\]/i,
TYPE_CANVAS = /\[object (Canvas|HTMLCanvasElement)\]/i,
@ -6,15 +7,24 @@ var TYPE_ARRAY = /\[object Array\]/i,
TYPE_CONTEXT = /\[object CanvasRenderingContext2D\]/i,
TYPE_IMAGE = /\[object (Image|HTMLImageElement)\]/i,
TYPE_IMAGE_DATA = /\[object ImageData\]/i,
UNDEFINED = 'undefined',
canvas = getCanvas(),
context = canvas.getContext('2d');
UNDEFINED = 'undefined';
// Creation
function getCanvas(width?, height?) {
return createCanvas(width, height);
return Konva.Util.createCanvasElement();
}
let singleCanvas;
function getSingleCanvas() {
if (!singleCanvas) {
singleCanvas = getCanvas();
}
return singleCanvas;
}
function getImageData(width, height) {
const canvas = getSingleCanvas();
const context = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
context.clearRect(0, 0, width, height);
@ -26,7 +36,7 @@ function isImage(object) {
return isType(object, TYPE_IMAGE);
}
function isCanvas(object) {
return isType(object, TYPE_CANVAS) || object instanceof Canvas;
return isType(object, TYPE_CANVAS);
}
function isContext(object) {
return isType(object, TYPE_CONTEXT);
@ -49,10 +59,7 @@ function isImageType(object) {
);
}
function isType(object, type) {
return (
typeof object === 'object' &&
!!Object.prototype.toString.apply(object).match(type)
);
return typeof object === 'object' && !!object.toString().match(type);
}
// Type Conversion
@ -61,6 +68,8 @@ function copyImageData(imageData) {
width = imageData.width,
data = imageData.data;
const canvas = getSingleCanvas();
const context = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
const newImageData = context.getImageData(0, 0, width, height);
@ -89,6 +98,8 @@ function toImageData(object) {
function toImageDataFromImage(image) {
const height = image.height,
width = image.width;
const canvas = getSingleCanvas();
const context = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
context.clearRect(0, 0, width, height);
@ -189,8 +200,7 @@ function diffUnequal(a, b, options) {
bData = b.data,
cData = c.data,
align = options && options.align;
var rowOffset,
columnOffset;
var rowOffset, columnOffset;
for (let i = cData.length - 1; i > 0; i = i - 4) {
cData[i] = 255;
@ -239,10 +249,10 @@ function diffUnequal(a, b, options) {
function checkType(...args) {
for (let i = 0; i < args.length; i++) {
if (!isImageType(args[i])) {
throw {
name: 'ImageTypeError',
message: 'Submitted object was not an image.',
};
// throw {
// name: 'ImageTypeError',
// message: 'Submitted object was not an image.',
// };
}
}
}

View File

@ -1,10 +1,9 @@
import { assert } from 'chai';
import KonvaModule from '../../src/index';
import '../../src/index-node';
export const Konva = KonvaModule;
import * as canvas from 'canvas';
// import * as canvas from 'canvas';
Konva.enableTrace = true;
Konva.showWarnings = true;
@ -84,12 +83,14 @@ export function loadImage(url, callback) {
url = (document.getElementById(url) as HTMLImageElement).src;
}
return canvas
.loadImage(url)
.then(callback)
.catch((e) => {
console.error(e);
});
const image = Konva.Util.createImageElement();
image.onload = () => {
callback(image);
};
image.onerror = (e) => {
console.error('Error loading image', url, e);
};
image.src = url;
}
export function getPixelRatio() {
@ -171,7 +172,7 @@ export function compareLayers(layer1: Layer, layer2: Layer, tol?, secondTol?) {
}
export function createCanvas() {
var node = canvas.createCanvas(300, 300);
var node = Konva.Util.createCanvasElement();
node.width = 578 * Konva.pixelRatio;
node.height = 200 * Konva.pixelRatio;
node.getContext('2d').scale(Konva.pixelRatio, Konva.pixelRatio);