鸿蒙系统(HarmonyOS)应用开发之实现电子签名效果
项目概述
DevEco 电子签名应用是一款专为移动设备设计的高效电子签名解决方案,基于 OpenHarmony 平台开发。该应用旨在满足日益增长的电子签名需求,为用户提供便捷、安全且具有法律效力的电子签名功能。在数字化转型的时代背景下,我们的应用致力于简化签名流程,提高工作效率,减少纸质文档的使用,为绿色环保贡献力量。
通过直观的用户界面和流畅的操作体验,DevEco 电子签名应用让用户能够随时随地完成签名任务,无需打印文件或亲自到场。无论是商务合同、法律文件还是日常文档,我们的应用都能提供专业的签名解决方案。
功能特点
核心功能
- 精准手写签名:采用先进的触控算法,确保签名流畅自然,完美还原用户的笔迹特点
- 多样化绘制选项:
- 四种标准颜色选择(黑色、红色、蓝色、绿色)
- 可调节的线条粗细(1-10 级调节)
- 圆润的线条连接,提供专业签名效果
- 操作管理功能:
- 一键清除画布,快速重新开始
- 撤销功能,方便纠正误操作
- 即时保存签名,防止工作丢失
用户体验优势
- 简洁直观的界面设计:遵循现代 UI 设计原则,界面清晰易懂
- 响应式布局:自适应不同屏幕尺寸,提供一致的用户体验
- 操作反馈:通过 Toast 提示等方式,提供及时的操作反馈
- 轻量级应用:占用资源少,运行流畅,适合各种设备
技术架构
开发框架
- 基于 OpenHarmony 的 ArkTS/ETS 语言开发
- 采用声明式 UI 编程范式,提高开发效率和代码可维护性
核心技术
- Canvas 绘图技术:利用 CanvasRenderingContext2D 实现高精度绘图
- 触控事件处理:精确捕捉并处理多点触控事件
- 状态管理:使用@State 装饰器进行组件状态管理
- 离屏渲染:通过 OffscreenCanvas 技术实现高效图像处理和导出
应用场景
- 合同签署:远程签署商业合同、协议和备忘录
- 报价确认:快速确认商业报价和订单
- 会议纪要:为会议纪要和决议添加签名确认
- 法律文件:签署法律文件和声明
- 公证材料:为需要公证的材料添加电子签名
- 授权确认:提供授权确认的电子签名
- 快递签收:替代传统的纸质签收单
- 考勤签到:用于员工考勤或活动签到
- 个人认证:在各类需要身份确认的场景中使用
完整源码
import promptAction from '@ohos.promptAction';
import image from '@ohos.multimedia.image';
import fs from '@ohos.file.fs';
import common from '@ohos.app.ability.common';
import router from '@ohos.router';// 定义点的接口
interface Point {x: number;y: number;
}// 定义路径的接口
interface PathData {path: Point[];color: string;width: number;
}@Entry
@Component
struct SignaturePage {// Canvas相关状态@State canvasWidth: number = 0;@State canvasHeight: number = 0;@State isDrawing: boolean = false;@State lineColor: string = '#000000';@State lineWidth: number = 3;@State lastX: number = 0;@State lastY: number = 0;// 用于保存绘制历史,支持撤销功能@State drawHistory: PathData[] = [];@State currentPath: Point[] = [];// 画布上下文private settings: RenderingContextSettings = new RenderingContextSettings(true);private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);// 获取应用上下文,用于保存图片private context16: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);private appContext: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;aboutToAppear() {// 页面加载时的初始化操作}// 开始绘制startDrawing(event: TouchEvent) {this.isDrawing = true;this.lastX = event.touches[0].x;this.lastY = event.touches[0].y;// 开始新路径this.context.beginPath();this.context.moveTo(this.lastX, this.lastY);// 记录当前路径的起点this.currentPath = [{ x: this.lastX, y: this.lastY }];}// 绘制中drawing(event: TouchEvent) {if (!this.isDrawing) {return;}const currentX = event.touches[0].x;const currentY = event.touches[0].y;// 绘制线条this.context.lineWidth = this.lineWidth;this.context.strokeStyle = this.lineColor;this.context.lineJoin = 'round';this.context.lineCap = 'round';this.context.lineTo(currentX, currentY);this.context.stroke();// 更新最后位置this.lastX = currentX;this.lastY = currentY;// 记录当前路径点this.currentPath.push({ x: currentX, y: currentY });}// 结束绘制endDrawing() {if (!this.isDrawing) {return;}this.isDrawing = false;// 保存当前路径到历史记录if (this.currentPath.length > 1) {this.drawHistory.push({path: [...this.currentPath],color: this.lineColor,width: this.lineWidth});}this.currentPath = [];}// 清除画布clearCanvas() {this.context.clearRect(0, 0, this.canvasWidth, this.canvasHeight);this.drawHistory = [];this.currentPath = [];}// 撤销上一步undo() {if (this.drawHistory.length === 0) {promptAction.showToast({message: '没有可撤销的操作',duration: 2000});return;}// 移除最后一个路径this.drawHistory.pop();// 重新绘制所有路径this.context.clearRect(0, 0, this.canvasWidth, this.canvasHeight);for (let item of this.drawHistory) {this.context.beginPath();this.context.lineWidth = item.width;this.context.strokeStyle = item.color;this.context.lineJoin = 'round';this.context.lineCap = 'round';if (item.path.length > 0) {this.context.moveTo(item.path[0].x, item.path[0].y);for (let i = 1; i < item.path.length; i++) {this.context.lineTo(item.path[i].x, item.path[i].y);}this.context.stroke();}}}// 保存签名async saveSignature() {try {// 创建离屏Canvaslet offscreenCanvas = new OffscreenCanvas(this.canvasWidth, this.canvasHeight);let offContext = offscreenCanvas.getContext("2d");// 将当前画布内容绘制到离屏CanvasoffContext.fillStyle = '#FFFFFF';offContext.fillRect(0, 0, this.canvasWidth, this.canvasHeight);// 重新绘制所有路径到离屏Canvasfor (let item of this.drawHistory) {offContext.beginPath();offContext.lineWidth = item.width;offContext.strokeStyle = item.color;offContext.lineJoin = 'round';offContext.lineCap = 'round';if (item.path.length > 0) {offContext.moveTo(item.path[0].x, item.path[0].y);for (let i = 1; i < item.path.length; i++) {offContext.lineTo(item.path[i].x, item.path[i].y);}offContext.stroke();}}// 转换为图片 - 使用transferToImageBitmap替代toDataURLlet imageBitmap = offscreenCanvas.transferToImageBitmap();// 显示成功消息promptAction.showToast({message: '签名已保存',duration: 2000});return imageBitmap;} catch (error) {console.error('保存签名失败:', error);promptAction.showToast({message: '保存签名失败',duration: 2000});return null;}}build() {Column() {// 标题栏Row() {Text('电子签名').fontSize(20).fontWeight(FontWeight.Medium).margin({ left: 16 })Blank()Button('保存').fontSize(16).height(36).backgroundColor('#007DFF').borderRadius(18).onClick(() => {this.saveSignature();})}.width('100%').height(56).padding({ left: 16, right: 16 }).backgroundColor('#FFFFFF')// 签名区域Column() {Text('请在下方区域签名').fontSize(16).fontColor('#666666').margin({ top: 20, bottom: 10 })// 签名画布Canvas(this.context).width('100%').layoutWeight(4) // 增加Canvas的权重,给予更多空间.backgroundColor('#F5F5F5').borderRadius(8).margin({ bottom: 16 }) // 添加底部间距.onAreaChange((oldArea: Area, newArea: Area) => {// 使用新区域的尺寸this.canvasWidth = newArea.width as number;this.canvasHeight = newArea.height as number;}).onReady(() => {// Canvas准备就绪}).onTouch((event: TouchEvent) => {if (event.type === TouchType.Down) {this.startDrawing(event);} else if (event.type === TouchType.Move) {this.drawing(event);} else if (event.type === TouchType.Up) {this.endDrawing();}})// 工具栏容器Column() {// 按钮和颜色选择器行Row() {Button('清除').fontSize(16).height(40).backgroundColor('#F5F5F5').fontColor('#333333').borderRadius(20).onClick(() => {this.clearCanvas();})Button('撤销').fontSize(16).height(40).backgroundColor('#F5F5F5').fontColor('#333333').borderRadius(20).margin({ left: 16 }).onClick(() => {this.undo();})Blank()// 颜色选择器Row() {ForEach(['#000000', '#FF0000', '#0000FF', '#008000'], (color: string) => {Column() {Circle({ width: 24, height: 24 }).fill(color).stroke(this.lineColor === color ? '#007DFF' : 'transparent').strokeWidth(2).margin(4).onClick(() => {this.lineColor = color;})}})}}.width('100%').height(48).margin({ top: 16 })// 线宽选择器行Row() {Text('线条粗细:').fontSize(16).fontColor('#666666')Slider({value: this.lineWidth,min: 1,max: 10,step: 1,style: SliderStyle.OutSet}).width('60%').onChange((value: number) => {this.lineWidth = value;})Text(this.lineWidth.toFixed(0)).fontSize(16).fontColor('#666666').width(24).textAlign(TextAlign.Center)}.width('100%').height(48).margin({ top: 8 })}.width('100%').layoutWeight(1).padding({ left: 16, right: 16 })}.width('100%').padding(16).backgroundColor('#FFFFFF').layoutWeight(1) // 使用layoutWeight而不是固定高度}.width('100%').height('100%').backgroundColor('#F5F5F5')}
}
鸿蒙系统(HarmonyOS)应用开发之实现手工签名效果 - 高质量源码分享平台-免费下载各类网站源码与模板及前沿动态资讯