From aad3e8332b4cb6a1f9c0a3c81e9fb7d5068f09b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=B8=8D=E5=A6=82=E6=91=B8=E9=B1=BC=E5=8E=BB?=
<1780903673@qq.com>
Date: Sun, 23 Mar 2025 21:34:29 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E2=9C=A8=20=E9=87=8D=E6=9E=84=20Signat?=
=?UTF-8?q?ure=20=E7=AD=BE=E5=AD=97=E6=9D=BF=E5=8E=86=E5=8F=B2=E8=AE=B0?=
=?UTF-8?q?=E5=BD=95=E6=A8=A1=E5=BC=8F=E5=B9=B6=E6=B7=BB=E5=8A=A0=E5=8E=8B?=
=?UTF-8?q?=E6=84=9F=E6=A8=A1=E5=BC=8F=E5=92=8C=E6=A8=AA=E5=B1=8F=E7=A4=BA?=
=?UTF-8?q?=E4=BE=8B=20(#967)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docs/component/signature.md | 502 +++++++++++++++---
src/pages.json | 11 +
src/pages/signature/Index.vue | 127 ++++-
src/pages/signature/Landscape.vue | 109 ++++
.../components/wd-signature/types.ts | 139 ++++-
.../components/wd-signature/wd-signature.vue | 457 ++++++++++------
6 files changed, 1083 insertions(+), 262 deletions(-)
create mode 100644 src/pages/signature/Landscape.vue
diff --git a/docs/component/signature.md b/docs/component/signature.md
index 4a840fc9..71400cff 100644
--- a/docs/component/signature.md
+++ b/docs/component/signature.md
@@ -1,83 +1,113 @@
# Signature 签名 1.6.0
-用于签名场景,基于 Canvas 实现的签名组件。它提供了多种自定义选项,包括签名笔的颜色、宽度以及自定义操作按钮。
+用于签名场景,基于 Canvas 实现的签名组件。提供了基础签名、历史记录、笔锋效果等功能。
:::tip 提醒
-如果遇到导出图片不清晰,可以将`exportScale`设置为`2`以上。
+如果遇到导出图片不清晰,可以将 `exportScale` 设置为 `2` 以上。
:::
## 基础用法
+基础的电子签名功能。签名完成后会使用预览组件显示签名图片。
+
```html
-
-
+
```
```typescript
-const img = ref({
- width: 0,
- height: 0,
- src: ''
-})
+const img = ref>({})
function confirm(result: SignatureResult) {
- img.value.src = result.tempFilePath
- img.value.height = result.height
- img.value.width = result.width
+ if (result.success) {
+ uni.previewImage({
+ urls: [result.tempFilePath]
+ })
+ }
+}
+
+function clear() {
+ img.value = {}
}
```
-## 开启历史记录
+## 历史记录
+
+通过 `enable-history` 开启历史记录功能,可以进行撤销和恢复操作。
```html
-
+
```
-## 自定义画笔颜色
+## 笔锋模式
-`pen-color`设置签名笔的颜色,默认为`黑色`。
+通过 `pressure` 开启笔锋模式,模拟真实书写效果。笔锋模式下笔画粗细会随书写速度变化。
+
+### 基础笔锋效果
```html
-
+
```
-## 自定义画笔宽度
+:::tip 使用建议
+1. 笔锋模式推荐参数范围:
+ - min-width: 1-2
+ - max-width: 4-6
+ - min-speed: 1-2
+2. max-width 和 min-width 的差值建议保持在 3-5 之间
+3. min-speed 值越小,压感越灵敏,建议根据实际书写习惯调整
+4. 对于签名场景,建议将画布高度设置在 300-400 之间
+:::
-`line-width`设置签名笔的宽度,默认为`2`。
+### 自定义笔锋参数
+
+可以通过以下属性精确控制笔锋效果:
+- `min-width`: 最小笔画宽度,快速书写时的线条粗细
+- `max-width`: 最大笔画宽度,慢速书写时的线条粗细
+- `min-speed`: 速度阈值,用于调整压感灵敏度
```html
-
+
+快速书写产生细线条,慢速书写产生粗线条
```
-## 自定义背景色
+### 笔锋模式 + 历史记录
-`background-color`设置画板的背景色,无默认值。
+笔锋模式可以与历史记录功能结合使用,支持对带有笔锋效果的线条进行撤销和恢复操作。
```html
-
+
+结合历史记录,支持笔锋效果的撤销与恢复
```
-## 禁用滚动
+## 自定义功能
-`disable-scroll`设置是否禁用画布滚动,默认为`true`。
+### 自定义按钮
+
+通过 `footer` 插槽自定义底部按钮。
```html
-
-```
-
-## 自定义按钮
-
-通过`footer`插槽可以自定义按钮。
-
-```html
-
-
+
+
开始签名
- 撤回三步
- 恢复三步
+ 撤回
+ 恢复
清除
- 确认
+ 确定
@@ -91,48 +121,372 @@ function changeDisabled() {
}
```
+### 自定义画笔
+
+可以自定义画笔的颜色和宽度。
+
+```html
+
+```
+
+### 弹窗中使用
+
+结合 `wd-popup` 组件在弹窗中使用签名板。建议使用 `after-enter` 事件调用签名板的 `init` 方法以确保正确初始化。
+
+```html
+打开签名板
+
+
+
+
+
+
+```
+
+```typescript
+import { ref } from 'vue'
+import type { SignatureInstance, SignatureResult } from '@/uni_modules/wot-design-uni/components/wd-signature/types'
+
+const show = ref(false)
+const img = ref>({})
+const signatureRef = ref()
+
+function handleConfirm(result: SignatureResult) {
+ show.value = false
+ if (result.success) {
+ uni.previewImage({
+ urls: [result.tempFilePath]
+ })
+ }
+}
+```
+
+
+```scss
+.popup-footer {
+ margin-top: 16px;
+ display: flex;
+ justify-content: flex-end;
+ gap: 12px;
+}
+```
+
+:::tip 提示
+弹窗中使用签名板时,建议:
+1. 开启 `closable` 显示关闭按钮
+2. 设置 `safe-area-inset-bottom` 以适配底部安全区
+3. 使用 `custom-style` 调整弹窗内边距,为关闭按钮留出空间
+4. 在弹窗的 `after-enter` 事件中调用签名板的 `init` 方法,确保正确初始化
+:::
+
+### 横屏签名页面
+
+可以通过配置页面的 `pageOrientation` 来实现横屏签名页面。
+
+```json
+// pages.json
+{
+ "pages": [
+ {
+ "path": "pages/signature-landscape/Index",
+ "style": {
+ "navigationBarTitleText": "横屏签名",
+ "pageOrientation": "landscape"
+ }
+ }
+ ]
+}
+```
+
+```html
+
+
+
+
+
+
+
+
+
+```
+
+:::tip 提示
+横屏签名页面的建议:
+1. 使用 `pageOrientation: "landscape"` 强制横屏显示
+2. 动态计算画布尺寸以适配不同设备
+3. 注意横屏时 windowWidth 和 windowHeight 的对调
+4. 建议开启笔锋模式提供更好的签名体验
+:::
+
+### 横屏签名
+
+支持以下两种横屏签名实现方案:
+
+#### 1. 通用横屏方案 (推荐)
+
+通过自定义布局和按钮旋转实现横屏效果,适用于所有平台。
+
+```html
+
+
+
+
+
+
+ 撤回
+ 恢复
+ 清除
+ 完成
+
+
+
+
+
+
+```
+
+```ts
+import { pause } from '@/uni_modules/wot-design-uni/components/common/util'
+
+const height = ref(0)
+const width = ref(0)
+const inited = ref(false)
+
+onMounted(() => {
+ const { windowWidth, windowHeight } = uni.getSystemInfoSync()
+ width.value = windowWidth - 48
+ height.value = windowHeight - 48
+
+ pause(100).then(() => {
+ inited.value = true
+ })
+})
+```
+
+```scss
+.landscape-signature {
+ height: 100vh;
+ // #ifdef H5
+ height: calc(100vh - 44px);
+ // #endif
+ background: #fff;
+ position: relative;
+ padding: 24px 0;
+ padding-left: 48px;
+ box-sizing: border-box;
+
+ .custom-actions {
+ position: fixed;
+ left: 0;
+ top: 50%;
+ width: 48px;
+ transform: translateY(-50%) rotate(90deg);
+ transform-origin: center;
+ z-index: 10;
+
+ .button-group {
+ display: flex;
+ flex-direction: row;
+ gap: 12px;
+ white-space: nowrap;
+ width: max-content;
+ transform: translateX(-50%);
+ }
+ }
+}
+```
+
+:::tip 实现说明
+通用横屏方案特点:
+1. 使用 fixed 布局配合旋转实现左侧垂直按钮栏
+2. 通过 footer 插槽自定义操作按钮
+3. 使用 transform 实现按钮的旋转效果
+4. 适用于所有平台,实现方式一致
+5. 建议使用 inited 变量配合延迟加载避免画布初始化问题
+:::
+
+#### 2. 原生横屏方案 (仅微信小程序)
+
+微信小程序提供了原生的横屏支持,使用时需要注意区分平台:
+
+```json
+{
+ "path": "pages/signature/landscape",
+ "style": {
+ "navigationBarTitleText": "横屏签名",
+ // #ifdef MP-WEIXIN
+ "pageOrientation": "landscape"
+ // #endif
+ }
+}
+```
+
+```html
+
+
+
+
+
+
+```
+
+```ts
+import { pause } from '@/uni_modules/wot-design-uni/components/common/util'
+
+const height = ref(0)
+const width = ref(0)
+const inited = ref(false)
+
+onMounted(() => {
+ const { windowWidth, windowHeight } = uni.getSystemInfoSync()
+ width.value = windowWidth
+ height.value = windowHeight - 60 // 预留底部按钮空间
+
+ pause(100).then(() => {
+ inited.value = true
+ })
+})
+```
+
+```scss
+.landscape-signature {
+ height: 100vh;
+ background: #fff;
+ position: relative;
+ box-sizing: border-box;
+
+ // #ifdef MP-WEIXIN
+ padding: 0;
+ display: flex;
+ flex-direction: column;
+
+ .weixin-actions {
+ padding: 12px;
+ background-color: #f8f8f8;
+
+ .button-group {
+ display: flex;
+ justify-content: center;
+ gap: 12px;
+ }
+ }
+ // #endif
+}
+```
+
+:::warning 注意事项
+1. `pageOrientation` 配置仅在微信小程序端生效
+2. 使用条件编译区分不同平台的布局结构
+3. 微信小程序页面会自动旋转,按钮布局不需要特殊处理
+4. 预留底部按钮空间时需要考虑横屏布局
+5. 其他平台请使用通用横屏方案
+:::
+
## Attributes
-| 参数 | 说明 | 类型 | 可选值 | 默认值 | 最低版本 |
-|-----------------|----------------------------------------------------------------------|---------|--------|----------|----------|
-| penColor | 签名笔颜色 | String | -- | #000000 | -- |
-| lineWidth | 签名笔宽度 | Number | -- | 2 | -- |
-| height | 画布的高度 | Number | -- | 200 | -- |
-| width | 画布的宽度 | Number | -- | 300 | -- |
-| clearText | 清空按钮的文本 | String | -- | 清空 | -- |
-| confirmText | 确认按钮的文本 | String | -- | 确认 | -- |
-| fileType | 目标文件的类型,[uni.canvasToTempFilePath属性介绍](https://uniapp.dcloud.net.cn/api/canvas/canvasToTempFilePath.html) | String | -- | png | -- |
-| quality | 图片的质量,取值范围为 `(0, 1]`,不在范围内时当作1.0处理,[uni.canvasToTempFilePath属性介绍](https://uniapp.dcloud.net.cn/api/canvas/canvasToTempFilePath.html) | Number | -- | 1 | -- |
-| exportScale | 导出图片的缩放比例 | Number | -- | 1 | -- |
-| disabled | 是否禁用签名板 | Boolean | -- | false | -- |
-| backgroundColor | 画板的背景色 | String | -- | -- | -- |
-| disableScroll | 是否禁用画布滚动 | Boolean | -- | true | -- |
-| history | 是否开启历史记录 | Boolean | -- | false | -- |
-| step | 开启历史记录之后的步长(撤回step步) | Number | -- | 1 | -- |
-
-## Slot
-
-| name | 说明 | 参数 | 最低版本 |
-|--------|----------------|-----------------------|----------|
-| footer | 自定义footer | `{ clear, confirm, restore, revoke, currentStep ,historyList }` | - |
+| 参数 | 说明 | 类型 | 默认值 | 最低版本 |
+|------|------|------|--------|----------|
+| pen-color | 签名笔颜色 | string | #000000 | - |
+| line-width | 签名笔宽度 | number | 3 | - |
+| height | 画布的高度 | number | 200 | - |
+| width | 画布的宽度 | number | 300 | - |
+| clear-text | 清空按钮的文本 | string | - | - |
+| confirm-text | 确认按钮的文本 | string | - | - |
+| file-type | 导出图片类型 | string | png | - |
+| quality | 导出图片质量(0-1) | number | 1 | - |
+| export-scale | 导出图片的缩放比例 | number | 1 | - |
+| disabled | 是否禁用签名板 | boolean | false | - |
+| background-color | 画板的背景色 | string | - | - |
+| disable-scroll | 是否禁用画布滚动 | boolean | true | - |
+| enable-history | 是否开启历史记录 | boolean | false | - |
+| step | 历史记录步长 | number | 1 | - |
+| pressure | 是否启用笔锋模式 | boolean | false | - |
+| min-width | 笔锋模式最小宽度 | number | 2 | - |
+| max-width | 笔锋模式最大宽度 | number | 6 | - |
+| min-speed | 笔锋模式速度阈值 | number | 1.5 | - |
## Events
-| 事件名称 | 说明 | 参数 | 最低版本 |
-|-----------|--------------------|-------------------------------------------|----------|
-| start | 开始签名时触发 | - | - |
-| end | 结束签名时触发 | - | - |
-| signing | 签名过程中触发 | `event` | - |
-| confirm | 点击确定按钮时触发 | `{tempFilePath, width, height, success}` 分别为生成文件的临时路径 (本地路径)、生成图片宽、生成图片高、是否成功 | - |
-| clear | 点击清空按钮时触发 | - | - |
+| 事件名称 | 说明 | 参数 | 最低版本 |
+|---------|------|------|----------|
+| start | 开始签名时触发 | event: TouchEvent | - |
+| end | 结束签名时触发 | event: TouchEvent | - |
+| signing | 签名过程中触发 | event: TouchEvent | - |
+| confirm | 确认签名时触发 | result: SignatureResult | - |
+| clear | 清空签名时触发 | - | - |
## Methods
-对外暴露函数
+| 方法名 | 说明 | 参数 | 最低版本 |
+|--------|------|------|----------|
+| init | 初始化签名板 | forceUpdate?: boolean | - |
+| confirm | 确认签名 | - | - |
+| clear | 清空签名 | - | - |
+| restore | 恢复上一步 | - | - |
+| revoke | 撤销上一步 | - | - |
-| 事件名称 | 说明 | 参数 | 最低版本 |
-|-----------|--------------------|-------------------------------------------|----------|
-| confirm | 点击确认按钮时触发 | `{tempFilePath, width, height, success}` 分别为生成文件的临时路径 (本地路径)、生成图片宽、生成图片高、是否成功 | - |
-| clear | 点击清空按钮时触发 | - | - |
-| restore | 暴露恢复方法 | - | - |
-| revoke | 暴露撤回方法 | - | - |
+## Slots
+
+| 名称 | 说明 | 参数 | 最低版本 |
+|------|------|------|----------|
+| footer | 自定义底部按钮 | `{ clear, confirm, restore, revoke, currentStep, historyList }` | - |
diff --git a/src/pages.json b/src/pages.json
index 375b5c8c..d757d6c6 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -811,6 +811,17 @@
"navigationBarTitleText": "Signature 签名"
}
},
+ {
+ "path": "pages/signature/Landscape",
+ "name": "signatureLandscape",
+ "style": {
+ "mp-alipay": {
+ "allowsBounceVertical": "NO"
+ },
+ "navigationBarTitleText": "横屏签名",
+ "pageOrientation": "landscape"
+ }
+ },
{
"path": "pages/backtop/Index",
"name": "backtop",
diff --git a/src/pages/signature/Index.vue b/src/pages/signature/Index.vue
index 8e807d02..a8b74a5f 100644
--- a/src/pages/signature/Index.vue
+++ b/src/pages/signature/Index.vue
@@ -1,51 +1,76 @@
-
-
+
-
-
+
+
+
-
-
+
+
+
-
-
+
+
+
+ 快速书写产生细线条,慢速书写产生粗线条
-
-
+
+
+
+ 结合历史记录,支持笔锋效果的撤销与恢复
-
-
+
+
+
开始签名
- 撤回三步
- 恢复三步
+ 撤回
+ 恢复
清除
- 确定
+ 确定
+
+
+
+
+
+
+ 打开签名板
+
+
+
+
+
+
+
+ 使用横屏签名
+
+
+
diff --git a/src/pages/signature/Landscape.vue b/src/pages/signature/Landscape.vue
new file mode 100644
index 00000000..37ad13f7
--- /dev/null
+++ b/src/pages/signature/Landscape.vue
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+ 撤回
+ 恢复
+ 清除
+ 完成
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/uni_modules/wot-design-uni/components/wd-signature/types.ts b/src/uni_modules/wot-design-uni/components/wd-signature/types.ts
index 5f228aae..39336e19 100644
--- a/src/uni_modules/wot-design-uni/components/wd-signature/types.ts
+++ b/src/uni_modules/wot-design-uni/components/wd-signature/types.ts
@@ -1,11 +1,12 @@
/*
* @Author: 810505339
* @Date: 2025-01-10 20:03:57
- * @LastEditors: 810505339
- * @LastEditTime: 2025-02-18 13:04:45
- * @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-signature\types.ts
+ * @LastEditors: weisheng
+ * @LastEditTime: 2025-03-23 16:35:14
+ * @FilePath: /wot-design-uni/src/uni_modules/wot-design-uni/components/wd-signature/types.ts
* 记得注释
*/
+import type { ComponentPublicInstance, ExtractPropTypes } from 'vue'
import { baseProps, numericProp } from '../common/props'
export const signatureProps = {
@@ -108,31 +109,155 @@ export const signatureProps = {
type: Boolean,
default: true
},
- /* 是否开始历史记录 */
- history: {
+ /**
+ * 是否开启历史记录
+ * 类型:boolean
+ * 默认值:false
+ */
+ enableHistory: {
type: Boolean,
default: false
},
+ /**
+ * 撤回和恢复的步长
+ * 类型:number
+ * 默认值:1
+ */
step: {
type: Number,
default: 1
},
+ /**
+ * 撤回按钮的文本
+ * 类型:string
+ * 默认值:撤销
+ */
undoText: String,
- redoText: String
+ /**
+ * 恢复按钮的文本
+ * 类型:string
+ * 默认值:恢复
+ */
+ redoText: String,
+ /**
+ * 是否启用压感模式(笔锋)
+ * 类型:boolean
+ * 默认值:false
+ */
+ pressure: {
+ type: Boolean,
+ default: false
+ },
+ /**
+ * 压感模式下笔画最小宽度
+ * 类型:number
+ * 默认值:2
+ */
+ minWidth: {
+ type: Number,
+ default: 2
+ },
+ /**
+ * 压感模式下笔画最大宽度
+ * 类型:number
+ * 默认值:6
+ */
+ maxWidth: {
+ type: Number,
+ default: 6
+ },
+ /**
+ * 最小速度阈值,影响压感模式下的笔画宽度变化
+ * 类型:number
+ * 默认值:1.5
+ */
+ minSpeed: {
+ type: Number,
+ default: 1.5
+ }
}
+
+/**
+ * 签名结果类型
+ * @property tempFilePath - 生成图片的临时路径
+ * @property success - 是否成功生成图片
+ * @property width - 生成图片的宽度
+ * @property height - 生成图片的高度
+ */
export type SignatureResult = {
tempFilePath: string
success: boolean
width: number
height: number
}
+
+/**
+ * 签名线条类型
+ * @property points - 线条所包含的所有点的数组
+ * @property color - 线条颜色
+ * @property width - 线条宽度
+ * @property backgroundColor - 线条背景色 (可选)
+ * @property isPressure - 是否为笔锋模式的线条 (可选)
+ */
+export interface Line {
+ points: Point[]
+ color: string
+ width: number
+ backgroundColor?: string
+ isPressure?: boolean
+}
+
+/**
+ * 签名点位类型
+ * @property x - 点的横坐标
+ * @property y - 点的纵坐标
+ * @property t - 点的时间戳
+ * @property speed - 当前点的绘制速度 (可选)
+ * @property distance - 与上一个点的距离 (可选)
+ * @property lineWidth - 当前点的线宽 (可选,用于笔锋模式)
+ * @property lastX1 - 贝塞尔曲线第一个控制点的x坐标 (可选)
+ * @property lastY1 - 贝塞尔曲线第一个控制点的y坐标 (可选)
+ * @property lastX2 - 贝塞尔曲线第二个控制点的x坐标 (可选)
+ * @property lastY2 - 贝塞尔曲线第二个控制点的y坐标 (可选)
+ * @property isFirstPoint - 是否为线条的第一个点 (可选)
+ */
+export interface Point {
+ x: number
+ y: number
+ t: number
+ speed?: number
+ distance?: number
+ lineWidth?: number
+ lastX1?: number
+ lastY1?: number
+ lastX2?: number
+ lastY2?: number
+ isFirstPoint?: boolean
+}
+
+/**
+ * 签名组件暴露的方法类型
+ * @property init - 初始化签名板
+ * @property clear - 清除签名
+ * @property confirm - 确认签名并生成图片
+ * @property restore - 恢复上一步操作
+ * @property revoke - 撤销上一步操作
+ */
export type SignatureExpose = {
+ /** 初始化签名板
+ * @param forceUpdate - 是否强制更新
+ */
+ init: (forceUpdate?: boolean) => void
/** 点击清除按钮清除签名 */
clear: () => void
/** 点击确定按钮 */
- confirm: (result: SignatureResult) => void
+ confirm: () => void
/* 点击恢复 */
restore: () => void
/* 点击撤回 */
revoke: () => void
}
+
+export type SignatureProps = ExtractPropTypes
+
+export type SignatureInstance = ComponentPublicInstance
diff --git a/src/uni_modules/wot-design-uni/components/wd-signature/wd-signature.vue b/src/uni_modules/wot-design-uni/components/wd-signature/wd-signature.vue
index 2a4e33c8..b5bebf16 100644
--- a/src/uni_modules/wot-design-uni/components/wd-signature/wd-signature.vue
+++ b/src/uni_modules/wot-design-uni/components/wd-signature/wd-signature.vue
@@ -1,9 +1,10 @@
-
+