@ibiz-template/vue3-util 0.7.41-alpha.13 → 0.7.41-alpha.131
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.min.css +1 -1
- package/dist/index.system.min.js +1 -1
- package/es/common/badge/badge.css +1 -1
- package/es/common/badge/badge.d.ts +6 -8
- package/es/common/badge/badge.d.ts.map +1 -1
- package/es/common/badge/badge.mjs +13 -7
- package/es/common/code-list/code-list.d.ts +10 -10
- package/es/common/code-list/code-list.d.ts.map +1 -1
- package/es/common/code-list/code-list.mjs +1 -1
- package/es/common/control-base/control-base.d.ts.map +1 -1
- package/es/common/control-base/control-base.mjs +9 -15
- package/es/common/control-loading-placeholder/control-loading-placeholder.d.ts +4 -4
- package/es/common/control-loading-placeholder/control-loading-placeholder.d.ts.map +1 -1
- package/es/common/control-shell/control-shell.d.ts +7 -7
- package/es/common/control-shell/control-shell.d.ts.map +1 -1
- package/es/common/control-shell/control-shell.mjs +1 -1
- package/es/common/custom-render/custom-render.d.ts +4 -4
- package/es/common/custom-render/custom-render.d.ts.map +1 -1
- package/es/common/icon/icon.d.ts +4 -4
- package/es/common/icon/icon.d.ts.map +1 -1
- package/es/common/icon/icon.mjs +12 -0
- package/es/common/index.d.ts +1 -0
- package/es/common/index.d.ts.map +1 -1
- package/es/common/index.mjs +1 -0
- package/es/common/router-view/router-view.d.ts +7 -8
- package/es/common/router-view/router-view.d.ts.map +1 -1
- package/es/common/router-view/router-view.mjs +1 -1
- package/es/common/signature-pad/signature-pad.css +1 -0
- package/es/common/signature-pad/signature-pad.d.ts +19 -0
- package/es/common/signature-pad/signature-pad.d.ts.map +1 -0
- package/es/common/signature-pad/signature-pad.mjs +165 -0
- package/es/common/signature-pad/util/bezier.d.ts +58 -0
- package/es/common/signature-pad/util/bezier.d.ts.map +1 -0
- package/es/common/signature-pad/util/bezier.mjs +109 -0
- package/es/common/signature-pad/util/point.d.ts +55 -0
- package/es/common/signature-pad/util/point.d.ts.map +1 -0
- package/es/common/signature-pad/util/point.mjs +51 -0
- package/es/common/signature-pad/util/signature_pad.d.ts +593 -0
- package/es/common/signature-pad/util/signature_pad.d.ts.map +1 -0
- package/es/common/signature-pad/util/signature_pad.mjs +1018 -0
- package/es/common/view-shell/view-shell.d.ts +19 -12
- package/es/common/view-shell/view-shell.d.ts.map +1 -1
- package/es/common/view-shell/view-shell.mjs +42 -23
- package/es/control/panel/panel/index.d.ts +5 -5
- package/es/control/panel/panel/index.d.ts.map +1 -1
- package/es/control/panel/panel/panel.d.ts +6 -6
- package/es/control/panel/panel/panel.d.ts.map +1 -1
- package/es/control/panel/panel/panel.mjs +13 -5
- package/es/control/panel/view-layout-panel/index.d.ts +5 -5
- package/es/control/panel/view-layout-panel/index.d.ts.map +1 -1
- package/es/control/panel/view-layout-panel/view-layout-panel.d.ts +7 -7
- package/es/control/panel/view-layout-panel/view-layout-panel.d.ts.map +1 -1
- package/es/control/panel/view-layout-panel/view-layout-panel.mjs +6 -6
- package/es/index.mjs +9 -11
- package/es/locale/en/index.d.ts +1 -0
- package/es/locale/en/index.d.ts.map +1 -1
- package/es/locale/en/index.mjs +2 -1
- package/es/locale/zh-CN/index.d.ts +1 -0
- package/es/locale/zh-CN/index.d.ts.map +1 -1
- package/es/locale/zh-CN/index.mjs +2 -1
- package/es/node_modules/.pnpm/path-browserify@1.0.1/node_modules/path-browserify/index.mjs +2 -2
- package/es/panel-component/auth-wxmp-qrcode/auth-wxmp-qrcode.controller.d.ts.map +1 -1
- package/es/panel-component/auth-wxmp-qrcode/auth-wxmp-qrcode.controller.mjs +3 -1
- package/es/panel-component/auth-wxmp-qrcode/auth-wxmp-qrcode.css +1 -1
- package/es/panel-component/auth-wxmp-qrcode/auth-wxmp-qrcode.d.ts +6 -4
- package/es/panel-component/auth-wxmp-qrcode/auth-wxmp-qrcode.d.ts.map +1 -1
- package/es/panel-component/auth-wxmp-qrcode/auth-wxmp-qrcode.mjs +17 -6
- package/es/panel-component/auth-wxmp-qrcode/index.d.ts +6 -4
- package/es/panel-component/auth-wxmp-qrcode/index.d.ts.map +1 -1
- package/es/panel-component/grid-container/grid-container.controller.d.ts +3 -3
- package/es/panel-component/grid-container/grid-container.controller.d.ts.map +1 -1
- package/es/panel-component/grid-container/grid-container.controller.mjs +2 -2
- package/es/panel-component/grid-container/grid-container.d.ts +8 -6
- package/es/panel-component/grid-container/grid-container.d.ts.map +1 -1
- package/es/panel-component/grid-container/grid-container.mjs +17 -6
- package/es/panel-component/grid-container/grid-container.state.d.ts +3 -3
- package/es/panel-component/grid-container/grid-container.state.d.ts.map +1 -1
- package/es/panel-component/grid-container/grid-container.state.mjs +2 -2
- package/es/panel-component/grid-container/index.d.ts +8 -6
- package/es/panel-component/grid-container/index.d.ts.map +1 -1
- package/es/panel-component/index.d.ts +0 -1
- package/es/panel-component/index.d.ts.map +1 -1
- package/es/panel-component/index.mjs +1 -5
- package/es/panel-component/multi-data-container/index.d.ts +6 -4
- package/es/panel-component/multi-data-container/index.d.ts.map +1 -1
- package/es/panel-component/multi-data-container/multi-data-container.controller.d.ts +4 -4
- package/es/panel-component/multi-data-container/multi-data-container.controller.d.ts.map +1 -1
- package/es/panel-component/multi-data-container/multi-data-container.controller.mjs +88 -69
- package/es/panel-component/multi-data-container/multi-data-container.d.ts +7 -5
- package/es/panel-component/multi-data-container/multi-data-container.d.ts.map +1 -1
- package/es/panel-component/multi-data-container/multi-data-container.mjs +20 -6
- package/es/panel-component/multi-data-container/multi-data-container.state.d.ts +3 -3
- package/es/panel-component/multi-data-container/multi-data-container.state.d.ts.map +1 -1
- package/es/panel-component/multi-data-container/multi-data-container.state.mjs +2 -2
- package/es/panel-component/multi-data-container-raw/index.d.ts +6 -4
- package/es/panel-component/multi-data-container-raw/index.d.ts.map +1 -1
- package/es/panel-component/multi-data-container-raw/multi-data-container-raw.controller.d.ts +4 -4
- package/es/panel-component/multi-data-container-raw/multi-data-container-raw.controller.d.ts.map +1 -1
- package/es/panel-component/multi-data-container-raw/multi-data-container-raw.controller.mjs +88 -69
- package/es/panel-component/multi-data-container-raw/multi-data-container-raw.d.ts +7 -5
- package/es/panel-component/multi-data-container-raw/multi-data-container-raw.d.ts.map +1 -1
- package/es/panel-component/multi-data-container-raw/multi-data-container-raw.mjs +23 -7
- package/es/panel-component/multi-data-container-raw/multi-data-container-raw.state.d.ts +3 -3
- package/es/panel-component/multi-data-container-raw/multi-data-container-raw.state.d.ts.map +1 -1
- package/es/panel-component/multi-data-container-raw/multi-data-container-raw.state.mjs +2 -2
- package/es/panel-component/nav-pos/index.d.ts +7 -5
- package/es/panel-component/nav-pos/index.d.ts.map +1 -1
- package/es/panel-component/nav-pos/nav-pos.controller.d.ts +1 -1
- package/es/panel-component/nav-pos/nav-pos.d.ts +8 -6
- package/es/panel-component/nav-pos/nav-pos.d.ts.map +1 -1
- package/es/panel-component/nav-pos/nav-pos.mjs +20 -5
- package/es/panel-component/panel-container/index.d.ts +7 -6
- package/es/panel-component/panel-container/index.d.ts.map +1 -1
- package/es/panel-component/panel-container/index.mjs +1 -2
- package/es/panel-component/panel-container/panel-container.d.ts +7 -5
- package/es/panel-component/panel-container/panel-container.d.ts.map +1 -1
- package/es/panel-component/panel-container/panel-container.mjs +36 -15
- package/es/panel-component/panel-container/panel-container.provider.d.ts +2 -2
- package/es/panel-component/panel-container/panel-container.provider.d.ts.map +1 -1
- package/es/panel-component/panel-container/panel-container.provider.mjs +1 -1
- package/es/panel-component/panel-container-image/index.d.ts +6 -4
- package/es/panel-component/panel-container-image/index.d.ts.map +1 -1
- package/es/panel-component/panel-container-image/panel-container-image.controller.d.ts +3 -3
- package/es/panel-component/panel-container-image/panel-container-image.controller.d.ts.map +1 -1
- package/es/panel-component/panel-container-image/panel-container-image.controller.mjs +2 -2
- package/es/panel-component/panel-container-image/panel-container-image.css +1 -1
- package/es/panel-component/panel-container-image/panel-container-image.d.ts +6 -4
- package/es/panel-component/panel-container-image/panel-container-image.d.ts.map +1 -1
- package/es/panel-component/panel-container-image/panel-container-image.mjs +24 -10
- package/es/panel-component/panel-container-image/panel-container-image.state.d.ts +3 -3
- package/es/panel-component/panel-container-image/panel-container-image.state.d.ts.map +1 -1
- package/es/panel-component/panel-container-image/panel-container-image.state.mjs +2 -2
- package/es/panel-component/panel-container-tabs/index.d.ts +6 -6
- package/es/panel-component/panel-container-tabs/index.d.ts.map +1 -1
- package/es/panel-component/panel-container-tabs/panel-container-tabs.d.ts +5 -5
- package/es/panel-component/panel-container-tabs/panel-container-tabs.d.ts.map +1 -1
- package/es/panel-component/panel-container-tabs/panel-container-tabs.mjs +1 -1
- package/es/panel-component/panel-container-tabs/panel-container-tabs.provider.d.ts +2 -2
- package/es/panel-component/panel-container-tabs/panel-container-tabs.provider.d.ts.map +1 -1
- package/es/panel-component/panel-container-tabs/panel-container-tabs.provider.mjs +1 -1
- package/es/panel-component/panel-ctrl-pos/index.d.ts +6 -4
- package/es/panel-component/panel-ctrl-pos/index.d.ts.map +1 -1
- package/es/panel-component/panel-ctrl-pos/panel-ctrl-pos.d.ts +6 -4
- package/es/panel-component/panel-ctrl-pos/panel-ctrl-pos.d.ts.map +1 -1
- package/es/panel-component/panel-ctrl-pos/panel-ctrl-pos.mjs +12 -4
- package/es/panel-component/panel-ctrl-view-page-caption/index.d.ts +6 -4
- package/es/panel-component/panel-ctrl-view-page-caption/index.d.ts.map +1 -1
- package/es/panel-component/panel-ctrl-view-page-caption/panel-ctrl-view-page-caption.css +1 -0
- package/es/panel-component/panel-ctrl-view-page-caption/panel-ctrl-view-page-caption.d.ts +7 -4
- package/es/panel-component/panel-ctrl-view-page-caption/panel-ctrl-view-page-caption.d.ts.map +1 -1
- package/es/panel-component/panel-ctrl-view-page-caption/panel-ctrl-view-page-caption.mjs +16 -8
- package/es/panel-component/panel-field/index.d.ts +7 -4
- package/es/panel-component/panel-field/index.d.ts.map +1 -1
- package/es/panel-component/panel-field/panel-field.controller.d.ts +12 -0
- package/es/panel-component/panel-field/panel-field.controller.d.ts.map +1 -1
- package/es/panel-component/panel-field/panel-field.controller.mjs +37 -3
- package/es/panel-component/panel-field/panel-field.css +1 -1
- package/es/panel-component/panel-field/panel-field.d.ts +7 -4
- package/es/panel-component/panel-field/panel-field.d.ts.map +1 -1
- package/es/panel-component/panel-field/panel-field.mjs +29 -12
- package/es/panel-component/panel-item-render/index.d.ts +6 -4
- package/es/panel-component/panel-item-render/index.d.ts.map +1 -1
- package/es/panel-component/panel-item-render/panel-item-render.controller.d.ts.map +1 -1
- package/es/panel-component/panel-item-render/panel-item-render.controller.mjs +7 -5
- package/es/panel-component/panel-item-render/panel-item-render.d.ts +6 -4
- package/es/panel-component/panel-item-render/panel-item-render.d.ts.map +1 -1
- package/es/panel-component/panel-item-render/panel-item-render.mjs +13 -4
- package/es/panel-component/panel-rawitem/index.d.ts +8 -6
- package/es/panel-component/panel-rawitem/index.d.ts.map +1 -1
- package/es/panel-component/panel-rawitem/panel-rawitem.d.ts +8 -6
- package/es/panel-component/panel-rawitem/panel-rawitem.d.ts.map +1 -1
- package/es/panel-component/panel-rawitem/panel-rawitem.mjs +15 -10
- package/es/panel-component/panel-tab-page/index.d.ts +8 -6
- package/es/panel-component/panel-tab-page/index.d.ts.map +1 -1
- package/es/panel-component/panel-tab-page/panel-tab-page.d.ts +10 -8
- package/es/panel-component/panel-tab-page/panel-tab-page.d.ts.map +1 -1
- package/es/panel-component/panel-tab-page/panel-tab-page.mjs +23 -8
- package/es/panel-component/panel-tab-page/panel-tab-page.provider.d.ts +2 -2
- package/es/panel-component/panel-tab-page/panel-tab-page.provider.d.ts.map +1 -1
- package/es/panel-component/panel-tab-page/panel-tab-page.provider.mjs +2 -2
- package/es/panel-component/scroll-container/index.d.ts +6 -4
- package/es/panel-component/scroll-container/index.d.ts.map +1 -1
- package/es/panel-component/scroll-container/scroll-container/scroll-container.controller.d.ts +3 -3
- package/es/panel-component/scroll-container/scroll-container/scroll-container.controller.d.ts.map +1 -1
- package/es/panel-component/scroll-container/scroll-container/scroll-container.controller.mjs +2 -2
- package/es/panel-component/scroll-container/scroll-container/scroll-container.d.ts +6 -4
- package/es/panel-component/scroll-container/scroll-container/scroll-container.d.ts.map +1 -1
- package/es/panel-component/scroll-container/scroll-container/scroll-container.mjs +26 -15
- package/es/panel-component/scroll-container/scroll-container-item/scroll-container-item.controller.d.ts +3 -3
- package/es/panel-component/scroll-container/scroll-container-item/scroll-container-item.controller.d.ts.map +1 -1
- package/es/panel-component/scroll-container/scroll-container-item/scroll-container-item.controller.mjs +2 -2
- package/es/panel-component/scroll-container/scroll-container-item/scroll-container-item.d.ts +6 -4
- package/es/panel-component/scroll-container/scroll-container-item/scroll-container-item.d.ts.map +1 -1
- package/es/panel-component/scroll-container/scroll-container-item/scroll-container-item.mjs +21 -6
- package/es/panel-component/single-data-container/index.d.ts +6 -4
- package/es/panel-component/single-data-container/index.d.ts.map +1 -1
- package/es/panel-component/single-data-container/single-data-container.controller.d.ts +4 -4
- package/es/panel-component/single-data-container/single-data-container.controller.d.ts.map +1 -1
- package/es/panel-component/single-data-container/single-data-container.controller.mjs +98 -73
- package/es/panel-component/single-data-container/single-data-container.d.ts +7 -5
- package/es/panel-component/single-data-container/single-data-container.d.ts.map +1 -1
- package/es/panel-component/single-data-container/single-data-container.mjs +22 -6
- package/es/panel-component/single-data-container/single-data-container.state.d.ts +3 -3
- package/es/panel-component/single-data-container/single-data-container.state.d.ts.map +1 -1
- package/es/panel-component/single-data-container/single-data-container.state.mjs +2 -2
- package/es/panel-component/teleport-placeholder/index.d.ts +7 -5
- package/es/panel-component/teleport-placeholder/index.d.ts.map +1 -1
- package/es/panel-component/teleport-placeholder/teleport-placeholder.d.ts +7 -5
- package/es/panel-component/teleport-placeholder/teleport-placeholder.d.ts.map +1 -1
- package/es/panel-component/teleport-placeholder/teleport-placeholder.mjs +11 -4
- package/es/plugin/plugin-factory/plugin-factory.d.ts +15 -0
- package/es/plugin/plugin-factory/plugin-factory.d.ts.map +1 -1
- package/es/plugin/plugin-factory/plugin-factory.mjs +34 -6
- package/es/props/editor/autocomplete.d.ts +2 -2
- package/es/props/editor/check-box-list.d.ts +2 -2
- package/es/props/editor/check-box.d.ts +2 -2
- package/es/props/editor/code.d.ts +17 -0
- package/es/props/editor/code.d.ts.map +1 -1
- package/es/props/editor/code.mjs +7 -2
- package/es/props/editor/common.d.ts +7 -0
- package/es/props/editor/common.d.ts.map +1 -1
- package/es/props/editor/common.mjs +5 -1
- package/es/props/editor/data-picker.d.ts +2 -2
- package/es/props/editor/date-picker.d.ts +2 -2
- package/es/props/editor/date-range-select.d.ts +4 -0
- package/es/props/editor/date-range-select.d.ts.map +1 -1
- package/es/props/editor/date-range.d.ts +2 -2
- package/es/props/editor/dropdown-list.d.ts +2 -2
- package/es/props/editor/html.d.ts +17 -0
- package/es/props/editor/html.d.ts.map +1 -1
- package/es/props/editor/html.mjs +7 -2
- package/es/props/editor/index.mjs +3 -3
- package/es/props/editor/list-box.d.ts +2 -2
- package/es/props/editor/markdown.d.ts +89 -0
- package/es/props/editor/markdown.d.ts.map +1 -1
- package/es/props/editor/markdown.mjs +28 -3
- package/es/props/editor/number-range.d.ts +2 -2
- package/es/props/editor/radio-button-list.d.ts +2 -2
- package/es/props/editor/rate.d.ts +2 -2
- package/es/props/editor/raw.d.ts +2 -2
- package/es/props/editor/slider.d.ts +2 -2
- package/es/props/editor/span.d.ts +18 -2
- package/es/props/editor/span.d.ts.map +1 -1
- package/es/props/editor/span.mjs +6 -1
- package/es/props/editor/stepper.d.ts +2 -2
- package/es/props/editor/switch.d.ts +2 -2
- package/es/props/editor/text-box.d.ts +2 -2
- package/es/props/index.mjs +3 -3
- package/es/use/index.d.ts +2 -0
- package/es/use/index.d.ts.map +1 -1
- package/es/use/index.mjs +4 -2
- package/es/use/popover/popover.d.ts +7 -0
- package/es/use/popover/popover.d.ts.map +1 -1
- package/es/use/popover/popover.mjs +9 -2
- package/es/use/storage/index.d.ts +4 -6
- package/es/use/storage/index.d.ts.map +1 -1
- package/es/use/storage/index.mjs +16 -11
- package/es/use/tooltip/tooltip.d.ts +103 -0
- package/es/use/tooltip/tooltip.d.ts.map +1 -0
- package/es/use/tooltip/tooltip.mjs +68 -0
- package/es/use/use-semantic-node/use-semantic-node.d.ts +15 -0
- package/es/use/use-semantic-node/use-semantic-node.d.ts.map +1 -0
- package/es/use/use-semantic-node/use-semantic-node.mjs +100 -0
- package/es/use/vue/vue.d.ts +9 -0
- package/es/use/vue/vue.d.ts.map +1 -1
- package/es/use/vue/vue.mjs +15 -2
- package/es/util/index.d.ts +0 -1
- package/es/util/index.d.ts.map +1 -1
- package/es/util/index.mjs +0 -1
- package/es/util/install.d.ts.map +1 -1
- package/es/util/overlay-container/overlay-container.d.ts +1 -1
- package/es/util/overlay-container/overlay-container.d.ts.map +1 -1
- package/es/util/overlay-container/overlay-container.mjs +7 -2
- package/es/util/overlay-view-util/overlay-view-util.d.ts +2 -2
- package/es/util/overlay-view-util/overlay-view-util.d.ts.map +1 -1
- package/es/util/overlay-view-util/overlay-view-util.mjs +2 -1
- package/es/util/route/route.d.ts.map +1 -1
- package/es/util/route/route.mjs +13 -3
- package/es/util/store/app-store/app-store.d.ts +2 -2
- package/es/util/store/ui-store/ui-store.d.ts +2 -2
- package/es/view/app-redirect-view/app-redirect-view.d.ts +1 -1
- package/es/view/app-redirect-view/app-redirect-view.d.ts.map +1 -1
- package/es/view/app-redirect-view/app-redirect-view.mjs +1 -1
- package/es/view/common/index.d.ts +5 -5
- package/es/view/common/index.d.ts.map +1 -1
- package/es/view/common/view.d.ts +5 -5
- package/es/view/common/view.d.ts.map +1 -1
- package/es/view/common/view.mjs +17 -3
- package/es/view/de-redirect-view/de-redirect-view.d.ts +8 -8
- package/es/view/de-redirect-view/de-redirect-view.d.ts.map +1 -1
- package/es/view/de-redirect-view/de-redirect-view.mjs +1 -1
- package/es/view/de-redirect-view/index.d.ts +8 -8
- package/es/view/de-redirect-view/index.d.ts.map +1 -1
- package/es/view/html-view/html-view.d.ts +8 -9
- package/es/view/html-view/html-view.d.ts.map +1 -1
- package/es/view/html-view/html-view.mjs +10 -17
- package/es/view/html-view/index.d.ts +7 -8
- package/es/view/html-view/index.d.ts.map +1 -1
- package/es/view/portal-view/index.d.ts +5 -5
- package/es/view/portal-view/index.d.ts.map +1 -1
- package/es/view/portal-view/portal-view.d.ts +5 -5
- package/es/view/portal-view/portal-view.d.ts.map +1 -1
- package/es/view/todo-redirect/todo-redirect.d.ts +1 -1
- package/es/view/todo-redirect/todo-redirect.d.ts.map +1 -1
- package/lib/common/badge/badge.cjs +12 -6
- package/lib/common/badge/badge.css +1 -1
- package/lib/common/control-base/control-base.cjs +8 -14
- package/lib/common/icon/icon.cjs +12 -0
- package/lib/common/index.cjs +2 -0
- package/lib/common/signature-pad/signature-pad.cjs +167 -0
- package/lib/common/signature-pad/signature-pad.css +1 -0
- package/lib/common/signature-pad/util/bezier.cjs +111 -0
- package/lib/common/signature-pad/util/point.cjs +53 -0
- package/lib/common/signature-pad/util/signature_pad.cjs +1022 -0
- package/lib/common/view-shell/view-shell.cjs +40 -21
- package/lib/control/panel/panel/panel.cjs +11 -3
- package/lib/control/panel/view-layout-panel/view-layout-panel.cjs +4 -4
- package/lib/index.cjs +57 -47
- package/lib/locale/en/index.cjs +2 -1
- package/lib/locale/zh-CN/index.cjs +2 -1
- package/lib/node_modules/.pnpm/path-browserify@1.0.1/node_modules/path-browserify/index.cjs +2 -2
- package/lib/panel-component/auth-wxmp-qrcode/auth-wxmp-qrcode.cjs +16 -5
- package/lib/panel-component/auth-wxmp-qrcode/auth-wxmp-qrcode.controller.cjs +3 -1
- package/lib/panel-component/auth-wxmp-qrcode/auth-wxmp-qrcode.css +1 -1
- package/lib/panel-component/grid-container/grid-container.cjs +16 -5
- package/lib/panel-component/grid-container/grid-container.controller.cjs +1 -1
- package/lib/panel-component/grid-container/grid-container.state.cjs +1 -1
- package/lib/panel-component/index.cjs +21 -22
- package/lib/panel-component/multi-data-container/multi-data-container.cjs +19 -5
- package/lib/panel-component/multi-data-container/multi-data-container.controller.cjs +87 -68
- package/lib/panel-component/multi-data-container/multi-data-container.state.cjs +1 -1
- package/lib/panel-component/multi-data-container-raw/multi-data-container-raw.cjs +22 -6
- package/lib/panel-component/multi-data-container-raw/multi-data-container-raw.controller.cjs +87 -68
- package/lib/panel-component/multi-data-container-raw/multi-data-container-raw.state.cjs +1 -1
- package/lib/panel-component/nav-pos/nav-pos.cjs +18 -3
- package/lib/panel-component/panel-container/index.cjs +8 -4
- package/lib/panel-component/panel-container/panel-container.cjs +36 -15
- package/lib/panel-component/panel-container/panel-container.provider.cjs +2 -2
- package/lib/panel-component/panel-container-image/panel-container-image.cjs +23 -9
- package/lib/panel-component/panel-container-image/panel-container-image.controller.cjs +1 -1
- package/lib/panel-component/panel-container-image/panel-container-image.css +1 -1
- package/lib/panel-component/panel-container-image/panel-container-image.state.cjs +1 -1
- package/lib/panel-component/panel-container-tabs/panel-container-tabs.cjs +2 -2
- package/lib/panel-component/panel-container-tabs/panel-container-tabs.provider.cjs +2 -2
- package/lib/panel-component/panel-ctrl-pos/panel-ctrl-pos.cjs +11 -3
- package/lib/panel-component/panel-ctrl-view-page-caption/panel-ctrl-view-page-caption.cjs +15 -7
- package/lib/panel-component/panel-ctrl-view-page-caption/panel-ctrl-view-page-caption.css +1 -0
- package/lib/panel-component/panel-field/panel-field.cjs +28 -11
- package/lib/panel-component/panel-field/panel-field.controller.cjs +37 -3
- package/lib/panel-component/panel-field/panel-field.css +1 -1
- package/lib/panel-component/panel-item-render/panel-item-render.cjs +12 -3
- package/lib/panel-component/panel-item-render/panel-item-render.controller.cjs +7 -5
- package/lib/panel-component/panel-rawitem/panel-rawitem.cjs +14 -9
- package/lib/panel-component/panel-tab-page/panel-tab-page.cjs +21 -6
- package/lib/panel-component/panel-tab-page/panel-tab-page.provider.cjs +1 -1
- package/lib/panel-component/scroll-container/scroll-container/scroll-container.cjs +25 -14
- package/lib/panel-component/scroll-container/scroll-container/scroll-container.controller.cjs +1 -1
- package/lib/panel-component/scroll-container/scroll-container-item/scroll-container-item.cjs +20 -5
- package/lib/panel-component/scroll-container/scroll-container-item/scroll-container-item.controller.cjs +1 -1
- package/lib/panel-component/single-data-container/single-data-container.cjs +21 -5
- package/lib/panel-component/single-data-container/single-data-container.controller.cjs +97 -72
- package/lib/panel-component/single-data-container/single-data-container.state.cjs +1 -1
- package/lib/panel-component/teleport-placeholder/teleport-placeholder.cjs +10 -3
- package/lib/plugin/plugin-factory/plugin-factory.cjs +33 -5
- package/lib/props/editor/code.cjs +6 -0
- package/lib/props/editor/common.cjs +5 -1
- package/lib/props/editor/html.cjs +6 -0
- package/lib/props/editor/index.cjs +3 -0
- package/lib/props/editor/markdown.cjs +27 -1
- package/lib/props/editor/span.cjs +6 -1
- package/lib/props/index.cjs +3 -0
- package/lib/use/index.cjs +8 -0
- package/lib/use/popover/popover.cjs +8 -0
- package/lib/use/storage/index.cjs +16 -11
- package/lib/use/tooltip/tooltip.cjs +72 -0
- package/lib/use/use-semantic-node/use-semantic-node.cjs +102 -0
- package/lib/use/vue/vue.cjs +14 -0
- package/lib/util/index.cjs +0 -2
- package/lib/util/overlay-container/overlay-container.cjs +7 -2
- package/lib/util/overlay-view-util/overlay-view-util.cjs +2 -1
- package/lib/util/route/route.cjs +13 -3
- package/lib/view/common/view.cjs +15 -1
- package/lib/view/html-view/html-view.cjs +8 -15
- package/package.json +8 -7
- package/src/common/badge/badge.scss +49 -0
- package/src/common/badge/badge.tsx +55 -0
- package/src/common/code-list/code-list.scss +15 -0
- package/src/common/code-list/code-list.tsx +184 -0
- package/src/common/control-base/control-base.scss +42 -0
- package/src/common/control-base/control-base.tsx +308 -0
- package/src/common/control-loading-placeholder/control-loading-placeholder.tsx +22 -0
- package/src/common/control-shell/control-shell.scss +5 -0
- package/src/common/control-shell/control-shell.tsx +90 -0
- package/src/common/custom-render/custom-render.scss +4 -0
- package/src/common/custom-render/custom-render.tsx +111 -0
- package/src/common/icon/icon.scss +13 -0
- package/src/common/icon/icon.tsx +105 -0
- package/src/common/index.ts +10 -0
- package/src/common/router-view/router-view.tsx +74 -0
- package/src/common/signature-pad/signature-pad.scss +10 -0
- package/src/common/signature-pad/signature-pad.tsx +174 -0
- package/src/common/signature-pad/util/bezier.ts +164 -0
- package/src/common/signature-pad/util/point.ts +96 -0
- package/src/common/signature-pad/util/signature_pad.ts +1543 -0
- package/src/common/view-shell/view-shell.scss +5 -0
- package/src/common/view-shell/view-shell.tsx +337 -0
- package/src/control/index.ts +1 -0
- package/src/control/panel/index.ts +2 -0
- package/src/control/panel/panel/index.ts +12 -0
- package/src/control/panel/panel/panel.provider.ts +14 -0
- package/src/control/panel/panel/panel.scss +9 -0
- package/src/control/panel/panel/panel.tsx +273 -0
- package/src/control/panel/view-layout-panel/index.ts +18 -0
- package/src/control/panel/view-layout-panel/view-layout-panel.provider.ts +14 -0
- package/src/control/panel/view-layout-panel/view-layout-panel.scss +9 -0
- package/src/control/panel/view-layout-panel/view-layout-panel.tsx +266 -0
- package/src/hooks/app/app.hooks.ts +63 -0
- package/src/hooks/index.ts +1 -0
- package/src/index.ts +19 -0
- package/src/interface/index.ts +1 -0
- package/src/interface/util/index.ts +1 -0
- package/src/interface/util/route/route.ts +116 -0
- package/src/locale/en/index.ts +74 -0
- package/src/locale/index.ts +2 -0
- package/src/locale/zh-CN/index.ts +66 -0
- package/src/panel-component/auth-wxmp-qrcode/auth-wxmp-qrcode.controller.ts +248 -0
- package/src/panel-component/auth-wxmp-qrcode/auth-wxmp-qrcode.provider.ts +28 -0
- package/src/panel-component/auth-wxmp-qrcode/auth-wxmp-qrcode.scss +51 -0
- package/src/panel-component/auth-wxmp-qrcode/auth-wxmp-qrcode.state.ts +58 -0
- package/src/panel-component/auth-wxmp-qrcode/auth-wxmp-qrcode.tsx +109 -0
- package/src/panel-component/auth-wxmp-qrcode/index.ts +18 -0
- package/src/panel-component/grid-container/grid-container.controller.ts +24 -0
- package/src/panel-component/grid-container/grid-container.provider.ts +30 -0
- package/src/panel-component/grid-container/grid-container.scss +17 -0
- package/src/panel-component/grid-container/grid-container.state.ts +12 -0
- package/src/panel-component/grid-container/grid-container.tsx +141 -0
- package/src/panel-component/grid-container/index.ts +19 -0
- package/src/panel-component/index.ts +17 -0
- package/src/panel-component/multi-data-container/index.ts +22 -0
- package/src/panel-component/multi-data-container/multi-data-container-item.controller.ts +179 -0
- package/src/panel-component/multi-data-container/multi-data-container-itm.state.ts +20 -0
- package/src/panel-component/multi-data-container/multi-data-container.controller.ts +456 -0
- package/src/panel-component/multi-data-container/multi-data-container.provider.ts +30 -0
- package/src/panel-component/multi-data-container/multi-data-container.scss +10 -0
- package/src/panel-component/multi-data-container/multi-data-container.state.ts +19 -0
- package/src/panel-component/multi-data-container/multi-data-container.tsx +137 -0
- package/src/panel-component/multi-data-container-raw/index.ts +22 -0
- package/src/panel-component/multi-data-container-raw/multi-data-container-raw.controller.ts +448 -0
- package/src/panel-component/multi-data-container-raw/multi-data-container-raw.provider.ts +30 -0
- package/src/panel-component/multi-data-container-raw/multi-data-container-raw.scss +12 -0
- package/src/panel-component/multi-data-container-raw/multi-data-container-raw.state.ts +19 -0
- package/src/panel-component/multi-data-container-raw/multi-data-container-raw.tsx +129 -0
- package/src/panel-component/nav-pos/index.ts +16 -0
- package/src/panel-component/nav-pos/nav-pos.controller.ts +438 -0
- package/src/panel-component/nav-pos/nav-pos.provider.ts +38 -0
- package/src/panel-component/nav-pos/nav-pos.scss +4 -0
- package/src/panel-component/nav-pos/nav-pos.state.ts +55 -0
- package/src/panel-component/nav-pos/nav-pos.tsx +166 -0
- package/src/panel-component/panel-container/index.ts +30 -0
- package/src/panel-component/panel-container/panel-container.provider.ts +30 -0
- package/src/panel-component/panel-container/panel-container.scss +21 -0
- package/src/panel-component/panel-container/panel-container.tsx +138 -0
- package/src/panel-component/panel-container-image/index.ts +22 -0
- package/src/panel-component/panel-container-image/panel-container-image.controller.ts +24 -0
- package/src/panel-component/panel-container-image/panel-container-image.provider.ts +30 -0
- package/src/panel-component/panel-container-image/panel-container-image.scss +17 -0
- package/src/panel-component/panel-container-image/panel-container-image.state.ts +12 -0
- package/src/panel-component/panel-container-image/panel-container-image.tsx +116 -0
- package/src/panel-component/panel-container-tabs/index.ts +18 -0
- package/src/panel-component/panel-container-tabs/panel-container-tabs.provider.ts +30 -0
- package/src/panel-component/panel-container-tabs/panel-container-tabs.scss +25 -0
- package/src/panel-component/panel-container-tabs/panel-container-tabs.tsx +47 -0
- package/src/panel-component/panel-ctrl-pos/index.ts +14 -0
- package/src/panel-component/panel-ctrl-pos/panel-ctrl-pos.controller.ts +50 -0
- package/src/panel-component/panel-ctrl-pos/panel-ctrl-pos.provider.ts +30 -0
- package/src/panel-component/panel-ctrl-pos/panel-ctrl-pos.scss +8 -0
- package/src/panel-component/panel-ctrl-pos/panel-ctrl-pos.tsx +72 -0
- package/src/panel-component/panel-ctrl-view-page-caption/index.ts +18 -0
- package/src/panel-component/panel-ctrl-view-page-caption/panel-ctrl-view-page-caption.controller.ts +32 -0
- package/src/panel-component/panel-ctrl-view-page-caption/panel-ctrl-view-page-caption.provider.ts +30 -0
- package/src/panel-component/panel-ctrl-view-page-caption/panel-ctrl-view-page-caption.scss +13 -0
- package/src/panel-component/panel-ctrl-view-page-caption/panel-ctrl-view-page-caption.state.ts +17 -0
- package/src/panel-component/panel-ctrl-view-page-caption/panel-ctrl-view-page-caption.tsx +77 -0
- package/src/panel-component/panel-field/index.ts +14 -0
- package/src/panel-component/panel-field/panel-field.controller.ts +272 -0
- package/src/panel-component/panel-field/panel-field.provider.ts +28 -0
- package/src/panel-component/panel-field/panel-field.scss +79 -0
- package/src/panel-component/panel-field/panel-field.state.ts +17 -0
- package/src/panel-component/panel-field/panel-field.tsx +138 -0
- package/src/panel-component/panel-item-render/index.ts +18 -0
- package/src/panel-component/panel-item-render/panel-item-render.controller.ts +53 -0
- package/src/panel-component/panel-item-render/panel-item-render.provider.ts +30 -0
- package/src/panel-component/panel-item-render/panel-item-render.tsx +69 -0
- package/src/panel-component/panel-rawitem/index.ts +26 -0
- package/src/panel-component/panel-rawitem/panel-rawitem.controller.ts +54 -0
- package/src/panel-component/panel-rawitem/panel-rawitem.provider.ts +28 -0
- package/src/panel-component/panel-rawitem/panel-rawitem.scss +8 -0
- package/src/panel-component/panel-rawitem/panel-rawitem.tsx +126 -0
- package/src/panel-component/panel-tab-page/index.ts +12 -0
- package/src/panel-component/panel-tab-page/panel-tab-page.provider.ts +28 -0
- package/src/panel-component/panel-tab-page/panel-tab-page.tsx +83 -0
- package/src/panel-component/scroll-container/index.ts +44 -0
- package/src/panel-component/scroll-container/scroll-container/index.ts +2 -0
- package/src/panel-component/scroll-container/scroll-container/scroll-container.controller.ts +29 -0
- package/src/panel-component/scroll-container/scroll-container/scroll-container.provider.ts +30 -0
- package/src/panel-component/scroll-container/scroll-container/scroll-container.scss +40 -0
- package/src/panel-component/scroll-container/scroll-container/scroll-container.tsx +155 -0
- package/src/panel-component/scroll-container/scroll-container-item/index.ts +2 -0
- package/src/panel-component/scroll-container/scroll-container-item/scroll-container-item.controller.ts +21 -0
- package/src/panel-component/scroll-container/scroll-container-item/scroll-container-item.provider.ts +30 -0
- package/src/panel-component/scroll-container/scroll-container-item/scroll-container-item.scss +9 -0
- package/src/panel-component/scroll-container/scroll-container-item/scroll-container-item.tsx +80 -0
- package/src/panel-component/single-data-container/index.ts +22 -0
- package/src/panel-component/single-data-container/single-data-container.controller.ts +507 -0
- package/src/panel-component/single-data-container/single-data-container.provider.ts +30 -0
- package/src/panel-component/single-data-container/single-data-container.scss +10 -0
- package/src/panel-component/single-data-container/single-data-container.state.ts +17 -0
- package/src/panel-component/single-data-container/single-data-container.tsx +124 -0
- package/src/panel-component/teleport-placeholder/index.ts +20 -0
- package/src/panel-component/teleport-placeholder/teleport-placeholder.controller.ts +54 -0
- package/src/panel-component/teleport-placeholder/teleport-placeholder.provider.ts +30 -0
- package/src/panel-component/teleport-placeholder/teleport-placeholder.scss +8 -0
- package/src/panel-component/teleport-placeholder/teleport-placeholder.state.ts +17 -0
- package/src/panel-component/teleport-placeholder/teleport-placeholder.tsx +65 -0
- package/src/plugin/index.ts +1 -0
- package/src/plugin/plugin-factory/plugin-factory.ts +519 -0
- package/src/props/common.ts +30 -0
- package/src/props/editor/array.ts +28 -0
- package/src/props/editor/autocomplete.ts +28 -0
- package/src/props/editor/cascader.ts +28 -0
- package/src/props/editor/check-box-list.ts +28 -0
- package/src/props/editor/check-box.ts +28 -0
- package/src/props/editor/code.ts +56 -0
- package/src/props/editor/color-picker.ts +28 -0
- package/src/props/editor/common.ts +120 -0
- package/src/props/editor/data-picker.ts +28 -0
- package/src/props/editor/date-picker.ts +29 -0
- package/src/props/editor/date-range-select.ts +52 -0
- package/src/props/editor/date-range.ts +29 -0
- package/src/props/editor/dropdown-list.ts +28 -0
- package/src/props/editor/html.ts +44 -0
- package/src/props/editor/index.ts +29 -0
- package/src/props/editor/input-ip.ts +28 -0
- package/src/props/editor/input-number.ts +28 -0
- package/src/props/editor/list-box.ts +28 -0
- package/src/props/editor/map-picker.ts +28 -0
- package/src/props/editor/markdown.ts +74 -0
- package/src/props/editor/number-range.ts +28 -0
- package/src/props/editor/radio-button-list.ts +28 -0
- package/src/props/editor/rate.ts +28 -0
- package/src/props/editor/raw.ts +28 -0
- package/src/props/editor/slider.ts +28 -0
- package/src/props/editor/span.ts +33 -0
- package/src/props/editor/stepper.ts +28 -0
- package/src/props/editor/switch.ts +28 -0
- package/src/props/editor/text-box.ts +28 -0
- package/src/props/editor/upload.ts +28 -0
- package/src/props/index.ts +2 -0
- package/src/types/index.d.ts +8 -0
- package/src/use/autofocus-blur/autofocus-blur.ts +31 -0
- package/src/use/click-outside/click-outside.ts +72 -0
- package/src/use/codeList-listen/codelist-listen.ts +28 -0
- package/src/use/control/index.ts +1 -0
- package/src/use/control/use-control-controller/use-control-controller.ts +186 -0
- package/src/use/event/event.ts +57 -0
- package/src/use/focus-blur/focus-blur.ts +83 -0
- package/src/use/index.ts +16 -0
- package/src/use/namespace/namespace.ts +14 -0
- package/src/use/popover/popover.ts +157 -0
- package/src/use/route/route.ts +47 -0
- package/src/use/storage/index.ts +46 -0
- package/src/use/tooltip/tooltip.ts +153 -0
- package/src/use/use-semantic-node/use-semantic-node.ts +154 -0
- package/src/use/util/index.ts +26 -0
- package/src/use/view/index.ts +2 -0
- package/src/use/view/use-view-controller/use-view-controller.ts +163 -0
- package/src/use/view/use-view-operation/use-view-operation.ts +44 -0
- package/src/use/vue/vue.ts +168 -0
- package/src/use/vue-use/computed-async.ts +151 -0
- package/src/use/vue-use/index.ts +1 -0
- package/src/util/index.ts +9 -0
- package/src/util/install.ts +14 -0
- package/src/util/overlay-container/overlay-container.ts +162 -0
- package/src/util/overlay-popover-container/overlay-popover-container.ts +30 -0
- package/src/util/overlay-view-util/overlay-view-util.ts +93 -0
- package/src/util/render/render.ts +54 -0
- package/src/util/route/route-listener.ts +91 -0
- package/src/util/route/route.ts +606 -0
- package/src/util/router-callback/router-callback-item.ts +98 -0
- package/src/util/router-callback/router-callback.ts +110 -0
- package/src/util/store/app-store/app-store.ts +10 -0
- package/src/util/store/index.ts +6 -0
- package/src/util/store/ui-store/ui-store.ts +37 -0
- package/src/util/store/ui-store/z-index.ts +53 -0
- package/src/view/app-data-upload-view/app-data-upload-view.provider.ts +31 -0
- package/src/view/app-redirect-view/app-redirect-view.tsx +26 -0
- package/src/view/common/index.ts +19 -0
- package/src/view/common/view.provider.ts +14 -0
- package/src/view/common/view.scss +39 -0
- package/src/view/common/view.tsx +285 -0
- package/src/view/de-redirect-view/de-redirect-view.provider.ts +14 -0
- package/src/view/de-redirect-view/de-redirect-view.tsx +86 -0
- package/src/view/de-redirect-view/index.ts +17 -0
- package/src/view/html-view/html-view.provider.ts +14 -0
- package/src/view/html-view/html-view.scss +7 -0
- package/src/view/html-view/html-view.tsx +86 -0
- package/src/view/html-view/index.ts +10 -0
- package/src/view/index.ts +6 -0
- package/src/view/md-custom-view/md-custom-view.provider.ts +30 -0
- package/src/view/portal-view/index.ts +18 -0
- package/src/view/portal-view/portal-view.provider.ts +14 -0
- package/src/view/portal-view/portal-view.tsx +83 -0
- package/src/view/todo-redirect/todo-redirect.tsx +51 -0
- package/es/panel-component/panel-container/panel-container.controller.d.ts +0 -21
- package/es/panel-component/panel-container/panel-container.controller.d.ts.map +0 -1
- package/es/panel-component/panel-container/panel-container.controller.mjs +0 -12
- package/es/panel-component/panel-container/panel-container.state.d.ts +0 -10
- package/es/panel-component/panel-container/panel-container.state.d.ts.map +0 -1
- package/es/panel-component/panel-container/panel-container.state.mjs +0 -7
- package/es/panel-component/panel-container-group/index.d.ts +0 -29
- package/es/panel-component/panel-container-group/index.d.ts.map +0 -1
- package/es/panel-component/panel-container-group/index.mjs +0 -21
- package/es/panel-component/panel-container-group/panel-container-group.controller.d.ts +0 -34
- package/es/panel-component/panel-container-group/panel-container-group.controller.d.ts.map +0 -1
- package/es/panel-component/panel-container-group/panel-container-group.controller.mjs +0 -31
- package/es/panel-component/panel-container-group/panel-container-group.css +0 -1
- package/es/panel-component/panel-container-group/panel-container-group.d.ts +0 -46
- package/es/panel-component/panel-container-group/panel-container-group.d.ts.map +0 -1
- package/es/panel-component/panel-container-group/panel-container-group.mjs +0 -119
- package/es/panel-component/panel-container-group/panel-container-group.provider.d.ts +0 -16
- package/es/panel-component/panel-container-group/panel-container-group.provider.d.ts.map +0 -1
- package/es/panel-component/panel-container-group/panel-container-group.provider.mjs +0 -15
- package/es/panel-component/panel-container-group/panel-container-group.state.d.ts +0 -13
- package/es/panel-component/panel-container-group/panel-container-group.state.d.ts.map +0 -1
- package/es/panel-component/panel-container-group/panel-container-group.state.mjs +0 -7
- package/es/util/control/prepare-control.d.ts +0 -15
- package/es/util/control/prepare-control.d.ts.map +0 -1
- package/es/util/control/prepare-control.mjs +0 -22
- package/lib/panel-component/panel-container/panel-container.controller.cjs +0 -14
- package/lib/panel-component/panel-container/panel-container.state.cjs +0 -9
- package/lib/panel-component/panel-container-group/index.cjs +0 -28
- package/lib/panel-component/panel-container-group/panel-container-group.cjs +0 -121
- package/lib/panel-component/panel-container-group/panel-container-group.controller.cjs +0 -33
- package/lib/panel-component/panel-container-group/panel-container-group.css +0 -1
- package/lib/panel-component/panel-container-group/panel-container-group.provider.cjs +0 -17
- package/lib/panel-component/panel-container-group/panel-container-group.state.cjs +0 -9
- package/lib/util/control/prepare-control.cjs +0 -24
|
@@ -0,0 +1,1543 @@
|
|
|
1
|
+
/* eslint-disable no-restricted-syntax */
|
|
2
|
+
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
3
|
+
/* eslint-disable no-param-reassign */
|
|
4
|
+
/* eslint-disable default-param-last */
|
|
5
|
+
import { isNumber, isObject, throttle } from 'lodash-es';
|
|
6
|
+
import { Bezier } from './bezier';
|
|
7
|
+
import { IBasicPoint, Point } from './point';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @description 签名事件对象接口,封装签名相关的事件信息
|
|
11
|
+
* @export
|
|
12
|
+
* @interface ISignatureEvent
|
|
13
|
+
*/
|
|
14
|
+
export interface ISignatureEvent {
|
|
15
|
+
/** 原始事件对象(鼠标、触摸或指针事件) */
|
|
16
|
+
event: MouseEvent | TouchEvent | PointerEvent;
|
|
17
|
+
/** 事件类型(如'mousedown'、'touchmove'等) */
|
|
18
|
+
type: string;
|
|
19
|
+
/** 事件发生时的X坐标 */
|
|
20
|
+
x: number;
|
|
21
|
+
/** 事件发生时的Y坐标 */
|
|
22
|
+
y: number;
|
|
23
|
+
/** 压力值(如触摸或绘图设备的压力感应值) */
|
|
24
|
+
pressure: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @description 从数据加载签名时的配置选项接口
|
|
29
|
+
* @export
|
|
30
|
+
* @interface IFromDataOptions
|
|
31
|
+
*/
|
|
32
|
+
export interface IFromDataOptions {
|
|
33
|
+
/** 是否在加载前清除现有签名,默认true */
|
|
34
|
+
clear?: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @description 导出为SVG格式时的配置选项接口
|
|
39
|
+
* @export
|
|
40
|
+
* @interface IToSVGOptions
|
|
41
|
+
*/
|
|
42
|
+
export interface IToSVGOptions {
|
|
43
|
+
/** 是否在SVG中包含背景色,默认false */
|
|
44
|
+
includeBackgroundColor?: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @description 点组的样式配置选项接口,用于定义签名线条/点的绘制样式
|
|
49
|
+
* @export
|
|
50
|
+
* @interface IPointGroupOptions
|
|
51
|
+
*/
|
|
52
|
+
export interface IPointGroupOptions {
|
|
53
|
+
/** 点的大小(像素) */
|
|
54
|
+
dotSize: number;
|
|
55
|
+
/** 线条最小宽度(像素) */
|
|
56
|
+
minWidth: number;
|
|
57
|
+
/** 线条最大宽度(像素) */
|
|
58
|
+
maxWidth: number;
|
|
59
|
+
/** 画笔颜色(CSS颜色格式) */
|
|
60
|
+
penColor: string;
|
|
61
|
+
/** 速度过滤权重(用于平滑线条粗细变化) */
|
|
62
|
+
velocityFilterWeight: number;
|
|
63
|
+
/** 合成操作(遵循Canvas的globalCompositeOperation规范) */
|
|
64
|
+
compositeOperation: GlobalCompositeOperation;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @description SignaturePad的初始化配置选项接口,继承点组样式配置并支持部分可选扩展
|
|
69
|
+
* @export
|
|
70
|
+
* @interface ISignaturePadOptions
|
|
71
|
+
* @extends {Partial<IPointGroupOptions>}
|
|
72
|
+
*/
|
|
73
|
+
export interface ISignaturePadOptions extends Partial<IPointGroupOptions> {
|
|
74
|
+
/** 连续点之间的最小距离(像素),小于此值则不记录新点 */
|
|
75
|
+
minDistance?: number;
|
|
76
|
+
/** 画布背景色(CSS颜色格式) */
|
|
77
|
+
backgroundColor?: string;
|
|
78
|
+
/** 事件节流时间(毫秒),限制绘制事件触发频率 */
|
|
79
|
+
throttle?: number;
|
|
80
|
+
/** Canvas 2D上下文的初始化配置 */
|
|
81
|
+
canvasContextOptions?: CanvasRenderingContext2DSettings;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @description 点组接口,包含一组点及对应的绘制样式配置,用于记录签名的一段轨迹
|
|
86
|
+
* @export
|
|
87
|
+
* @interface IPointGroup
|
|
88
|
+
* @extends {IPointGroupOptions}
|
|
89
|
+
*/
|
|
90
|
+
export interface IPointGroup extends IPointGroupOptions {
|
|
91
|
+
/** 该组包含的点集合(基础点信息) */
|
|
92
|
+
points: IBasicPoint[];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export default class SignaturePad {
|
|
96
|
+
/**
|
|
97
|
+
* @description 点的大小,默认值为0(单位:像素)。控制点击画布时生成的点的尺寸。0表示根据线条宽度自动计算点的大小
|
|
98
|
+
* @type {number}
|
|
99
|
+
* @memberof SignaturePad
|
|
100
|
+
*/
|
|
101
|
+
|
|
102
|
+
public dotSize: number;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @description 画笔最小宽度,默认值为0.5(单位:像素)。控制签名线条的最细宽度,绘制速度越快,线条越接近此值
|
|
106
|
+
* @type {number}
|
|
107
|
+
* @memberof SignaturePad
|
|
108
|
+
*/
|
|
109
|
+
public minWidth: number;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @description 画笔最大宽度,默认值为2.5(单位:像素)。控制签名线条的最粗宽度,绘制速度越慢,线条越接近此值。
|
|
113
|
+
* @type {number}
|
|
114
|
+
* @memberof SignaturePad
|
|
115
|
+
*/
|
|
116
|
+
public maxWidth: number;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @description 画笔颜色,默认值为'black'。签名轨迹的颜色,可接受 CSS 颜色格式(如#ff0000、rgb(255,0,0)等)。
|
|
120
|
+
* @type {string}
|
|
121
|
+
* @memberof SignaturePad
|
|
122
|
+
*/
|
|
123
|
+
public penColor: string;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* @description 最小绘制距离,默认值为5(单位:像素)。当连续两个绘制点的距离小于此值时,不会记录新点,用于减少冗余数据并优化绘制流畅度。
|
|
127
|
+
* @type {number}
|
|
128
|
+
* @memberof SignaturePad
|
|
129
|
+
*/
|
|
130
|
+
public minDistance: number;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @description 速度过滤权重,默认值为0.7。用于平滑处理绘制速度的计算,影响线条粗细随速度的变化幅度。值越接近 1,当前速度对线条粗细的影响越大;值越小,线条过渡越平滑
|
|
134
|
+
* @type {number}
|
|
135
|
+
* @memberof SignaturePad
|
|
136
|
+
*/
|
|
137
|
+
public velocityFilterWeight: number;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @description 合成操作,默认值为'source-over'。控制新绘制的线条与已有内容的混合方式,遵循 Canvas 的globalCompositeOperation属性规范
|
|
141
|
+
* @type {GlobalCompositeOperation}
|
|
142
|
+
* @memberof SignaturePad
|
|
143
|
+
*/
|
|
144
|
+
public compositeOperation: GlobalCompositeOperation;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @description 画布背景色,默认值为'rgba(0,0,0,0)'(透明)。签名画布的背景颜色,导出图片时会包含此背景。
|
|
148
|
+
* @type {string}
|
|
149
|
+
* @memberof SignaturePad
|
|
150
|
+
*/
|
|
151
|
+
public backgroundColor: string;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @description 节流时间,默认值为16(单位:毫秒)。限制绘制事件的触发频率,避免高频操作导致性能问题。??运算符确保0值会被正常应用(而||会忽略0)
|
|
155
|
+
* @type {number}
|
|
156
|
+
* @memberof SignaturePad
|
|
157
|
+
*/
|
|
158
|
+
public throttle: number;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* @description Canvas 上下文配置,默认值为{}。用于初始化 Canvas 2D 上下文的额外配置项(如alpha、willReadFrequently等)
|
|
162
|
+
* @type {CanvasRenderingContext2DSettings}
|
|
163
|
+
* @memberof SignaturePad
|
|
164
|
+
*/
|
|
165
|
+
public canvasContextOptions: CanvasRenderingContext2DSettings;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* @description Canvas 2D 渲染上下文,用于实际绘制签名轨迹
|
|
169
|
+
* @private
|
|
170
|
+
* @type {CanvasRenderingContext2D}
|
|
171
|
+
* @memberof SignaturePad
|
|
172
|
+
*/
|
|
173
|
+
private _ctx: CanvasRenderingContext2D;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* @description 是否正在绘制中(笔触未抬起)
|
|
177
|
+
* @private
|
|
178
|
+
* @memberof SignaturePad
|
|
179
|
+
*/
|
|
180
|
+
private _drawingStroke = false;
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* @description 签名是否为空(未绘制任何内容)
|
|
184
|
+
* @private
|
|
185
|
+
* @memberof SignaturePad
|
|
186
|
+
*/
|
|
187
|
+
private _isEmpty = true;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* @description 是否重新绘制过签名(用于判断是否从数据恢复过签名)
|
|
191
|
+
* @private
|
|
192
|
+
* @memberof SignaturePad
|
|
193
|
+
*/
|
|
194
|
+
private _isRedrawn = false;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* @description 上一次从DataURL加载的签名图片地址,用于撤销操作时恢复
|
|
198
|
+
* @private
|
|
199
|
+
* @memberof SignaturePad
|
|
200
|
+
*/
|
|
201
|
+
private _oldFromDataURL = '';
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* @description 存储最近的点(最多4个),用于生成新的贝塞尔曲线
|
|
205
|
+
* @private
|
|
206
|
+
* @type {Point[]}
|
|
207
|
+
* @memberof SignaturePad
|
|
208
|
+
*/
|
|
209
|
+
private _lastPoints: Point[] = [];
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* @description 存储所有签名数据(按轨迹分组,每组包含一段连续绘制的点及样式配置)
|
|
213
|
+
* @private
|
|
214
|
+
* @type {IPointGroup[]}
|
|
215
|
+
* @memberof SignaturePad
|
|
216
|
+
*/
|
|
217
|
+
private _data: IPointGroup[] = [];
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* @description 上一次计算的绘制速度(用于平滑线条宽度变化)
|
|
221
|
+
* @private
|
|
222
|
+
* @memberof SignaturePad
|
|
223
|
+
*/
|
|
224
|
+
private _lastVelocity = 0;
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* @description 上一次绘制的线条宽度(用于平滑过渡到当前宽度)
|
|
228
|
+
* @private
|
|
229
|
+
* @memberof SignaturePad
|
|
230
|
+
*/
|
|
231
|
+
private _lastWidth = 0;
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* @description 节流处理后的笔触移动更新函数(根据配置的throttle值决定是否节流)
|
|
235
|
+
* @private
|
|
236
|
+
* @memberof SignaturePad
|
|
237
|
+
*/
|
|
238
|
+
private _strokeMoveUpdate: (event: ISignatureEvent) => void;
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* @description 当前活跃的指针事件ID(用于区分多指针设备的不同笔触)
|
|
242
|
+
* @private
|
|
243
|
+
* @type {(number | undefined)}
|
|
244
|
+
* @memberof SignaturePad
|
|
245
|
+
*/
|
|
246
|
+
private _strokePointerId: number | undefined;
|
|
247
|
+
|
|
248
|
+
constructor(
|
|
249
|
+
private canvas: HTMLCanvasElement,
|
|
250
|
+
options: ISignaturePadOptions = {},
|
|
251
|
+
) {
|
|
252
|
+
this.velocityFilterWeight = options.velocityFilterWeight || 0.7;
|
|
253
|
+
this.minWidth = options.minWidth || 2;
|
|
254
|
+
this.maxWidth = options.maxWidth || 2;
|
|
255
|
+
|
|
256
|
+
// We need to handle 0 value, so use `??` instead of `||`
|
|
257
|
+
this.throttle = options.throttle ?? 16; // in milliseconds
|
|
258
|
+
this.minDistance = options.minDistance ?? 5; // in pixels
|
|
259
|
+
this.dotSize = options.dotSize || 0;
|
|
260
|
+
this.penColor = options.penColor || 'black';
|
|
261
|
+
this.backgroundColor = options.backgroundColor || 'rgba(0,0,0,0)';
|
|
262
|
+
this.compositeOperation = options.compositeOperation || 'source-over';
|
|
263
|
+
this.canvasContextOptions = options.canvasContextOptions ?? {};
|
|
264
|
+
|
|
265
|
+
this._strokeMoveUpdate = this.throttle
|
|
266
|
+
? throttle(SignaturePad.prototype._strokeUpdate, this.throttle)
|
|
267
|
+
: SignaturePad.prototype._strokeUpdate;
|
|
268
|
+
|
|
269
|
+
this._handleMouseDown = this._handleMouseDown.bind(this);
|
|
270
|
+
this._handleMouseMove = this._handleMouseMove.bind(this);
|
|
271
|
+
this._handleMouseUp = this._handleMouseUp.bind(this);
|
|
272
|
+
this._handleTouchStart = this._handleTouchStart.bind(this);
|
|
273
|
+
this._handleTouchMove = this._handleTouchMove.bind(this);
|
|
274
|
+
this._handleTouchEnd = this._handleTouchEnd.bind(this);
|
|
275
|
+
this._handlePointerDown = this._handlePointerDown.bind(this);
|
|
276
|
+
this._handlePointerMove = this._handlePointerMove.bind(this);
|
|
277
|
+
this._handlePointerUp = this._handlePointerUp.bind(this);
|
|
278
|
+
|
|
279
|
+
this._ctx = canvas.getContext(
|
|
280
|
+
'2d',
|
|
281
|
+
this.canvasContextOptions,
|
|
282
|
+
) as CanvasRenderingContext2D;
|
|
283
|
+
|
|
284
|
+
this.clear();
|
|
285
|
+
|
|
286
|
+
this.on();
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
public clear(): void {
|
|
290
|
+
const { _ctx: ctx, canvas } = this;
|
|
291
|
+
|
|
292
|
+
// 使用背景颜色清除画布
|
|
293
|
+
ctx.fillStyle = this.backgroundColor;
|
|
294
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
295
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
296
|
+
|
|
297
|
+
this._data = [];
|
|
298
|
+
this._reset(this._getPointGroupOptions());
|
|
299
|
+
this._isEmpty = true;
|
|
300
|
+
this._strokePointerId = undefined;
|
|
301
|
+
this._oldFromDataURL = '';
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* 从数据URL加载图像并绘制到签名画布上
|
|
306
|
+
* 支持对图像进行旋转、缩放和偏移等处理,适用于恢复保存的签名图像
|
|
307
|
+
* @param {string} dataUrl - 图像的DataURL(如base64编码的图片数据)
|
|
308
|
+
* @param {Object} [options={}] - 加载配置选项
|
|
309
|
+
* @returns {Promise<void>} - 加载完成的Promise(成功时resolve,失败时reject)
|
|
310
|
+
*/
|
|
311
|
+
public async fromDataURL(
|
|
312
|
+
dataUrl: string,
|
|
313
|
+
options: {
|
|
314
|
+
// 设备像素比,用于适配高清屏幕
|
|
315
|
+
ratio?: number;
|
|
316
|
+
// 图像绘制宽度(默认适应画布宽度)
|
|
317
|
+
width?: number;
|
|
318
|
+
// 图像绘制高度(默认适应画布高度)
|
|
319
|
+
height?: number;
|
|
320
|
+
// 图像绘制的X轴偏移量(相对于画布左上角)
|
|
321
|
+
xOffset?: number;
|
|
322
|
+
// 图像绘制的Y轴偏移量(相对于画布左上角)
|
|
323
|
+
yOffset?: number;
|
|
324
|
+
// 图像旋转角度(度数,顺时针方向)
|
|
325
|
+
rotation?: number;
|
|
326
|
+
} = {},
|
|
327
|
+
): Promise<void> {
|
|
328
|
+
let _tempDataUrl = dataUrl;
|
|
329
|
+
// 如果需要旋转且旋转角度不为0,先处理图像旋转
|
|
330
|
+
if (isNumber(options.rotation) && options.rotation !== 0) {
|
|
331
|
+
_tempDataUrl = await this.rotateDataURL(
|
|
332
|
+
_tempDataUrl,
|
|
333
|
+
options.rotation, // 顺时针旋转指定角度
|
|
334
|
+
'image/png',
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
// 返回Promise,封装图像加载和绘制过程
|
|
338
|
+
return new Promise((resolve, reject) => {
|
|
339
|
+
const image = new Image();
|
|
340
|
+
// 计算设备像素比(默认使用window.devicePixelRatio,无则为1)
|
|
341
|
+
const ratio = options.ratio || window.devicePixelRatio || 1;
|
|
342
|
+
// 计算图像绘制宽度(默认按比例适应画布宽度)
|
|
343
|
+
const width = options.width || this.canvas.width / ratio;
|
|
344
|
+
// 计算图像绘制高度(默认按比例适应画布高度)
|
|
345
|
+
const height = options.height || this.canvas.height / ratio;
|
|
346
|
+
// 图像X轴偏移量(默认0)
|
|
347
|
+
const xOffset = options.xOffset || 0;
|
|
348
|
+
// 图像Y轴偏移量(默认0)
|
|
349
|
+
const yOffset = options.yOffset || 0;
|
|
350
|
+
|
|
351
|
+
// 重置绘制状态
|
|
352
|
+
this._reset(this._getPointGroupOptions());
|
|
353
|
+
|
|
354
|
+
// 图像加载完成回调
|
|
355
|
+
image.onload = (): void => {
|
|
356
|
+
// 将图像绘制到画布指定位置和大小
|
|
357
|
+
this._ctx.drawImage(image, xOffset, yOffset, width, height);
|
|
358
|
+
resolve(); // 通知加载完成
|
|
359
|
+
};
|
|
360
|
+
// 图像加载失败回调
|
|
361
|
+
image.onerror = (error): void => {
|
|
362
|
+
reject(error); // 通知加载失败
|
|
363
|
+
};
|
|
364
|
+
// 允许跨域图像加载
|
|
365
|
+
image.crossOrigin = 'anonymous';
|
|
366
|
+
// 设置图像源为处理后的DataURL
|
|
367
|
+
image.src = _tempDataUrl;
|
|
368
|
+
|
|
369
|
+
// 记录当前加载的DataURL(用于撤销操作)
|
|
370
|
+
this._oldFromDataURL = _tempDataUrl;
|
|
371
|
+
// 标记画布不为空
|
|
372
|
+
this._isEmpty = false;
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* @description 将已有的 DataURL 旋转指定角度后,返回新的 DataURL
|
|
378
|
+
* @private
|
|
379
|
+
* @param {string} dataUrl - 原始图片的DataURL
|
|
380
|
+
* @param {number} rotation - 旋转角度(度数,顺时针),默认0
|
|
381
|
+
* @param {string} type - 图片格式,默认'image/png'
|
|
382
|
+
* @param {number} [encoderOptions] - 图片质量(0-1),仅适用于jpeg等格式
|
|
383
|
+
* @returns {*} {Promise<string>}
|
|
384
|
+
* @memberof SignaturePad
|
|
385
|
+
*/
|
|
386
|
+
private rotateDataURL(
|
|
387
|
+
dataUrl: string,
|
|
388
|
+
rotation: number = 0,
|
|
389
|
+
type: string = 'image/png',
|
|
390
|
+
encoderOptions?: number,
|
|
391
|
+
): Promise<string> {
|
|
392
|
+
return new Promise((resolve, reject) => {
|
|
393
|
+
const image = new Image();
|
|
394
|
+
image.onload = () => {
|
|
395
|
+
const radians = (rotation * Math.PI) / 180;
|
|
396
|
+
|
|
397
|
+
const width = image.width;
|
|
398
|
+
const height = image.height;
|
|
399
|
+
|
|
400
|
+
// 创建临时 canvas
|
|
401
|
+
const tmpCanvas = document.createElement('canvas');
|
|
402
|
+
const ctx = tmpCanvas.getContext('2d')!;
|
|
403
|
+
|
|
404
|
+
// 判断旋转后宽高(90/270度需交换宽高)
|
|
405
|
+
if (rotation % 180 === 0) {
|
|
406
|
+
tmpCanvas.width = width;
|
|
407
|
+
tmpCanvas.height = height;
|
|
408
|
+
} else {
|
|
409
|
+
tmpCanvas.width = height;
|
|
410
|
+
tmpCanvas.height = width;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// 平移到中心 -> 旋转 -> 绘制图片
|
|
414
|
+
ctx.translate(tmpCanvas.width / 2, tmpCanvas.height / 2);
|
|
415
|
+
ctx.rotate(radians);
|
|
416
|
+
ctx.drawImage(image, -width / 2, -height / 2);
|
|
417
|
+
|
|
418
|
+
// 输出新的 dataURL
|
|
419
|
+
resolve(tmpCanvas.toDataURL(type, encoderOptions));
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
image.onerror = reject;
|
|
423
|
+
image.crossOrigin = 'anonymous';
|
|
424
|
+
image.src = dataUrl;
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* @description 撤销上一步
|
|
430
|
+
* @returns {*} {void}
|
|
431
|
+
* @memberof SignaturePad
|
|
432
|
+
*/
|
|
433
|
+
public undoLastStep(): void {
|
|
434
|
+
const tempData = [...this._data];
|
|
435
|
+
const tempFromDataURL = this._oldFromDataURL;
|
|
436
|
+
this.clear();
|
|
437
|
+
|
|
438
|
+
this._isRedrawn = true;
|
|
439
|
+
// 没有可撤销的操作
|
|
440
|
+
if (tempData.length === 0) {
|
|
441
|
+
this._oldFromDataURL = '';
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
// 移除最后一笔数据
|
|
445
|
+
tempData.pop();
|
|
446
|
+
// 重新渲染剩余数据
|
|
447
|
+
this.fromDataURL(tempFromDataURL);
|
|
448
|
+
this.fromData(tempData, { clear: false });
|
|
449
|
+
this._isEmpty = tempData.length <= 0;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* @description 封装获取当前旋转方位的方法
|
|
454
|
+
* @returns {*} {IData} 包含屏幕状态、旋转角度和方向的对象
|
|
455
|
+
* @memberof SignaturePad
|
|
456
|
+
*/
|
|
457
|
+
getCurrentOrientation(): IData {
|
|
458
|
+
// 获取屏幕方向
|
|
459
|
+
const { screen } = window as IData;
|
|
460
|
+
const screenOrientation =
|
|
461
|
+
screen.orientation || screen.mozOrientation || screen.msOrientation;
|
|
462
|
+
let angle = 0;
|
|
463
|
+
|
|
464
|
+
if (screenOrientation) {
|
|
465
|
+
angle = screenOrientation.angle;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// 方向文本映射
|
|
469
|
+
|
|
470
|
+
const orientationText: IData = {
|
|
471
|
+
'0': 'DEFAULT',
|
|
472
|
+
'90': 'Rotated right',
|
|
473
|
+
'-90': 'Rotated left',
|
|
474
|
+
'180': 'Upside down',
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
// 判断是否横屏
|
|
478
|
+
const isLandscape = window.innerWidth > window.innerHeight;
|
|
479
|
+
const status = isLandscape ? '横屏' : '竖屏';
|
|
480
|
+
|
|
481
|
+
// 确定方向文本
|
|
482
|
+
const orientation = orientationText[`${angle}`] || `未知 (${angle}°)`;
|
|
483
|
+
|
|
484
|
+
return {
|
|
485
|
+
isLandscape,
|
|
486
|
+
status,
|
|
487
|
+
angle,
|
|
488
|
+
orientation,
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* @description 将签名图像作为数据 URL 返回
|
|
494
|
+
* @param {string} [type='image/png']
|
|
495
|
+
* @param {{
|
|
496
|
+
* rotation?: number;
|
|
497
|
+
* quality?: number;
|
|
498
|
+
* encoderOptions?: IToSVGOptions;
|
|
499
|
+
* }} [options={}]
|
|
500
|
+
* @returns {*} {string}
|
|
501
|
+
* @memberof SignaturePad
|
|
502
|
+
*/
|
|
503
|
+
public toDataURL(
|
|
504
|
+
type: string = 'image/png',
|
|
505
|
+
options: {
|
|
506
|
+
rotation?: number;
|
|
507
|
+
quality?: number;
|
|
508
|
+
encoderOptions?: IToSVGOptions;
|
|
509
|
+
} = {},
|
|
510
|
+
): string {
|
|
511
|
+
switch (type) {
|
|
512
|
+
case 'image/svg+xml':
|
|
513
|
+
if (isObject(options?.encoderOptions)) {
|
|
514
|
+
options.encoderOptions = undefined;
|
|
515
|
+
}
|
|
516
|
+
return `data:image/svg+xml;base64,${btoa(
|
|
517
|
+
this.toSVG(options?.encoderOptions as unknown as IToSVGOptions),
|
|
518
|
+
)}`;
|
|
519
|
+
default:
|
|
520
|
+
return this.toCanvasDataURL(
|
|
521
|
+
type,
|
|
522
|
+
options.encoderOptions as number,
|
|
523
|
+
options.rotation as number,
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* @description 导出为 Canvas DataURL(支持旋转)
|
|
530
|
+
* @private
|
|
531
|
+
* @param {string} [type='image/png'] 图片格式
|
|
532
|
+
* @param {number} [encoderOptions] 图片质量(0-1)
|
|
533
|
+
* @param {number} [rotation] 旋转角度(度数)
|
|
534
|
+
* @returns {*} {string}
|
|
535
|
+
* @memberof SignaturePad
|
|
536
|
+
*/
|
|
537
|
+
private toCanvasDataURL(
|
|
538
|
+
type: string = 'image/png',
|
|
539
|
+
encoderOptions?: number,
|
|
540
|
+
rotation?: number, // 单位:度
|
|
541
|
+
): string {
|
|
542
|
+
if (typeof encoderOptions !== 'number') {
|
|
543
|
+
encoderOptions = undefined;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
if (isNumber(rotation) && rotation !== 0) {
|
|
547
|
+
// 旋转逻辑
|
|
548
|
+
const radians = (rotation * Math.PI) / 180;
|
|
549
|
+
const tmpCanvas = document.createElement('canvas');
|
|
550
|
+
const ctx = tmpCanvas.getContext('2d')!;
|
|
551
|
+
|
|
552
|
+
const width = this.canvas.width;
|
|
553
|
+
const height = this.canvas.height;
|
|
554
|
+
|
|
555
|
+
// 旋转 90/270 度时,需要交换宽高
|
|
556
|
+
if (rotation % 180 === 0) {
|
|
557
|
+
tmpCanvas.width = width;
|
|
558
|
+
tmpCanvas.height = height;
|
|
559
|
+
} else {
|
|
560
|
+
tmpCanvas.width = height;
|
|
561
|
+
tmpCanvas.height = width;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
ctx.translate(tmpCanvas.width / 2, tmpCanvas.height / 2);
|
|
565
|
+
ctx.rotate(radians);
|
|
566
|
+
ctx.drawImage(this.canvas, -width / 2, -height / 2);
|
|
567
|
+
|
|
568
|
+
return tmpCanvas.toDataURL(type, encoderOptions as number);
|
|
569
|
+
}
|
|
570
|
+
// 不旋转直接导出
|
|
571
|
+
return this.canvas.toDataURL(type, encoderOptions as number);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* @description 启用签名功能的事件监听,配置画布样式以禁用默认的触摸行为(如平移、缩放),并根据设备类型绑定相应的事件处理器
|
|
576
|
+
* @memberof SignaturePad
|
|
577
|
+
*/
|
|
578
|
+
public on(): void {
|
|
579
|
+
// 禁用画布元素的触摸平移/缩放行为
|
|
580
|
+
this.canvas.style.touchAction = 'none';
|
|
581
|
+
// 针对IE浏览器设置触摸行为(兼容性处理)
|
|
582
|
+
(
|
|
583
|
+
this.canvas.style as CSSStyleDeclaration & {
|
|
584
|
+
msTouchAction: string | null;
|
|
585
|
+
}
|
|
586
|
+
).msTouchAction = 'none';
|
|
587
|
+
// 禁用画布上的文本选择
|
|
588
|
+
this.canvas.style.userSelect = 'none';
|
|
589
|
+
|
|
590
|
+
// 判断是否为iOS设备(通过用户代理和触摸事件支持检测)
|
|
591
|
+
const isIOS =
|
|
592
|
+
/Macintosh/.test(navigator.userAgent) && 'ontouchstart' in document;
|
|
593
|
+
|
|
594
|
+
// iOS的"Scribble"功能会拦截指针事件,快速点击时可能丢失部分事件
|
|
595
|
+
// 因此对iOS设备使用触摸事件,其他支持指针事件的设备使用指针事件
|
|
596
|
+
if (window.PointerEvent && !isIOS) {
|
|
597
|
+
this._handlePointerEvents();
|
|
598
|
+
} else {
|
|
599
|
+
this._handleMouseEvents();
|
|
600
|
+
|
|
601
|
+
// 如果浏览器支持触摸事件,绑定触摸事件处理器
|
|
602
|
+
if ('ontouchstart' in window) {
|
|
603
|
+
this._handleTouchEvents();
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* @description 禁用签名功能的事件监听,恢复画布默认样式(允许平移、缩放等),并移除所有已绑定的事件处理器
|
|
610
|
+
* @memberof SignaturePad
|
|
611
|
+
*/
|
|
612
|
+
public off(): void {
|
|
613
|
+
// 恢复画布的默认触摸行为(允许平移/缩放)
|
|
614
|
+
this.canvas.style.touchAction = 'auto';
|
|
615
|
+
// 恢复IE浏览器的默认触摸行为
|
|
616
|
+
(
|
|
617
|
+
this.canvas.style as CSSStyleDeclaration & {
|
|
618
|
+
msTouchAction: string | null;
|
|
619
|
+
}
|
|
620
|
+
).msTouchAction = 'auto';
|
|
621
|
+
// 恢复画布上的文本选择功能
|
|
622
|
+
this.canvas.style.userSelect = 'auto';
|
|
623
|
+
|
|
624
|
+
// 移除画布上的各类起始事件监听器
|
|
625
|
+
this.canvas.removeEventListener('pointerdown', this._handlePointerDown);
|
|
626
|
+
this.canvas.removeEventListener('mousedown', this._handleMouseDown);
|
|
627
|
+
this.canvas.removeEventListener('touchstart', this._handleTouchStart);
|
|
628
|
+
|
|
629
|
+
// 移除所有移动和结束事件的监听器(如mousemove、mouseup等)
|
|
630
|
+
this._removeMoveUpEventListeners();
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* @description 获取事件监听器的工具函数(适配不同文档上下文的窗口)
|
|
635
|
+
* @private
|
|
636
|
+
* @returns {*} 包含addEventListener和removeEventListener的对象
|
|
637
|
+
* @memberof SignaturePad
|
|
638
|
+
*/
|
|
639
|
+
private _getListenerFunctions() {
|
|
640
|
+
const canvasWindow =
|
|
641
|
+
window.document === this.canvas.ownerDocument
|
|
642
|
+
? window
|
|
643
|
+
: (this.canvas.ownerDocument.defaultView ?? this.canvas.ownerDocument);
|
|
644
|
+
|
|
645
|
+
return {
|
|
646
|
+
addEventListener: canvasWindow.addEventListener.bind(
|
|
647
|
+
canvasWindow,
|
|
648
|
+
) as typeof window.addEventListener,
|
|
649
|
+
removeEventListener: canvasWindow.removeEventListener.bind(
|
|
650
|
+
canvasWindow,
|
|
651
|
+
) as typeof window.removeEventListener,
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* @description 移除所有移动和抬起事件的监听器(清理事件绑定)
|
|
657
|
+
* @private
|
|
658
|
+
* @memberof SignaturePad
|
|
659
|
+
*/
|
|
660
|
+
private _removeMoveUpEventListeners(): void {
|
|
661
|
+
const { removeEventListener } = this._getListenerFunctions();
|
|
662
|
+
removeEventListener('pointermove', this._handlePointerMove);
|
|
663
|
+
removeEventListener('pointerup', this._handlePointerUp);
|
|
664
|
+
|
|
665
|
+
removeEventListener('mousemove', this._handleMouseMove);
|
|
666
|
+
removeEventListener('mouseup', this._handleMouseUp);
|
|
667
|
+
|
|
668
|
+
removeEventListener('touchmove', this._handleTouchMove);
|
|
669
|
+
removeEventListener('touchend', this._handleTouchEnd);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* @description 判断签名画布是否为空(未绘制任何内容)
|
|
674
|
+
* @returns {*} {boolean}
|
|
675
|
+
* @memberof SignaturePad
|
|
676
|
+
*/
|
|
677
|
+
public isEmpty(): boolean {
|
|
678
|
+
return this._isEmpty;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* @description 判断签名是否经过重新绘制(如从数据恢复签名、执行撤销后重新渲染等场景)
|
|
683
|
+
* @returns {*} {boolean}
|
|
684
|
+
* @memberof SignaturePad
|
|
685
|
+
*/
|
|
686
|
+
public isRedrawn(): boolean {
|
|
687
|
+
return this._isRedrawn;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* @description 从点组数据加载并渲染签名,可根据配置决定是否先清空现有签名,再基于传入的点组数据重新绘制曲线和点
|
|
692
|
+
* @param {IPointGroup[]} pointGroups - 签名点组数据数组,每个点组包含一段签名的点集合及对应的样式配置
|
|
693
|
+
* @param {IFromDataOptions} [options={ clear: true }] - 加载配置项,默认清空现有签名
|
|
694
|
+
* @memberof SignaturePad
|
|
695
|
+
*/
|
|
696
|
+
public fromData(
|
|
697
|
+
pointGroups: IPointGroup[],
|
|
698
|
+
{ clear = true }: IFromDataOptions = {},
|
|
699
|
+
): void {
|
|
700
|
+
if (clear) {
|
|
701
|
+
this.clear(); // 若配置需要清空,则先执行清空操作
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// 调用内部方法,传入点组数据及绘制曲线、点的工具方法,完成签名渲染
|
|
705
|
+
this._fromData(
|
|
706
|
+
pointGroups,
|
|
707
|
+
this._drawCurve.bind(this), // 绑定当前实例上下文的曲线绘制方法
|
|
708
|
+
this._drawDot.bind(this), // 绑定当前实例上下文的点绘制方法
|
|
709
|
+
);
|
|
710
|
+
|
|
711
|
+
// 将加载的点组数据合并到当前签名数据中,更新数据记录
|
|
712
|
+
this._data = this._data.concat(pointGroups);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
/**
|
|
716
|
+
* @description 导出当前签名的点组数据,用于保存签名原始数据,后续可通过fromData方法恢复签名
|
|
717
|
+
* @returns {*} {IPointGroup[]}
|
|
718
|
+
* @memberof SignaturePad
|
|
719
|
+
*/
|
|
720
|
+
public toData(): IPointGroup[] {
|
|
721
|
+
return this._data;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* @description 判断鼠标左键是否按下(支持判断是否仅左键按下)
|
|
726
|
+
* @private
|
|
727
|
+
* @param {MouseEvent} event - 鼠标事件对象
|
|
728
|
+
* @param {boolean} [only] - 是否要求仅左键按下
|
|
729
|
+
* @returns {*} {boolean}
|
|
730
|
+
* @memberof SignaturePad
|
|
731
|
+
*/
|
|
732
|
+
private _isLeftButtonPressed(event: MouseEvent, only?: boolean): boolean {
|
|
733
|
+
if (only) {
|
|
734
|
+
return event.buttons === 1;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// eslint-disable-next-line no-bitwise
|
|
738
|
+
return (event.buttons & 1) === 1;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/**
|
|
742
|
+
* @description 将鼠标/指针事件转换为签名事件对象
|
|
743
|
+
* @private
|
|
744
|
+
* @param {(MouseEvent | PointerEvent)} event - 原始事件对象
|
|
745
|
+
* @returns {*} {ISignatureEvent}
|
|
746
|
+
* @memberof SignaturePad
|
|
747
|
+
*/
|
|
748
|
+
private _pointerEventToSignatureEvent(
|
|
749
|
+
event: MouseEvent | PointerEvent,
|
|
750
|
+
): ISignatureEvent {
|
|
751
|
+
return {
|
|
752
|
+
event,
|
|
753
|
+
type: event.type,
|
|
754
|
+
x: event.clientX,
|
|
755
|
+
y: event.clientY,
|
|
756
|
+
pressure: 'pressure' in event ? event.pressure : 0,
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
/**
|
|
761
|
+
* @description 将触摸事件转换为签名事件对象
|
|
762
|
+
* @private
|
|
763
|
+
* @param {TouchEvent} event - 原始触摸事件
|
|
764
|
+
* @returns {*} {ISignatureEvent}
|
|
765
|
+
* @memberof SignaturePad
|
|
766
|
+
*/
|
|
767
|
+
private _touchEventToSignatureEvent(event: TouchEvent): ISignatureEvent {
|
|
768
|
+
const touch = event.changedTouches[0];
|
|
769
|
+
return {
|
|
770
|
+
event,
|
|
771
|
+
type: event.type,
|
|
772
|
+
x: touch.clientX,
|
|
773
|
+
y: touch.clientY,
|
|
774
|
+
pressure: touch.force,
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* @description 处理鼠标按下事件,当左键按下且未正在绘制时,开始新的笔触
|
|
780
|
+
* @private
|
|
781
|
+
* @param {MouseEvent} event
|
|
782
|
+
* @returns {*} {void}
|
|
783
|
+
* @memberof SignaturePad
|
|
784
|
+
*/
|
|
785
|
+
private _handleMouseDown(event: MouseEvent): void {
|
|
786
|
+
// 若不是左键单独按下,或正在绘制中,则不处理
|
|
787
|
+
if (!this._isLeftButtonPressed(event, true) || this._drawingStroke) {
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
// 将鼠标事件转换为签名事件,并开始笔触
|
|
791
|
+
this._strokeBegin(this._pointerEventToSignatureEvent(event));
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* @description 处理鼠标移动事件,当左键持续按下且正在绘制时,更新笔触;否则结束笔触
|
|
796
|
+
* @private
|
|
797
|
+
* @param {MouseEvent} event
|
|
798
|
+
* @returns {*} {void}
|
|
799
|
+
* @memberof SignaturePad
|
|
800
|
+
*/
|
|
801
|
+
private _handleMouseMove(event: MouseEvent): void {
|
|
802
|
+
// 若不是左键单独按下,或不在绘制状态,则结束笔触
|
|
803
|
+
if (!this._isLeftButtonPressed(event, true) || !this._drawingStroke) {
|
|
804
|
+
// 当未按主按钮或按了多个按钮时停止绘制
|
|
805
|
+
this._strokeEnd(this._pointerEventToSignatureEvent(event), false);
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// 更新笔触(带节流处理)
|
|
810
|
+
this._strokeMoveUpdate(this._pointerEventToSignatureEvent(event));
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
/**
|
|
814
|
+
* @description 处理鼠标抬起事件,当左键抬起时,结束当前笔触
|
|
815
|
+
* @private
|
|
816
|
+
* @param {MouseEvent} event
|
|
817
|
+
* @returns {*} {void}
|
|
818
|
+
* @memberof SignaturePad
|
|
819
|
+
*/
|
|
820
|
+
private _handleMouseUp(event: MouseEvent): void {
|
|
821
|
+
// 若左键仍按下,则不处理
|
|
822
|
+
if (this._isLeftButtonPressed(event)) {
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// 结束笔触
|
|
827
|
+
this._strokeEnd(this._pointerEventToSignatureEvent(event));
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
/**
|
|
831
|
+
* @description 处理触摸开始事件,当单点触摸且不在绘制状态时,开始新的笔触,并阻止页面滚动
|
|
832
|
+
* @private
|
|
833
|
+
* @param {TouchEvent} event
|
|
834
|
+
* @returns {*} {void}
|
|
835
|
+
* @memberof SignaturePad
|
|
836
|
+
*/
|
|
837
|
+
private _handleTouchStart(event: TouchEvent): void {
|
|
838
|
+
// 若不是单点触摸,或正在绘制中,则不处理
|
|
839
|
+
if (event.targetTouches.length !== 1 || this._drawingStroke) {
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// 阻止页面滚动
|
|
844
|
+
if (event.cancelable) {
|
|
845
|
+
event.preventDefault();
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// 将触摸事件转换为签名事件,并开始笔触
|
|
849
|
+
this._strokeBegin(this._touchEventToSignatureEvent(event));
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
/**
|
|
853
|
+
* @description 处理触摸移动事件,当单点触摸且正在绘制时,更新笔触;否则结束笔触,并阻止页面滚动
|
|
854
|
+
* @private
|
|
855
|
+
* @param {TouchEvent} event
|
|
856
|
+
* @returns {*} {void}
|
|
857
|
+
* @memberof SignaturePad
|
|
858
|
+
*/
|
|
859
|
+
private _handleTouchMove(event: TouchEvent): void {
|
|
860
|
+
// 若不是单点触摸,则不处理
|
|
861
|
+
if (event.targetTouches.length !== 1) {
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
// 阻止页面滚动
|
|
866
|
+
if (event.cancelable) {
|
|
867
|
+
event.preventDefault();
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
// 若不在绘制状态,则结束笔触
|
|
871
|
+
if (!this._drawingStroke) {
|
|
872
|
+
this._strokeEnd(this._touchEventToSignatureEvent(event), false);
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
// 更新笔触(带节流处理)
|
|
877
|
+
this._strokeMoveUpdate(this._touchEventToSignatureEvent(event));
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
/**
|
|
881
|
+
* @description 处理触摸结束事件,当所有触摸点离开时,结束当前笔触,并阻止默认行为
|
|
882
|
+
* @private
|
|
883
|
+
* @param {TouchEvent} event
|
|
884
|
+
* @returns {*} {void}
|
|
885
|
+
* @memberof SignaturePad
|
|
886
|
+
*/
|
|
887
|
+
private _handleTouchEnd(event: TouchEvent): void {
|
|
888
|
+
// 若仍有触摸点未离开,则不处理
|
|
889
|
+
if (event.targetTouches.length !== 0) {
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
// 阻止默认行为(如点击事件冒泡)
|
|
894
|
+
if (event.cancelable) {
|
|
895
|
+
event.preventDefault();
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
// 结束笔触
|
|
899
|
+
this._strokeEnd(this._touchEventToSignatureEvent(event));
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
/**
|
|
903
|
+
* @description 获取指针事件的唯一ID(优先使用persistentDeviceId,兼容旧设备用pointerId)
|
|
904
|
+
* @private
|
|
905
|
+
* @param {PointerEvent} event
|
|
906
|
+
* @returns {*} {number}
|
|
907
|
+
* @memberof SignaturePad
|
|
908
|
+
*/
|
|
909
|
+
private _getPointerId(event: PointerEvent): number {
|
|
910
|
+
return (event as IData)?.persistentDeviceId || event.pointerId;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
/**
|
|
914
|
+
* @description 判断当前指针事件的ID是否为当前活跃的笔触ID
|
|
915
|
+
* @private
|
|
916
|
+
* @param {PointerEvent} event - 指针事件对象
|
|
917
|
+
* @param {boolean} [allowUndefined] - 是否允许当前无活跃ID(初始状态)
|
|
918
|
+
* @returns {*} {boolean}
|
|
919
|
+
* @memberof SignaturePad
|
|
920
|
+
*/
|
|
921
|
+
private _allowPointerId(
|
|
922
|
+
event: PointerEvent,
|
|
923
|
+
allowUndefined = false,
|
|
924
|
+
): boolean {
|
|
925
|
+
if (typeof this._strokePointerId === 'undefined') {
|
|
926
|
+
return allowUndefined;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
return this._getPointerId(event) === this._strokePointerId;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
/**
|
|
933
|
+
* @description 处理指针按下事件(兼容鼠标、触摸等多种输入设备)
|
|
934
|
+
* @private
|
|
935
|
+
* @param {PointerEvent} event
|
|
936
|
+
* @returns {*} {void}
|
|
937
|
+
* @memberof SignaturePad
|
|
938
|
+
*/
|
|
939
|
+
private _handlePointerDown(event: PointerEvent): void {
|
|
940
|
+
// 若正在绘制中,或左键未按下,或指针ID不合法,则不处理
|
|
941
|
+
if (
|
|
942
|
+
this._drawingStroke ||
|
|
943
|
+
!this._isLeftButtonPressed(event) ||
|
|
944
|
+
!this._allowPointerId(event, true)
|
|
945
|
+
) {
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
// 记录当前活跃的指针ID(用于区分多指针操作)
|
|
950
|
+
this._strokePointerId = this._getPointerId(event);
|
|
951
|
+
|
|
952
|
+
// 阻止默认行为(如页面滚动、文本选择等)
|
|
953
|
+
event.preventDefault();
|
|
954
|
+
|
|
955
|
+
// 将指针事件转换为签名事件,并开始笔触
|
|
956
|
+
this._strokeBegin(this._pointerEventToSignatureEvent(event));
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
/**
|
|
960
|
+
* @description 处理指针移动事件,当指针ID有效、左键持续按下且正在绘制时,更新笔触;否则结束笔触
|
|
961
|
+
* @private
|
|
962
|
+
* @param {PointerEvent} event
|
|
963
|
+
* @returns {*} {void}
|
|
964
|
+
* @memberof SignaturePad
|
|
965
|
+
*/
|
|
966
|
+
private _handlePointerMove(event: PointerEvent): void {
|
|
967
|
+
// 若指针ID不匹配当前活跃ID,则不处理
|
|
968
|
+
if (!this._allowPointerId(event)) {
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
// 若左键未单独按下,或不在绘制状态,则结束笔触
|
|
973
|
+
if (!this._isLeftButtonPressed(event, true) || !this._drawingStroke) {
|
|
974
|
+
// 当主按钮未按下或按下多个按钮时停止绘制
|
|
975
|
+
this._strokeEnd(this._pointerEventToSignatureEvent(event), false);
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
// 阻止默认行为
|
|
980
|
+
event.preventDefault();
|
|
981
|
+
|
|
982
|
+
// 更新笔触(带节流处理)
|
|
983
|
+
this._strokeMoveUpdate(this._pointerEventToSignatureEvent(event));
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
/**
|
|
987
|
+
* @description 处理指针抬起事件,当左键抬起且指针ID有效时,结束当前笔触
|
|
988
|
+
* @private
|
|
989
|
+
* @param {PointerEvent} event
|
|
990
|
+
* @returns {*} {void}
|
|
991
|
+
* @memberof SignaturePad
|
|
992
|
+
*/
|
|
993
|
+
private _handlePointerUp(event: PointerEvent): void {
|
|
994
|
+
// 若左键仍按下,或指针ID不匹配当前活跃ID,则不处理
|
|
995
|
+
if (this._isLeftButtonPressed(event) || !this._allowPointerId(event)) {
|
|
996
|
+
return;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
// 阻止默认行为
|
|
1000
|
+
event.preventDefault();
|
|
1001
|
+
|
|
1002
|
+
// 结束笔触
|
|
1003
|
+
this._strokeEnd(this._pointerEventToSignatureEvent(event));
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
/**
|
|
1007
|
+
* @description 获取点组的样式配置(优先使用点组自身配置,否则用全局配置)
|
|
1008
|
+
* @private
|
|
1009
|
+
* @param {IPointGroup} [group] - 点组对象(可选)
|
|
1010
|
+
* @returns {*} {IPointGroupOptions}
|
|
1011
|
+
* @memberof SignaturePad
|
|
1012
|
+
*/
|
|
1013
|
+
private _getPointGroupOptions(group?: IPointGroup): IPointGroupOptions {
|
|
1014
|
+
return {
|
|
1015
|
+
penColor: group && 'penColor' in group ? group.penColor : this.penColor,
|
|
1016
|
+
dotSize: group && 'dotSize' in group ? group.dotSize : this.dotSize,
|
|
1017
|
+
minWidth: group && 'minWidth' in group ? group.minWidth : this.minWidth,
|
|
1018
|
+
maxWidth: group && 'maxWidth' in group ? group.maxWidth : this.maxWidth,
|
|
1019
|
+
velocityFilterWeight:
|
|
1020
|
+
group && 'velocityFilterWeight' in group
|
|
1021
|
+
? group.velocityFilterWeight
|
|
1022
|
+
: this.velocityFilterWeight,
|
|
1023
|
+
compositeOperation:
|
|
1024
|
+
group && 'compositeOperation' in group
|
|
1025
|
+
? group.compositeOperation
|
|
1026
|
+
: this.compositeOperation,
|
|
1027
|
+
};
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
/**
|
|
1031
|
+
* @description 开始绘制笔触(初始化事件监听和绘制状态)
|
|
1032
|
+
* @private
|
|
1033
|
+
* @param {ISignatureEvent} event - 签名事件对象
|
|
1034
|
+
* @memberof SignaturePad
|
|
1035
|
+
*/
|
|
1036
|
+
private _strokeBegin(event: ISignatureEvent): void {
|
|
1037
|
+
const { addEventListener } = this._getListenerFunctions();
|
|
1038
|
+
switch (event.event.type) {
|
|
1039
|
+
case 'mousedown':
|
|
1040
|
+
addEventListener('mousemove', this._handleMouseMove, {
|
|
1041
|
+
passive: false,
|
|
1042
|
+
});
|
|
1043
|
+
addEventListener('mouseup', this._handleMouseUp, { passive: false });
|
|
1044
|
+
break;
|
|
1045
|
+
case 'touchstart':
|
|
1046
|
+
addEventListener('touchmove', this._handleTouchMove, {
|
|
1047
|
+
passive: false,
|
|
1048
|
+
});
|
|
1049
|
+
addEventListener('touchend', this._handleTouchEnd, { passive: false });
|
|
1050
|
+
break;
|
|
1051
|
+
case 'pointerdown':
|
|
1052
|
+
addEventListener('pointermove', this._handlePointerMove, {
|
|
1053
|
+
passive: false,
|
|
1054
|
+
});
|
|
1055
|
+
addEventListener('pointerup', this._handlePointerUp, {
|
|
1056
|
+
passive: false,
|
|
1057
|
+
});
|
|
1058
|
+
break;
|
|
1059
|
+
default:
|
|
1060
|
+
// do nothing
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
this._drawingStroke = true;
|
|
1064
|
+
|
|
1065
|
+
const pointGroupOptions = this._getPointGroupOptions();
|
|
1066
|
+
|
|
1067
|
+
const newPointGroup: IPointGroup = {
|
|
1068
|
+
...pointGroupOptions,
|
|
1069
|
+
points: [],
|
|
1070
|
+
};
|
|
1071
|
+
|
|
1072
|
+
this._data.push(newPointGroup);
|
|
1073
|
+
this._reset(pointGroupOptions);
|
|
1074
|
+
this._strokeUpdate(event);
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
/**
|
|
1078
|
+
* @description 更新绘制(处理新点并绘制曲线/点)
|
|
1079
|
+
* @private
|
|
1080
|
+
* @param {ISignatureEvent} event
|
|
1081
|
+
* @returns {*} {void}
|
|
1082
|
+
* @memberof SignaturePad
|
|
1083
|
+
*/
|
|
1084
|
+
private _strokeUpdate(event: ISignatureEvent): void {
|
|
1085
|
+
if (!this._drawingStroke) {
|
|
1086
|
+
return;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
if (this._data.length === 0) {
|
|
1090
|
+
// 如果在签名仍在进行时调用 clear() ,则可能会发生这种情况,
|
|
1091
|
+
// 或者,如果启动/更新事件之间存在争用条件。
|
|
1092
|
+
this._strokeBegin(event);
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
const point = this._createPoint(event.x, event.y, event.pressure);
|
|
1097
|
+
const lastPointGroup = this._data[this._data.length - 1];
|
|
1098
|
+
const lastPoints = lastPointGroup.points;
|
|
1099
|
+
const lastPoint =
|
|
1100
|
+
lastPoints.length > 0 && lastPoints[lastPoints.length - 1];
|
|
1101
|
+
const isLastPointTooClose = lastPoint
|
|
1102
|
+
? point.distanceTo(lastPoint) <= this.minDistance
|
|
1103
|
+
: false;
|
|
1104
|
+
const pointGroupOptions = this._getPointGroupOptions(lastPointGroup);
|
|
1105
|
+
|
|
1106
|
+
// 如果它与上一个点太近,跳过这一点
|
|
1107
|
+
if (!lastPoint || !(lastPoint && isLastPointTooClose)) {
|
|
1108
|
+
const curve = this._addPoint(point, pointGroupOptions);
|
|
1109
|
+
|
|
1110
|
+
if (!lastPoint) {
|
|
1111
|
+
this._drawDot(point, pointGroupOptions);
|
|
1112
|
+
} else if (curve) {
|
|
1113
|
+
this._drawCurve(curve, pointGroupOptions);
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
lastPoints.push({
|
|
1117
|
+
time: point.time,
|
|
1118
|
+
x: point.x,
|
|
1119
|
+
y: point.y,
|
|
1120
|
+
pressure: point.pressure,
|
|
1121
|
+
});
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
/**
|
|
1126
|
+
* @description 结束绘制笔触(清理事件监听和绘制状态)
|
|
1127
|
+
* @private
|
|
1128
|
+
* @param {ISignatureEvent} event - 签名事件对象
|
|
1129
|
+
* @param {boolean} [shouldUpdate=true] - 是否在结束前更新绘制
|
|
1130
|
+
* @returns {*} {void}
|
|
1131
|
+
* @memberof SignaturePad
|
|
1132
|
+
*/
|
|
1133
|
+
private _strokeEnd(event: ISignatureEvent, shouldUpdate = true): void {
|
|
1134
|
+
this._removeMoveUpEventListeners();
|
|
1135
|
+
|
|
1136
|
+
if (!this._drawingStroke) {
|
|
1137
|
+
return;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
if (shouldUpdate) {
|
|
1141
|
+
this._strokeUpdate(event);
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
this._drawingStroke = false;
|
|
1145
|
+
this._strokePointerId = undefined;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
/**
|
|
1149
|
+
* @description 初始化指针事件处理(绑定指针按下事件)
|
|
1150
|
+
* @private
|
|
1151
|
+
* @memberof SignaturePad
|
|
1152
|
+
*/
|
|
1153
|
+
private _handlePointerEvents(): void {
|
|
1154
|
+
this._drawingStroke = false;
|
|
1155
|
+
|
|
1156
|
+
this.canvas.addEventListener('pointerdown', this._handlePointerDown, {
|
|
1157
|
+
passive: false,
|
|
1158
|
+
});
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
/**
|
|
1162
|
+
* @description 初始化鼠标事件处理(绑定鼠标按下事件)
|
|
1163
|
+
* @private
|
|
1164
|
+
* @memberof SignaturePad
|
|
1165
|
+
*/
|
|
1166
|
+
private _handleMouseEvents(): void {
|
|
1167
|
+
this._drawingStroke = false;
|
|
1168
|
+
|
|
1169
|
+
this.canvas.addEventListener('mousedown', this._handleMouseDown, {
|
|
1170
|
+
passive: false,
|
|
1171
|
+
});
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
/**
|
|
1175
|
+
* @description 初始化触摸事件处理(绑定触摸开始事件)
|
|
1176
|
+
* @private
|
|
1177
|
+
* @memberof SignaturePad
|
|
1178
|
+
*/
|
|
1179
|
+
private _handleTouchEvents(): void {
|
|
1180
|
+
this.canvas.addEventListener('touchstart', this._handleTouchStart, {
|
|
1181
|
+
passive: false,
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
/**
|
|
1186
|
+
* @description 重置绘制状态(清空最近点、重置速度和宽度等)
|
|
1187
|
+
* @private
|
|
1188
|
+
* @param {IPointGroupOptions} options - 点组样式配置
|
|
1189
|
+
* @memberof SignaturePad
|
|
1190
|
+
*/
|
|
1191
|
+
private _reset(options: IPointGroupOptions): void {
|
|
1192
|
+
this._lastPoints = [];
|
|
1193
|
+
this._lastVelocity = 0;
|
|
1194
|
+
this._lastWidth = (options.minWidth + options.maxWidth) / 2;
|
|
1195
|
+
this._ctx.fillStyle = options.penColor;
|
|
1196
|
+
this._ctx.globalCompositeOperation = options.compositeOperation;
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
/**
|
|
1200
|
+
* @description 创建点对象(转换坐标为画布相对坐标)
|
|
1201
|
+
* @private
|
|
1202
|
+
* @param {number} x - 原始X坐标(相对于视口)
|
|
1203
|
+
* @param {number} y - 原始Y坐标(相对于视口)
|
|
1204
|
+
* @param {number} pressure - 压力值
|
|
1205
|
+
* @returns {*} {Point}
|
|
1206
|
+
* @memberof SignaturePad
|
|
1207
|
+
*/
|
|
1208
|
+
private _createPoint(x: number, y: number, pressure: number): Point {
|
|
1209
|
+
const rect = this.canvas.getBoundingClientRect();
|
|
1210
|
+
|
|
1211
|
+
return new Point(
|
|
1212
|
+
x - rect.left,
|
|
1213
|
+
y - rect.top,
|
|
1214
|
+
pressure,
|
|
1215
|
+
new Date().getTime(),
|
|
1216
|
+
);
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
/**
|
|
1220
|
+
* @description 添加点到最近点列表,并在点足够时生成贝塞尔曲线
|
|
1221
|
+
* @private
|
|
1222
|
+
* @param {Point} point - 新点
|
|
1223
|
+
* @param {IPointGroupOptions} options - 样式配置
|
|
1224
|
+
* @returns {*} {(Bezier | null)}
|
|
1225
|
+
* @memberof SignaturePad
|
|
1226
|
+
*/
|
|
1227
|
+
private _addPoint(point: Point, options: IPointGroupOptions): Bezier | null {
|
|
1228
|
+
const { _lastPoints } = this;
|
|
1229
|
+
|
|
1230
|
+
_lastPoints.push(point);
|
|
1231
|
+
|
|
1232
|
+
if (_lastPoints.length > 2) {
|
|
1233
|
+
// 初始时用3个点生成曲线,通过复制第一个点到开头凑齐4个点
|
|
1234
|
+
if (_lastPoints.length === 3) {
|
|
1235
|
+
_lastPoints.unshift(_lastPoints[0]);
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
// 此时_lastPoints一定有4个点,用于生成曲线
|
|
1239
|
+
const widths = this._calculateCurveWidths(
|
|
1240
|
+
_lastPoints[1],
|
|
1241
|
+
_lastPoints[2],
|
|
1242
|
+
options,
|
|
1243
|
+
);
|
|
1244
|
+
const curve = Bezier.fromPoints(_lastPoints, widths);
|
|
1245
|
+
|
|
1246
|
+
// 移除第一个点,保持列表最多4个点
|
|
1247
|
+
_lastPoints.shift();
|
|
1248
|
+
|
|
1249
|
+
return curve;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
return null;
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
/**
|
|
1256
|
+
* @description 计算曲线的起始和结束宽度(基于速度动态调整)
|
|
1257
|
+
* @private
|
|
1258
|
+
* @param {Point} startPoint - 曲线起点
|
|
1259
|
+
* @param {Point} endPoint - 曲线终点
|
|
1260
|
+
* @param {IPointGroupOptions} options - 样式配置
|
|
1261
|
+
* @returns {*} {{ start: number; end: number }}
|
|
1262
|
+
* @memberof SignaturePad
|
|
1263
|
+
*/
|
|
1264
|
+
private _calculateCurveWidths(
|
|
1265
|
+
startPoint: Point,
|
|
1266
|
+
endPoint: Point,
|
|
1267
|
+
options: IPointGroupOptions,
|
|
1268
|
+
): { start: number; end: number } {
|
|
1269
|
+
const velocity =
|
|
1270
|
+
options.velocityFilterWeight * endPoint.velocityFrom(startPoint) +
|
|
1271
|
+
(1 - options.velocityFilterWeight) * this._lastVelocity;
|
|
1272
|
+
|
|
1273
|
+
const newWidth = this._strokeWidth(velocity, options);
|
|
1274
|
+
|
|
1275
|
+
const widths = {
|
|
1276
|
+
end: newWidth,
|
|
1277
|
+
start: this._lastWidth,
|
|
1278
|
+
};
|
|
1279
|
+
|
|
1280
|
+
this._lastVelocity = velocity;
|
|
1281
|
+
this._lastWidth = newWidth;
|
|
1282
|
+
|
|
1283
|
+
return widths;
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
/**
|
|
1287
|
+
* @description 根据速度计算线条宽度(速度越快,宽度越接近最小宽度)
|
|
1288
|
+
* @private
|
|
1289
|
+
* @param {number} velocity - 绘制速度
|
|
1290
|
+
* @param {IPointGroupOptions} options - 样式配置
|
|
1291
|
+
* @returns {*} {number}
|
|
1292
|
+
* @memberof SignaturePad
|
|
1293
|
+
*/
|
|
1294
|
+
private _strokeWidth(velocity: number, options: IPointGroupOptions): number {
|
|
1295
|
+
return Math.max(options.maxWidth / (velocity + 1), options.minWidth);
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
/**
|
|
1299
|
+
* @description 绘制曲线片段(以点为中心的圆,用于模拟线条)
|
|
1300
|
+
* @private
|
|
1301
|
+
* @param {number} x - 片段X坐标
|
|
1302
|
+
* @param {number} y - 片段Y坐标
|
|
1303
|
+
* @param {number} width - 片段宽度(圆的半径)
|
|
1304
|
+
* @memberof SignaturePad
|
|
1305
|
+
*/
|
|
1306
|
+
private _drawCurveSegment(x: number, y: number, width: number): void {
|
|
1307
|
+
const ctx = this._ctx;
|
|
1308
|
+
|
|
1309
|
+
ctx.moveTo(x, y);
|
|
1310
|
+
ctx.arc(x, y, width, 0, 2 * Math.PI, false);
|
|
1311
|
+
this._isEmpty = false;
|
|
1312
|
+
this._isRedrawn = true;
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
/**
|
|
1316
|
+
* @description 绘制贝塞尔曲线(通过分段绘制多个圆模拟平滑线条)
|
|
1317
|
+
* @private
|
|
1318
|
+
* @param {Bezier} curve - 贝塞尔曲线对象
|
|
1319
|
+
* @param {IPointGroupOptions} options - 样式配置
|
|
1320
|
+
* @memberof SignaturePad
|
|
1321
|
+
*/
|
|
1322
|
+
private _drawCurve(curve: Bezier, options: IPointGroupOptions): void {
|
|
1323
|
+
const ctx = this._ctx;
|
|
1324
|
+
const widthDelta = curve.endWidth - curve.startWidth;
|
|
1325
|
+
// '2'是经验值,仅用长度计算会导致曲线段之间有间隙
|
|
1326
|
+
const drawSteps = Math.ceil(curve.length()) * 2;
|
|
1327
|
+
|
|
1328
|
+
ctx.beginPath();
|
|
1329
|
+
ctx.fillStyle = options.penColor;
|
|
1330
|
+
|
|
1331
|
+
for (let i = 0; i < drawSteps; i += 1) {
|
|
1332
|
+
// 计算当前步骤在曲线上的坐标
|
|
1333
|
+
const t = i / drawSteps;
|
|
1334
|
+
const tt = t * t;
|
|
1335
|
+
const ttt = tt * t;
|
|
1336
|
+
const u = 1 - t;
|
|
1337
|
+
const uu = u * u;
|
|
1338
|
+
const uuu = uu * u;
|
|
1339
|
+
|
|
1340
|
+
let x = uuu * curve.startPoint.x;
|
|
1341
|
+
x += 3 * uu * t * curve.control1.x;
|
|
1342
|
+
x += 3 * u * tt * curve.control2.x;
|
|
1343
|
+
x += ttt * curve.endPoint.x;
|
|
1344
|
+
|
|
1345
|
+
let y = uuu * curve.startPoint.y;
|
|
1346
|
+
y += 3 * uu * t * curve.control1.y;
|
|
1347
|
+
y += 3 * u * tt * curve.control2.y;
|
|
1348
|
+
y += ttt * curve.endPoint.y;
|
|
1349
|
+
|
|
1350
|
+
const width = Math.min(
|
|
1351
|
+
curve.startWidth + ttt * widthDelta,
|
|
1352
|
+
options.maxWidth,
|
|
1353
|
+
);
|
|
1354
|
+
this._drawCurveSegment(x, y, width);
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
ctx.closePath();
|
|
1358
|
+
ctx.fill();
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
/**
|
|
1362
|
+
* @description 绘制点(用于笔触起始或单点点击)
|
|
1363
|
+
* @private
|
|
1364
|
+
* @param {IBasicPoint} point - 点对象
|
|
1365
|
+
* @param {IPointGroupOptions} options - 样式配置
|
|
1366
|
+
* @memberof SignaturePad
|
|
1367
|
+
*/
|
|
1368
|
+
private _drawDot(point: IBasicPoint, options: IPointGroupOptions): void {
|
|
1369
|
+
const ctx = this._ctx;
|
|
1370
|
+
const width =
|
|
1371
|
+
options.dotSize > 0
|
|
1372
|
+
? options.dotSize
|
|
1373
|
+
: (options.minWidth + options.maxWidth) / 2;
|
|
1374
|
+
|
|
1375
|
+
ctx.beginPath();
|
|
1376
|
+
this._drawCurveSegment(point.x, point.y, width);
|
|
1377
|
+
ctx.closePath();
|
|
1378
|
+
ctx.fillStyle = options.penColor;
|
|
1379
|
+
ctx.fill();
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
/**
|
|
1383
|
+
* @description 从点组数据绘制签名(用于从保存的数据恢复签名)
|
|
1384
|
+
* @private
|
|
1385
|
+
* @param {IPointGroup[]} pointGroups - 点组数据数组
|
|
1386
|
+
* @param {Function} drawCurve - 绘制曲线的函数
|
|
1387
|
+
* @param {Function} drawDot - 绘制点的函数
|
|
1388
|
+
* @memberof SignaturePad
|
|
1389
|
+
*/
|
|
1390
|
+
private _fromData(
|
|
1391
|
+
pointGroups: IPointGroup[],
|
|
1392
|
+
drawCurve: SignaturePad['_drawCurve'],
|
|
1393
|
+
drawDot: SignaturePad['_drawDot'],
|
|
1394
|
+
): void {
|
|
1395
|
+
for (const group of pointGroups) {
|
|
1396
|
+
const { points } = group;
|
|
1397
|
+
const pointGroupOptions = this._getPointGroupOptions(group);
|
|
1398
|
+
|
|
1399
|
+
if (points.length > 1) {
|
|
1400
|
+
for (let j = 0; j < points.length; j += 1) {
|
|
1401
|
+
const basicPoint = points[j];
|
|
1402
|
+
const point = new Point(
|
|
1403
|
+
basicPoint.x,
|
|
1404
|
+
basicPoint.y,
|
|
1405
|
+
basicPoint.pressure,
|
|
1406
|
+
basicPoint.time,
|
|
1407
|
+
);
|
|
1408
|
+
|
|
1409
|
+
if (j === 0) {
|
|
1410
|
+
this._reset(pointGroupOptions);
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
const curve = this._addPoint(point, pointGroupOptions);
|
|
1414
|
+
|
|
1415
|
+
if (curve) {
|
|
1416
|
+
drawCurve(curve, pointGroupOptions);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
} else {
|
|
1420
|
+
this._reset(pointGroupOptions);
|
|
1421
|
+
|
|
1422
|
+
drawDot(points[0], pointGroupOptions);
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
/**
|
|
1428
|
+
* @description 返回 svg 字符串而不转换为 base64
|
|
1429
|
+
* @param {IToSVGOptions} [{ includeBackgroundColor = false }={}] includeBackgroundColor值为true时将背景颜色添加到 SVG 输出
|
|
1430
|
+
* @returns {*} {string}
|
|
1431
|
+
* @memberof SignaturePad
|
|
1432
|
+
*/
|
|
1433
|
+
public toSVG({ includeBackgroundColor = false }: IToSVGOptions = {}): string {
|
|
1434
|
+
const pointGroups = this._data;
|
|
1435
|
+
const ratio = Math.max(window.devicePixelRatio || 1, 1);
|
|
1436
|
+
const minX = 0;
|
|
1437
|
+
const minY = 0;
|
|
1438
|
+
const maxX = this.canvas.width / ratio;
|
|
1439
|
+
const maxY = this.canvas.height / ratio;
|
|
1440
|
+
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
1441
|
+
|
|
1442
|
+
svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
|
1443
|
+
svg.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
|
|
1444
|
+
svg.setAttribute('viewBox', `${minX} ${minY} ${maxX} ${maxY}`);
|
|
1445
|
+
svg.setAttribute('width', maxX.toString());
|
|
1446
|
+
svg.setAttribute('height', maxY.toString());
|
|
1447
|
+
|
|
1448
|
+
if (includeBackgroundColor && this.backgroundColor) {
|
|
1449
|
+
const rect = document.createElement('rect');
|
|
1450
|
+
rect.setAttribute('width', '100%');
|
|
1451
|
+
rect.setAttribute('height', '100%');
|
|
1452
|
+
rect.setAttribute('fill', this.backgroundColor);
|
|
1453
|
+
|
|
1454
|
+
svg.appendChild(rect);
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
this._fromData(
|
|
1458
|
+
pointGroups,
|
|
1459
|
+
|
|
1460
|
+
(curve, { penColor }) => {
|
|
1461
|
+
const path = document.createElement('path');
|
|
1462
|
+
|
|
1463
|
+
// 检查曲线是否有无效值(绘制不连续线条时可能出现)
|
|
1464
|
+
if (
|
|
1465
|
+
!Number.isNaN(curve.control1.x) &&
|
|
1466
|
+
!Number.isNaN(curve.control1.y) &&
|
|
1467
|
+
!Number.isNaN(curve.control2.x) &&
|
|
1468
|
+
!Number.isNaN(curve.control2.y)
|
|
1469
|
+
) {
|
|
1470
|
+
const attr =
|
|
1471
|
+
`M ${curve.startPoint.x.toFixed(3)},${curve.startPoint.y.toFixed(
|
|
1472
|
+
3,
|
|
1473
|
+
)} ` +
|
|
1474
|
+
`C ${curve.control1.x.toFixed(3)},${curve.control1.y.toFixed(3)} ` +
|
|
1475
|
+
`${curve.control2.x.toFixed(3)},${curve.control2.y.toFixed(3)} ` +
|
|
1476
|
+
`${curve.endPoint.x.toFixed(3)},${curve.endPoint.y.toFixed(3)}`;
|
|
1477
|
+
path.setAttribute('d', attr);
|
|
1478
|
+
path.setAttribute('stroke-width', (curve.endWidth * 2.25).toFixed(3));
|
|
1479
|
+
path.setAttribute('stroke', penColor);
|
|
1480
|
+
path.setAttribute('fill', 'none');
|
|
1481
|
+
path.setAttribute('stroke-linecap', 'round');
|
|
1482
|
+
|
|
1483
|
+
svg.appendChild(path);
|
|
1484
|
+
}
|
|
1485
|
+
},
|
|
1486
|
+
|
|
1487
|
+
(point, { penColor, dotSize, minWidth, maxWidth }) => {
|
|
1488
|
+
const circle = document.createElement('circle');
|
|
1489
|
+
const size = dotSize > 0 ? dotSize : (minWidth + maxWidth) / 2;
|
|
1490
|
+
circle.setAttribute('r', size.toString());
|
|
1491
|
+
circle.setAttribute('cx', point.x.toString());
|
|
1492
|
+
circle.setAttribute('cy', point.y.toString());
|
|
1493
|
+
circle.setAttribute('fill', penColor);
|
|
1494
|
+
|
|
1495
|
+
svg.appendChild(circle);
|
|
1496
|
+
},
|
|
1497
|
+
);
|
|
1498
|
+
|
|
1499
|
+
return svg.outerHTML;
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
/**
|
|
1503
|
+
* @description 将Blob对象转换为DataURL
|
|
1504
|
+
* @param {Blob} blob - 要转换的Blob对象
|
|
1505
|
+
* @returns {*} {Promise<string>}
|
|
1506
|
+
* @memberof SignaturePad
|
|
1507
|
+
*/
|
|
1508
|
+
public blobToDataURL(blob: Blob): Promise<string> {
|
|
1509
|
+
return new Promise((resolve, reject) => {
|
|
1510
|
+
// 创建FileReader实例
|
|
1511
|
+
const reader = new FileReader();
|
|
1512
|
+
|
|
1513
|
+
// 读取完成时的回调
|
|
1514
|
+
reader.onload = () => {
|
|
1515
|
+
// result属性包含DataURL
|
|
1516
|
+
resolve(reader.result as string);
|
|
1517
|
+
};
|
|
1518
|
+
|
|
1519
|
+
// 处理错误
|
|
1520
|
+
reader.onerror = () => {
|
|
1521
|
+
reject(new Error('无法转换Blob为DataURL'));
|
|
1522
|
+
};
|
|
1523
|
+
|
|
1524
|
+
// 以DataURL格式读取Blob
|
|
1525
|
+
reader.readAsDataURL(blob);
|
|
1526
|
+
});
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
/**
|
|
1530
|
+
* @description 处理图片加载并计算加载时间(通过回调通知完成状态)
|
|
1531
|
+
* @param {string} imageUrl
|
|
1532
|
+
* @param {() => void} _callBack
|
|
1533
|
+
* @memberof SignaturePad
|
|
1534
|
+
*/
|
|
1535
|
+
public loadImage(imageUrl: string, _callBack: () => void): void {
|
|
1536
|
+
const img = new Image();
|
|
1537
|
+
img.onload = () => _callBack();
|
|
1538
|
+
img.onerror = () => _callBack;
|
|
1539
|
+
|
|
1540
|
+
// 开始加载图片
|
|
1541
|
+
img.src = imageUrl;
|
|
1542
|
+
}
|
|
1543
|
+
}
|