diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 544c440..4e3f979 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -31,9 +31,6 @@ jobs:
- run: npm publish --provenance --access public -w ./packages/renderer
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- - run: npm publish --provenance --access public -w ./packages/board
- env:
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- run: npm publish --provenance --access public -w ./packages/core
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
diff --git a/package.json b/package.json
index 36000d3..9fcd592 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"private": false,
- "version": "0.4.0-beta.39",
+ "version": "0.4.0-beta.40",
"workspaces": [
"packages/*"
],
@@ -30,47 +30,47 @@
"upgrade:version": "npm run version:reset && pnpm i"
},
"devDependencies": {
- "@babel/core": "^7.25.2",
- "@babel/preset-env": "^7.25.3",
- "@babel/preset-typescript": "^7.24.7",
+ "@babel/core": "^7.26.10",
+ "@babel/preset-env": "^7.26.9",
+ "@babel/preset-typescript": "^7.27.0",
"@rollup/plugin-json": "^6.1.0",
"@types/glob": "^8.1.0",
- "@types/jest": "^29.5.12",
+ "@types/jest": "^29.5.14",
"@types/koa-compose": "^3.2.8",
- "@types/node": "^22.1.0",
+ "@types/node": "^22.14.1",
"@types/serve-handler": "^6.1.4",
- "@typescript-eslint/eslint-plugin": "^8.0.0",
- "@typescript-eslint/parser": "^8.0.0",
- "@vitejs/plugin-react": "^4.3.1",
+ "@typescript-eslint/eslint-plugin": "^8.29.1",
+ "@typescript-eslint/parser": "^8.29.1",
+ "@vitejs/plugin-react": "^4.3.4",
"babel-jest": "^29.7.0",
- "chalk": "^5.3.0",
- "dotenv": "^16.4.5",
+ "chalk": "^5.4.1",
+ "dotenv": "^16.5.0",
"enquirer": "^2.4.1",
- "esbuild": "^0.23.0",
- "eslint": "^9.8.0",
- "execa": "^9.3.0",
- "fs-extra": "^11.2.0",
- "glob": "^11.0.0",
+ "esbuild": "^0.25.2",
+ "eslint": "^9.24.0",
+ "execa": "^9.5.2",
+ "fs-extra": "^11.3.0",
+ "glob": "^11.0.1",
"http-server": "^14.1.1",
- "husky": "^9.1.4",
+ "husky": "^9.1.7",
"jest": "^29.7.0",
"jest-canvas-mock": "^2.5.2",
"jest-environment-jsdom": "^29.7.0",
- "jimp": "^0.22.12",
+ "jimp": "^1.6.0",
"koa-compose": "^4.1.0",
- "less": "^4.2.0",
- "pixelmatch": "^6.0.0",
+ "less": "^4.3.0",
+ "pixelmatch": "^7.1.0",
"pngjs": "^7.0.0",
- "puppeteer": "^22.6.4",
- "rollup": "^4.20.0",
- "rollup-plugin-dts": "^6.1.1",
- "rollup-plugin-esbuild": "^6.1.1",
- "serve-handler": "^6.1.5",
- "terser": "^5.31.3",
- "ts-morph": "^23.0.0",
+ "puppeteer": "^24.6.1",
+ "rollup": "^4.40.0",
+ "rollup-plugin-dts": "^6.2.1",
+ "rollup-plugin-esbuild": "^6.2.1",
+ "serve-handler": "^6.1.6",
+ "terser": "^5.39.0",
+ "ts-morph": "^25.0.1",
"ts-node": "^10.9.2",
- "tslib": "^2.6.3",
- "typescript": "^5.5.4",
- "vite": "^5.3.5"
+ "tslib": "^2.8.1",
+ "typescript": "^5.8.3",
+ "vite": "^6.2.6"
}
}
diff --git a/packages/board/README.md b/packages/board/README.md
deleted file mode 100644
index 14977d1..0000000
--- a/packages/board/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# @idraw/board
-
-[](https://github.com/idrawjs/idraw/actions/workflows/node.js.yml)
\ No newline at end of file
diff --git a/packages/board/__tests__/__snapshots__/index.test.ts.snap b/packages/board/__tests__/__snapshots__/index.test.ts.snap
deleted file mode 100644
index a6d89d4..0000000
--- a/packages/board/__tests__/__snapshots__/index.test.ts.snap
+++ /dev/null
@@ -1,197 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`@idraw/board context 1`] = `
-[
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 40,
- "y": 40,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 320,
- "y": 320,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 640,
- "y": 640,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 400,
- "width": 800,
- "x": 1560,
- "y": 1160,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
-]
-`;
-
-exports[`@idraw/board context 2`] = `
-[
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "dHeight": 3600,
- "dWidth": 4000,
- "dx": 0,
- "dy": 0,
- "img": ,
- "sHeight": 3600,
- "sWidth": 4000,
- "sx": 0,
- "sy": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "drawImage",
- },
- {
- "props": {
- "dHeight": 3600,
- "dWidth": 4000,
- "dx": 0,
- "dy": 0,
- "img": ,
- "sHeight": 3600,
- "sWidth": 4000,
- "sx": 0,
- "sy": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "drawImage",
- },
-]
-`;
diff --git a/packages/board/__tests__/__snapshots__/other-api.test.ts.snap b/packages/board/__tests__/__snapshots__/other-api.test.ts.snap
deleted file mode 100644
index b340f11..0000000
--- a/packages/board/__tests__/__snapshots__/other-api.test.ts.snap
+++ /dev/null
@@ -1,197 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`@idraw/board getTransform 1`] = `
-[
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 40,
- "y": 40,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 320,
- "y": 320,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 640,
- "y": 640,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 400,
- "width": 800,
- "x": 1560,
- "y": 1160,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
-]
-`;
-
-exports[`@idraw/board getTransform 2`] = `
-[
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "dHeight": 1600,
- "dWidth": 2400,
- "dx": -2400,
- "dy": -1600,
- "img": ,
- "sHeight": 1600,
- "sWidth": 2400,
- "sx": 0,
- "sy": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "drawImage",
- },
- {
- "props": {
- "dHeight": 1600,
- "dWidth": 2400,
- "dx": -2400,
- "dy": -1600,
- "img": ,
- "sHeight": 1600,
- "sWidth": 2400,
- "sx": 0,
- "sy": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "drawImage",
- },
-]
-`;
diff --git a/packages/board/__tests__/__snapshots__/scale.test.ts.snap b/packages/board/__tests__/__snapshots__/scale.test.ts.snap
deleted file mode 100644
index 5af11e5..0000000
--- a/packages/board/__tests__/__snapshots__/scale.test.ts.snap
+++ /dev/null
@@ -1,785 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`@idraw/board scale 001 1`] = `
-[
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 40,
- "y": 40,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 320,
- "y": 320,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 640,
- "y": 640,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 400,
- "width": 800,
- "x": 1560,
- "y": 1160,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
-]
-`;
-
-exports[`@idraw/board scale 001 2`] = `
-[
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "dHeight": 3600,
- "dWidth": 4000,
- "dx": 200,
- "dy": 0,
- "img": ,
- "sHeight": 3600,
- "sWidth": 4000,
- "sx": 0,
- "sy": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "drawImage",
- },
- {
- "props": {
- "dHeight": 3600,
- "dWidth": 4000,
- "dx": 200,
- "dy": 0,
- "img": ,
- "sHeight": 3600,
- "sWidth": 4000,
- "sx": 0,
- "sy": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "drawImage",
- },
-]
-`;
-
-exports[`@idraw/board scale 002 1`] = `
-[
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 40,
- "y": 40,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 320,
- "y": 320,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 640,
- "y": 640,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 400,
- "width": 800,
- "x": 1560,
- "y": 1160,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
-]
-`;
-
-exports[`@idraw/board scale 002 2`] = `
-[
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "dHeight": 2400,
- "dWidth": 4800,
- "dx": 0,
- "dy": 200,
- "img": ,
- "sHeight": 2400,
- "sWidth": 4800,
- "sx": 0,
- "sy": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "drawImage",
- },
- {
- "props": {
- "dHeight": 2400,
- "dWidth": 4800,
- "dx": 0,
- "dy": 200,
- "img": ,
- "sHeight": 2400,
- "sWidth": 4800,
- "sx": 0,
- "sy": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "drawImage",
- },
-]
-`;
-
-exports[`@idraw/board scale 003 1`] = `
-[
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 40,
- "y": 40,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 320,
- "y": 320,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 640,
- "y": 640,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 400,
- "width": 800,
- "x": 1560,
- "y": 1160,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
-]
-`;
-
-exports[`@idraw/board scale 003 2`] = `
-[
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "dHeight": 2400,
- "dWidth": 4000,
- "dx": 0,
- "dy": 0,
- "img": ,
- "sHeight": 2400,
- "sWidth": 4000,
- "sx": 0,
- "sy": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "drawImage",
- },
- {
- "props": {
- "dHeight": 2400,
- "dWidth": 4000,
- "dx": 0,
- "dy": 0,
- "img": ,
- "sHeight": 2400,
- "sWidth": 4000,
- "sx": 0,
- "sy": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "drawImage",
- },
-]
-`;
-
-exports[`@idraw/board scale 1`] = `
-[
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 40,
- "y": 40,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 320,
- "y": 320,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 640,
- "y": 640,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 400,
- "width": 800,
- "x": 1560,
- "y": 1160,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
-]
-`;
-
-exports[`@idraw/board scale 2`] = `
-[
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "dHeight": 1600,
- "dWidth": 2400,
- "dx": 600,
- "dy": 400,
- "img": ,
- "sHeight": 1600,
- "sWidth": 2400,
- "sx": 0,
- "sy": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "drawImage",
- },
- {
- "props": {
- "dHeight": 1600,
- "dWidth": 2400,
- "dx": 600,
- "dy": 400,
- "img": ,
- "sHeight": 1600,
- "sWidth": 2400,
- "sx": 0,
- "sy": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "drawImage",
- },
-]
-`;
diff --git a/packages/board/__tests__/__snapshots__/scroll.test.ts.snap b/packages/board/__tests__/__snapshots__/scroll.test.ts.snap
deleted file mode 100644
index 26aa655..0000000
--- a/packages/board/__tests__/__snapshots__/scroll.test.ts.snap
+++ /dev/null
@@ -1,197 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`@idraw/board scroll 1`] = `
-[
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 40,
- "y": 40,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 320,
- "y": 320,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 640,
- "y": 640,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 400,
- "width": 800,
- "x": 1560,
- "y": 1160,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
-]
-`;
-
-exports[`@idraw/board scroll 2`] = `
-[
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "dHeight": 1600,
- "dWidth": 2400,
- "dx": -2400,
- "dy": -1600,
- "img": ,
- "sHeight": 1600,
- "sWidth": 2400,
- "sx": 0,
- "sy": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "drawImage",
- },
- {
- "props": {
- "dHeight": 1600,
- "dWidth": 2400,
- "dx": -2400,
- "dy": -1600,
- "img": ,
- "sHeight": 1600,
- "sWidth": 2400,
- "sx": 0,
- "sy": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "drawImage",
- },
-]
-`;
diff --git a/packages/board/__tests__/__snapshots__/wheel.test.ts.snap b/packages/board/__tests__/__snapshots__/wheel.test.ts.snap
deleted file mode 100644
index 0d7e7f6..0000000
--- a/packages/board/__tests__/__snapshots__/wheel.test.ts.snap
+++ /dev/null
@@ -1,737 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`@idraw/board scroll 1`] = `
-[
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 40,
- "y": 40,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 320,
- "y": 320,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 480,
- "width": 800,
- "x": 640,
- "y": 640,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "height": 400,
- "width": 800,
- "x": 1560,
- "y": 1160,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
-]
-`;
-
-exports[`@idraw/board scroll 2`] = `
-[
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "height": 1600,
- "width": 2400,
- "x": 0,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "clearRect",
- },
- {
- "props": {
- "dHeight": 1600,
- "dWidth": 2400,
- "dx": -2400,
- "dy": -1600,
- "img": ,
- "sHeight": 1600,
- "sWidth": 2400,
- "sx": 0,
- "sy": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "drawImage",
- },
- {
- "props": {
- "dHeight": 1600,
- "dWidth": 2400,
- "dx": -2400,
- "dy": -1600,
- "img": ,
- "sHeight": 1600,
- "sWidth": 2400,
- "sx": 0,
- "sy": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "drawImage",
- },
- {
- "props": {
- "height": 80,
- "width": 2400,
- "x": 0,
- "y": 1520,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "fillRule": "nonzero",
- "path": [
- {
- "props": {},
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "beginPath",
- },
- {
- "props": {
- "x": 2220,
- "y": 1541,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "moveTo",
- },
- {
- "props": {
- "cpx1": 2400,
- "cpx2": 2400,
- "cpy1": 1541,
- "cpy2": 1581,
- "radius": 20,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "arcTo",
- },
- {
- "props": {
- "cpx1": 2400,
- "cpx2": 2200,
- "cpy1": 1581,
- "cpy2": 1581,
- "radius": 20,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "arcTo",
- },
- {
- "props": {
- "cpx1": 2200,
- "cpx2": 2200,
- "cpy1": 1581,
- "cpy2": 1541,
- "radius": 20,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "arcTo",
- },
- {
- "props": {
- "cpx1": 2200,
- "cpx2": 2400,
- "cpy1": 1541,
- "cpy2": 1541,
- "radius": 20,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "arcTo",
- },
- {
- "props": {},
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "closePath",
- },
- ],
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fill",
- },
- {
- "props": {
- "path": [
- {
- "props": {},
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "beginPath",
- },
- {
- "props": {
- "x": 2220,
- "y": 1541,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "moveTo",
- },
- {
- "props": {
- "cpx1": 2400,
- "cpx2": 2400,
- "cpy1": 1541,
- "cpy2": 1581,
- "radius": 20,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "arcTo",
- },
- {
- "props": {
- "cpx1": 2400,
- "cpx2": 2200,
- "cpy1": 1581,
- "cpy2": 1581,
- "radius": 20,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "arcTo",
- },
- {
- "props": {
- "cpx1": 2200,
- "cpx2": 2200,
- "cpy1": 1581,
- "cpy2": 1541,
- "radius": 20,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "arcTo",
- },
- {
- "props": {
- "cpx1": 2200,
- "cpx2": 2400,
- "cpy1": 1541,
- "cpy2": 1541,
- "radius": 20,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "arcTo",
- },
- {
- "props": {},
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "closePath",
- },
- ],
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "stroke",
- },
- {
- "props": {
- "height": 1600,
- "width": 80,
- "x": 2320,
- "y": 0,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fillRect",
- },
- {
- "props": {
- "fillRule": "nonzero",
- "path": [
- {
- "props": {},
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "beginPath",
- },
- {
- "props": {
- "x": 2361,
- "y": 1400,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "moveTo",
- },
- {
- "props": {
- "cpx1": 2381,
- "cpx2": 2381,
- "cpy1": 1400,
- "cpy2": 1600,
- "radius": 20,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "arcTo",
- },
- {
- "props": {
- "cpx1": 2381,
- "cpx2": 2341,
- "cpy1": 1600,
- "cpy2": 1600,
- "radius": 20,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "arcTo",
- },
- {
- "props": {
- "cpx1": 2341,
- "cpx2": 2341,
- "cpy1": 1600,
- "cpy2": 1400,
- "radius": 20,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "arcTo",
- },
- {
- "props": {
- "cpx1": 2341,
- "cpx2": 2381,
- "cpy1": 1400,
- "cpy2": 1400,
- "radius": 20,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "arcTo",
- },
- {
- "props": {},
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "closePath",
- },
- ],
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "fill",
- },
- {
- "props": {
- "path": [
- {
- "props": {},
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "beginPath",
- },
- {
- "props": {
- "x": 2361,
- "y": 1400,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "moveTo",
- },
- {
- "props": {
- "cpx1": 2381,
- "cpx2": 2381,
- "cpy1": 1400,
- "cpy2": 1600,
- "radius": 20,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "arcTo",
- },
- {
- "props": {
- "cpx1": 2381,
- "cpx2": 2341,
- "cpy1": 1600,
- "cpy2": 1600,
- "radius": 20,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "arcTo",
- },
- {
- "props": {
- "cpx1": 2341,
- "cpx2": 2341,
- "cpy1": 1600,
- "cpy2": 1400,
- "radius": 20,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "arcTo",
- },
- {
- "props": {
- "cpx1": 2341,
- "cpx2": 2381,
- "cpy1": 1400,
- "cpy2": 1400,
- "radius": 20,
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "arcTo",
- },
- {
- "props": {},
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "closePath",
- },
- ],
- },
- "transform": [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0,
- ],
- "type": "stroke",
- },
-]
-`;
diff --git a/packages/board/__tests__/data.ts b/packages/board/__tests__/data.ts
deleted file mode 100644
index 266f32a..0000000
--- a/packages/board/__tests__/data.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-export function getData() {
- const data = {
- elements: [
- {
- x: 10,
- y: 10,
- w: 200,
- h: 120,
- type: 'rect',
- detail: {
- color: '#f0f0f0'
- }
- },
- {
- x: 80,
- y: 80,
- w: 200,
- h: 120,
- type: 'rect',
- detail: {
- color: '#cccccc'
- }
- },
- {
- x: 160,
- y: 160,
- w: 200,
- h: 120,
- type: 'rect',
- detail: {
- color: '#c0c0c0'
- }
- },
- {
- x: 400 - 10,
- y: 300 - 10,
- w: 200,
- h: 100,
- type: 'rect',
- detail: {
- color: '#e0e0e0'
- }
- }
- ]
- };
- return data;
-}
diff --git a/packages/board/__tests__/index.test.ts b/packages/board/__tests__/index.test.ts
deleted file mode 100644
index b63c89d..0000000
--- a/packages/board/__tests__/index.test.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import Board from './../src';
-import { getData } from './data';
-
-describe('@idraw/board', () => {
- test('context', async () => {
- document.body.innerHTML = `
-
- `;
- const opts = {
- width: 600,
- height: 400,
- contextWidth: 1000,
- contextHeight: 900,
- devicePixelRatio: 4
- };
- const mount = document.querySelector('#mount') as HTMLDivElement;
- const board = new Board(mount, opts);
-
- const ctx = board.getContext();
- const data = getData();
-
- board.clear();
- ctx.clearRect(0, 0, opts.width, opts.height);
- ctx.setFillStyle('#ffffff');
- ctx.fillRect(0, 0, opts.width, opts.height);
- data.elements.forEach((ele) => {
- ctx.setFillStyle(ele.desc.color);
- ctx.fillRect(ele.x, ele.y, ele.w, ele.h);
- });
- board.draw();
-
- const originCtx = board.getOriginContext2D();
- // @ts-ignore;
- const originCalls = originCtx.__getDrawCalls();
- expect(originCalls).toMatchSnapshot();
-
- const displayCtx = board.getDisplayContext2D();
- // @ts-ignore;
- const displayCalls = displayCtx.__getDrawCalls();
- expect(displayCalls).toMatchSnapshot();
- });
-});
diff --git a/packages/board/__tests__/lib/__snapshots__/style.test.ts.snap b/packages/board/__tests__/lib/__snapshots__/style.test.ts.snap
deleted file mode 100644
index abdb3ac..0000000
--- a/packages/board/__tests__/lib/__snapshots__/style.test.ts.snap
+++ /dev/null
@@ -1,22 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`@idraw/board: src/lib/style getStyle 1`] = `
-{
- "height": "20px",
- "margin-top": "123px",
- "overflow": "auto",
- "width": "12px",
-}
-`;
-
-exports[`@idraw/board: src/lib/style setDomTransform 1`] = `
-
-`;
-
-exports[`@idraw/board: src/lib/style setStyle 1`] = `
-
-`;
diff --git a/packages/board/__tests__/lib/event.test.ts b/packages/board/__tests__/lib/event.test.ts
deleted file mode 100644
index 3275058..0000000
--- a/packages/board/__tests__/lib/event.test.ts
+++ /dev/null
@@ -1,108 +0,0 @@
-import { TypePoint } from '@idraw/types';
-import { BoardEvent } from './../../src/lib/event';
-
-describe('@idraw/board: src/lib/event', () => {
-
- // 'doubleClick': TypePoint;
- // 'hover': TypePoint;
- // 'leave': void;
- // 'point': TypePoint;
- // 'move': TypePoint;
- // 'moveStart': TypePoint;
- // 'moveEnd': TypePoint;
- // 'wheelX': number;
- // 'wheelY': number;
-
- test('BoardEvent event:off', async () => {
- const event = new BoardEvent();
- const point = { x: 123, y: 456 }
- const callback = (p: TypePoint) => {
- expect(p).toStrictEqual(point);
- }
- event.on('doubleClick', callback);
- event.trigger('doubleClick', point)
- event.off('doubleClick', callback);
- });
-
- test('BoardEvent event:doubleClick', async () => {
- const event = new BoardEvent();
- const point = { x: 123, y: 456 }
- event.on('doubleClick', (p) => {
- expect(p).toStrictEqual(point);
- });
- event.trigger('doubleClick', point)
- });
-
- test('BoardEvent event:hover', async () => {
- const event = new BoardEvent();
- const point = { x: 123, y: 456 }
- event.on('hover', (p) => {
- expect(p).toStrictEqual(point);
- });
- event.trigger('hover', point)
- });
-
- test('BoardEvent event:leave', async () => {
- const event = new BoardEvent();
- event.on('leave', (e) => {
- expect(e).toStrictEqual(undefined);
- });
- event.trigger('leave', undefined)
- });
-
- test('BoardEvent event:point', async () => {
- const event = new BoardEvent();
- const point = { x: 123, y: 456 }
- event.on('point', (p) => {
- expect(p).toStrictEqual(point);
- });
- event.trigger('point', point)
- });
-
- test('BoardEvent event:move', async () => {
- const event = new BoardEvent();
- const point = { x: 123, y: 456 }
- event.on('move', (p) => {
- expect(p).toStrictEqual(point);
- });
- event.trigger('move', point)
- });
-
-
- test('BoardEvent event:moveStart', async () => {
- const event = new BoardEvent();
- const point = { x: 123, y: 456 }
- event.on('moveStart', (p) => {
- expect(p).toStrictEqual(point);
- });
- event.trigger('moveStart', point)
- });
-
- test('BoardEvent event:moveEnd', async () => {
- const event = new BoardEvent();
- const point = { x: 123, y: 456 }
- event.on('moveEnd', (p) => {
- expect(p).toStrictEqual(point);
- });
- event.trigger('moveEnd', point)
- });
-
- test('BoardEvent event:wheelX', async () => {
- const event = new BoardEvent();
- const num = 123
- event.on('wheelX', (e) => {
- expect(e).toStrictEqual(num);
- });
- event.trigger('wheelX', num)
- });
-
- test('BoardEvent event:wheelY', async () => {
- const event = new BoardEvent();
- const num = 123
- event.on('wheelY', (e) => {
- expect(e).toStrictEqual(num);
- });
- event.trigger('wheelY', num)
- });
-
-});
\ No newline at end of file
diff --git a/packages/board/__tests__/lib/style.test.ts b/packages/board/__tests__/lib/style.test.ts
deleted file mode 100644
index 61a446d..0000000
--- a/packages/board/__tests__/lib/style.test.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-import {
- mergeCSS2StyleAttr, setStyle, getStyle, getDomTransform,
- setDomTransform,
-} from './../../src/lib/style';
-
-
-describe('@idraw/board: src/lib/style', () => {
- test('mergeCSS2StyleAttr', () => {
- const str = mergeCSS2StyleAttr({
- 'width': '12px',
- 'height': '20px',
- 'overflow': 'auto',
- 'margin-top': '123px',
- });
- expect(str).toStrictEqual('width:12px; height:20px; overflow:auto; margin-top:123px;');
- });
-
- test('setStyle', () => {
- const div = document.createElement('div');
- setStyle(div, {
- 'width': '12px',
- 'height': '20px',
- 'overflow': 'auto',
- 'margin-top': '123px',
- });
- expect(div).toMatchSnapshot();
- });
-
- test('getStyle', () => {
- const div = document.createElement('div');
- setStyle(div, {
- 'width': '12px',
- 'height': '20px',
- 'overflow': 'auto',
- 'margin-top': '123px',
- });
- expect(getStyle(div)).toMatchSnapshot({
- 'width': '12px',
- 'height': '20px',
- 'overflow': 'auto',
- 'margin-top': '123px',
- });
- });
-
- test('setDomTransform', () => {
- // transform: matrix( scaleX(), skewY(), skewX(), scaleY(), translateX(), translateY() )
- // matrix(1, 2, -1, 1, 80, 80)
- const div = document.createElement('div');
- setDomTransform(div, {
- scaleX: 1,
- skewY: 2,
- skewX: -1,
- scaleY: 1,
- translateX: 80,
- translateY: 90,
- });
- expect(div).toMatchSnapshot();
- })
-
- test('getDomTransform', () => {
- // transform: matrix( scaleX(), skewY(), skewX(), scaleY(), translateX(), translateY() )
- // matrix(1, 2, -1, 1, 80, 80)
- const div = document.createElement('div');
- setDomTransform(div, {
- scaleX: 1,
- skewY: 2,
- skewX: -1,
- scaleY: 1,
- translateX: 80,
- translateY: 90,
- });
- expect(getDomTransform(div)).toStrictEqual({
- scaleX: 1,
- skewY: 2,
- skewX: -1,
- scaleY: 1,
- translateX: 80,
- translateY: 90,
- });
- })
-})
\ No newline at end of file
diff --git a/packages/board/__tests__/other-api.test.ts b/packages/board/__tests__/other-api.test.ts
deleted file mode 100644
index 5523d12..0000000
--- a/packages/board/__tests__/other-api.test.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import Board from '../src';
-import { getData } from './data';
-
-describe('@idraw/board', () => {
- document.body.innerHTML = `
-
- `;
- const opts = {
- width: 600,
- height: 400,
- contextWidth: 600,
- contextHeight: 400,
- devicePixelRatio: 4
- };
- const mount = document.querySelector('#mount') as HTMLDivElement;
- const board = new Board(mount, opts);
-
- const ctx = board.getContext();
- const data = getData();
- board.clear();
- ctx.clearRect(0, 0, opts.width, opts.height);
- ctx.setFillStyle('#ffffff');
- ctx.fillRect(0, 0, opts.width, opts.height);
- data.elements.forEach((ele) => {
- ctx.setFillStyle(ele.desc.color);
- ctx.fillRect(ele.x, ele.y, ele.w, ele.h);
- });
-
- test('getTransform', async () => {
- const resultScale = board.scale(2);
- expect(resultScale).toStrictEqual({
- position: { top: 0, bottom: -400, left: 0, right: -600 },
- size: { x: 0, y: 0, w: 1200, h: 800 }
- });
-
- const resultX = board.scrollX(-600);
- expect(resultX).toStrictEqual({
- position: { top: 0, bottom: -400, left: -600, right: 0 },
- size: { x: -1200, y: 0, w: 1200, h: 800 }
- });
-
- const resultY = board.scrollY(-400);
- expect(resultY).toStrictEqual({
- position: { top: -400, bottom: 0, left: -600, right: 0 },
- size: { x: -1200, y: -800, w: 1200, h: 800 }
- });
-
- board.draw();
-
- const originCtx = board.getOriginContext2D();
- // @ts-ignore;
- const originCalls = originCtx.__getDrawCalls();
- expect(originCalls).toMatchSnapshot();
-
- const displayCtx = board.getDisplayContext2D();
- // @ts-ignore;
- const displayCalls = displayCtx.__getDrawCalls();
- expect(displayCalls).toMatchSnapshot();
-
- const transform = board.getTransform();
- expect(transform).toStrictEqual({ scale: 2, scrollX: -600, scrollY: -400 });
- });
-});
diff --git a/packages/board/__tests__/point.test.ts b/packages/board/__tests__/point.test.ts
deleted file mode 100644
index 7f8d8e0..0000000
--- a/packages/board/__tests__/point.test.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import Board from '../src';
-
-describe('@idraw/board', () => {
- document.body.innerHTML = `
-
- `;
- const opts = {
- width: 800,
- height: 600,
- contextWidth: 600,
- contextHeight: 400,
- devicePixelRatio: 4,
- canScroll: true
- };
- const transform = {
- scale: 2,
- scrollX: -200,
- scrollY: -100
- };
- const mount = document.querySelector('#mount') as HTMLDivElement;
- const board = new Board(mount, opts);
-
- board.scale(transform.scale);
- board.scrollX(transform.scrollX);
- board.scrollY(transform.scrollY);
- board.draw();
-
- const p1 = { x: 400, y: 300 };
- const p2 = { x: 300, y: 200 };
-
- test('pointScreenToContext', async () => {
- expect(board.pointScreenToContext(p1)).toStrictEqual(p2);
- });
-
- test('pointContextToScreen', async () => {
- expect(board.pointContextToScreen(p2)).toStrictEqual(p1);
- });
-});
diff --git a/packages/board/__tests__/scale.test.ts b/packages/board/__tests__/scale.test.ts
deleted file mode 100644
index a0ae67c..0000000
--- a/packages/board/__tests__/scale.test.ts
+++ /dev/null
@@ -1,184 +0,0 @@
-import Board from '../src';
-import { getData } from './data';
-
-describe('@idraw/board', () => {
- test('scale', async () => {
- document.body.innerHTML = `
-
- `;
- const opts = {
- width: 600,
- height: 400,
- contextWidth: 600,
- contextHeight: 400,
- devicePixelRatio: 4
- };
- const mount = document.querySelector('#mount') as HTMLDivElement;
- const board = new Board(mount, opts);
-
- const ctx = board.getContext();
- const data = getData();
-
- board.clear();
- ctx.clearRect(0, 0, opts.width, opts.height);
- ctx.setFillStyle('#ffffff');
- ctx.fillRect(0, 0, opts.width, opts.height);
- data.elements.forEach((ele) => {
- ctx.setFillStyle(ele.desc.color);
- ctx.fillRect(ele.x, ele.y, ele.w, ele.h);
- });
-
- const result = board.scale(0.5);
- expect(result).toStrictEqual({
- position: { top: 100, bottom: 100, left: 150, right: 150 },
- size: { x: 75, y: 50, w: 300, h: 200 }
- });
- board.draw();
-
- const originCtx = board.getOriginContext2D();
- // @ts-ignore;
- const originCalls = originCtx.__getDrawCalls();
- expect(originCalls).toMatchSnapshot();
-
- const displayCtx = board.getDisplayContext2D();
- // @ts-ignore;
- const displayCalls = displayCtx.__getDrawCalls();
- expect(displayCalls).toMatchSnapshot();
- });
-
- test('scale 001', async () => {
- document.body.innerHTML = `
-
- `;
- const opts = {
- width: 600,
- height: 400,
- contextWidth: 1000,
- contextHeight: 900,
- devicePixelRatio: 4
- };
- const mount = document.querySelector('#mount-001') as HTMLDivElement;
- const board = new Board(mount, opts);
-
- const ctx = board.getContext();
- const data = getData();
-
- board.clear();
- ctx.clearRect(0, 0, opts.width, opts.height);
- ctx.setFillStyle('#ffffff');
- ctx.fillRect(0, 0, opts.width, opts.height);
- data.elements.forEach((ele) => {
- ctx.setFillStyle(ele.desc.color);
- ctx.fillRect(ele.x, ele.y, ele.w, ele.h);
- });
-
- const result = board.scale(0.5);
- expect(result).toStrictEqual({
- position: { top: 0, bottom: -50, left: 50, right: 50 },
- size: { x: 25, y: 0, w: 500, h: 450 }
- });
- board.draw();
-
- const originCtx = board.getOriginContext2D();
- // @ts-ignore;
- const originCalls = originCtx.__getDrawCalls();
- expect(originCalls).toMatchSnapshot();
-
- const displayCtx = board.getDisplayContext2D();
- // @ts-ignore;
- const displayCalls = displayCtx.__getDrawCalls();
- expect(displayCalls).toMatchSnapshot();
- });
-
- test('scale 002', async () => {
- document.body.innerHTML = `
-
- `;
- const opts = {
- width: 600,
- height: 400,
- contextWidth: 1200,
- contextHeight: 600,
- devicePixelRatio: 4
- };
- const mount = document.querySelector('#mount-002') as HTMLDivElement;
- const board = new Board(mount, opts);
-
- const ctx = board.getContext();
- const data = getData();
-
- board.clear();
- ctx.clearRect(0, 0, opts.width, opts.height);
- ctx.setFillStyle('#ffffff');
- ctx.fillRect(0, 0, opts.width, opts.height);
- data.elements.forEach((ele) => {
- ctx.setFillStyle(ele.desc.color);
- ctx.fillRect(ele.x, ele.y, ele.w, ele.h);
- });
-
- board.scrollX(-600);
- board.scrollY(-400);
- const result = board.scale(0.5);
- expect(result).toStrictEqual({
- position: { top: 50, bottom: 50, left: 0, right: 0 },
- size: { x: 0, y: 25, w: 600, h: 300 }
- });
- board.draw();
-
- const originCtx = board.getOriginContext2D();
- // @ts-ignore;
- const originCalls = originCtx.__getDrawCalls();
- expect(originCalls).toMatchSnapshot();
-
- const displayCtx = board.getDisplayContext2D();
- // @ts-ignore;
- const displayCalls = displayCtx.__getDrawCalls();
- expect(displayCalls).toMatchSnapshot();
- });
-
- test('scale 003', async () => {
- document.body.innerHTML = `
-
- `;
- const opts = {
- width: 600,
- height: 400,
- contextWidth: 1000,
- contextHeight: 600,
- devicePixelRatio: 4
- };
- const mount = document.querySelector('#mount-003') as HTMLDivElement;
- const board = new Board(mount, opts);
-
- const ctx = board.getContext();
- const data = getData();
-
- board.clear();
- ctx.clearRect(0, 0, opts.width, opts.height);
- ctx.setFillStyle('#ffffff');
- ctx.fillRect(0, 0, opts.width, opts.height);
- data.elements.forEach((ele) => {
- ctx.setFillStyle(ele.desc.color);
- ctx.fillRect(ele.x, ele.y, ele.w, ele.h);
- });
-
- board.scrollX(400);
- board.scrollY(400);
- const result = board.scale(0.8);
- expect(result).toStrictEqual({
- position: { top: 0, bottom: -80, left: 0, right: -200 },
- size: { x: 0, y: 0, w: 800, h: 480 }
- });
- board.draw();
-
- const originCtx = board.getOriginContext2D();
- // @ts-ignore;
- const originCalls = originCtx.__getDrawCalls();
- expect(originCalls).toMatchSnapshot();
-
- const displayCtx = board.getDisplayContext2D();
- // @ts-ignore;
- const displayCalls = displayCtx.__getDrawCalls();
- expect(displayCalls).toMatchSnapshot();
- });
-});
diff --git a/packages/board/__tests__/scroll.test.ts b/packages/board/__tests__/scroll.test.ts
deleted file mode 100644
index 5c2b217..0000000
--- a/packages/board/__tests__/scroll.test.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import Board from '../src';
-import { getData } from './data';
-
-describe('@idraw/board', () => {
- document.body.innerHTML = `
-
- `;
- const opts = {
- width: 600,
- height: 400,
- contextWidth: 600,
- contextHeight: 400,
- devicePixelRatio: 4
- };
- const mount = document.querySelector('#mount') as HTMLDivElement;
- const board = new Board(mount, opts);
-
- const ctx = board.getContext();
- const data = getData();
- board.clear();
- ctx.clearRect(0, 0, opts.width, opts.height);
- ctx.setFillStyle('#ffffff');
- ctx.fillRect(0, 0, opts.width, opts.height);
- data.elements.forEach((ele) => {
- ctx.setFillStyle(ele.desc.color);
- ctx.fillRect(ele.x, ele.y, ele.w, ele.h);
- });
-
- test('scroll', async () => {
- const resultScale = board.scale(2);
- expect(resultScale).toStrictEqual({
- position: { top: 0, bottom: -400, left: 0, right: -600 },
- size: { x: 0, y: 0, w: 1200, h: 800 }
- });
-
- const resultX = board.scrollX(-600);
- expect(resultX).toStrictEqual({
- position: { top: 0, bottom: -400, left: -600, right: 0 },
- size: { x: -1200, y: 0, w: 1200, h: 800 }
- });
-
- const resultY = board.scrollY(-400);
- expect(resultY).toStrictEqual({
- position: { top: -400, bottom: 0, left: -600, right: 0 },
- size: { x: -1200, y: -800, w: 1200, h: 800 }
- });
-
- board.draw();
-
- const originCtx = board.getOriginContext2D();
- // @ts-ignore;
- const originCalls = originCtx.__getDrawCalls();
- expect(originCalls).toMatchSnapshot();
-
- const displayCtx = board.getDisplayContext2D();
- // @ts-ignore;
- const displayCalls = displayCtx.__getDrawCalls();
- expect(displayCalls).toMatchSnapshot();
-
- const screenInfo = board.getScreenInfo();
- expect(screenInfo).toStrictEqual({
- size: { x: -1200, y: -800, w: 1200, h: 800 },
- position: { top: -400, bottom: 0, left: -600, right: 0 },
- deviceSize: { x: -2400, y: -1600, w: 4800, h: 3200 },
- width: 600,
- height: 400,
- devicePixelRatio: 4,
- canScrollXNext: true,
- canScrollXPrev: true,
- canScrollYNext: true,
- canScrollYPrev: true
- });
- });
-});
diff --git a/packages/board/__tests__/wheel.test.ts b/packages/board/__tests__/wheel.test.ts
deleted file mode 100644
index dee7e9f..0000000
--- a/packages/board/__tests__/wheel.test.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-/* eslint-disable @typescript-eslint/ban-ts-comment */
-import Board from '../src';
-import { getData } from './data';
-
-describe('@idraw/board', () => {
- test('scroll', async () => {
- document.body.innerHTML = `
-
- `;
- const opts = {
- width: 600,
- height: 400,
- contextWidth: 600,
- contextHeight: 400,
- devicePixelRatio: 4,
- canScroll: true,
- scrollConfig: {
- width: 20,
- color: '#666666'
- }
- };
- const mount = document.querySelector('#mount') as HTMLDivElement;
- const board = new Board(mount, opts);
-
- const ctx = board.getContext();
- const data = getData();
- board.clear();
- ctx.clearRect(0, 0, opts.width, opts.height);
- ctx.setFillStyle('#ffffff');
- ctx.fillRect(0, 0, opts.width, opts.height);
- data.elements.forEach((ele) => {
- ctx.setFillStyle(ele.desc.color);
- ctx.fillRect(ele.x, ele.y, ele.w, ele.h);
- });
-
- const resultScale = board.scale(2);
- expect(resultScale).toStrictEqual({
- position: { top: 0, bottom: -400, left: 0, right: -600 },
- size: { x: 0, y: 0, w: 1200, h: 800 }
- });
-
- const resultX = board.scrollX(-600);
- expect(resultX).toStrictEqual({
- position: { top: 0, bottom: -400, left: -600, right: 0 },
- size: { x: -1200, y: 0, w: 1200, h: 800 }
- });
-
- const resultY = board.scrollY(-400);
- expect(resultY).toStrictEqual({
- position: { top: -400, bottom: 0, left: -600, right: 0 },
- size: { x: -1200, y: -800, w: 1200, h: 800 }
- });
-
- board.draw();
-
- const originCtx = board.getOriginContext2D();
- // @ts-ignore;
- const originCalls = originCtx.__getDrawCalls();
- expect(originCalls).toMatchSnapshot();
-
- const displayCtx = board.getDisplayContext2D();
- // @ts-ignore;
- const displayCalls = displayCtx.__getDrawCalls();
- expect(displayCalls).toMatchSnapshot();
-
- const scrollLineWidth = board.getScrollLineWidth();
- expect(scrollLineWidth).toStrictEqual(opts.scrollConfig.width);
- });
-});
diff --git a/packages/board/dev/data.ts b/packages/board/dev/data.ts
deleted file mode 100644
index df4f0ea..0000000
--- a/packages/board/dev/data.ts
+++ /dev/null
@@ -1,195 +0,0 @@
-import type { Data } from '@idraw/types';
-import { createUUID, parseSVGPath } from '@idraw/util';
-
-const data: Data = {
- elements: [
- // {
- // uuid: createUUID(),
- // type: 'image',
- // x: 100,
- // y: 100,
- // w: 100,
- // h: 100,
- // angle: 30,
- // detail: {
- // // src: '/public/images/lena.png?t=002'
- // src: '@assets/0ee02fb0-ec43-6b9a-9ab4-55be5816ca4a'
- // },
- // operations: {
- // limitRatio: true
- // }
- // },
- {
- uuid: createUUID(),
- x: 2,
- y: 2,
- w: 100,
- h: 100,
- type: 'circle',
- detail: {
- background: '#f44336'
- }
- },
- {
- uuid: createUUID(),
- type: 'rect',
- x: 50,
- y: 50,
- w: 100,
- h: 100,
- detail: {
- background: '#8bc34a'
- }
- },
- // {
- // uuid: createUUID(),
- // type: 'image',
- // x: 250,
- // y: 250,
- // w: 100,
- // h: 100,
- // detail: {
- // // src: '/public/images/github.png?t=003'
- // src: '@assets/25a0e630-a958-a522-29a4-5dccf04985da'
- // }
- // },
- // {
- // uuid: createUUID(),
- // type: 'group',
- // x: 250,
- // y: 250,
- // w: 100,
- // h: 100,
- // detail: {
- // children: [
- // {
- // uuid: createUUID(),
- // type: 'image',
- // x: 0,
- // y: 0,
- // w: 100,
- // h: 100,
- // detail: {
- // // src: '/public/images/github.png?t=003'
- // src: '@assets/489c64d2-f642-3855-7bd6-cb40624b62c3'
- // }
- // }
- // ],
- // // assets: {
- // // '@assets/489c64d2-f642-3855-7bd6-cb40624b62c3': {
- // // type: 'image',
- // // value: '/public/images/github.png?t=003'
- // // }
- // // }
- // }
- // },
- {
- uuid: createUUID(),
- x: 0,
- y: 300,
- w: 100,
- h: 100,
- type: 'circle',
- detail: {
- background: '#009688'
- }
- },
- {
- uuid: createUUID(),
- x: 300,
- y: 300,
- w: 100,
- h: 100,
- type: 'circle',
- detail: {
- background: '#673ab7'
- }
- },
- {
- uuid: createUUID(),
- x: 300,
- y: 0,
- w: 100,
- h: 100,
- type: 'circle',
- detail: {
- background: '#ffc107'
- }
- },
- {
- uuid: createUUID(),
- x: 150,
- y: 150,
- w: 100,
- h: 100,
- // angle: 30,
- type: 'rect',
- detail: {
- background: '#4caf50',
- clipPath: {
- commands: parseSVGPath(`
- M 10,30
- A 20,20 0,0,1 50,30
- A 20,20 0,0,1 90,30
- Q 90,60 50,90
- Q 10,60 10,30 z`),
- // fill: '#ff0000',
- originX: 10,
- originY: 10,
- originH: 80,
- originW: 80
- // background: '#0000002A'
- }
- }
- },
- {
- uuid: createUUID(),
- x: 100,
- y: 10,
- w: 80,
- h: 80,
- // angle: 30,
- type: 'path',
- detail: {
- commands: parseSVGPath(`
- M 10,30
- A 20,20 0,0,1 50,30
- A 20,20 0,0,1 90,30
- Q 90,60 50,90
- Q 10,60 10,30 z`),
- fill: 'red',
- originX: 10,
- originY: 10,
- originH: 80,
- originW: 80,
- background: '#0000002A'
-
- // clipPath: {
- // commands: parseSVGPath(`
- // M 10,30
- // A 20,20 0,0,1 50,30
- // A 20,20 0,0,1 90,30
- // Q 90,60 50,90
- // Q 10,60 10,30 z`),
- // fill: '#ff0000',
- // originX: 10,
- // originY: 10,
- // originH: 80,
- // originW: 80
- // }
- }
- }
- ]
- // assets: {
- // '@assets/0ee02fb0-ec43-6b9a-9ab4-55be5816ca4a': {
- // type: 'image',
- // value: '/public/images/lena.png?t=003'
- // },
- // '@assets/25a0e630-a958-a522-29a4-5dccf04985da': {
- // type: 'image',
- // value: '/public/images/github.png?t=002'
- // }
- // }
-};
-
-export default data;
diff --git a/packages/board/dev/index.html b/packages/board/dev/index.html
deleted file mode 100644
index 4df3be5..0000000
--- a/packages/board/dev/index.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/packages/board/dev/main.ts b/packages/board/dev/main.ts
deleted file mode 100644
index 63d3ac0..0000000
--- a/packages/board/dev/main.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import { createBoardContent, deepClone } from '../../util/src';
-import { Board } from '../src';
-import { MiddlewareSelector, MiddlewareScroller, MiddlewareScaler } from '../../core/src';
-import data from './data';
-
-const devicePixelRatio = window.devicePixelRatio;
-// const width = window.innerWidth;
-// const height = window.innerHeight;
-
-const width = 800;
-const height = 600;
-
-const canvas = document.querySelector('#canvas') as HTMLCanvasElement;
-canvas.width = width * devicePixelRatio;
-canvas.height = height * devicePixelRatio;
-canvas.style.width = `${width}px`;
-canvas.style.height = `${height}px`;
-// const ctx1 = canvas.getContext('2d') as CanvasRenderingContext2D;
-const boardContent1 = createBoardContent(canvas, { width, height, devicePixelRatio });
-const board = new Board({ boardContent: boardContent1 });
-
-const sharer1 = board.getSharer();
-sharer1.setActiveViewSizeInfo({
- devicePixelRatio,
- width,
- height,
- contextWidth: width,
- contextHeight: height
-});
-const data1 = deepClone(data);
-board.resize(sharer1.getActiveViewSizeInfo());
-board.setData(data1);
-board.use(MiddlewareSelector);
-board.use(MiddlewareScroller);
-board.use(MiddlewareScaler);
-// board.scale(2);
-// board.scrollX(-50);
-// board.scrollY(-50);
diff --git a/packages/board/package.json b/packages/board/package.json
deleted file mode 100644
index 243bc94..0000000
--- a/packages/board/package.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "name": "@idraw/board",
- "version": "0.4.0-beta.39",
- "description": "",
- "main": "dist/esm/index.js",
- "module": "dist/esm/index.js",
- "unpkg": "dist/index.global.js",
- "types": "dist/esm/index.d.ts",
- "files": [
- "dist/**/*.ts",
- "dist/**/*.js"
- ],
- "repository": {
- "type": "git",
- "url": "git+https://github.com/idrawjs/idraw.git"
- },
- "bugs": {
- "url": "https://github.com/idrawjs/idraw/issues"
- },
- "homepage": "https://github.com/idrawjs/idraw#readme",
- "author": "chenshenhai",
- "license": "MIT",
- "devDependencies": {
- "@idraw/types": "workspace:^0.4.0-beta.39"
- },
- "dependencies": {},
- "peerDependencies": {
- "@idraw/util": "workspace:^0.4.0-beta.39",
- "@idraw/renderer": "workspace:^0.4.0-beta.39"
- },
- "publishConfig": {
- "access": "public",
- "provenance": true
- }
-}
\ No newline at end of file
diff --git a/packages/core/package.json b/packages/core/package.json
index a7de194..d39851c 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -1,6 +1,6 @@
{
"name": "@idraw/core",
- "version": "0.4.0-beta.39",
+ "version": "0.4.0-beta.40",
"description": "",
"main": "dist/esm/index.js",
"module": "dist/esm/index.js",
@@ -18,16 +18,15 @@
"url": "https://github.com/idrawjs/idraw/issues"
},
"homepage": "https://github.com/idrawjs/idraw#readme",
- "author": "chenshenhai",
+ "author": "idrawjs",
"license": "MIT",
"devDependencies": {
- "@idraw/types": "workspace:^0.4.0-beta.39"
+ "@idraw/types": "workspace:^0.4.0-beta.40"
},
"dependencies": {},
"peerDependencies": {
- "@idraw/board": "workspace:^0.4.0-beta.39",
- "@idraw/renderer": "workspace:^0.4.0-beta.39",
- "@idraw/util": "workspace:^0.4.0-beta.39"
+ "@idraw/renderer": "workspace:^0.4.0-beta.40",
+ "@idraw/util": "workspace:^0.4.0-beta.40"
},
"publishConfig": {
"access": "public",
diff --git a/packages/board/src/index.ts b/packages/core/src/board/index.ts
similarity index 95%
rename from packages/board/src/index.ts
rename to packages/core/src/board/index.ts
index 48efe2e..b4628b1 100644
--- a/packages/board/src/index.ts
+++ b/packages/core/src/board/index.ts
@@ -1,4 +1,4 @@
-import { Renderer } from '@idraw/renderer';
+import { Renderer, Calculator } from '@idraw/renderer';
import {
// throttle,
calcElementsContextSize,
@@ -16,10 +16,9 @@ import type {
UtilEventEmitter,
ModifyOptions
} from '@idraw/types';
-import { Calculator } from './lib/calculator';
-import { BoardWatcher } from './lib/watcher';
-import { Sharer } from './lib/sharer';
-import { Viewer } from './lib/viewer';
+import { BoardWatcher } from './watcher';
+import { Sharer } from './sharer';
+import { Viewer } from './viewer';
// const throttleTime = 10; // ms
@@ -44,16 +43,17 @@ export class Board {
constructor(opts: BoardOptions) {
const { boardContent } = opts;
const sharer = new Sharer();
- const calculator = new Calculator({ viewContext: boardContent.viewContext });
+
const watcher = new BoardWatcher({
boardContent,
sharer
});
const renderer = new Renderer({
viewContext: boardContent.viewContext,
- sharer,
- calculator
+ tempContext: boardContent.tempContext,
+ sharer
});
+ const calculator = renderer.getCalculator();
this.#opts = opts;
this.#sharer = sharer;
@@ -331,12 +331,12 @@ export class Board {
extend: true
});
if (modifiedOptions) {
- this.#viewer.resetViewVisibleInfoMap(data, {
+ this.#viewer.resetVirtualFlatItemMap(data, {
viewSizeInfo,
viewScaleInfo
});
} else {
- this.#viewer.resetViewVisibleInfoMap(data, {
+ this.#viewer.resetVirtualFlatItemMap(data, {
viewSizeInfo,
viewScaleInfo
});
@@ -374,7 +374,10 @@ export class Board {
const calculator = this.#calculator;
const eventHub = this.#eventHub;
- const obj = middleware({ boardContent, sharer, viewer, calculator, eventHub: eventHub as UtilEventEmitter, container }, config);
+ const obj = middleware(
+ { boardContent, sharer, viewer, calculator, eventHub: eventHub as UtilEventEmitter, container },
+ config
+ );
obj.use?.();
this.#middlewares.push(middleware);
this.#activeMiddlewareObjs.push(obj);
diff --git a/packages/board/src/lib/sharer.ts b/packages/core/src/board/sharer.ts
similarity index 100%
rename from packages/board/src/lib/sharer.ts
rename to packages/core/src/board/sharer.ts
diff --git a/packages/board/src/lib/viewer.ts b/packages/core/src/board/viewer.ts
similarity index 93%
rename from packages/board/src/lib/viewer.ts
rename to packages/core/src/board/viewer.ts
index e57242e..3385547 100644
--- a/packages/board/src/lib/viewer.ts
+++ b/packages/core/src/board/viewer.ts
@@ -45,7 +45,18 @@ export class Viewer extends EventEmitter implements BoardVi
const { renderer, boardContent, beforeDrawFrame, afterDrawFrame } = this.#opts;
if (snapshot) {
- const { scale, offsetTop, offsetBottom, offsetLeft, offsetRight, width, height, contextHeight, contextWidth, devicePixelRatio } = snapshot.activeStore;
+ const {
+ scale,
+ offsetTop,
+ offsetBottom,
+ offsetLeft,
+ offsetRight,
+ width,
+ height,
+ contextHeight,
+ contextWidth,
+ devicePixelRatio
+ } = snapshot.activeStore;
const viewScaleInfo: ViewScaleInfo = {
scale,
@@ -86,7 +97,7 @@ export class Viewer extends EventEmitter implements BoardVi
}
}
- resetViewVisibleInfoMap(
+ resetVirtualFlatItemMap(
data: Data,
opts: {
viewScaleInfo: ViewScaleInfo;
@@ -94,7 +105,7 @@ export class Viewer extends EventEmitter implements BoardVi
}
): void {
if (data) {
- this.#opts.calculator.resetViewVisibleInfoMap(data, opts);
+ this.#opts.calculator.resetVirtualFlatItemMap(data, opts);
}
}
@@ -111,7 +122,10 @@ export class Viewer extends EventEmitter implements BoardVi
this.#drawAnimationFrame();
}
- scale(opts: { scale: number; point: PointSize; ignoreUpdateVisibleStatus?: boolean }): { moveX: number; moveY: number } {
+ scale(opts: { scale: number; point: PointSize; ignoreUpdateVisibleStatus?: boolean }): {
+ moveX: number;
+ moveY: number;
+ } {
const { scale, point, ignoreUpdateVisibleStatus } = opts;
const { sharer } = this.#opts;
const { moveX, moveY } = viewScale({
diff --git a/packages/board/src/lib/watcher.ts b/packages/core/src/board/watcher.ts
similarity index 89%
rename from packages/board/src/lib/watcher.ts
rename to packages/core/src/board/watcher.ts
index 2529ff9..1dbcfac 100644
--- a/packages/board/src/lib/watcher.ts
+++ b/packages/core/src/board/watcher.ts
@@ -1,4 +1,12 @@
-import type { Point, BoardWatcherEventMap, Data, Element, ElementType, BoardWatcherOptions, BoardWatcherStore } from '@idraw/types';
+import type {
+ Point,
+ BoardWatcherEventMap,
+ Data,
+ Element,
+ ElementType,
+ BoardWatcherOptions,
+ BoardWatcherStore
+} from '@idraw/types';
import { EventEmitter, Store } from '@idraw/util';
function isBoardAvailableNum(num: any): boolean {
@@ -11,7 +19,9 @@ export class BoardWatcher extends EventEmitter {
#hasDestroyed: boolean = false;
constructor(opts: BoardWatcherOptions) {
super();
- const store = new Store({ defaultStorage: { hasPointDown: false, prevClickPoint: null, inCanvas: true } });
+ const store = new Store({
+ defaultStorage: { hasPointDown: false, prevClickPoint: null, inCanvas: true }
+ });
this.#store = store;
this.#opts = opts;
this.#init();
@@ -25,25 +35,27 @@ export class BoardWatcher extends EventEmitter {
if (this.#hasDestroyed) {
return;
}
+ const canvas = this.#opts.boardContent.boardContext.canvas;
const container = window;
container.addEventListener('mousemove', this.#onHover);
container.addEventListener('mousedown', this.#onPointStart);
container.addEventListener('mousemove', this.#onPointMove);
container.addEventListener('mouseup', this.#onPointEnd);
// container.addEventListener('mouseleave', this.#onPointLeave);
- container.addEventListener('wheel', this.#onWheel, { passive: false });
+ canvas.addEventListener('wheel', this.#onWheel, { passive: false });
container.addEventListener('click', this.#onClick);
container.addEventListener('contextmenu', this.#onContextMenu);
}
offEvents() {
const container = window;
+ const canvas = this.#opts.boardContent.boardContext.canvas;
container.removeEventListener('mousemove', this.#onHover);
container.removeEventListener('mousedown', this.#onPointStart);
container.removeEventListener('mousemove', this.#onPointMove);
container.removeEventListener('mouseup', this.#onPointEnd);
container.removeEventListener('mouseleave', this.#onPointLeave);
- container.removeEventListener('wheel', this.#onWheel);
+ canvas.removeEventListener('wheel', this.#onWheel);
container.removeEventListener('click', this.#onClick);
container.removeEventListener('contextmenu', this.#onContextMenu);
}
@@ -101,7 +113,12 @@ export class BoardWatcher extends EventEmitter {
const maxLimitTime = 500;
const t = Date.now();
const preClickPoint = this.#store.get('prevClickPoint');
- if (preClickPoint && t - preClickPoint.t <= maxLimitTime && Math.abs(preClickPoint.x - point.x) <= 5 && Math.abs(preClickPoint.y - point.y) <= 5) {
+ if (
+ preClickPoint &&
+ t - preClickPoint.t <= maxLimitTime &&
+ Math.abs(preClickPoint.x - point.x) <= 5 &&
+ Math.abs(preClickPoint.y - point.y) <= 5
+ ) {
this.trigger('doubleClick', { point });
} else {
this.#store.set('prevClickPoint', point);
diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts
index a152150..d220792 100644
--- a/packages/core/src/config.ts
+++ b/packages/core/src/config.ts
@@ -3,6 +3,7 @@ export const EVENT_KEY_CURSOR = 'cursor';
export const EVENT_KEY_RULER = 'ruler';
export const EVENT_KEY_SCALE = 'scale';
export const EVENT_KEY_SELECT = 'select';
+export const EVENT_KEY_SELECT_LAYOUT = 'selectLayout';
export const EVENT_KEY_CLEAR_SELECT = 'clearSelect';
export const EVENT_KEY_TEXT_EDIT = 'textEdit';
export const EVENT_KEY_TEXT_CHANGE = 'textChange';
@@ -16,6 +17,7 @@ export type CoreEventKeys = {
RULER: typeof EVENT_KEY_RULER;
SCALE: typeof EVENT_KEY_SCALE;
SELECT: typeof EVENT_KEY_SELECT;
+ SELECT_LAYOUT: typeof EVENT_KEY_SELECT_LAYOUT;
CLEAR_SELECT: typeof EVENT_KEY_CLEAR_SELECT;
TEXT_EDIT: typeof EVENT_KEY_TEXT_EDIT;
TEXT_CHANGE: typeof EVENT_KEY_TEXT_CHANGE;
@@ -29,6 +31,7 @@ const innerEventKeys: CoreEventKeys = {
CHANGE: EVENT_KEY_CHANGE,
RULER: EVENT_KEY_RULER,
SCALE: EVENT_KEY_SCALE,
+ SELECT_LAYOUT: EVENT_KEY_SELECT_LAYOUT,
SELECT: EVENT_KEY_SELECT,
CLEAR_SELECT: EVENT_KEY_CLEAR_SELECT,
TEXT_EDIT: EVENT_KEY_TEXT_EDIT,
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index f3c16d4..a6a82c2 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -1,10 +1,22 @@
-import type { Data, PointSize, CoreOptions, BoardMiddleware, ViewSizeInfo, CoreEventMap, ViewScaleInfo, LoadItemMap, ModifyOptions } from '@idraw/types';
-import { Board } from '@idraw/board';
+import type {
+ Data,
+ PointSize,
+ CoreOptions,
+ BoardMiddleware,
+ ViewSizeInfo,
+ CoreEventMap,
+ ViewScaleInfo,
+ LoadItemMap,
+ ModifyOptions
+} from '@idraw/types';
+import { Board, Sharer, Calculator } from './board';
import { createBoardContent, validateElements } from '@idraw/util';
import { Cursor } from './lib/cursor';
export { coreEventKeys } from './config';
export type { CoreEventKeys } from './config';
+export { Board, Sharer, Calculator };
+
// export { MiddlewareSelector } from './middleware/selector';
export { MiddlewareSelector } from './middleware/selector';
export { MiddlewareScroller } from './middleware/scroller';
@@ -23,7 +35,7 @@ export class Core {
#container: HTMLDivElement;
constructor(container: HTMLDivElement, opts: CoreOptions) {
- const { devicePixelRatio = 1, width, height, createCustomContext2D } = opts;
+ const { devicePixelRatio = 1, width, height } = opts;
// this.#opts = opts;
this.#container = container;
@@ -33,7 +45,7 @@ export class Core {
this.#initContainer();
container.appendChild(canvas);
- const boardContent = createBoardContent(canvas, { width, height, devicePixelRatio, offscreen: true, createCustomContext2D });
+ const boardContent = createBoardContent(canvas, { width, height, devicePixelRatio });
const board = new Board({ boardContent, container });
const sharer = board.getSharer();
sharer.setActiveViewSizeInfo({
diff --git a/packages/core/src/middleware/layout-selector/index.ts b/packages/core/src/middleware/layout-selector/index.ts
index ea49106..89ee133 100644
--- a/packages/core/src/middleware/layout-selector/index.ts
+++ b/packages/core/src/middleware/layout-selector/index.ts
@@ -1,5 +1,11 @@
import type { BoardMiddleware, ElementSize, Point, MiddlewareLayoutSelectorConfig, CoreEventMap } from '@idraw/types';
-import { calcLayoutSizeController, isViewPointInVertexes, getViewScaleInfoFromSnapshot, isViewPointInElementSize, calcViewElementSize } from '@idraw/util';
+import {
+ calcLayoutSizeController,
+ isViewPointInVertexes,
+ getViewScaleInfoFromSnapshot,
+ isViewPointInElementSize,
+ calcViewElementSize
+} from '@idraw/util';
import type { LayoutSelectorSharedStorage, ControlType } from './types';
import {
keyLayoutActionType,
@@ -21,7 +27,11 @@ import { coreEventKeys } from '../../config';
export { keyLayoutIsSelected, keyLayoutIsBusyMoving };
-export const MiddlewareLayoutSelector: BoardMiddleware = (opts, config) => {
+export const MiddlewareLayoutSelector: BoardMiddleware<
+ LayoutSelectorSharedStorage,
+ CoreEventMap,
+ MiddlewareLayoutSelectorConfig
+> = (opts, config) => {
const { sharer, boardContent, calculator, viewer, eventHub } = opts;
const { overlayContext } = boardContent;
let innerConfig = {
@@ -242,6 +252,7 @@ export const MiddlewareLayoutSelector: BoardMiddleware elem.uuid);
const data = sharer.getActiveStorage('data');
const positionMap = getElementPositionMapFromList(uuids, data?.elements || []);
- eventHub.trigger(coreEventKeys.SELECT, { uuids, positions: list.map((elem) => [...positionMap[elem.uuid]]) });
+ eventHub.trigger(coreEventKeys.SELECT, {
+ type: 'clickCanvas',
+ uuids,
+ positions: list.map((elem) => [...positionMap[elem.uuid]])
+ });
}
};
@@ -515,7 +522,14 @@ export const MiddlewareSelector: BoardMiddleware<
eventHub.trigger(MIDDLEWARE_INTERNAL_EVENT_SHOW_INFO_ANGLE, { show: false });
- if (data && elems?.length === 1 && moveOriginalStartElementSize && originalStart && end && elems[0]?.operations?.locked !== true) {
+ if (
+ data &&
+ elems?.length === 1 &&
+ moveOriginalStartElementSize &&
+ originalStart &&
+ end &&
+ elems[0]?.operations?.locked !== true
+ ) {
const { moveX, moveY } = calcPointMoveElementInGroup(originalStart, end, groupQueue);
let totalMoveX = calculator.toGridNum(moveX / scale);
@@ -547,7 +561,7 @@ export const MiddlewareSelector: BoardMiddleware<
elems[0].x = calculator.toGridNum(moveOriginalStartElementSize.x + totalMoveX);
elems[0].y = calculator.toGridNum(moveOriginalStartElementSize.y + totalMoveY);
updateSelectedElementList([elems[0]]);
- calculator.modifyViewVisibleInfoMap(data, {
+ calculator.modifyVirtualFlatItemMap(data, {
modifyOptions: {
type: 'updateElement',
content: {
@@ -571,7 +585,7 @@ export const MiddlewareSelector: BoardMiddleware<
elem.x = calculator.toGridNum(elem.x + moveX);
elem.y = calculator.toGridNum(elem.y + moveY);
- calculator.modifyViewVisibleInfoMap(data, {
+ calculator.modifyVirtualFlatItemMap(data, {
modifyOptions: {
type: 'updateElement',
content: {
@@ -589,7 +603,13 @@ export const MiddlewareSelector: BoardMiddleware<
}
viewer.drawFrame();
} else if (actionType === 'resize') {
- if (data && elems?.length === 1 && originalStart && moveOriginalStartElementSize && resizeType?.startsWith('resize-')) {
+ if (
+ data &&
+ elems?.length === 1 &&
+ originalStart &&
+ moveOriginalStartElementSize &&
+ resizeType?.startsWith('resize-')
+ ) {
hasChangedData = true;
inBusyMode = 'resize';
const pointGroupQueue: Element<'group'>[] = [];
@@ -612,7 +632,9 @@ export const MiddlewareSelector: BoardMiddleware<
resizeEnd = rotatePointInGroup(end, pointGroupQueue);
}
if (resizeType === 'resize-rotate') {
- const controller: ElementSizeController = sharer.getSharedStorage(keySelectedElementController) as ElementSizeController;
+ const controller: ElementSizeController = sharer.getSharedStorage(
+ keySelectedElementController
+ ) as ElementSizeController;
const viewVertexes: ViewRectVertexes = [
controller.topLeft.center,
controller.topRight.center,
@@ -633,7 +655,10 @@ export const MiddlewareSelector: BoardMiddleware<
elems[0].angle = calculator.toGridNum(resizedElemSize.angle || 0);
} else {
- const resizedElemSize = resizeElement(moveOriginalStartElementSize, { scale, start: resizeStart, end: resizeEnd, resizeType, sharer });
+ const resizedElemSize = resizeElement(
+ { ...moveOriginalStartElementSize, operations: elems[0].operations },
+ { scale, start: resizeStart, end: resizeEnd, resizeType, sharer }
+ );
const calcOpts = { ignore: !!moveOriginalStartElementSize.angle };
elems[0].x = calculator.toGridNum(resizedElemSize.x, calcOpts);
elems[0].y = calculator.toGridNum(resizedElemSize.y, calcOpts);
@@ -649,7 +674,7 @@ export const MiddlewareSelector: BoardMiddleware<
}
updateSelectedElementList([elems[0]]);
- calculator.modifyViewVisibleInfoMap(data, {
+ calculator.modifyVirtualFlatItemMap(data, {
modifyOptions: {
type: 'updateElement',
content: {
@@ -788,11 +813,18 @@ export const MiddlewareSelector: BoardMiddleware<
viewer.drawFrame();
return;
}
- } else if (target.elements.length === 1 && target.elements[0]?.type === 'text' && !target.elements[0]?.operations?.invisible) {
+ } else if (
+ target.elements.length === 1 &&
+ target.elements[0]?.type === 'text' &&
+ !target.elements[0]?.operations?.invisible
+ ) {
eventHub.trigger(coreEventKeys.TEXT_EDIT, {
element: target.elements[0] as Element<'text'>,
groupQueue: sharer.getSharedStorage(keyGroupQueue) || [],
- position: getElementPositionFromList(target.elements[0]?.uuid, sharer.getActiveStorage('data')?.elements || []),
+ position: getElementPositionFromList(
+ target.elements[0]?.uuid,
+ sharer.getActiveStorage('data')?.elements || []
+ ),
viewScaleInfo: sharer.getActiveViewScaleInfo()
});
}
@@ -858,7 +890,18 @@ export const MiddlewareSelector: BoardMiddleware<
const style = { activeColor, activeAreaColor, lockedColor, referenceColor };
const { activeStore, sharedStore } = snapshot;
- const { scale, offsetLeft, offsetTop, offsetRight, offsetBottom, width, height, contextHeight, contextWidth, devicePixelRatio } = activeStore;
+ const {
+ scale,
+ offsetLeft,
+ offsetTop,
+ offsetRight,
+ offsetBottom,
+ width,
+ height,
+ contextHeight,
+ contextWidth,
+ devicePixelRatio
+ } = activeStore;
if (rotateControllerPattern.fill !== activeColor) {
rotateControllerPattern = createRotateControllerPattern({
fill: innerConfig.activeColor,
diff --git a/packages/core/src/middleware/selector/util.ts b/packages/core/src/middleware/selector/util.ts
index 0409134..fd480a8 100644
--- a/packages/core/src/middleware/selector/util.ts
+++ b/packages/core/src/middleware/selector/util.ts
@@ -11,7 +11,14 @@ import {
limitAngle,
calcRadian
} from '@idraw/util';
-import type { ViewRectVertexes, ElementSizeController, StoreSharer, ViewScaleInfo, ViewSizeInfo } from '@idraw/types';
+import type {
+ ViewRectVertexes,
+ ElementSizeController,
+ StoreSharer,
+ ViewScaleInfo,
+ ViewSizeInfo,
+ ElementOperations
+} from '@idraw/types';
import type {
Data,
Element,
@@ -65,7 +72,12 @@ export function isPointInViewActiveVertexes(
export function isPointInViewActiveGroup(
p: PointSize,
- opts: { ctx: ViewContext2D; viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo; groupQueue: Element<'group'>[] | null }
+ opts: {
+ ctx: ViewContext2D;
+ viewScaleInfo: ViewScaleInfo;
+ viewSizeInfo: ViewSizeInfo;
+ groupQueue: Element<'group'>[] | null;
+ }
): boolean {
const { ctx, viewScaleInfo, viewSizeInfo, groupQueue } = opts;
if (!groupQueue || !(groupQueue?.length > 0)) {
@@ -100,7 +112,17 @@ export function getPointTarget(
groupQueue: [],
groupQueueVertexesList: []
};
- const { ctx, data, calculator, selectedElements, viewScaleInfo, viewSizeInfo, areaSize, groupQueue, selectedElementController } = opts;
+ const {
+ ctx,
+ data,
+ calculator,
+ selectedElements,
+ viewScaleInfo,
+ viewSizeInfo,
+ areaSize,
+ groupQueue,
+ selectedElementController
+ } = opts;
// resize
if (selectedElementController) {
@@ -174,7 +196,7 @@ export function getPointTarget(
}
export function resizeElement(
- elem: ElementSize,
+ elem: ElementSize & { operations?: ElementOperations },
opts: {
start: PointSize;
end: PointSize;
@@ -260,7 +282,9 @@ export function resizeElement(
const maxHorizontalDist = Math.max(Math.abs(moveHorizontalX), Math.abs(moveHorizontalY));
moveHorizontalX = (moveHorizontalX >= 0 ? 1 : -1) * maxHorizontalDist;
moveHorizontalY = (((moveHorizontalY >= 0 ? 1 : -1) * maxHorizontalDist) / elem.w) * elem.h;
- } else if (['resize-top-left', 'resize-top-right', 'resize-bottom-left', 'resize-bottom-right'].includes(resizeType)) {
+ } else if (
+ ['resize-top-left', 'resize-top-right', 'resize-bottom-left', 'resize-bottom-right'].includes(resizeType)
+ ) {
{
// const maxDist = Math.max(Math.abs(moveX), Math.abs(moveY));
const maxDist = Math.abs(moveX);
@@ -533,7 +557,8 @@ export function resizeElement(
if (angle < 90) {
moveVerticalDist = 0 - changeMoveDistDirect(moveVerticalDist, moveVerticalY);
- moveHorizontalDist = 0 - changeMoveDistDirect(moveHorizontalDist, limitRatio ? 0 - moveVerticalDist : moveHorizontalX);
+ moveHorizontalDist =
+ 0 - changeMoveDistDirect(moveHorizontalDist, limitRatio ? 0 - moveVerticalDist : moveHorizontalX);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX + centerMoveVerticalDist * Math.sin(radian);
@@ -544,7 +569,10 @@ export function resizeElement(
centerY = centerY - centerMoveHorizontalDist * Math.sin(radian);
} else if (angle < 180) {
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalX);
- moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, limitRatio ? moveVerticalDist : moveHorizontalX);
+ moveHorizontalDist = changeMoveDistDirect(
+ moveHorizontalDist,
+ limitRatio ? moveVerticalDist : moveHorizontalX
+ );
const radian = parseRadian(angle - 90);
const centerMoveVerticalDist = moveVerticalDist / 2;
@@ -556,7 +584,10 @@ export function resizeElement(
centerY = centerY - centerMoveDist * Math.cos(radian);
} else if (angle < 270) {
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalY);
- moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, limitRatio ? moveVerticalDist : moveHorizontalY);
+ moveHorizontalDist = changeMoveDistDirect(
+ moveHorizontalDist,
+ limitRatio ? moveVerticalDist : moveHorizontalY
+ );
const radian = parseRadian(angle - 180);
const centerMoveVerticalDist = moveVerticalDist / 2;
@@ -568,7 +599,10 @@ export function resizeElement(
centerY = centerY + centerMoveHorizontalDist * Math.sin(radian);
} else if (angle < 360) {
moveVerticalDist = 0 - changeMoveDistDirect(moveVerticalDist, moveVerticalX);
- moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, limitRatio ? moveVerticalDist : moveHorizontalY);
+ moveHorizontalDist = changeMoveDistDirect(
+ moveHorizontalDist,
+ limitRatio ? moveVerticalDist : moveHorizontalY
+ );
const radian = parseRadian(angle - 270);
const centerMoveVerticalDist = moveVerticalDist / 2;
@@ -604,7 +638,10 @@ export function resizeElement(
let centerY = elemCenter.y;
if (angle < 90) {
moveVerticalDist = 0 - changeMoveDistDirect(moveVerticalDist, moveVerticalY);
- moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, limitRatio ? moveVerticalDist : moveHorizontalY);
+ moveHorizontalDist = changeMoveDistDirect(
+ moveHorizontalDist,
+ limitRatio ? moveVerticalDist : moveHorizontalY
+ );
const radian = parseRadian(angle);
const centerMoveVerticalDist = moveVerticalDist / 2;
@@ -616,7 +653,10 @@ export function resizeElement(
centerY = centerY + centerMoveHorizontalDist * Math.sin(radian);
} else if (angle < 180) {
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalX);
- moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, limitRatio ? moveVerticalDist : moveHorizontalY);
+ moveHorizontalDist = changeMoveDistDirect(
+ moveHorizontalDist,
+ limitRatio ? moveVerticalDist : moveHorizontalY
+ );
const radian = parseRadian(angle - 90);
const centerMoveVerticalDist = moveVerticalDist / 2;
@@ -629,7 +669,10 @@ export function resizeElement(
} else if (angle < 270) {
const radian = parseRadian(angle - 180);
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalY);
- moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, limitRatio ? moveVerticalDist : 0 - moveHorizontalX);
+ moveHorizontalDist = changeMoveDistDirect(
+ moveHorizontalDist,
+ limitRatio ? moveVerticalDist : 0 - moveHorizontalX
+ );
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX - centerMoveVerticalDist * Math.sin(radian);
centerY = centerY + centerMoveVerticalDist * Math.cos(radian);
@@ -639,7 +682,10 @@ export function resizeElement(
centerY = centerY - centerMoveHorizontalDist * Math.sin(radian);
} else if (angle < 360) {
moveVerticalDist = 0 - changeMoveDistDirect(moveVerticalDist, moveVerticalX);
- moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, limitRatio ? moveVerticalDist : moveHorizontalX);
+ moveHorizontalDist = changeMoveDistDirect(
+ moveHorizontalDist,
+ limitRatio ? moveVerticalDist : moveHorizontalX
+ );
const radian = parseRadian(angle - 270);
const centerMoveVerticalDist = moveVerticalDist / 2;
@@ -675,7 +721,8 @@ export function resizeElement(
let centerY = elemCenter.y;
if (angle < 90) {
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalY);
- moveHorizontalDist = 0 - changeMoveDistDirect(moveHorizontalDist, limitRatio ? 0 - moveVerticalDist : moveHorizontalX);
+ moveHorizontalDist =
+ 0 - changeMoveDistDirect(moveHorizontalDist, limitRatio ? 0 - moveVerticalDist : moveHorizontalX);
const radian = parseRadian(angle);
const centerMoveVerticalDist = moveVerticalDist / 2;
@@ -687,7 +734,10 @@ export function resizeElement(
centerY = centerY - centerMoveHorizontalDist * Math.sin(radian);
} else if (angle < 180) {
moveVerticalDist = 0 - changeMoveDistDirect(moveVerticalDist, moveVerticalX);
- moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, limitRatio ? moveVerticalDist : moveHorizontalX);
+ moveHorizontalDist = changeMoveDistDirect(
+ moveHorizontalDist,
+ limitRatio ? moveVerticalDist : moveHorizontalX
+ );
const radian = parseRadian(angle - 90);
const centerMoveVerticalDist = moveVerticalDist / 2;
@@ -699,7 +749,10 @@ export function resizeElement(
centerY = centerY - centerMoveDist * Math.cos(radian);
} else if (angle < 270) {
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalX);
- moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, limitRatio ? moveVerticalDist : moveHorizontalY);
+ moveHorizontalDist = changeMoveDistDirect(
+ moveHorizontalDist,
+ limitRatio ? moveVerticalDist : moveHorizontalY
+ );
const radian = parseRadian(angle - 180);
const centerMoveVerticalDist = moveVerticalDist / 2;
@@ -711,7 +764,10 @@ export function resizeElement(
centerY = centerY + centerMoveHorizontalDist * Math.sin(radian);
} else if (angle < 360) {
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalX);
- moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, limitRatio ? moveVerticalDist : moveHorizontalY);
+ moveHorizontalDist = changeMoveDistDirect(
+ moveHorizontalDist,
+ limitRatio ? moveVerticalDist : moveHorizontalY
+ );
const radian = parseRadian(angle - 270);
const centerMoveDist = moveVerticalDist / 2;
centerX = centerX + centerMoveDist * Math.cos(radian);
@@ -745,7 +801,10 @@ export function resizeElement(
let centerY = elemCenter.y;
if (angle < 90) {
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalY);
- moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, limitRatio ? moveVerticalDist : moveHorizontalY);
+ moveHorizontalDist = changeMoveDistDirect(
+ moveHorizontalDist,
+ limitRatio ? moveVerticalDist : moveHorizontalY
+ );
const radian = parseRadian(angle);
const centerMoveVerticalDist = moveVerticalDist / 2;
@@ -769,7 +828,10 @@ export function resizeElement(
centerY = centerY + centerMoveHorizontalDist * Math.cos(radian);
} else if (angle < 270) {
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalX);
- moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, limitRatio ? moveVerticalDist : 0 - moveHorizontalY);
+ moveHorizontalDist = changeMoveDistDirect(
+ moveHorizontalDist,
+ limitRatio ? moveVerticalDist : 0 - moveHorizontalY
+ );
const radian = parseRadian(angle - 180);
const centerMoveVerticalDist = moveVerticalDist / 2;
@@ -781,7 +843,10 @@ export function resizeElement(
centerY = centerY - centerMoveHorizontalDist * Math.sin(radian);
} else if (angle < 360) {
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalX);
- moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, limitRatio ? moveVerticalDist : moveHorizontalX);
+ moveHorizontalDist = changeMoveDistDirect(
+ moveHorizontalDist,
+ limitRatio ? moveVerticalDist : moveHorizontalX
+ );
const radian = parseRadian(angle - 270);
const centerMoveDist = moveVerticalDist / 2;
@@ -865,7 +930,7 @@ export function getSelectedListArea(
const indexes: number[] = [];
const uuids: string[] = [];
const elements: Element[] = [];
- const { viewScaleInfo, viewSizeInfo, start, end } = opts;
+ const { viewScaleInfo, start, end } = opts;
if (!(Array.isArray(data.elements) && start && end)) {
return { indexes, uuids, elements };
diff --git a/packages/figma/package.json b/packages/figma/package.json
index 9c3c977..cf5be46 100644
--- a/packages/figma/package.json
+++ b/packages/figma/package.json
@@ -1,6 +1,6 @@
{
"name": "@idraw/figma",
- "version": "0.4.0-beta.39",
+ "version": "0.4.0-beta.40",
"description": "",
"main": "dist/esm/index.js",
"module": "dist/esm/index.js",
@@ -11,8 +11,8 @@
"dist/**/*.js"
],
"dependencies": {
- "@idraw/types": "workspace:^0.4.0-beta.39",
- "@idraw/util": "workspace:^0.4.0-beta.39",
+ "@idraw/types": "workspace:^0.4.0-beta.40",
+ "@idraw/util": "workspace:^0.4.0-beta.40",
"kiwi-schema": "^0.5.0",
"matrix-inverse": "^2.0.0",
"pako": "^2.1.0",
@@ -20,7 +20,7 @@
},
"devDependencies": {
"@types/pako": "^2.0.3",
- "@idraw/types": "workspace:^0.4.0-beta.39"
+ "@idraw/types": "workspace:^0.4.0-beta.40"
},
"repository": {
"type": "git",
@@ -30,7 +30,7 @@
"url": "https://github.com/idrawjs/idraw/issues"
},
"homepage": "https://github.com/idrawjs/idraw#readme",
- "author": "chenshenhai",
+ "author": "idrawjs",
"license": "MIT",
"publishConfig": {
"access": "public",
diff --git a/packages/idraw/package.json b/packages/idraw/package.json
index 155ffb0..81395fc 100644
--- a/packages/idraw/package.json
+++ b/packages/idraw/package.json
@@ -1,6 +1,6 @@
{
"name": "idraw",
- "version": "0.4.0-beta.39",
+ "version": "0.4.0-beta.40",
"description": "",
"main": "dist/esm/index.js",
"module": "dist/esm/index.js",
@@ -18,15 +18,14 @@
"url": "https://github.com/idrawjs/idraw/issues"
},
"homepage": "https://github.com/idrawjs/idraw#readme",
- "author": "chenshenhai",
+ "author": "idrawjs",
"license": "MIT",
"devDependencies": {},
"dependencies": {
- "@idraw/board": "workspace:^0.4.0-beta.39",
- "@idraw/core": "workspace:^0.4.0-beta.39",
- "@idraw/renderer": "workspace:^0.4.0-beta.39",
- "@idraw/types": "workspace:^0.4.0-beta.39",
- "@idraw/util": "workspace:^0.4.0-beta.39"
+ "@idraw/core": "workspace:^0.4.0-beta.40",
+ "@idraw/renderer": "workspace:^0.4.0-beta.40",
+ "@idraw/types": "workspace:^0.4.0-beta.40",
+ "@idraw/util": "workspace:^0.4.0-beta.40"
},
"publishConfig": {
"access": "public",
diff --git a/packages/idraw/src/file.ts b/packages/idraw/src/file.ts
index 5d733ee..fbf5379 100644
--- a/packages/idraw/src/file.ts
+++ b/packages/idraw/src/file.ts
@@ -1,5 +1,4 @@
import { Renderer } from '@idraw/renderer';
-import { Calculator } from '@idraw/board';
import { createOffscreenContext2D } from '@idraw/util';
import type { Data, LoadItemMap, ViewContext2D, ViewScaleInfo, ViewSizeInfo } from '@idraw/types';
@@ -26,10 +25,9 @@ export type ExportImageFileResult = {
export async function exportImageFileBlobURL(opts: ExportImageFileOptions): Promise {
const { data, width, height, devicePixelRatio, viewScaleInfo, viewSizeInfo, loadItemMap } = opts;
let viewContext: ViewContext2D | null = createOffscreenContext2D({ width, height, devicePixelRatio });
- let calculator: Calculator | null = new Calculator({ viewContext });
+ // let calculator: Calculator | null = new Calculator({ viewContext });
let renderer: Renderer | null = new Renderer({
- viewContext,
- calculator
+ viewContext
});
renderer.setLoadItemMap(loadItemMap);
renderer.drawData(data, {
@@ -46,7 +44,6 @@ export async function exportImageFileBlobURL(opts: ExportImageFileOptions): Prom
offScreenCanvas = null;
viewContext = null;
- calculator = null;
renderer = null;
return {
diff --git a/packages/idraw/src/idraw.ts b/packages/idraw/src/idraw.ts
index 957fcdc..c17bcc8 100644
--- a/packages/idraw/src/idraw.ts
+++ b/packages/idraw/src/idraw.ts
@@ -12,7 +12,8 @@ import type {
Element,
RecursivePartial,
ElementPosition,
- IDrawStorage
+ IDrawStorage,
+ DataLayout
} from '@idraw/types';
import {
createElement,
@@ -25,9 +26,17 @@ import {
filterCompactData,
calcViewCenterContent,
calcViewCenter,
- Store
+ Store,
+ merge
} from '@idraw/util';
-import { defaultSettings, getDefaultStorage, defaultMode, parseStyles, parseSettings } from './setting/config';
+import {
+ defaultSettings,
+ defaultOptions,
+ getDefaultStorage,
+ defaultMode,
+ parseStyles,
+ parseSettings
+} from './setting/config';
import { exportImageFileBlobURL } from './file';
import type { ExportImageFileBaseOptions, ExportImageFileResult } from './file';
import type { IDrawEvent } from './event';
@@ -42,10 +51,10 @@ export class iDraw {
});
constructor(mount: HTMLDivElement, options: IDrawOptions) {
- const opts = { ...defaultSettings, ...options };
+ const opts = { ...defaultSettings, ...defaultOptions, ...options };
this.#store.set('middlewareStyles', parseStyles(opts));
- const { width, height, devicePixelRatio, createCustomContext2D } = opts;
- const core = new Core(mount, { width, height, devicePixelRatio, createCustomContext2D });
+ const { width, height, devicePixelRatio } = opts;
+ const core = new Core(mount, { width, height, devicePixelRatio });
this.#core = core;
this.#opts = opts;
this.#init();
@@ -85,7 +94,7 @@ export class iDraw {
const store = this.#store;
const { mode, styles } = parseSettings(opts);
let needFresh = false;
- let newOpts: IDrawSettings = {};
+ const newOpts: IDrawSettings = {};
store.clear();
if (mode) {
changeMode(mode, core, store);
@@ -181,20 +190,20 @@ export class iDraw {
this.#core.trigger(name, e as IDrawEvent[T]);
}
- selectElement(uuid: string) {
- this.selectElements([uuid]);
+ selectElement(uuid: string, opts?: { type?: string }) {
+ this.trigger(coreEventKeys.SELECT, { uuids: [uuid], type: opts?.type || 'selectElement' });
}
- selectElements(uuids: string[]) {
- this.trigger(coreEventKeys.SELECT, { uuids });
+ selectElements(uuids: string[], opts?: { type?: string }) {
+ this.trigger(coreEventKeys.SELECT, { uuids, type: opts?.type || 'selectElements' });
}
- selectElementByPosition(position: ElementPosition) {
- this.selectElementsByPositions([position]);
+ selectElementByPosition(position: ElementPosition, opts?: { type?: string }) {
+ this.trigger(coreEventKeys.SELECT, { positions: [position], type: opts?.type || 'selectElementByPosition' });
}
- selectElementsByPositions(positions: ElementPosition[]) {
- this.trigger(coreEventKeys.SELECT, { positions });
+ selectElementsByPositions(positions: ElementPosition[], opts?: { type?: string }) {
+ this.trigger(coreEventKeys.SELECT, { positions, type: opts?.type || 'selectElementsByPositions' });
}
cancelElements() {
@@ -230,6 +239,14 @@ export class iDraw {
core.trigger(coreEventKeys.CHANGE, { data, type: 'updateElement' });
}
+ updateElementName(uuid: string, name: string) {
+ const core = this.#core;
+ const data: Data = core.getData() || { elements: [] };
+ updateElementInList(uuid, { name }, data.elements);
+ core.setData(data);
+ core.trigger(coreEventKeys.CHANGE, { data, type: 'updateElementName' });
+ }
+
addElement(
element: Element,
opts?: {
@@ -241,7 +258,7 @@ export class iDraw {
if (!opts || !opts?.position?.length) {
data.elements.push(element);
} else if (opts?.position) {
- const position = [...opts?.position];
+ const position = [...(opts?.position || [])];
insertElementToListByPosition(element, position, data.elements);
}
core.setData(data);
@@ -270,6 +287,15 @@ export class iDraw {
core.trigger(coreEventKeys.CHANGE, { data, type: 'moveElement' });
}
+ updateLayout(layout: Partial) {
+ const core = this.#core;
+ const data: Data = core.getData() || { elements: [] };
+ data.layout = merge(data.layout || {}, layout) as DataLayout;
+ core.setData(data);
+ core.refresh();
+ core.trigger(coreEventKeys.CHANGE, { data, type: 'updateLayout' });
+ }
+
async getImageBlobURL(opts?: ExportImageFileBaseOptions): Promise {
const data = this.getData() || { elements: [] };
const { devicePixelRatio } = opts || { devicePixelRatio: 1 };
diff --git a/packages/idraw/src/index.ts b/packages/idraw/src/index.ts
index 975fc41..f69408f 100644
--- a/packages/idraw/src/index.ts
+++ b/packages/idraw/src/index.ts
@@ -1,6 +1,15 @@
export type * from '@idraw/types';
-export { Core, MiddlewareSelector, MiddlewareScroller, MiddlewareScaler, MiddlewareRuler, MiddlewareTextEditor, coreEventKeys } from '@idraw/core';
-export { Sharer, Calculator } from '@idraw/board';
+export {
+ Sharer,
+ Calculator,
+ Core,
+ MiddlewareSelector,
+ MiddlewareScroller,
+ MiddlewareScaler,
+ MiddlewareRuler,
+ MiddlewareTextEditor,
+ coreEventKeys
+} from '@idraw/core';
export { Renderer } from '@idraw/renderer';
export {
delay,
@@ -23,6 +32,7 @@ export {
isAssetId,
createAssetId,
deepClone,
+ deepCloneData,
sortDataAsserts,
istype,
loadImage,
@@ -111,10 +121,10 @@ export {
modifyElement,
calcElementViewRectInfo,
calcElementOriginRectInfo,
- calcElementViewRectInfoMap,
- sortElementsViewVisiableInfoMap,
flatElementList,
- calcPointMoveElementInGroup
+ calcPointMoveElementInGroup,
+ merge,
+ omit
} from '@idraw/util';
export { iDraw } from './idraw';
export { eventKeys } from './event';
diff --git a/packages/idraw/src/setting/config.ts b/packages/idraw/src/setting/config.ts
index ea60790..b1fb9a0 100644
--- a/packages/idraw/src/setting/config.ts
+++ b/packages/idraw/src/setting/config.ts
@@ -1,4 +1,4 @@
-import type { IDrawSettings, IDrawStorage, IDrawMode } from '@idraw/types';
+import type { IDrawSettings, IDrawOptions, IDrawStorage, IDrawMode } from '@idraw/types';
import { istype } from '@idraw/util';
export const defaultMode: IDrawMode = 'select';
@@ -7,6 +7,10 @@ export const defaultSettings: Required> = {
mode: defaultMode
};
+export const defaultOptions: Required> = {
+ devicePixelRatio: window.devicePixelRatio
+};
+
export function getDefaultStorage(): IDrawStorage {
const storage: IDrawStorage = {
mode: defaultMode,
diff --git a/packages/renderer/package.json b/packages/renderer/package.json
index 139e981..f4bd140 100644
--- a/packages/renderer/package.json
+++ b/packages/renderer/package.json
@@ -1,6 +1,6 @@
{
"name": "@idraw/renderer",
- "version": "0.4.0-beta.39",
+ "version": "0.4.0-beta.40",
"description": "",
"main": "dist/esm/index.js",
"module": "dist/esm/index.js",
@@ -18,14 +18,14 @@
"url": "https://github.com/idrawjs/idraw/issues"
},
"homepage": "https://github.com/idrawjs/idraw#readme",
- "author": "chenshenhai",
+ "author": "idrawjs",
"license": "MIT",
"devDependencies": {
- "@idraw/types": "workspace:^0.4.0-beta.39"
+ "@idraw/types": "workspace:^0.4.0-beta.40"
},
"dependencies": {},
"peerDependencies": {
- "@idraw/util": "workspace:^0.4.0-beta.39"
+ "@idraw/util": "workspace:^0.4.0-beta.40"
},
"publishConfig": {
"access": "public",
diff --git a/packages/board/src/lib/calculator.ts b/packages/renderer/src/calculator.ts
similarity index 74%
rename from packages/board/src/lib/calculator.ts
rename to packages/renderer/src/calculator.ts
index eaf7339..8015c10 100644
--- a/packages/board/src/lib/calculator.ts
+++ b/packages/renderer/src/calculator.ts
@@ -7,34 +7,34 @@ import type {
ViewCalculatorOptions,
ViewScaleInfo,
ViewSizeInfo,
- ViewCalculatorStorage,
+ VirtualFlatStorage,
ViewRectInfo,
ModifyOptions,
- ViewVisibleInfo
+ VirtualFlatItem
} from '@idraw/types';
import {
is,
- isViewPointInElement,
getViewPointAtElement,
Store,
- sortElementsViewVisiableInfoMap,
- updateViewVisibleInfoMapStatus,
calcViewPointSize,
findElementFromListByPosition,
getGroupQueueByElementPosition,
calcElementOriginRectInfo,
originRectInfoToRangeRectInfo
+ // elementToBoxInfo
} from '@idraw/util';
+import { sortElementsViewVisiableInfoMap, updateVirtualFlatItemMapStatus } from './view-visible';
+import { calcVirtualFlatDetail } from './virtual-flat';
export class Calculator implements ViewCalculator {
#opts: ViewCalculatorOptions;
- #store: Store;
+ #store: Store;
constructor(opts: ViewCalculatorOptions) {
this.#opts = opts;
- this.#store = new Store({
+ this.#store = new Store({
defaultStorage: {
- viewVisibleInfoMap: {},
+ virtualFlatItemMap: {},
visibleCount: 0,
invisibleCount: 0
}
@@ -55,36 +55,23 @@ export class Calculator implements ViewCalculator {
}
needRender(elem: Element): boolean {
- const viewVisibleInfoMap = this.#store.get('viewVisibleInfoMap');
- const info = viewVisibleInfoMap[elem.uuid];
+ const virtualFlatItemMap = this.#store.get('virtualFlatItemMap');
+ const info = virtualFlatItemMap[elem.uuid];
if (!info) {
return true;
}
return info.isVisibleInView;
}
- /**
- * @deprecated
- */
- isPointInElement(p: Point, elem: Element, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): boolean {
- const context2d = this.#opts.viewContext;
- return isViewPointInElement(p, {
- context2d,
- element: elem,
- viewScaleInfo,
- viewSizeInfo
- });
- }
-
getPointElement(
p: Point,
opts: { data: Data; viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }
): { index: number; element: null | Element; groupQueueIndex: number } {
- const context2d = this.#opts.viewContext;
+ const context2d = this.#opts.tempContext;
return getViewPointAtElement(p, { ...opts, ...{ context2d } });
}
- resetViewVisibleInfoMap(
+ resetVirtualFlatItemMap(
data: Data,
opts: {
viewScaleInfo: ViewScaleInfo;
@@ -92,16 +79,24 @@ export class Calculator implements ViewCalculator {
}
): void {
if (data) {
- const { viewVisibleInfoMap, invisibleCount, visibleCount } = sortElementsViewVisiableInfoMap(data.elements, opts);
- this.#store.set('viewVisibleInfoMap', viewVisibleInfoMap);
+ const { virtualFlatItemMap, invisibleCount, visibleCount } = sortElementsViewVisiableInfoMap(data.elements, {
+ ...opts,
+ ...{
+ tempContext: this.#opts.tempContext
+ }
+ });
+ this.#store.set('virtualFlatItemMap', virtualFlatItemMap);
this.#store.set('invisibleCount', invisibleCount);
this.#store.set('visibleCount', visibleCount);
}
}
updateVisiableStatus(opts: { viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }) {
- const { viewVisibleInfoMap, invisibleCount, visibleCount } = updateViewVisibleInfoMapStatus(this.#store.get('viewVisibleInfoMap'), opts);
- this.#store.set('viewVisibleInfoMap', viewVisibleInfoMap);
+ const { virtualFlatItemMap, invisibleCount, visibleCount } = updateVirtualFlatItemMapStatus(
+ this.#store.get('virtualFlatItemMap'),
+ opts
+ );
+ this.#store.set('virtualFlatItemMap', virtualFlatItemMap);
this.#store.set('invisibleCount', invisibleCount);
this.#store.set('visibleCount', visibleCount);
}
@@ -114,7 +109,7 @@ export class Calculator implements ViewCalculator {
viewSizeInfo: ViewSizeInfo;
}
): ViewRectInfo | null {
- const infoData = this.#store.get('viewVisibleInfoMap')[uuid];
+ const infoData = this.#store.get('virtualFlatItemMap')[uuid];
if (!infoData?.originRectInfo) {
return null;
}
@@ -148,7 +143,7 @@ export class Calculator implements ViewCalculator {
viewSizeInfo: ViewSizeInfo;
}
): ViewRectInfo | null {
- const infoData = this.#store.get('viewVisibleInfoMap')[uuid];
+ const infoData = this.#store.get('virtualFlatItemMap')[uuid];
if (!infoData?.originRectInfo) {
return null;
}
@@ -174,7 +169,7 @@ export class Calculator implements ViewCalculator {
return viewRectInfo;
}
- modifyViewVisibleInfoMap(
+ modifyVirtualFlatItemMap(
data: Data,
opts: {
modifyOptions: ModifyOptions; // TODO
@@ -185,7 +180,7 @@ export class Calculator implements ViewCalculator {
const { modifyOptions, viewScaleInfo, viewSizeInfo } = opts;
const { type, content } = modifyOptions;
const list = data.elements;
- const viewVisibleInfoMap = this.#store.get('viewVisibleInfoMap');
+ const virtualFlatItemMap = this.#store.get('virtualFlatItemMap');
if (type === 'deleteElement') {
const { element } = content as ModifyOptions<'deleteElement'>['content'];
const uuids: string[] = [];
@@ -199,13 +194,13 @@ export class Calculator implements ViewCalculator {
};
_walk(element);
uuids.forEach((uuid) => {
- delete viewVisibleInfoMap[uuid];
+ delete virtualFlatItemMap[uuid];
});
- this.#store.set('viewVisibleInfoMap', viewVisibleInfoMap);
+ this.#store.set('virtualFlatItemMap', virtualFlatItemMap);
}
// else if (type === 'updateElement') {
// // TODO
- // this.resetViewVisibleInfoMap(data, { viewScaleInfo, viewSizeInfo });
+ // this.resetVirtualFlatItemMap(data, { viewScaleInfo, viewSizeInfo });
// }
else if (type === 'addElement' || type === 'updateElement') {
const { position } = content as ModifyOptions<'addElement'>['content'];
@@ -214,27 +209,35 @@ export class Calculator implements ViewCalculator {
if (element) {
if (type === 'updateElement' && element.type === 'group') {
// TODO
- this.resetViewVisibleInfoMap(data, { viewScaleInfo, viewSizeInfo });
+ this.resetVirtualFlatItemMap(data, { viewScaleInfo, viewSizeInfo });
} else {
const originRectInfo = calcElementOriginRectInfo(element, {
groupQueue: groupQueue || []
});
- const newViewVisibleInfo: ViewVisibleInfo = {
+ const newVirtualFlatItem: VirtualFlatItem = {
+ type: element.type,
originRectInfo,
rangeRectInfo: is.angle(element.angle) ? originRectInfoToRangeRectInfo(originRectInfo) : originRectInfo,
isVisibleInView: true,
- isGroup: element?.type === 'group',
- position: [...position]
+ position: [...position],
+ ...calcVirtualFlatDetail(element, {
+ tempContext: this.#opts.tempContext
+ })
};
- viewVisibleInfoMap[element.uuid] = newViewVisibleInfo;
- this.#store.set('viewVisibleInfoMap', viewVisibleInfoMap);
+ virtualFlatItemMap[element.uuid] = newVirtualFlatItem;
+ this.#store.set('virtualFlatItemMap', virtualFlatItemMap);
if (type === 'updateElement') {
this.updateVisiableStatus({ viewScaleInfo, viewSizeInfo });
}
}
}
} else if (type === 'moveElement') {
- this.resetViewVisibleInfoMap(data, { viewScaleInfo, viewSizeInfo });
+ this.resetVirtualFlatItemMap(data, { viewScaleInfo, viewSizeInfo });
}
}
+
+ getVirtualFlatItem(uuid: string): VirtualFlatItem | null {
+ const itemMap = this.#store.get('virtualFlatItemMap');
+ return itemMap[uuid] || null;
+ }
}
diff --git a/packages/renderer/src/draw/box.ts b/packages/renderer/src/draw/box.ts
index 7281440..01bda23 100644
--- a/packages/renderer/src/draw/box.ts
+++ b/packages/renderer/src/draw/box.ts
@@ -1,5 +1,25 @@
-import { ViewContext2D, Element, ElementType, ElementSize, ViewScaleInfo, ViewSizeInfo, TransformAction } from '@idraw/types';
-import { istype, isColorStr, generateSVGPath, rotateElement, is, getDefaultElementDetailConfig, calcViewBoxSize } from '@idraw/util';
+import {
+ ViewContext2D,
+ Element,
+ ElementType,
+ ElementSize,
+ ViewScaleInfo,
+ ViewSizeInfo,
+ TransformAction
+ // PointSize
+} from '@idraw/types';
+import {
+ istype,
+ isColorStr,
+ generateSVGPath,
+ rotateElement,
+ is,
+ getDefaultElementDetailConfig,
+ calcViewBoxSize
+ // elementToBoxInfo,
+ // calcViewPointSize
+} from '@idraw/util';
+import { Calculator } from '../calculator';
import { createColorStyle } from './color';
const defaultElemConfig = getDefaultElementDetailConfig();
@@ -35,7 +55,7 @@ export function drawBox(
ctx.globalAlpha = opacity;
drawBoxBackground(ctx, viewElem, { pattern, viewScaleInfo, viewSizeInfo });
renderContent?.();
- drawBoxBorder(ctx, viewElem, { viewScaleInfo, viewSizeInfo });
+ drawBoxBorder(ctx, viewElem, { originElem, viewScaleInfo, viewSizeInfo });
ctx.globalAlpha = parentOpacity;
};
if (clipPath) {
@@ -122,7 +142,14 @@ function drawClipPathStroke(
const { renderContent, originElem, calcElemSize, viewSizeInfo, parentOpacity } = opts;
const totalScale = viewSizeInfo.devicePixelRatio;
const { clipPath, clipPathStrokeColor, clipPathStrokeWidth } = originElem?.detail || {};
- if (clipPath && calcElemSize && clipPath.commands && typeof clipPathStrokeWidth === 'number' && clipPathStrokeWidth > 0 && clipPathStrokeColor) {
+ if (
+ clipPath &&
+ calcElemSize &&
+ clipPath.commands &&
+ typeof clipPathStrokeWidth === 'number' &&
+ clipPathStrokeWidth > 0 &&
+ clipPathStrokeColor
+ ) {
const { x, y, w, h } = calcElemSize;
const { originW, originH, originX, originY } = clipPath;
const scaleW = w / originW;
@@ -217,7 +244,11 @@ export function drawBoxBackground(
}
}
-export function drawBoxBorder(ctx: ViewContext2D, viewElem: Element, opts: { viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }): void {
+export function drawBoxBorder(
+ ctx: ViewContext2D,
+ viewElem: Element,
+ opts: { originElem: Element; viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo; calculator?: Calculator }
+): void {
if (viewElem.detail.borderWidth === 0) {
return;
}
@@ -230,12 +261,18 @@ export function drawBoxBorder(ctx: ViewContext2D, viewElem: Element
if (isColorStr(viewElem.detail.borderColor) === true) {
borderColor = viewElem.detail.borderColor as string;
}
- const { borderWidth, borderRadius, borderDash, boxSizing = defaultElemConfig.boxSizing } = viewElem.detail;
- let bw: number = 0;
- if (typeof borderWidth === 'number') {
- bw = borderWidth || 1;
+
+ const { borderDash, borderWidth, borderRadius, boxSizing = defaultElemConfig.boxSizing } = viewElem.detail;
+ let viewBorderDash: number[] = [];
+ if (Array.isArray(borderDash) && borderDash.length > 0) {
+ viewBorderDash = borderDash.map((num) => Math.ceil(num * scale));
}
- bw = bw * scale;
+ if (viewBorderDash.length > 0) {
+ ctx.lineCap = 'butt';
+ } else {
+ ctx.lineCap = 'square';
+ }
+
let radiusList: [number, number, number, number] = [0, 0, 0, 0];
if (typeof borderRadius === 'number') {
const br = borderRadius * scale;
@@ -243,11 +280,75 @@ export function drawBoxBorder(ctx: ViewContext2D, viewElem: Element
} else if (Array.isArray(borderRadius) && borderRadius?.length === 4) {
radiusList = [borderRadius[0] * scale, borderRadius[1] * scale, borderRadius[2] * scale, borderRadius[3] * scale];
}
- ctx.strokeStyle = borderColor;
- let viewBorderDash: number[] = [];
- if (Array.isArray(borderDash) && borderDash.length > 0) {
- viewBorderDash = borderDash.map((num) => Math.ceil(num * scale));
+
+ // // TODO
+ // const boxInfo = elementToBoxInfo(opts.originElem);
+ // const calcViewOpts = { viewScaleInfo, viewSizeInfo: opts.viewSizeInfo };
+ // const op0: PointSize = calcViewPointSize(boxInfo.op0, calcViewOpts);
+ // const op1: PointSize = calcViewPointSize(boxInfo.op1, calcViewOpts);
+ // const op2: PointSize = calcViewPointSize(boxInfo.op2, calcViewOpts);
+ // const op3: PointSize = calcViewPointSize(boxInfo.op3, calcViewOpts);
+ // const op0s: PointSize = calcViewPointSize(boxInfo.op0s, calcViewOpts);
+ // const op0e: PointSize = calcViewPointSize(boxInfo.op0e, calcViewOpts);
+ // const op1s: PointSize = calcViewPointSize(boxInfo.op1s, calcViewOpts);
+ // const op1e: PointSize = calcViewPointSize(boxInfo.op1e, calcViewOpts);
+ // const op2s: PointSize = calcViewPointSize(boxInfo.op2s, calcViewOpts);
+ // const op2e: PointSize = calcViewPointSize(boxInfo.op2e, calcViewOpts);
+ // const op3s: PointSize = calcViewPointSize(boxInfo.op3s, calcViewOpts);
+ // const op3e: PointSize = calcViewPointSize(boxInfo.op3e, calcViewOpts);
+
+ // const ip0: PointSize = calcViewPointSize(boxInfo.ip0, calcViewOpts);
+ // const ip1: PointSize = calcViewPointSize(boxInfo.ip1, calcViewOpts);
+ // const ip2: PointSize = calcViewPointSize(boxInfo.ip2, calcViewOpts);
+ // const ip3: PointSize = calcViewPointSize(boxInfo.ip3, calcViewOpts);
+ // const ip0s: PointSize = calcViewPointSize(boxInfo.ip0s, calcViewOpts);
+ // const ip0e: PointSize = calcViewPointSize(boxInfo.ip0e, calcViewOpts);
+ // const ip1s: PointSize = calcViewPointSize(boxInfo.ip1s, calcViewOpts);
+ // const ip1e: PointSize = calcViewPointSize(boxInfo.ip1e, calcViewOpts);
+ // const ip2s: PointSize = calcViewPointSize(boxInfo.ip2s, calcViewOpts);
+ // const ip2e: PointSize = calcViewPointSize(boxInfo.ip2e, calcViewOpts);
+ // const ip3s: PointSize = calcViewPointSize(boxInfo.ip3s, calcViewOpts);
+ // const ip3e: PointSize = calcViewPointSize(boxInfo.ip3e, calcViewOpts);
+
+ // ctx.fillStyle = borderColor;
+ // ctx.beginPath();
+ // ctx.moveTo(op0s.x, op0s.y);
+ // ctx.quadraticCurveTo(op0.x, op0.y, op0e.x, op0e.y);
+ // ctx.lineTo(op1s.x, op1s.y);
+ // ctx.quadraticCurveTo(op1.x, op1.y, op1e.x, op1e.y);
+ // ctx.lineTo(op2s.x, op2s.y);
+ // ctx.quadraticCurveTo(op2.x, op2.y, op2e.x, op2e.y);
+ // ctx.lineTo(op3s.x, op3s.y);
+ // ctx.quadraticCurveTo(op3.x, op3.y, op3e.x, op3e.y);
+ // ctx.lineTo(op0s.x, op0s.y);
+ // ctx.closePath();
+ // ctx.fill();
+
+ // ctx.fillStyle = '#000000';
+ // ctx.globalCompositeOperation = 'destination-out';
+ // ctx.beginPath();
+ // ctx.moveTo(ip0s.x, ip0s.y);
+ // ctx.quadraticCurveTo(ip0.x, ip0.y, ip0e.x, ip0e.y);
+ // ctx.lineTo(ip1s.x, ip1s.y);
+ // ctx.quadraticCurveTo(ip1.x, ip1.y, ip1e.x, ip1e.y);
+ // ctx.lineTo(ip2s.x, ip2s.y);
+ // ctx.quadraticCurveTo(ip2.x, ip2.y, ip2e.x, ip2e.y);
+ // ctx.lineTo(ip3s.x, ip3s.y);
+ // ctx.quadraticCurveTo(ip3.x, ip3.y, ip3e.x, ip3e.y);
+ // ctx.lineTo(ip0s.x, ip0s.y);
+ // ctx.closePath();
+ // ctx.fill();
+ // ctx.globalCompositeOperation = 'source-over';
+ // return;
+ // // TODO
+
+ let bw: number = 0;
+ if (typeof borderWidth === 'number') {
+ bw = borderWidth || 1;
}
+ bw = bw * scale;
+
+ ctx.strokeStyle = borderColor;
let borderTop = 0;
let borderRight = 0;
@@ -338,11 +439,6 @@ export function drawBoxBorder(ctx: ViewContext2D, viewElem: Element
// if (r < w / 2 && r < h / 2) {
// r = r + bw / 2;
// }
- if (viewBorderDash.length > 0) {
- ctx.lineCap = 'butt';
- } else {
- ctx.lineCap = 'square';
- }
// TODO
w = Math.max(w, 1);
diff --git a/packages/renderer/src/draw/circle.ts b/packages/renderer/src/draw/circle.ts
index ef5009b..90239f4 100644
--- a/packages/renderer/src/draw/circle.ts
+++ b/packages/renderer/src/draw/circle.ts
@@ -33,8 +33,8 @@ export function drawCircle(ctx: ViewContext2D, elem: Element<'circle'>, opts: Re
const radiusB = b;
if (bw > 0) {
if (boxSizing === 'content-box') {
- a = a;
- b = b;
+ // a = a;
+ // b = b;
} else if (boxSizing === 'center-line') {
a = a - bw / 2;
b = b - bw / 2;
diff --git a/packages/renderer/src/draw/group.ts b/packages/renderer/src/draw/group.ts
index 804841d..bac066e 100644
--- a/packages/renderer/src/draw/group.ts
+++ b/packages/renderer/src/draw/group.ts
@@ -72,13 +72,15 @@ export function drawElement(ctx: ViewContext2D, elem: Element, opts
}
}
} catch (err) {
+ // eslint-disable-next-line no-console
console.error(err);
}
}
export function drawGroup(ctx: ViewContext2D, elem: Element<'group'>, opts: RendererDrawElementOptions) {
const { viewScaleInfo, viewSizeInfo, parentOpacity } = opts;
- const { x, y, w, h, angle } = calcViewElementSize({ x: elem.x, y: elem.y, w: elem.w, h: elem.h, angle: elem.angle }, { viewScaleInfo }) || elem;
+ const { x, y, w, h, angle } =
+ calcViewElementSize({ x: elem.x, y: elem.y, w: elem.w, h: elem.h, angle: elem.angle }, { viewScaleInfo }) || elem;
const viewElem = { ...elem, ...{ x, y, w, h, angle } };
rotateElement(ctx, { x, y, w, h, angle }, () => {
ctx.globalAlpha = getOpacity(elem) * parentOpacity;
@@ -141,6 +143,7 @@ export function drawGroup(ctx: ViewContext2D, elem: Element<'group'>, opts: Rend
try {
drawElement(ctx, child, { ...opts, ...{ parentOpacity: parentOpacity * getOpacity(elem) } });
} catch (err) {
+ // eslint-disable-next-line no-console
console.error(err);
}
}
diff --git a/packages/renderer/src/draw/layout.ts b/packages/renderer/src/draw/layout.ts
index 80558e3..fbe7bb4 100644
--- a/packages/renderer/src/draw/layout.ts
+++ b/packages/renderer/src/draw/layout.ts
@@ -2,7 +2,12 @@ import type { RendererDrawElementOptions, ViewContext2D, DataLayout, Element } f
import { calcViewElementSize, calcViewBoxSize } from '@idraw/util';
import { drawBoxShadow, drawBoxBackground, drawBoxBorder } from './box';
-export function drawLayout(ctx: ViewContext2D, layout: DataLayout, opts: RendererDrawElementOptions, renderContent: (ctx: ViewContext2D) => void) {
+export function drawLayout(
+ ctx: ViewContext2D,
+ layout: DataLayout,
+ opts: RendererDrawElementOptions,
+ renderContent: (ctx: ViewContext2D) => void
+) {
const { viewScaleInfo, viewSizeInfo, parentOpacity } = opts;
const elem: Element = { uuid: 'layout', type: 'group', ...layout } as Element;
const { x, y, w, h } = calcViewElementSize(elem, { viewScaleInfo }) || elem;
@@ -46,6 +51,6 @@ export function drawLayout(ctx: ViewContext2D, layout: DataLayout, opts: Rendere
ctx.restore();
}
- drawBoxBorder(ctx, viewElem, { viewScaleInfo, viewSizeInfo });
+ drawBoxBorder(ctx, viewElem, { originElem: elem, viewScaleInfo, viewSizeInfo });
ctx.globalAlpha = parentOpacity;
}
diff --git a/packages/renderer/src/draw/text.ts b/packages/renderer/src/draw/text.ts
index a18036f..66191e0 100644
--- a/packages/renderer/src/draw/text.ts
+++ b/packages/renderer/src/draw/text.ts
@@ -5,18 +5,8 @@ import { drawBox, drawBoxShadow } from './box';
const detailConfig = getDefaultElementDetailConfig();
-// TODO
-function isTextWidthWithinErrorRange(w0: number, w1: number, scale: number): boolean {
- if (scale < 0.5) {
- if (w0 < w1 && (w0 - w1) / w0 > -0.15) {
- return true;
- }
- }
- return w0 >= w1;
-}
-
export function drawText(ctx: ViewContext2D, elem: Element<'text'>, opts: RendererDrawElementOptions) {
- const { viewScaleInfo, viewSizeInfo, parentOpacity } = opts;
+ const { viewScaleInfo, viewSizeInfo, parentOpacity, calculator } = opts;
const { x, y, w, h, angle } = calcViewElementSize(elem, { viewScaleInfo }) || elem;
const viewElem = { ...elem, ...{ x, y, w, h, angle } };
rotateElement(ctx, { x, y, w, h, angle }, () => {
@@ -45,9 +35,6 @@ export function drawText(ctx: ViewContext2D, elem: Element<'text'>, opts: Render
return;
}
- const originLineHeight = detail.lineHeight || originFontSize;
- const lineHeight = originLineHeight * viewScaleInfo.scale;
-
ctx.fillStyle = elem.detail.color || detailConfig.color;
ctx.textBaseline = 'top';
ctx.$setFont({
@@ -55,143 +42,28 @@ export function drawText(ctx: ViewContext2D, elem: Element<'text'>, opts: Render
fontSize: fontSize,
fontFamily: enhanceFontFamliy(detail.fontFamily)
});
- let detailText = detail.text.replace(/\r\n/gi, '\n');
- if (detail.textTransform === 'lowercase') {
- detailText = detailText.toLowerCase();
- } else if (detail.textTransform === 'uppercase') {
- detailText = detailText.toUpperCase();
- }
- const fontHeight = lineHeight;
- const detailTextList = detailText.split('\n');
- const lines: { text: string; width: number }[] = [];
-
- let lineNum = 0;
- detailTextList.forEach((itemText: string, idx: number) => {
- if (detail.minInlineSize === 'maxContent') {
- lines.push({
- text: itemText,
- width: ctx.$undoPixelRatio(ctx.measureText(itemText).width)
- });
- } else {
- let lineText = '';
- let splitStr = '';
- let tempStrList: string[] = itemText.split(splitStr);
- if (detail.wordBreak === 'normal') {
- const splitStr = ' ';
- const wordList = itemText.split(splitStr);
- tempStrList = [];
- wordList.forEach((word: string, idx: number) => {
- tempStrList.push(word);
- if (idx < wordList.length - 1) {
- tempStrList.push(splitStr);
- }
- });
- }
-
- if (tempStrList.length === 1 && detail.overflow === 'visible') {
- lines.push({
- text: tempStrList[0],
- width: ctx.$undoPixelRatio(ctx.measureText(tempStrList[0]).width)
- });
- } else if (tempStrList.length > 0) {
- for (let i = 0; i < tempStrList.length; i++) {
- if (isTextWidthWithinErrorRange(ctx.$doPixelRatio(w), ctx.measureText(lineText + tempStrList[i]).width, viewScaleInfo.scale)) {
- lineText += tempStrList[i] || '';
- } else {
- lines.push({
- text: lineText,
- width: ctx.$undoPixelRatio(ctx.measureText(lineText).width)
- });
- lineText = tempStrList[i] || '';
- lineNum++;
- }
- if ((lineNum + 1) * fontHeight > h && detail.overflow === 'hidden') {
- break;
- }
- if (tempStrList.length - 1 === i) {
- if ((lineNum + 1) * fontHeight <= h) {
- lines.push({
- text: lineText,
- width: ctx.$undoPixelRatio(ctx.measureText(lineText).width)
- });
- if (idx < detailTextList.length - 1) {
- lineNum++;
- }
- break;
- }
- }
- }
- } else {
- lines.push({
- text: '',
- width: 0
- });
- }
- }
- });
-
- let startY = 0;
- let eachLineStartY = 0;
- if (fontHeight > fontSize) {
- eachLineStartY = (fontHeight - fontSize) / 2;
- }
- if (lines.length * fontHeight < h) {
- if (elem.detail.verticalAlign === 'top') {
- startY = 0;
- } else if (elem.detail.verticalAlign === 'bottom') {
- startY += h - lines.length * fontHeight;
- } else {
- // middle and default
- startY += (h - lines.length * fontHeight) / 2;
- }
- }
-
- // draw text lines
{
- const _y = y + startY;
- if (detail.textShadowColor !== undefined && isColorStr(detail.textShadowColor)) {
- ctx.shadowColor = detail.textShadowColor;
- }
- if (detail.textShadowOffsetX !== undefined && is.number(detail.textShadowOffsetX)) {
- ctx.shadowOffsetX = detail.textShadowOffsetX;
- }
- if (detail.textShadowOffsetY !== undefined && is.number(detail.textShadowOffsetY)) {
- ctx.shadowOffsetY = detail.textShadowOffsetY;
- }
- if (detail.textShadowBlur !== undefined && is.number(detail.textShadowBlur)) {
- ctx.shadowBlur = detail.textShadowBlur;
- }
- lines.forEach((line, i) => {
- let _x = x;
- if (detail.textAlign === 'center') {
- _x = x + (w - line.width) / 2;
- } else if (detail.textAlign === 'right') {
- _x = x + (w - line.width);
+ const virtualTextDetail = calculator.getVirtualFlatItem(elem.uuid);
+ if (Array.isArray(virtualTextDetail?.textLines) && virtualTextDetail?.textLines?.length > 0) {
+ if (detail.textShadowColor !== undefined && isColorStr(detail.textShadowColor)) {
+ ctx.shadowColor = detail.textShadowColor;
+ }
+ if (detail.textShadowOffsetX !== undefined && is.number(detail.textShadowOffsetX)) {
+ ctx.shadowOffsetX = detail.textShadowOffsetX;
+ }
+ if (detail.textShadowOffsetY !== undefined && is.number(detail.textShadowOffsetY)) {
+ ctx.shadowOffsetY = detail.textShadowOffsetY;
+ }
+ if (detail.textShadowBlur !== undefined && is.number(detail.textShadowBlur)) {
+ ctx.shadowBlur = detail.textShadowBlur;
}
- ctx.fillText(line.text, _x, _y + fontHeight * i + eachLineStartY);
- });
- }
- // // draw text stroke
- // if (isColorStr(detail.strokeColor) && detail.strokeWidth !== undefined && detail.strokeWidth > 0) {
- // const _y = y + startY;
- // lines.forEach((line, i) => {
- // let _x = x;
- // if (detail.textAlign === 'center') {
- // _x = x + (w - line.width) / 2;
- // } else if (detail.textAlign === 'right') {
- // _x = x + (w - line.width);
- // }
- // if (detail.strokeColor !== undefined) {
- // ctx.strokeStyle = detail.strokeColor;
- // }
- // if (detail.strokeWidth !== undefined && detail.strokeWidth > 0) {
- // ctx.lineWidth = detail.strokeWidth;
- // }
- // ctx.strokeText(line.text, _x, _y + fontHeight * i);
- // });
- // }
+ virtualTextDetail?.textLines?.forEach((line) => {
+ ctx.fillText(line.text, x + line.x * viewScaleInfo.scale, y + line.y * viewScaleInfo.scale);
+ });
+ }
+ }
}
});
}
diff --git a/packages/renderer/src/index.ts b/packages/renderer/src/index.ts
index d8b5cab..3b9e0b8 100644
--- a/packages/renderer/src/index.ts
+++ b/packages/renderer/src/index.ts
@@ -3,15 +3,21 @@ import type { DataLayout, LoadItemMap } from '@idraw/types';
import { drawElementList, drawLayout, drawGlobalBackground } from './draw/index';
import { Loader } from './loader';
import type { Data, BoardRenderer, RendererOptions, RendererEventMap, RendererDrawOptions } from '@idraw/types';
+import { Calculator } from './calculator';
+export { Calculator };
export class Renderer extends EventEmitter implements BoardRenderer {
#opts: RendererOptions;
#loader: Loader = new Loader();
+ #calculator: Calculator;
#hasDestroyed: boolean = false;
constructor(opts: RendererOptions) {
super();
this.#opts = opts;
+ this.#calculator = new Calculator({
+ tempContext: opts.tempContext
+ });
this.#init();
}
@@ -45,7 +51,8 @@ export class Renderer extends EventEmitter implements BoardRen
drawData(data: Data, opts: RendererDrawOptions) {
const loader = this.#loader;
- const { calculator, sharer } = this.#opts;
+ const calculator = this.#calculator;
+ const { sharer } = this.#opts;
const viewContext = this.#opts.viewContext;
viewContext.clearRect(0, 0, viewContext.canvas.width, viewContext.canvas.height);
const parentElementSize = {
@@ -88,8 +95,18 @@ export class Renderer extends EventEmitter implements BoardRen
// TODO
return;
}
- const { data, offsetTop, offsetBottom, offsetLeft, offsetRight, width, height, contextHeight, contextWidth, devicePixelRatio } =
- sharer.getActiveStoreSnapshot();
+ const {
+ data,
+ offsetTop,
+ offsetBottom,
+ offsetLeft,
+ offsetRight,
+ width,
+ height,
+ contextHeight,
+ contextWidth,
+ devicePixelRatio
+ } = sharer.getActiveStoreSnapshot();
if (data) {
this.drawData(data, {
viewScaleInfo: {
@@ -121,6 +138,10 @@ export class Renderer extends EventEmitter implements BoardRen
getLoader(): Loader {
return this.#loader;
}
+
+ getCalculator(): Calculator {
+ return this.#calculator;
+ }
}
export {
diff --git a/packages/util/src/lib/view-visible.ts b/packages/renderer/src/view-visible/index.ts
similarity index 56%
rename from packages/util/src/lib/view-visible.ts
rename to packages/renderer/src/view-visible/index.ts
index b5dcf67..286f3b9 100644
--- a/packages/util/src/lib/view-visible.ts
+++ b/packages/renderer/src/view-visible/index.ts
@@ -1,61 +1,22 @@
-import { Element, ElementPosition, Elements, ViewScaleInfo, ViewSizeInfo, ViewRectInfo, ViewVisibleInfoMap, ViewVisibleInfo } from '@idraw/types';
-import { calcElementOriginRectInfo, originRectInfoToRangeRectInfo } from './view-calc';
-import { getGroupQueueByElementPosition } from './element';
-import { calcElementCenter } from './rotate';
-import { is } from './is';
+import { Elements, ViewScaleInfo, ViewSizeInfo, ViewRectInfo, VirtualFlatItemMap, ViewContext2D } from '@idraw/types';
+import { calcElementCenter } from '@idraw/util';
+import { elementsToVirtualFlatMap } from '../virtual-flat';
export function sortElementsViewVisiableInfoMap(
elements: Elements,
opts: {
viewScaleInfo: ViewScaleInfo;
viewSizeInfo: ViewSizeInfo;
+ tempContext: ViewContext2D;
}
): {
- viewVisibleInfoMap: ViewVisibleInfoMap;
+ virtualFlatItemMap: VirtualFlatItemMap;
visibleCount: number;
invisibleCount: number;
} {
- const visibleInfoMap: ViewVisibleInfoMap = {};
- const currentPosition: ElementPosition = [];
-
- const _walk = (elem: Element) => {
- const baseInfo: Omit = {
- isVisibleInView: true,
- isGroup: elem.type === 'group',
- position: [...currentPosition]
- };
- let originRectInfo: ViewRectInfo | null = null;
-
- const groupQueue = getGroupQueueByElementPosition(elements, currentPosition);
-
- originRectInfo = calcElementOriginRectInfo(elem, {
- groupQueue: groupQueue || []
- });
-
- visibleInfoMap[elem.uuid] = {
- ...baseInfo,
- ...{
- originRectInfo: originRectInfo as ViewRectInfo,
- rangeRectInfo: is.angle(elem.angle) ? originRectInfoToRangeRectInfo(originRectInfo as ViewRectInfo) : originRectInfo
- }
- };
-
- if (elem.type === 'group') {
- (elem as Element<'group'>).detail.children.forEach((ele, i) => {
- currentPosition.push(i);
- _walk(ele);
- currentPosition.pop();
- });
- }
- };
-
- elements.forEach((elem, index) => {
- currentPosition.push(index);
- _walk(elem);
- currentPosition.pop();
- });
-
- return updateViewVisibleInfoMapStatus(visibleInfoMap, opts);
+ const { viewScaleInfo, viewSizeInfo, tempContext } = opts;
+ const visibleInfoMap: VirtualFlatItemMap = elementsToVirtualFlatMap(elements, { tempContext });
+ return updateVirtualFlatItemMapStatus(visibleInfoMap, { viewScaleInfo, viewSizeInfo });
}
function isRangeRectInfoCollide(info1: ViewRectInfo, info2: ViewRectInfo): boolean {
@@ -79,10 +40,10 @@ function isRangeRectInfoCollide(info1: ViewRectInfo, info2: ViewRectInfo): boole
return false;
}
-// function logViewVisibleInfoMapStatus(viewVisibleInfoMap: ViewVisibleInfoMap) {
+// function logVirtualFlatItemMapStatus(virtualFlatItemMap: VirtualFlatItemMap) {
// console.log('------------------------------------------------');
-// Object.keys(viewVisibleInfoMap).forEach((uuid) => {
-// const item = viewVisibleInfoMap[uuid];
+// Object.keys(virtualFlatItemMap).forEach((uuid) => {
+// const item = virtualFlatItemMap[uuid];
// const info = item.originRectInfo;
// const rect = {
// x: info.topLeft.x,
@@ -94,31 +55,34 @@ function isRangeRectInfoCollide(info1: ViewRectInfo, info2: ViewRectInfo): boole
// });
// }
-export function updateViewVisibleInfoMapStatus(
- viewVisibleInfoMap: ViewVisibleInfoMap,
+export function updateVirtualFlatItemMapStatus(
+ virtualFlatItemMap: VirtualFlatItemMap,
opts: { viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }
): {
- viewVisibleInfoMap: ViewVisibleInfoMap;
+ virtualFlatItemMap: VirtualFlatItemMap;
visibleCount: number;
invisibleCount: number;
} {
const canvasRectInfo = calcVisibleOriginCanvasRectInfo(opts);
let visibleCount = 0;
let invisibleCount = 0;
- Object.keys(viewVisibleInfoMap).forEach((uuid) => {
- const info = viewVisibleInfoMap[uuid];
+ Object.keys(virtualFlatItemMap).forEach((uuid) => {
+ const info = virtualFlatItemMap[uuid];
info.isVisibleInView = isRangeRectInfoCollide(info.rangeRectInfo, canvasRectInfo);
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
info.isVisibleInView ? visibleCount++ : invisibleCount++;
});
- // logViewVisibleInfoMapStatus(viewVisibleInfoMap);
+ // logVirtualFlatItemMapStatus(virtualFlatItemMap);
- return { viewVisibleInfoMap, visibleCount, invisibleCount };
+ return { virtualFlatItemMap, visibleCount, invisibleCount };
}
-export function calcVisibleOriginCanvasRectInfo(opts: { viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }): ViewRectInfo {
+export function calcVisibleOriginCanvasRectInfo(opts: {
+ viewScaleInfo: ViewScaleInfo;
+ viewSizeInfo: ViewSizeInfo;
+}): ViewRectInfo {
const { viewScaleInfo, viewSizeInfo } = opts;
- // console.log('xxx ===== ', viewScaleInfo, viewSizeInfo);
const { scale, offsetTop, offsetLeft } = viewScaleInfo;
const { width, height } = viewSizeInfo;
diff --git a/packages/renderer/src/virtual-flat/index.ts b/packages/renderer/src/virtual-flat/index.ts
new file mode 100644
index 0000000..66e7401
--- /dev/null
+++ b/packages/renderer/src/virtual-flat/index.ts
@@ -0,0 +1,75 @@
+import {
+ Element,
+ ElementPosition,
+ Elements,
+ ViewRectInfo,
+ VirtualFlatItemMap,
+ VirtualFlatItem,
+ VirtualFlatDetail,
+ ViewContext2D
+} from '@idraw/types';
+import {
+ is,
+ getGroupQueueByElementPosition,
+ calcElementOriginRectInfo,
+ originRectInfoToRangeRectInfo
+} from '@idraw/util';
+
+import { calcVirtualTextDetail } from './text';
+
+export function calcVirtualFlatDetail(elem: Element, opts: { tempContext: ViewContext2D }): VirtualFlatDetail {
+ let virtualDetail: VirtualFlatDetail = {};
+ if (elem.type === 'text') {
+ virtualDetail = calcVirtualTextDetail(elem as Element<'text'>, opts);
+ }
+ return virtualDetail;
+}
+
+export function elementsToVirtualFlatMap(elements: Elements, opts: { tempContext: ViewContext2D }): VirtualFlatItemMap {
+ const virtualFlatMap: VirtualFlatItemMap = {};
+ const currentPosition: ElementPosition = [];
+
+ const _walk = (elem: Element) => {
+ const baseInfo: Omit = {
+ type: elem.type,
+ isVisibleInView: true,
+ position: [...currentPosition]
+ };
+ let originRectInfo: ViewRectInfo | null = null;
+
+ const groupQueue = getGroupQueueByElementPosition(elements, currentPosition);
+
+ originRectInfo = calcElementOriginRectInfo(elem, {
+ groupQueue: groupQueue || []
+ });
+
+ const virtualItem: VirtualFlatItem = {
+ ...baseInfo,
+ ...{
+ originRectInfo: originRectInfo as ViewRectInfo,
+ rangeRectInfo: is.angle(elem.angle)
+ ? originRectInfoToRangeRectInfo(originRectInfo as ViewRectInfo)
+ : originRectInfo
+ },
+ ...calcVirtualFlatDetail(elem, opts)
+ };
+
+ virtualFlatMap[elem.uuid] = virtualItem;
+
+ if (elem.type === 'group') {
+ (elem as Element<'group'>).detail.children.forEach((ele, i) => {
+ currentPosition.push(i);
+ _walk(ele);
+ currentPosition.pop();
+ });
+ }
+ };
+
+ elements.forEach((elem, index) => {
+ currentPosition.push(index);
+ _walk(elem);
+ currentPosition.pop();
+ });
+
+ return virtualFlatMap;
+}
diff --git a/packages/renderer/src/virtual-flat/text.ts b/packages/renderer/src/virtual-flat/text.ts
new file mode 100644
index 0000000..06492fb
--- /dev/null
+++ b/packages/renderer/src/virtual-flat/text.ts
@@ -0,0 +1,163 @@
+import type { Element, CalcVirtualDetailOptions, VirtualFlatTextDetail, VirtualFlatTextLine } from '@idraw/types';
+import { enhanceFontFamliy, getDefaultElementDetailConfig } from '@idraw/util';
+
+const detailConfig = getDefaultElementDetailConfig();
+
+// TODO
+function isTextWidthWithinErrorRange(w0: number, w1: number, scale: number): boolean {
+ if (scale < 0.5) {
+ if (w0 < w1 && (w0 - w1) / w0 > -0.15) {
+ return true;
+ }
+ }
+ return w0 >= w1;
+}
+
+export function calcVirtualTextDetail(elem: Element<'text'>, opts: CalcVirtualDetailOptions): VirtualFlatTextDetail {
+ const { w, h } = elem;
+ const x = 0;
+ const y = 0;
+ const ctx = opts.tempContext;
+
+ const lines: VirtualFlatTextLine[] = [];
+ const detail: Element<'text'>['detail'] = {
+ ...detailConfig,
+ ...elem.detail
+ };
+ const originFontSize = detail.fontSize || detailConfig.fontSize;
+ const fontSize = originFontSize;
+
+ if (fontSize < 2) {
+ return {};
+ }
+
+ const originLineHeight = detail.lineHeight || originFontSize;
+ const lineHeight = originLineHeight;
+
+ ctx.textBaseline = 'top';
+ ctx.$setFont({
+ fontWeight: detail.fontWeight,
+ fontSize: fontSize,
+ fontFamily: enhanceFontFamliy(detail.fontFamily)
+ });
+ let detailText = detail.text.replace(/\r\n/gi, '\n');
+ if (detail.textTransform === 'lowercase') {
+ detailText = detailText.toLowerCase();
+ } else if (detail.textTransform === 'uppercase') {
+ detailText = detailText.toUpperCase();
+ }
+
+ const fontHeight = lineHeight;
+ const detailTextList = detailText.split('\n');
+
+ let lineNum = 0;
+ detailTextList.forEach((itemText: string, idx: number) => {
+ if (detail.minInlineSize === 'maxContent') {
+ lines.push({
+ x,
+ y: 0, // TODO
+ text: itemText,
+ width: ctx.$undoPixelRatio(ctx.measureText(itemText).width)
+ });
+ } else {
+ let lineText = '';
+ let splitStr = '';
+ let tempStrList: string[] = itemText.split(splitStr);
+ if (detail.wordBreak === 'normal') {
+ splitStr = ' ';
+ const wordList = itemText.split(splitStr);
+ tempStrList = [];
+ wordList.forEach((word: string, idx: number) => {
+ tempStrList.push(word);
+ if (idx < wordList.length - 1) {
+ tempStrList.push(splitStr);
+ }
+ });
+ }
+
+ if (tempStrList.length === 1 && detail.overflow === 'visible') {
+ lines.push({
+ x,
+ y: 0, // TODO
+ text: tempStrList[0],
+ width: ctx.$undoPixelRatio(ctx.measureText(tempStrList[0]).width)
+ });
+ } else if (tempStrList.length > 0) {
+ for (let i = 0; i < tempStrList.length; i++) {
+ if (isTextWidthWithinErrorRange(ctx.$doPixelRatio(w), ctx.measureText(lineText + tempStrList[i]).width, 1)) {
+ lineText += tempStrList[i] || '';
+ } else {
+ lines.push({
+ x,
+ y: 0, // TODO
+ text: lineText,
+ width: ctx.$undoPixelRatio(ctx.measureText(lineText).width)
+ });
+ lineText = tempStrList[i] || '';
+ lineNum++;
+ }
+ if ((lineNum + 1) * fontHeight > h && detail.overflow === 'hidden') {
+ break;
+ }
+ if (tempStrList.length - 1 === i) {
+ if ((lineNum + 1) * fontHeight <= h) {
+ lines.push({
+ x,
+ y: 0, // TODO
+ text: lineText,
+ width: ctx.$undoPixelRatio(ctx.measureText(lineText).width)
+ });
+ if (idx < detailTextList.length - 1) {
+ lineNum++;
+ }
+ break;
+ }
+ }
+ }
+ } else {
+ lines.push({
+ x,
+ y: 0, // TODO
+ text: '',
+ width: 0
+ });
+ }
+ }
+ });
+
+ let startY = 0;
+ let eachLineStartY = 0;
+ if (fontHeight > fontSize) {
+ eachLineStartY = (fontHeight - fontSize) / 2;
+ }
+ if (lines.length * fontHeight < h) {
+ if (elem.detail.verticalAlign === 'top') {
+ startY = 0;
+ } else if (elem.detail.verticalAlign === 'bottom') {
+ startY += h - lines.length * fontHeight;
+ } else {
+ // middle and default
+ startY += (h - lines.length * fontHeight) / 2;
+ }
+ }
+
+ // draw text lines
+ {
+ const _y = y + startY;
+ lines.forEach((line, i) => {
+ let _x = x;
+ if (detail.textAlign === 'center') {
+ _x = x + (w - line.width) / 2;
+ } else if (detail.textAlign === 'right') {
+ _x = x + (w - line.width);
+ }
+ lines[i].x = _x;
+ lines[i].y = _y + fontHeight * i + eachLineStartY;
+ });
+ }
+
+ const virtualTextDetail: VirtualFlatTextDetail = {
+ textLines: lines
+ };
+ return virtualTextDetail;
+}
diff --git a/packages/types/package.json b/packages/types/package.json
index 3c2ad6a..359e3b1 100644
--- a/packages/types/package.json
+++ b/packages/types/package.json
@@ -1,11 +1,11 @@
{
"name": "@idraw/types",
- "version": "0.4.0-beta.39",
+ "version": "0.4.0-beta.40",
"description": "",
"main": "src/index.ts",
"types": "src/index.ts",
"scripts": {},
- "author": "chenshenhai",
+ "author": "idrawjs",
"license": "MIT",
"files": [
"src/**/*.ts",
diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts
index a91c616..f358e57 100644
--- a/packages/types/src/index.ts
+++ b/packages/types/src/index.ts
@@ -1,5 +1,6 @@
export * from './lib/util';
export * from './lib/point';
+export * from './lib/box';
export * from './lib/data';
export * from './lib/element';
export * from './lib/view';
@@ -17,3 +18,4 @@ export * from './lib/html';
export * from './lib/svg-path';
export * from './lib/config';
export * from './lib/modify';
+export * from './lib/virtual-flat';
diff --git a/packages/types/src/lib/board.ts b/packages/types/src/lib/board.ts
index 4d794df..966cd1d 100644
--- a/packages/types/src/lib/board.ts
+++ b/packages/types/src/lib/board.ts
@@ -88,7 +88,10 @@ export interface BoardMiddlewareObject = any
clear?(e: BoardWatcherEventMap['clear']): void | boolean;
}
-export interface BoardMiddlewareOptions = Record, E extends BoardExtendEventMap = BoardExtendEventMap> {
+export interface BoardMiddlewareOptions<
+ S extends Record = Record,
+ E extends BoardExtendEventMap = BoardExtendEventMap
+> {
boardContent: BoardContent;
sharer: StoreSharer;
viewer: BoardViewer;
@@ -98,10 +101,11 @@ export interface BoardMiddlewareOptions = Re
canvas?: HTMLCanvasElement;
}
-export type BoardMiddleware = any, E extends BoardExtendEventMap = BoardExtendEventMap, C extends any = undefined> = (
- opts: BoardMiddlewareOptions,
- config?: C
-) => BoardMiddlewareObject;
+export type BoardMiddleware<
+ S extends Record = any,
+ E extends BoardExtendEventMap = BoardExtendEventMap,
+ C extends any = undefined
+> = (opts: BoardMiddlewareOptions, config?: C) => BoardMiddlewareObject;
export interface BoardOptions {
boardContent: BoardContent;
@@ -114,8 +118,7 @@ export interface BoardViewerFrameSnapshot =
}
export interface BoardViewerEventMap {
- // eslint-disable-next-line @typescript-eslint/ban-types
- drawFrame: {};
+ drawFrame: object;
}
export interface BoardViewerOptions {
@@ -128,24 +131,27 @@ export interface BoardViewerOptions {
}
// export interface BoardViewerStorage {
-// viewVisibleInfoMap: ViewVisibleInfoMap;
+// virtualFlatItemMap: VirtualFlatItemMap;
// }
export interface BoardViewer extends UtilEventEmitter {
drawFrame(): void;
- scale(opts: { scale: number; point: PointSize; ignoreUpdateVisibleStatus?: boolean }): { moveX: number; moveY: number };
+ scale(opts: { scale: number; point: PointSize; ignoreUpdateVisibleStatus?: boolean }): {
+ moveX: number;
+ moveY: number;
+ };
scroll(opts: { moveX?: number; moveY?: number; ignoreUpdateVisibleStatus?: boolean }): ViewScaleInfo;
resize(viewSize: Partial, opts?: { ignoreUpdateVisibleStatus?: boolean }): ViewSizeInfo;
updateViewScaleInfo(opts: { scale: number; offsetX: number; offsetY: number }): ViewScaleInfo;
- // resetViewVisibleInfoMap(
+ // resetVirtualFlatItemMap(
// data: Data,
// opts: {
// viewScaleInfo: ViewScaleInfo;
// viewSizeInfo: ViewSizeInfo;
// }
// ): void;
- // modifyViewVisibleInfoMap(
+ // modifyVirtualFlatItemMap(
// data: Data,
// opts: {
// modifyOptions: ModifyOptions;
diff --git a/packages/types/src/lib/box.ts b/packages/types/src/lib/box.ts
new file mode 100644
index 0000000..e8cccf4
--- /dev/null
+++ b/packages/types/src/lib/box.ts
@@ -0,0 +1,56 @@
+import type { PointSize } from './point';
+
+export type BoxInfo = {
+ // p0: PointSize; // top-left
+ // p1: PointSize; // top-right
+ // p2: PointSize; // bottom-right
+ // p3: PointSize; // bottom-left
+
+ btw: number; // border-top-width
+ brw: number; // border-right-width
+ bbw: number; // border-bottom-width
+ blw: number; // border-left-width
+ btlr: number; // border-top-left-radius
+ btrr: number; // border-top-right-radius
+ bblr: number; // border-bottom-left-radius
+ bbrr: number; // border-bottom-right-radius
+
+ p0: PointSize; // pointer border-top-left
+ p1: PointSize; // pointer border-top-right
+ p2: PointSize; // pointer border-bottom-right
+ p3: PointSize; // pointer border-bottom-left
+ p0s: PointSize; // pointer border-top-left start
+ p0e: PointSize; // pointer border-top-left end
+ p1s: PointSize; // pointer border-top-right start
+ p1e: PointSize; // pointer border-top-right start
+ p2s: PointSize; // pointer border-bottom-right start
+ p2e: PointSize; // pointer border-bottom-right end
+ p3s: PointSize; // pointer border-bottom-left start
+ p3e: PointSize; // pointer border-bottom-left end
+
+ op0: PointSize; // outer pointer border-top-left
+ op1: PointSize; // outer pointer border-top-right
+ op2: PointSize; // outer pointer border-bottom-right
+ op3: PointSize; // outer pointer border-bottom-left
+ op0s: PointSize; // outer pointer border-top-left start
+ op0e: PointSize; // outer pointer border-top-left end
+ op1s: PointSize; // outer pointer border-top-right start
+ op1e: PointSize; // outer pointer border-top-right start
+ op2s: PointSize; // outer pointer border-bottom-right start
+ op2e: PointSize; // outer pointer border-bottom-right end
+ op3s: PointSize; // outer pointer border-bottom-left start
+ op3e: PointSize; // outer pointer border-bottom-left end
+
+ ip0: PointSize; // inner pointer border-top-left
+ ip1: PointSize; // inner pointer border-top-right
+ ip2: PointSize; // inner pointer border-bottom-right
+ ip3: PointSize; // inner pointer border-bottom-left
+ ip0s: PointSize; // inner pointer border-top-left start
+ ip0e: PointSize; // inner pointer border-top-left end
+ ip1s: PointSize; // inner pointer border-top-right start
+ ip1e: PointSize; // inner pointer border-top-right start
+ ip2s: PointSize; // inner pointer border-bottom-right start
+ ip2e: PointSize; // inner pointer border-bottom-right end
+ ip3s: PointSize; // inner pointer border-bottom-left start
+ ip3e: PointSize; // inner pointer border-bottom-left end
+};
diff --git a/packages/types/src/lib/context2d.ts b/packages/types/src/lib/context2d.ts
index f9ed7c1..b543584 100644
--- a/packages/types/src/lib/context2d.ts
+++ b/packages/types/src/lib/context2d.ts
@@ -31,6 +31,8 @@ export interface ViewContext2D {
moveTo(x: number, y: number): void;
lineTo(x: number, y: number): void;
arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void;
+ bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void;
+ quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void;
lineWidth: number;
getLineDash(): number[];
setLineDash(segments: number[]): void;
@@ -49,7 +51,17 @@ export interface ViewContext2D {
scale(x: number, y: number): void;
drawImage(image: CanvasImageSource, dx: number, dy: number): void;
drawImage(image: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void;
- drawImage(image: CanvasImageSource, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): void;
+ drawImage(
+ image: CanvasImageSource,
+ sx: number,
+ sy: number,
+ sw: number,
+ sh: number,
+ dx: number,
+ dy: number,
+ dw: number,
+ dh: number
+ ): void;
createPattern(image: CanvasImageSource, repetition: string | null): CanvasPattern | null;
globalAlpha: number;
globalCompositeOperation: GlobalCompositeOperation;
@@ -57,7 +69,16 @@ export interface ViewContext2D {
shadowColor: string;
shadowOffsetX: number;
shadowOffsetY: number;
- circle(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void;
+ circle(
+ x: number,
+ y: number,
+ radiusX: number,
+ radiusY: number,
+ rotation: number,
+ startAngle: number,
+ endAngle: number,
+ counterclockwise?: boolean
+ ): void;
isPointInPath(x: number, y: number, fillRule?: CanvasFillRule): boolean;
clip(fillRule?: CanvasFillRule): void;
clip(path: Path2D, fillRule?: CanvasFillRule): void;
diff --git a/packages/types/src/lib/core.ts b/packages/types/src/lib/core.ts
index 60c2a24..5a03b5a 100644
--- a/packages/types/src/lib/core.ts
+++ b/packages/types/src/lib/core.ts
@@ -1,14 +1,12 @@
import type { Element, ElementSize, ElementType, ElementPosition } from './element';
import type { ViewScaleInfo } from './view';
import type { Data } from './data';
-import type { ViewContext2D } from './context2d';
import type { BoardBaseEventMap } from './board';
export interface CoreOptions {
width: number;
height: number;
devicePixelRatio?: number;
- createCustomContext2D?: (opts: { width: number; height: number; devicePixelRatio: number }) => ViewContext2D;
}
export type CursorType =
@@ -46,7 +44,9 @@ export interface CoreEventChange {
| 'setData'
| 'undo'
| 'redo'
- | 'changeLayout' // TODO
+ | 'dragLayout'
+ | 'updateLayout'
+ | 'updateElementName'
| 'other';
selectedElements?: Element[] | null;
hoverElement?: Element | null;
@@ -82,7 +82,19 @@ export type CoreEventMap = BoardBaseEventMap & {
change: CoreEventChange;
ruler: { show: boolean; showGrid: boolean };
scale: { scale: number };
- select: { uuids?: string[]; positions?: ElementPosition[] };
+ select: {
+ uuids?: string[];
+ positions?: ElementPosition[];
+ type?:
+ | 'clickCanvas'
+ | 'selectElement'
+ | 'selectElements'
+ | 'selectElementByPosition'
+ | 'selectElementsByPositions'
+ | 'other'
+ | string;
+ };
+ selectLayout: void; // TODO
clearSelect: { uuids?: string[] } | void;
textEdit: CoreEventTextEdit;
textChange: CoreEventTextChange;
diff --git a/packages/types/src/lib/data.ts b/packages/types/src/lib/data.ts
index 40ae62a..ef87813 100644
--- a/packages/types/src/lib/data.ts
+++ b/packages/types/src/lib/data.ts
@@ -1,20 +1,34 @@
-import type { Element, ElementType, ElementAssets, ElementSize, ElementGroupDetail, ElementGlobalDetail } from './element';
+import type { Element, ElementType, ElementAssets, ElementSize, ElementGroupDetail } from './element';
export type DataLayout = Pick & {
detail: Pick<
ElementGroupDetail,
- 'background' | 'borderWidth' | 'overflow' | 'borderColor' | 'borderDash' | 'borderRadius' | 'shadowBlur' | 'shadowColor' | 'shadowOffsetX' | 'shadowOffsetY'
+ | 'background'
+ | 'borderWidth'
+ | 'overflow'
+ | 'borderColor'
+ | 'borderDash'
+ | 'borderRadius'
+ | 'shadowBlur'
+ | 'shadowColor'
+ | 'shadowOffsetX'
+ | 'shadowOffsetY'
>;
operations?: {
position?: 'absolute' | 'relative';
};
};
+export interface DataGlobalDetail {
+ background?: string;
+}
+
export type Data = Record> = {
+ name?: string;
elements: Element[];
assets?: ElementAssets;
layout?: DataLayout;
- global?: ElementGlobalDetail;
+ global?: DataGlobalDetail;
};
export type Matrix = [
diff --git a/packages/types/src/lib/element.ts b/packages/types/src/lib/element.ts
index 4e606e0..7fa6179 100644
--- a/packages/types/src/lib/element.ts
+++ b/packages/types/src/lib/element.ts
@@ -44,7 +44,7 @@ export interface TransformScale {
export type TransformAction = TransformMatrix | TransformTranslate | TransformRotate | TransformScale;
export interface GradientStop {
- offset: number;
+ offset: number; // [0, 1] eg. 0.5
color: string;
}
@@ -92,7 +92,7 @@ export interface ElementBaseDetail {
// // background?: string;
// }
-export interface ElementRectDetail extends ElementBaseDetail {}
+export type ElementRectDetail = ElementBaseDetail;
export interface ElementTextDetail extends ElementBaseDetail {
text: string;
@@ -182,14 +182,15 @@ export interface ElementGlobalDetail {
background?: string;
}
-export interface Element = Record> extends ElementSize {
+export interface Element = Record>
+ extends ElementSize {
uuid: string;
name?: string;
type: T;
detail: ElementDetailMap[T];
operations?: ElementOperations;
extends?: E;
- global?: ElementGlobalDetail;
+ // global?: ElementGlobalDetail;
}
export type Elements = Element[];
diff --git a/packages/types/src/lib/renderer.ts b/packages/types/src/lib/renderer.ts
index 134b0be..b32a7be 100644
--- a/packages/types/src/lib/renderer.ts
+++ b/packages/types/src/lib/renderer.ts
@@ -7,8 +7,8 @@ import { ViewContext2D } from '@idraw/types';
export interface RendererOptions {
viewContext: ViewContext2D;
+ tempContext: ViewContext2D;
sharer?: StoreSharer;
- calculator?: ViewCalculator;
}
export interface RendererEvent {
@@ -37,7 +37,7 @@ export interface RendererDrawOptions {
export interface RendererDrawElementOptions extends RendererDrawOptions {
loader: RendererLoader;
- calculator?: ViewCalculator;
+ calculator: ViewCalculator;
viewScaleInfo: ViewScaleInfo;
viewSizeInfo: ViewSizeInfo;
parentElementSize: ElementSize;
diff --git a/packages/types/src/lib/view.ts b/packages/types/src/lib/view.ts
index 3f6ee5b..7694d41 100644
--- a/packages/types/src/lib/view.ts
+++ b/packages/types/src/lib/view.ts
@@ -1,8 +1,10 @@
-import type { Element, ElementType, ElementPosition } from './element';
+import type { Element, ElementType } from './element';
import type { Point, PointSize } from './point';
import type { Data } from './data';
import type { ViewContext2D } from './context2d';
import type { ModifyOptions } from './modify';
+import { VirtualFlatItem } from './virtual-flat';
+// import type { BoxInfo } from './box';
export interface ViewScaleInfo {
scale: number;
@@ -28,31 +30,22 @@ export interface BoardContent {
viewContext: ViewContext2D;
overlayContext: ViewContext2D;
underlayContext: ViewContext2D;
+ tempContext: ViewContext2D;
drawView: () => void;
}
export interface ViewCalculatorOptions {
// boardContent?: BoardContent;
- viewContext: ViewContext2D;
-}
-
-export interface ViewCalculatorStorage {
- viewVisibleInfoMap: ViewVisibleInfoMap;
- visibleCount: number;
- invisibleCount: number;
+ tempContext: ViewContext2D;
}
export interface ViewCalculator {
- /**
- * @deprecated
- */
- isPointInElement(p: Point, elem: Element, viewScaleInfo: ViewScaleInfo, viewSize: ViewSizeInfo): boolean;
needRender(elem: Element): boolean;
getPointElement(
p: Point,
opts: { data: Data; viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo; groupQueue?: Element<'group'>[] }
): { index: number; element: null | Element; groupQueueIndex: number };
- resetViewVisibleInfoMap(
+ resetVirtualFlatItemMap(
data: Data,
opts: {
viewScaleInfo: ViewScaleInfo;
@@ -76,7 +69,7 @@ export interface ViewCalculator {
viewSizeInfo: ViewSizeInfo;
}
): ViewRectInfo | null;
- modifyViewVisibleInfoMap(
+ modifyVirtualFlatItemMap(
data: Data,
opts: {
modifyOptions: ModifyOptions;
@@ -86,6 +79,7 @@ export interface ViewCalculator {
): void;
toGridNum(num: number, opts?: { ignore?: boolean }): number;
+ getVirtualFlatItem: (uuid: string) => VirtualFlatItem | null;
}
export type ViewRectVertexes = [PointSize, PointSize, PointSize, PointSize];
@@ -109,18 +103,3 @@ export type ViewRectInfo = {
left: PointSize;
center: PointSize;
};
-
-export type ViewRectInfoMap = {
- originRectInfo: ViewRectInfo;
- rangeRectInfo: ViewRectInfo;
-};
-
-export type ViewVisibleInfo = ViewRectInfoMap & {
- isVisibleInView: boolean;
- isGroup: boolean;
- position: ElementPosition;
-};
-
-export type ViewVisibleInfoMap = {
- [uuid: string]: ViewVisibleInfo;
-};
diff --git a/packages/types/src/lib/virtual-flat.ts b/packages/types/src/lib/virtual-flat.ts
new file mode 100644
index 0000000..3c7da2c
--- /dev/null
+++ b/packages/types/src/lib/virtual-flat.ts
@@ -0,0 +1,39 @@
+import type { ViewRectInfo } from './view';
+import type { ElementPosition, ElementType } from './element';
+import type { ViewContext2D } from './context2d';
+
+export type CalcVirtualDetailOptions = {
+ tempContext: ViewContext2D;
+};
+
+export type VirtualFlatTextLine = {
+ x: number;
+ y: number;
+ width: number;
+ text: string;
+};
+
+export type VirtualFlatTextDetail = {
+ textLines?: Array;
+};
+export type VirtualFlatDetail = VirtualFlatTextDetail & {
+ // TODO
+};
+
+export type VirtualFlatItem = {
+ type: ElementType;
+ position: ElementPosition;
+ originRectInfo: ViewRectInfo;
+ rangeRectInfo: ViewRectInfo;
+ isVisibleInView: boolean;
+} & VirtualFlatDetail;
+
+export type VirtualFlatItemMap = {
+ [uuid: string]: VirtualFlatItem;
+};
+
+export interface VirtualFlatStorage {
+ virtualFlatItemMap: VirtualFlatItemMap;
+ visibleCount: number;
+ invisibleCount: number;
+}
diff --git a/packages/util/package.json b/packages/util/package.json
index 86f2cf3..d79bca3 100644
--- a/packages/util/package.json
+++ b/packages/util/package.json
@@ -1,6 +1,6 @@
{
"name": "@idraw/util",
- "version": "0.4.0-beta.39",
+ "version": "0.4.0-beta.40",
"description": "",
"main": "dist/esm/index.js",
"module": "dist/esm/index.js",
@@ -18,7 +18,7 @@
"url": "https://github.com/idrawjs/idraw/issues"
},
"homepage": "https://github.com/idrawjs/idraw#readme",
- "author": "chenshenhai",
+ "author": "idrawjs",
"license": "MIT",
"devDependencies": {
"@idraw/types": "^0.4.0-alpha.0"
diff --git a/packages/util/src/index.ts b/packages/util/src/index.ts
index 931b584..68c9161 100644
--- a/packages/util/src/index.ts
+++ b/packages/util/src/index.ts
@@ -1,15 +1,37 @@
export { delay, compose, throttle, debounce } from './lib/time';
-export { downloadImageFromCanvas, parseFileToBase64, pickFile, parseFileToText, downloadFileFromText } from './lib/file';
-export { toColorHexStr, toColorHexNum, isColorStr, colorNameToHex, colorToCSS, colorToLinearGradientCSS, mergeHexColorAlpha } from './lib/color';
+export {
+ downloadImageFromCanvas,
+ parseFileToBase64,
+ pickFile,
+ parseFileToText,
+ downloadFileFromText
+} from './lib/file';
+export {
+ toColorHexStr,
+ toColorHexNum,
+ isColorStr,
+ colorNameToHex,
+ colorToCSS,
+ colorToLinearGradientCSS,
+ mergeHexColorAlpha
+} from './lib/color';
export { createUUID, isAssetId, createAssetId } from './lib/uuid';
-export { deepClone, sortDataAsserts, deepCloneElement, filterCompactData } from './lib/data';
+export { deepClone, sortDataAsserts, deepCloneElement, deepCloneData, filterCompactData } from './lib/data';
export { istype } from './lib/istype';
export { loadImage, loadSVG, loadHTML } from './lib/load';
export { is } from './lib/is';
export { check } from './lib/check';
export { createBoardContent, createContext2D, createOffscreenContext2D } from './lib/canvas';
export { EventEmitter } from './lib/event';
-export { calcDistance, calcSpeed, equalPoint, equalTouchPoint, vaildPoint, vaildTouchPoint, getCenterFromTwoPoints } from './lib/point';
+export {
+ calcDistance,
+ calcSpeed,
+ equalPoint,
+ equalTouchPoint,
+ vaildPoint,
+ vaildTouchPoint,
+ getCenterFromTwoPoints
+} from './lib/point';
export { Store } from './lib/store';
export { getViewScaleInfoFromSnapshot, getViewSizeInfoFromSnapshot } from './lib/middleware';
export { Context2D } from './lib/context2d';
@@ -60,14 +82,17 @@ export {
calcViewScaleInfo,
calcElementViewRectInfo,
calcElementOriginRectInfo,
- calcElementViewRectInfoMap,
originRectInfoToRangeRectInfo,
isViewPointInElementSize,
isViewPointInVertexes
} from './lib/view-calc';
-export { sortElementsViewVisiableInfoMap, calcVisibleOriginCanvasRectInfo, updateViewVisibleInfoMapStatus } from './lib/view-visible';
export { rotatePoint, rotateVertexes, rotateByCenter } from './lib/rotate';
-export { getElementVertexes, calcElementVertexesInGroup, calcElementVertexesQueueInGroup, calcElementQueueVertexesQueueInGroup } from './lib/vertex';
+export {
+ getElementVertexes,
+ calcElementVertexesInGroup,
+ calcElementVertexesQueueInGroup,
+ calcElementQueueVertexesQueueInGroup
+} from './lib/vertex';
export { calcElementSizeController, calcLayoutSizeController } from './lib/controller';
export { generateSVGPath, parseSVGPath } from './lib/svg-path';
export { generateHTML, parseHTML } from './lib/html';
@@ -93,3 +118,6 @@ export { enhanceFontFamliy } from './lib/text';
export { flatElementList } from './lib/flat';
export { groupElementsByPosition, ungroupElementsByPosition } from './lib/group';
export { calcPointMoveElementInGroup } from './lib/point-move-element';
+export { merge } from './lib/merge';
+export { omit } from './lib/omit';
+export { elementToBoxInfo } from './lib/box';
diff --git a/packages/util/src/lib/box.ts b/packages/util/src/lib/box.ts
new file mode 100644
index 0000000..d7f5b8d
--- /dev/null
+++ b/packages/util/src/lib/box.ts
@@ -0,0 +1,186 @@
+import type { BoxInfo, Element, PointSize } from '@idraw/types';
+import { is } from './is';
+
+export function elementToBoxInfo(elem: Element): BoxInfo {
+ const { x, y, w, h, detail } = elem;
+ const { borderWidth, borderRadius, boxSizing } = detail;
+ let btw: number = 0; // border-top-width
+ let brw: number = 0; // border-right-width
+ let bbw: number = 0; // border-bottom-width
+ let blw: number = 0; // border-left-width
+
+ let btlr: number = 0; // border-top-left-radius
+ let btrr: number = 0; // border-top-right-radius
+ let bblr: number = 0; // border-bottom-left-radius
+ let bbrr: number = 0; // border-bottom-right-radius
+
+ if (typeof borderWidth === 'number' && borderWidth > 0) {
+ btw = borderWidth;
+ brw = borderWidth;
+ bbw = borderWidth;
+ blw = borderWidth;
+ } else if (Array.isArray(borderWidth)) {
+ btw = is.positiveNum(borderWidth[0]) ? borderWidth[0] : 0;
+ brw = is.positiveNum(borderWidth[1]) ? borderWidth[0] : 0;
+ bbw = is.positiveNum(borderWidth[2]) ? borderWidth[0] : 0;
+ blw = is.positiveNum(borderWidth[3]) ? borderWidth[0] : 0;
+ }
+
+ if (typeof borderRadius === 'number' && borderRadius > 0) {
+ btlr = borderRadius;
+ btrr = borderRadius;
+ bblr = borderRadius;
+ bbrr = borderRadius;
+ } else if (Array.isArray(borderRadius)) {
+ btlr = is.positiveNum(borderRadius[0]) ? borderRadius[0] : 0;
+ btrr = is.positiveNum(borderRadius[0]) ? borderRadius[0] : 0;
+ bblr = is.positiveNum(borderRadius[0]) ? borderRadius[0] : 0;
+ bbrr = is.positiveNum(borderRadius[0]) ? borderRadius[0] : 0;
+ }
+ const p0: PointSize = { x: x, y: y }; // pointer border-top-left
+ const p1: PointSize = { x: x + w, y: y }; // pointer border-top-right
+ const p2: PointSize = { x: x + w, y: y + h }; // pointer border-bottom-right
+ const p3: PointSize = { x: x, y: y + h }; // pointer border-bottom-left
+
+ const p0s: PointSize = { x: x, y: y + btlr }; // pointer border-top-left start
+ const p0e: PointSize = { x: x + btlr, y: y }; // pointer border-top-left end
+ const p1s: PointSize = { x: x + w - btrr, y: y }; // pointer border-top-right start
+ const p1e: PointSize = { x: x + w, y: y + btrr }; // pointer border-top-right start
+ const p2s: PointSize = { x: x + w, y: y + h - bbrr }; // pointer border-bottom-right start
+ const p2e: PointSize = { x: x + w - bbrr, y: y + h }; // pointer border-bottom-right end
+ const p3s: PointSize = { x: x + bblr, y: y + h }; // pointer border-bottom-left start
+ const p3e: PointSize = { x: x, y: y + h - bblr }; // pointer border-bottom-left end
+
+ let op0: PointSize = { ...p0 }; // outer pointer border-top-left
+ let op1: PointSize = { ...p1 }; // outer pointer border-top-right
+ let op2: PointSize = { ...p2 }; // outer pointer border-bottom-right
+ let op3: PointSize = { ...p3 }; // outer pointer border-bottom-left
+
+ let op0s: PointSize = { ...p0s }; // outer pointer border-top-left start
+ let op0e: PointSize = { ...p0e }; // outer pointer border-top-left end
+ let op1s: PointSize = { ...p1s }; // outer pointer border-top-right start
+ let op1e: PointSize = { ...p1e }; // outer pointer border-top-right start
+ let op2s: PointSize = { ...p2s }; // outer pointer border-bottom-right start
+ let op2e: PointSize = { ...p2e }; // outer pointer border-bottom-right end
+ let op3s: PointSize = { ...p3s }; // outer pointer border-bottom-left start
+ let op3e: PointSize = { ...p3e }; // outer pointer border-bottom-left end
+
+ let ip0: PointSize = { ...p0 }; // inner pointer border-top-left
+ let ip1: PointSize = { ...p1 }; // inner pointer border-top-right
+ let ip2: PointSize = { ...p2 }; // inner pointer border-bottom-right
+ let ip3: PointSize = { ...p3 }; // inner pointer border-bottom-left
+
+ let ip0s: PointSize = { ...p0s }; // inner pointer border-top-left start
+ let ip0e: PointSize = { ...p0e }; // inner pointer border-top-left end
+ let ip1s: PointSize = { ...p1s }; // inner pointer border-top-right start
+ let ip1e: PointSize = { ...p1e }; // inner pointer border-top-right start
+ let ip2s: PointSize = { ...p2s }; // inner pointer border-bottom-right start
+ let ip2e: PointSize = { ...p2e }; // inner pointer border-bottom-right end
+ let ip3s: PointSize = { ...p3s }; // inner pointer border-bottom-left start
+ let ip3e: PointSize = { ...p3e }; // inner pointer border-bottom-left end
+
+ if (boxSizing === 'border-box') {
+ ip0 = { x: ip0.x + blw, y: ip0.y + btw };
+ ip1 = { x: ip1.x - brw, y: ip1.y + btw };
+ ip2 = { x: ip2.x - brw, y: ip2.y - bbw };
+ ip3 = { x: ip3.x + blw, y: ip3.y - bbw };
+ ip0s = { x: ip0s.x + blw, y: ip0s.y + btw };
+ ip0e = { x: ip0e.x + blw, y: ip0e.y + btw };
+ ip1s = { x: ip1s.x - brw, y: ip1s.y + btw };
+ ip1e = { x: ip1e.x - brw, y: ip1e.y + btw };
+ ip2s = { x: ip2s.x - brw, y: ip2s.y - bbw };
+ ip2e = { x: ip2e.x - brw, y: ip2e.y - bbw };
+ ip3s = { x: ip3s.x + blw, y: ip3s.y - bbw };
+ ip3e = { x: ip3e.x + blw, y: ip3e.y - bbw };
+ } else if (boxSizing === 'content-box') {
+ op0 = { x: op0.x - blw, y: op0.y - btw };
+ op1 = { x: op1.x + brw, y: op1.y - btw };
+ op2 = { x: op2.x + brw, y: op2.y + bbw };
+ op3 = { x: op3.x - blw, y: op3.y + bbw };
+ op0s = { x: op0s.x - blw, y: op0s.y - btw };
+ op0e = { x: op0e.x - blw, y: op0e.y - btw };
+ op1s = { x: op1s.x + brw, y: op1s.y - btw };
+ op1e = { x: op1e.x + brw, y: op1e.y - btw };
+ op2s = { x: op2s.x + brw, y: op2s.y + bbw };
+ op2e = { x: op2e.x + brw, y: op2e.y + bbw };
+ op3s = { x: op3s.x - blw, y: op3s.y + bbw };
+ op3e = { x: op3e.x - blw, y: op3e.y + bbw };
+ } else {
+ ip0 = { x: ip0.x + blw / 2, y: ip0.y + btw / 2 };
+ ip1 = { x: ip1.x - brw / 2, y: ip1.y + btw / 2 };
+ ip2 = { x: ip2.x - brw / 2, y: ip2.y - bbw / 2 };
+ ip3 = { x: ip3.x + blw / 2, y: ip3.y - bbw / 2 };
+ ip0s = { x: ip0s.x + blw / 2, y: ip0s.y + btw / 2 };
+ ip0e = { x: ip0e.x + blw / 2, y: ip0e.y + btw / 2 };
+ ip1s = { x: ip1s.x - brw / 2, y: ip1s.y + btw / 2 };
+ ip1e = { x: ip1e.x - brw / 2, y: ip1e.y + btw / 2 };
+ ip2s = { x: ip2s.x - brw / 2, y: ip2s.y - bbw / 2 };
+ ip2e = { x: ip2e.x - brw / 2, y: ip2e.y - bbw / 2 };
+ ip3s = { x: ip3s.x + blw / 2, y: ip3s.y - bbw / 2 };
+ ip3e = { x: ip3e.x + blw / 2, y: ip3e.y - bbw / 2 };
+
+ op0 = { x: op0.x - blw / 2, y: op0.y - btw / 2 };
+ op1 = { x: op1.x + brw / 2, y: op1.y - btw / 2 };
+ op2 = { x: op2.x + brw / 2, y: op2.y + bbw / 2 };
+ op3 = { x: op3.x - blw / 2, y: op3.y + bbw / 2 };
+ op0s = { x: op0s.x - blw / 2, y: op0s.y - btw / 2 };
+ op0e = { x: op0e.x - blw / 2, y: op0e.y - btw / 2 };
+ op1s = { x: op1s.x + brw / 2, y: op1s.y - btw / 2 };
+ op1e = { x: op1e.x + brw / 2, y: op1e.y - btw / 2 };
+ op2s = { x: op2s.x + brw / 2, y: op2s.y + bbw / 2 };
+ op2e = { x: op2e.x + brw / 2, y: op2e.y + bbw / 2 };
+ op3s = { x: op3s.x - blw / 2, y: op3s.y + bbw / 2 };
+ op3e = { x: op3e.x - blw / 2, y: op3e.y + bbw / 2 };
+ }
+
+ return {
+ btw,
+ brw,
+ bbw,
+ blw,
+
+ btlr,
+ btrr,
+ bblr,
+ bbrr,
+
+ p0,
+ p1,
+ p2,
+ p3,
+ p0s,
+ p0e,
+ p1s,
+ p1e,
+ p2s,
+ p2e,
+ p3s,
+ p3e,
+
+ op0,
+ op1,
+ op2,
+ op3,
+ op0s,
+ op0e,
+ op1s,
+ op1e,
+ op2s,
+ op2e,
+ op3s,
+ op3e,
+
+ ip0,
+ ip1,
+ ip2,
+ ip3,
+ ip0s,
+ ip0e,
+ ip1s,
+ ip1e,
+ ip2s,
+ ip2e,
+ ip3s,
+ ip3e
+ };
+}
diff --git a/packages/util/src/lib/canvas.ts b/packages/util/src/lib/canvas.ts
index 39cf9c3..6a646c6 100644
--- a/packages/util/src/lib/canvas.ts
+++ b/packages/util/src/lib/canvas.ts
@@ -1,7 +1,12 @@
-import type { BoardContent, ViewContext2D } from '@idraw/types';
+import type { BoardContent } from '@idraw/types';
import { Context2D } from './context2d';
-export function createContext2D(opts: { ctx?: CanvasRenderingContext2D; width: number; height: number; devicePixelRatio: number }): Context2D {
+export function createContext2D(opts: {
+ ctx?: CanvasRenderingContext2D;
+ width: number;
+ height: number;
+ devicePixelRatio: number;
+}): Context2D {
const { width, height, ctx, devicePixelRatio } = opts;
let context: CanvasRenderingContext2D | undefined = ctx;
if (!context) {
@@ -34,11 +39,9 @@ export function createBoardContent(
width: number;
height: number;
devicePixelRatio: number;
- offscreen?: boolean;
- createCustomContext2D?: (opts: { width: number; height: number; devicePixelRatio: number }) => ViewContext2D;
}
): BoardContent {
- const { width, height, devicePixelRatio, offscreen, createCustomContext2D } = opts;
+ const { width, height, devicePixelRatio } = opts;
const ctxOpts = {
width,
height,
@@ -47,86 +50,32 @@ export function createBoardContent(
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
- if (createCustomContext2D) {
- // TODO
- const viewContext = createCustomContext2D(ctxOpts);
- const overlayContext = createCustomContext2D(ctxOpts);
- const underlayContext = createCustomContext2D(ctxOpts);
- const boardContext = createContext2D({ ctx, ...ctxOpts });
+ // const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
+ const viewContext = createOffscreenContext2D(ctxOpts);
+ const overlayContext = createOffscreenContext2D(ctxOpts);
+ const underlayContext = createOffscreenContext2D(ctxOpts);
+ const boardContext = createContext2D({ ctx, ...ctxOpts });
+ const tempContext = createOffscreenContext2D(ctxOpts);
- const drawView = () => {
- const { width: w, height: h } = viewContext.$getSize();
+ const drawView = () => {
+ const { width: w, height: h } = viewContext.$getSize();
- boardContext.clearRect(0, 0, w, h);
- boardContext.drawImage(underlayContext.canvas, 0, 0, w, h);
- boardContext.drawImage(viewContext.canvas, 0, 0, w, h);
- boardContext.drawImage(overlayContext.canvas, 0, 0, w, h);
- underlayContext.clearRect(0, 0, w, h);
- viewContext.clearRect(0, 0, w, h);
- overlayContext.clearRect(0, 0, w, h);
- };
+ boardContext.clearRect(0, 0, w, h);
+ boardContext.drawImage(underlayContext.canvas, 0, 0, w, h);
+ boardContext.drawImage(viewContext.canvas, 0, 0, w, h);
+ boardContext.drawImage(overlayContext.canvas, 0, 0, w, h);
+ underlayContext.clearRect(0, 0, w, h);
+ viewContext.clearRect(0, 0, w, h);
+ overlayContext.clearRect(0, 0, w, h);
+ };
- const content: BoardContent = {
- underlayContext,
- viewContext,
- overlayContext,
- boardContext,
- drawView
- };
- return content;
- }
-
- if (offscreen === true) {
- // const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
- const viewContext = createOffscreenContext2D(ctxOpts);
- const overlayContext = createOffscreenContext2D(ctxOpts);
- const underlayContext = createOffscreenContext2D(ctxOpts);
- const boardContext = createContext2D({ ctx, ...ctxOpts });
-
- const drawView = () => {
- const { width: w, height: h } = viewContext.$getSize();
-
- boardContext.clearRect(0, 0, w, h);
- boardContext.drawImage(underlayContext.canvas, 0, 0, w, h);
- boardContext.drawImage(viewContext.canvas, 0, 0, w, h);
- boardContext.drawImage(overlayContext.canvas, 0, 0, w, h);
- underlayContext.clearRect(0, 0, w, h);
- viewContext.clearRect(0, 0, w, h);
- overlayContext.clearRect(0, 0, w, h);
- };
-
- const content: BoardContent = {
- underlayContext,
- viewContext,
- overlayContext,
- boardContext,
- drawView
- };
- return content;
- } else {
- // const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
- const viewContext = createContext2D(ctxOpts);
- const overlayContext = createContext2D(ctxOpts);
- const underlayContext = createContext2D(ctxOpts);
- const boardContext = createContext2D({ ctx, ...ctxOpts });
-
- const drawView = () => {
- boardContext.clearRect(0, 0, width, height);
- boardContext.drawImage(underlayContext.canvas, 0, 0, width, height);
- boardContext.drawImage(viewContext.canvas, 0, 0, width, height);
- boardContext.drawImage(overlayContext.canvas, 0, 0, width, height);
- underlayContext.clearRect(0, 0, width, height);
- viewContext.clearRect(0, 0, width, height);
- overlayContext.clearRect(0, 0, width, height);
- };
-
- const content: BoardContent = {
- underlayContext,
- viewContext,
- overlayContext,
- boardContext,
- drawView
- };
- return content;
- }
+ const content: BoardContent = {
+ underlayContext,
+ viewContext,
+ overlayContext,
+ boardContext,
+ tempContext,
+ drawView
+ };
+ return content;
}
diff --git a/packages/util/src/lib/color.ts b/packages/util/src/lib/color.ts
index a4311ee..42d70ea 100644
--- a/packages/util/src/lib/color.ts
+++ b/packages/util/src/lib/color.ts
@@ -1,7 +1,7 @@
import type { LinearGradientColor, RadialGradientColor } from '@idraw/types';
export function toColorHexNum(color: string): number {
- return parseInt(color.replace(/^\#/, '0x'));
+ return parseInt(color.replace(/^#/, '0x'));
}
export function toColorHexStr(color: number): string {
@@ -9,7 +9,9 @@ export function toColorHexStr(color: number): string {
}
export function isColorStr(color?: string): boolean {
- return typeof color === 'string' && (/^\#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(color) || /^[a-z]{1,}$/i.test(color));
+ return (
+ typeof color === 'string' && (/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(color) || /^[a-z]{1,}$/i.test(color))
+ );
}
// https://stackoverflow.com/questions/1573053/javascript-function-to-convert-color-names-to-hex-codes
@@ -170,6 +172,8 @@ export function colorToCSS(color?: string | LinearGradientColor | RadialGradient
let css = 'transparent';
if (typeof color === 'string') {
css = color;
+ } else if (color?.stops.length === 1) {
+ css = color.stops[0].color;
} else if (color?.type === 'linear-gradient') {
const items: string[] = [];
if (typeof color.angle === 'number') {
@@ -220,13 +224,13 @@ export function mergeHexColorAlpha(hex: string, alpha: number): string {
return hex;
}
let hexAlpha = 1;
- const regHex1 = /^\#[0-9a-f]{6,6}$/i;
- const regHex2 = /^\#[0-9a-f]{8,8}$/i;
+ const regHex1 = /^#[0-9a-f]{6,6}$/i;
+ const regHex2 = /^#[0-9a-f]{8,8}$/i;
let result = hex;
if (regHex1.test(hex)) {
- hexAlpha = parseInt(hex.substring(5, 7).replace(/^\#/, '0x'));
+ hexAlpha = parseInt(hex.substring(5, 7).replace(/^#/, '0x'));
} else if (regHex2.test(hex)) {
- hexAlpha = parseInt(hex.substring(7, 9).replace(/^\#/, '0x'));
+ hexAlpha = parseInt(hex.substring(7, 9).replace(/^#/, '0x'));
result = hex.substring(0, 7);
}
hexAlpha = hexAlpha * alpha;
diff --git a/packages/util/src/lib/context2d.ts b/packages/util/src/lib/context2d.ts
index d1c96db..ed8ffe1 100644
--- a/packages/util/src/lib/context2d.ts
+++ b/packages/util/src/lib/context2d.ts
@@ -175,8 +175,22 @@ export class Context2D implements ViewContext2D {
return this.#ctx.fill(...(args as [path: Path2D, fillRule?: CanvasFillRule | undefined]));
}
- arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean | undefined): void {
- return this.#ctx.arc(this.$doPixelRatio(x), this.$doPixelRatio(y), this.$doPixelRatio(radius), startAngle, endAngle, anticlockwise);
+ arc(
+ x: number,
+ y: number,
+ radius: number,
+ startAngle: number,
+ endAngle: number,
+ anticlockwise?: boolean | undefined
+ ): void {
+ return this.#ctx.arc(
+ this.$doPixelRatio(x),
+ this.$doPixelRatio(y),
+ this.$doPixelRatio(radius),
+ startAngle,
+ endAngle,
+ anticlockwise
+ );
}
rect(x: number, y: number, w: number, h: number) {
@@ -184,11 +198,21 @@ export class Context2D implements ViewContext2D {
}
fillRect(x: number, y: number, w: number, h: number) {
- return this.#ctx.fillRect(this.$doPixelRatio(x), this.$doPixelRatio(y), this.$doPixelRatio(w), this.$doPixelRatio(h));
+ return this.#ctx.fillRect(
+ this.$doPixelRatio(x),
+ this.$doPixelRatio(y),
+ this.$doPixelRatio(w),
+ this.$doPixelRatio(h)
+ );
}
clearRect(x: number, y: number, w: number, h: number) {
- return this.#ctx.clearRect(this.$doPixelRatio(x), this.$doPixelRatio(y), this.$doPixelRatio(w), this.$doPixelRatio(h));
+ return this.#ctx.clearRect(
+ this.$doPixelRatio(x),
+ this.$doPixelRatio(y),
+ this.$doPixelRatio(w),
+ this.$doPixelRatio(h)
+ );
}
beginPath() {
@@ -208,7 +232,32 @@ export class Context2D implements ViewContext2D {
}
arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void {
- return this.#ctx.arcTo(this.$doPixelRatio(x1), this.$doPixelRatio(y1), this.$doPixelRatio(x2), this.$doPixelRatio(y2), this.$doPixelRatio(radius));
+ return this.#ctx.arcTo(
+ this.$doPixelRatio(x1),
+ this.$doPixelRatio(y1),
+ this.$doPixelRatio(x2),
+ this.$doPixelRatio(y2),
+ this.$doPixelRatio(radius)
+ );
+ }
+
+ bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void {
+ return this.#ctx.bezierCurveTo(
+ this.$doPixelRatio(cp1x),
+ this.$doPixelRatio(cp1y),
+ this.$doPixelRatio(cp2x),
+ this.$doPixelRatio(cp2y),
+ this.$doPixelRatio(x),
+ this.$doPixelRatio(y)
+ );
+ }
+ quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void {
+ return this.#ctx.quadraticCurveTo(
+ this.$doPixelRatio(cpx),
+ this.$doPixelRatio(cpy),
+ this.$doPixelRatio(x),
+ this.$doPixelRatio(y)
+ );
}
getLineDash() {
@@ -257,7 +306,13 @@ export class Context2D implements ViewContext2D {
this.$doPixelRatio(dh)
);
} else {
- return this.#ctx.drawImage(image, this.$doPixelRatio(dx), this.$doPixelRatio(dy), this.$doPixelRatio(dw), this.$doPixelRatio(dh));
+ return this.#ctx.drawImage(
+ image,
+ this.$doPixelRatio(dx),
+ this.$doPixelRatio(dy),
+ this.$doPixelRatio(dw),
+ this.$doPixelRatio(dh)
+ );
}
}
@@ -338,7 +393,12 @@ export class Context2D implements ViewContext2D {
}
createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient {
- return this.#ctx.createLinearGradient(this.$doPixelRatio(x0), this.$doPixelRatio(y0), this.$doPixelRatio(x1), this.$doPixelRatio(y1));
+ return this.#ctx.createLinearGradient(
+ this.$doPixelRatio(x0),
+ this.$doPixelRatio(y0),
+ this.$doPixelRatio(x1),
+ this.$doPixelRatio(y1)
+ );
}
createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient {
return this.#ctx.createRadialGradient(
diff --git a/packages/util/src/lib/data.ts b/packages/util/src/lib/data.ts
index e899ac6..e4dc667 100644
--- a/packages/util/src/lib/data.ts
+++ b/packages/util/src/lib/data.ts
@@ -42,11 +42,24 @@ export function deepCloneElement(element: T): T {
return elem;
}
+export function deepCloneData(data: Data): Data {
+ const { elements, ...restData } = data;
+ return {
+ ...deepClone(restData),
+ ...{
+ elements: elements.map((elem) => deepCloneElement(elem))
+ }
+ };
+}
+
function is(target: any): string {
- return Object.prototype.toString
- .call(target)
- .replace(/[\]|\[]{1,1}/gi, '')
- .split(' ')[1];
+ return (
+ Object.prototype.toString
+ .call(target)
+ // eslint-disable-next-line no-useless-escape
+ .replace(/[\]|\[]{1,1}/gi, '')
+ .split(' ')[1]
+ );
}
export function sortDataAsserts(data: Data, opts?: { clone?: boolean }): Data {
diff --git a/packages/util/src/lib/is.ts b/packages/util/src/lib/is.ts
index 881844f..9521a3d 100644
--- a/packages/util/src/lib/is.ts
+++ b/packages/util/src/lib/is.ts
@@ -1,5 +1,9 @@
import { isColorStr } from './color';
+function positiveNum(value: any) {
+ return typeof value === 'number' && value >= 0;
+}
+
function number(value: any) {
return typeof value === 'number' && (value > 0 || value <= 0);
}
@@ -13,11 +17,11 @@ function y(value: any) {
}
function w(value: any) {
- return typeof value === 'number' && value >= 0;
+ return positiveNum(value);
}
function h(value: any) {
- return typeof value === 'number' && value >= 0;
+ return positiveNum(value);
}
function angle(value: any) {
@@ -25,11 +29,25 @@ function angle(value: any) {
}
function borderWidth(value: any) {
- return w(value);
+ return (
+ positiveNum(value) ||
+ (Array.isArray(value) &&
+ positiveNum(value[0]) &&
+ positiveNum(value[1]) &&
+ positiveNum(value[2]) &&
+ positiveNum(value[3]))
+ );
}
function borderRadius(value: any) {
- return number(value) && value >= 0;
+ return (
+ positiveNum(value) ||
+ (Array.isArray(value) &&
+ positiveNum(value[0]) &&
+ positiveNum(value[1]) &&
+ positiveNum(value[2]) &&
+ positiveNum(value[3]))
+ );
}
function color(value: any) {
@@ -49,7 +67,11 @@ function imageSrc(value: any) {
}
function svg(value: any) {
- return typeof value === 'string' && /^(