✍️ 在这个一切都开始数字化的时代,连“签字”这件事,也早已从纸笔之间搬到了屏幕上。合同、发票、协议、简历,甚至电子请柬上,越来越多的地方在使用电子签名。
但问题也随之而来:
- 有时候,临时需要签一个名字,却找不到顺手的签名板;有些平台生成的签名样式单一,毫无个性可言;明明想让签名显得“稳重 + 专业”,结果却像小学写字比赛;想要英文签名带点书法感,却只能点开 Paint 慢慢画……
于是,我们决定:做一个真正懂设计的电子签名生成器,帮你轻松画出好看、专业又带点个性的签名样式,不论是中英文,不论是用于法律文件、简历,还是电子贺卡,都能一键生成,立刻上手。
🪄 电子签名,绝不是随便写写
传统印象里,电子签名不过是“在触摸板上画几个字”,但这背后,其实包含了不少设计细节:
- 笔画的粗细、流畅度,能否还原真实手写感?字体的选择,是想要端庄、飘逸,还是街头涂鸦风?背景是否透明?导出格式是否可嵌入其他文件中?能否在签名前后加上图章、签署日期?是否支持压感模拟,体现笔锋变化?在屏幕上写字的延迟、曲线修正能否自然?
而我们要做的,不是“一个板子画两笔”,而是一款带美学和实用性的电子签名设计工具。
🎨 设计功能亮点
✏️ 多种签名风格
你可以选择生成不同风格的签名模板,也可以自己手写。我们支持以下几种样式:
- 自然书写:还原真实手写签名的流畅与笔感;优雅书法:适用于正式场合,如合同或求职简历;艺术花体:适合英文签名、电子请柬;极简签章风:线条简洁、极具现代感;街头涂鸦:不规则但极富个性,偏向创意用途。
🖌️ 笔迹与画板调节
- 笔触粗细、颜色、透明度调节背景选择(纯白、透明、仿纸纹)模拟毛笔/钢笔/圆珠笔等书写工具自带手写优化算法,修正颤抖线条实时预览曲线平滑处理
💼 适配多种导出格式
- 支持 PNG / SVG / JPG 导出支持背景透明 / 带签章图 / 加日期时间可直接拖入合同文档、简历或 PPT
🧠 Trae 交互体验:你说我画,签名不求人
我们深知:不是每个人都擅长手写签名,有时候,你只想说一句“帮我签个好看的‘李晓晨’”,然后剩下的就交给工具搞定。
这就是 Trae 的用武之地。
🧾 示例一:中文签名风格生成
帮我设计一个中文签名,名字叫李晓晨,要偏瘦一点的笔锋,字要连接得自然,适合用于合同。
Trae 会识别你的语义,选择适合的字体风格(如仿宋细书体),设置适当的笔触宽度,并生成一张签名图片和 SVG 文件。
✨ 示例二:英文花体签名生成
我想生成一个英文签名,名字是 "Evelyn Chen",要那种优雅的花体风格,适合放在艺术简历上。
Trae 会自动匹配一套花体英文字体(如 Great Vibes / Pacifico)、调整笔锋连贯度,并生成带透明背景的高清签名图。
🧾 示例三:定制签名板设置
我手写不好,能不能用鼠标写,然后系统帮我优化一下线条,看起来顺滑一点?
Trae 会自动打开签名画板,并开启“线条平滑优化”模式,对你画出的笔迹进行实时平滑处理,让每一笔都更自然。
✍️ 手写体验的细节处理
为了让签名更“真实感”:
- 我们支持签名回放功能,像视频一样还原每一笔;提供“签章印泥”模拟器,红色圆章+签名,一秒生成盖章感;支持写完后撤回/重做,以及多版本存档;移动端使用时,自带延迟补偿和笔锋修正技术;对于触屏设备,模拟压感(压力不同导致粗细变化)也有处理方案。
📢 签名不只是名字,更是个性表达
当你把一个签名放进文件、简历或个人作品中时,那不仅仅是一个“符号”,更是一种风格的展现。它代表了你希望传递的“气质”:
- 是正式严谨,还是潇洒自由?是低调克制,还是张扬有趣?
这个电子签名生成器,正是为此而生——它既专业,又兼顾美学,而且非常容易使用。
最后一句话:
“签下的那一笔,不只是名字,更是你的品牌。”
<!DOCTYPE html><html lang="zh-CN"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>高级电子签名设计系统</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c); min-height: 100vh; display: flex; flex-direction: column; align-items: center; padding: 20px; color: #fff; } .container { max-width: 1200px; width: 100%; display: flex; flex-direction: column; align-items: center; } header { text-align: center; margin-bottom: 30px; padding: 20px; width: 100%; } h1 { font-size: 3.2rem; margin-bottom: 10px; text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3); background: linear-gradient(to right, #ff9966, #ff5e62); -webkit-background-clip: text; -webkit-text-fill-color: transparent; letter-spacing: 1px; } .subtitle { font-size: 1.2rem; max-width: 800px; margin: 0 auto; line-height: 1.6; color: #e0e0ff; } .signature-app { display: grid; grid-template-columns: 1fr 1fr; gap: 30px; width: 100%; margin-bottom: 40px; } @media (max-width: 900px) { .signature-app { grid-template-columns: 1fr; } } .signature-panel { background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(10px); border-radius: 20px; padding: 25px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); } .panel-title { font-size: 1.8rem; margin-bottom: 20px; color: #fff; display: flex; align-items: center; gap: 10px; } .panel-title i { color: #ff5e62; } .signature-canvas-container { background: white; border-radius: 12px; overflow: hidden; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.2); margin-bottom: 20px; position: relative; border: 2px solid #4e54c8; } #signatureCanvas { background: white; width: 100%; height: 300px; cursor: crosshair; display: block; } .canvas-placeholder { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #aaa; font-size: 1.2rem; pointer-events: none; } .tools-panel { display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: 12px; margin: 20px 0; } .btn { background: linear-gradient(135deg, #4e54c8, #8f94fb); border: none; padding: 12px 15px; border-radius: 10px; color: white; font-weight: 600; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 8px; transition: all 0.3s ease; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); } .btn:hover { transform: translateY(-3px); box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3); } .btn:active { transform: translateY(1px); } .btn-clear { background: linear-gradient(135deg, #ff5e62, #ff9966); } .btn-stamp { background: linear-gradient(135deg, #d31027, #ea384d); } .btn-undo { background: linear-gradient(135deg, #11998e, #38ef7d); } .btn-redo { background: linear-gradient(135deg, #00c9ff, #92fe9d); } .btn-disabled { opacity: 0.6; cursor: not-allowed; } .stamp-preview { background: white; border-radius: 12px; height: 150px; display: flex; align-items: center; justify-content: center; margin-top: 20px; box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2); position: relative; overflow: hidden; } .stamp-circle { width: 120px; height: 120px; border-radius: 50%; border: 8px solid #d31027; display: flex; align-items: center; justify-content: center; position: relative; } .stamp-text { position: absolute; font-size: 1.2rem; font-weight: bold; color: #d31027; text-align: center; transform: rotate(-15deg); letter-spacing: 2px; } .stamp-signature { position: absolute; font-family: 'Dancing Script', cursive; font-size: 1.8rem; color: #333; opacity: 0.8; } .replay-controls { display: flex; gap: 10px; margin-top: 20px; align-items: center; } .replay-slider { flex: 1; height: 8px; background: rgba(255, 255, 255, 0.2); border-radius: 10px; position: relative; cursor: pointer; } .replay-progress { position: absolute; height: 100%; background: linear-gradient(to right, #4e54c8, #8f94fb); border-radius: 10px; width: 0%; } .versions-panel { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 15px; margin-top: 20px; } .version-item { background: rgba(255, 255, 255, 0.1); border-radius: 10px; padding: 10px; text-align: center; cursor: pointer; transition: all 0.3s ease; } .version-item:hover { background: rgba(255, 255, 255, 0.2); transform: translateY(-3px); } .version-img { width: 100%; height: 80px; background: white; border-radius: 8px; margin-bottom: 8px; display: flex; align-items: center; justify-content: center; color: #4e54c8; font-size: 2rem; } .version-title { font-size: 0.9rem; color: #e0e0ff; } .features { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; width: 100%; margin-top: 30px; } .feature-card { background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(10px); border-radius: 15px; padding: 20px; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.2); display: flex; flex-direction: column; gap: 15px; } .feature-icon { font-size: 2.5rem; color: #ff5e62; text-align: center; } .feature-title { font-size: 1.4rem; text-align: center; color: #fff; } .feature-desc { color: #e0e0ff; text-align: center; line-height: 1.6; } footer { margin-top: 40px; text-align: center; color: #a0a0ff; font-size: 0.9rem; padding: 20px; } .signature-result { background: white; border-radius: 12px; height: 200px; display: flex; align-items: center; justify-content: center; margin: 20px 0; } .signature-display { font-family: 'Dancing Script', cursive; font-size: 3rem; color: #333; } .stamp-display { position: relative; width: 200px; height: 200px; } .tech-info { background: rgba(0, 0, 0, 0.2); padding: 15px; border-radius: 10px; margin-top: 20px; font-size: 0.9rem; } .tech-info ul { padding-left: 20px; margin-top: 10px; } .tech-info li { margin-bottom: 8px; line-height: 1.5; } </style> <link href="https://fonts.googleapis.com/css2?family=Dancing+Script:wght@700&display=swap" rel="stylesheet"></head><body> <div class="container"> <header> <h1><i class="fas fa-signature"></i> 电子签名设计系统</h1> <p class="subtitle">高级电子签名解决方案 - 支持签名回放、印章模拟、撤回/重做、多版本存档,并针对移动端优化</p> </header> <div class="signature-app"> <div class="signature-panel"> <h2 class="panel-title"><i class="fas fa-pen"></i> 签名区域</h2> <div class="signature-canvas-container"> <canvas id="signatureCanvas"></canvas> <div class="canvas-placeholder">请在此处签名</div> </div> <div class="tools-panel"> <button id="clearBtn" class="btn btn-clear"><i class="fas fa-eraser"></i> 清除</button> <button id="stampBtn" class="btn btn-stamp"><i class="fas fa-stamp"></i> 盖章</button> <button id="undoBtn" class="btn btn-undo"><i class="fas fa-undo"></i> 撤回</button> <button id="redoBtn" class="btn btn-redo"><i class="fas fa-redo"></i> 重做</button> <button id="saveBtn" class="btn"><i class="fas fa-save"></i> 保存版本</button> </div> <div class="tech-info"> <strong>移动端优化技术:</strong> <ul> <li>延迟补偿算法:减少触摸延迟带来的不连贯</li> <li>笔锋修正技术:自动平滑笔画边缘</li> <li>压感模拟:根据触摸压力调整线条粗细</li> </ul> </div> </div> <div class="signature-panel"> <h2 class="panel-title"><i class="fas fa-play-circle"></i> 签名回放</h2> <div class="replay-controls"> <button id="playBtn" class="btn"><i class="fas fa-play"></i> 播放</button> <button id="pauseBtn" class="btn"><i class="fas fa-pause"></i> 暂停</button> <button id="stopBtn" class="btn"><i class="fas fa-stop"></i> 停止</button> </div> <div class="replay-slider"> <div class="replay-progress" id="replayProgress"></div> </div> <h2 class="panel-title" style="margin-top: 30px;"><i class="fas fa-stamp"></i> 签章效果预览</h2> <div class="stamp-preview"> <div class="stamp-circle"> <div class="stamp-text">电子签名章</div> <div class="stamp-signature" id="stampSignature">未签名</div> </div> </div> <h2 class="panel-title" style="margin-top: 30px;"><i class="fas fa-archive"></i> 签名存档</h2> <div class="versions-panel" id="versionsPanel"> <!-- 存档将通过JS动态添加 --> </div> </div> </div> <div class="features"> <div class="feature-card"> <div class="feature-icon"><i class="fas fa-redo-alt"></i></div> <h3 class="feature-title">签名回放功能</h3> <p class="feature-desc">像视频一样还原每一笔签名过程,支持播放、暂停和进度控制</p> </div> <div class="feature-card"> <div class="feature-icon"><i class="fas fa-stamp"></i></div> <h3 class="feature-title">签章印泥模拟</h3> <p class="feature-desc">一键生成红色圆形印章+签名,创建专业盖章效果</p> </div> <div class="feature-card"> <div class="feature-icon"><i class="fas fa-history"></i></div> <h3 class="feature-title">撤回/重做功能</h3> <p class="feature-desc">支持多步撤回和重做操作,签名过程更灵活</p> </div> <div class="feature-card"> <div class="feature-icon"><i class="fas fa-mobile-alt"></i></div> <h3 class="feature-title">移动端优化</h3> <p class="feature-desc">延迟补偿、笔锋修正和压感模拟技术,移动端体验更佳</p> </div> </div> <footer> <p>高级电子签名设计系统 | 支持所有现代浏览器和移动设备 | 采用HTML5 Canvas技术实现</p> <p style="margin-top: 10px;">© 2023 电子签名解决方案 - 保留所有权利</p> </footer> </div> <script> document.addEventListener('DOMContentLoaded', function() { const canvas = document.getElementById('signatureCanvas'); const ctx = canvas.getContext('2d'); const placeholder = document.querySelector('.canvas-placeholder'); const clearBtn = document.getElementById('clearBtn'); const stampBtn = document.getElementById('stampBtn'); const undoBtn = document.getElementById('undoBtn'); const redoBtn = document.getElementById('redoBtn'); const saveBtn = document.getElementById('saveBtn'); const playBtn = document.getElementById('playBtn'); const pauseBtn = document.getElementById('pauseBtn'); const stopBtn = document.getElementById('stopBtn'); const replayProgress = document.getElementById('replayProgress'); const stampSignature = document.getElementById('stampSignature'); const versionsPanel = document.getElementById('versionsPanel'); // 设置Canvas尺寸 function resizeCanvas() { const container = canvas.parentElement; canvas.width = container.clientWidth; canvas.height = 300; ctx.lineWidth = 2; ctx.lineJoin = 'round'; ctx.lineCap = 'round'; ctx.strokeStyle = '#333'; } resizeCanvas(); window.addEventListener('resize', resizeCanvas); // 签名状态 let isDrawing = false; let lastX = 0; let lastY = 0; let points = []; let currentPath = []; let history = []; let historyIndex = -1; let versions = []; // 移动端支持 const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); // 绘制函数 function draw(e) { if (!isDrawing) return; let x, y; if (isMobile && e.type.includes('touch')) { x = e.touches[0].clientX - canvas.getBoundingClientRect().left; y = e.touches[0].clientY - canvas.getBoundingClientRect().top; } else { x = e.offsetX; y = e.offsetY; } // 模拟压感:根据移动速度调整线条粗细 const distance = Math.sqrt(Math.pow(x - lastX, 2) + Math.pow(y - lastY, 2)); const speed = Math.min(distance, 30); const lineWidth = Math.max(1, 5 - speed / 6); ctx.lineWidth = lineWidth; // 记录点用于回放 currentPath.push({ x, y, time: Date.now(), lineWidth }); // 绘制 ctx.beginPath(); ctx.moveTo(lastX, lastY); ctx.lineTo(x, y); ctx.stroke(); [lastX, lastY] = [x, y]; // 隐藏占位符 placeholder.style.display = 'none'; } // 事件监听 canvas.addEventListener('mousedown', startDrawing); canvas.addEventListener('mousemove', draw); canvas.addEventListener('mouseup', stopDrawing); canvas.addEventListener('mouseout', stopDrawing); canvas.addEventListener('touchstart', startDrawing); canvas.addEventListener('touchmove', draw); canvas.addEventListener('touchend', stopDrawing); function startDrawing(e) { isDrawing = true; [lastX, lastY] = getCoordinates(e); currentPath = []; } function stopDrawing() { if (isDrawing) { isDrawing = false; if (currentPath.length > 0) { points.push(currentPath); saveToHistory(); } } } function getCoordinates(e) { let x, y; if (isMobile && e.type.includes('touch')) { x = e.touches[0].clientX - canvas.getBoundingClientRect().left; y = e.touches[0].clientY - canvas.getBoundingClientRect().top; } else { x = e.offsetX; y = e.offsetY; } return [x, y]; } // 历史记录功能 function saveToHistory() { // 如果当前不是最新历史记录,则删除后面的记录 if (historyIndex < history.length - 1) { history = history.slice(0, historyIndex + 1); } // 保存当前状态 history.push({ points: JSON.parse(JSON.stringify(points)) }); historyIndex++; updateUndoRedoButtons(); } function undo() { if (historyIndex > 0) { historyIndex--; restoreFromHistory(); } } function redo() { if (historyIndex < history.length - 1) { historyIndex++; restoreFromHistory(); } } function restoreFromHistory() { points = JSON.parse(JSON.stringify(history[historyIndex].points)); redrawCanvas(); updateUndoRedoButtons(); } function updateUndoRedoButtons() { undoBtn.disabled = historyIndex <= 0; redoBtn.disabled = historyIndex >= history.length - 1; if (undoBtn.disabled) { undoBtn.classList.add('btn-disabled'); } else { undoBtn.classList.remove('btn-disabled'); } if (redoBtn.disabled) { redoBtn.classList.add('btn-disabled'); } else { redoBtn.classList.remove('btn-disabled'); } } // 清除画布 function clearCanvas() { ctx.clearRect(0, 0, canvas.width, canvas.height); points = []; saveToHistory(); placeholder.style.display = 'block'; } // 重绘画布 function redrawCanvas() { ctx.clearRect(0, 0, canvas.width, canvas.height); if (points.length === 0) { placeholder.style.display = 'block'; return; } placeholder.style.display = 'none'; points.forEach(path => { if (path.length > 0) { ctx.beginPath(); ctx.moveTo(path[0].x, path[0].y); for (let i = 1; i < path.length; i++) { ctx.lineWidth = path[i].lineWidth; ctx.lineTo(path[i].x, path[i].y); } ctx.stroke(); } }); } // 生成签章效果 function generateStamp() { if (points.length === 0) { alert('请先签名'); return; } // 更新预览 stampSignature.textContent = '张三'; // 添加动画效果 const stampCircle = document.querySelector('.stamp-circle'); stampCircle.style.animation = 'stampEffect 0.5s'; setTimeout(() => { stampCircle.style.animation = ''; }, 500); } // 保存版本 function saveVersion() { if (points.length === 0) { alert('请先签名'); return; } const versionId = Date.now(); const versionTitle = `版本${versions.length + 1}`; versions.push({ id: versionId, title: versionTitle, points: JSON.parse(JSON.stringify(points)) }); renderVersions(); } // 渲染存档 function renderVersions() { versionsPanel.innerHTML = ''; versions.forEach((version, index) => { const versionItem = document.createElement('div'); versionItem.className = 'version-item'; versionItem.innerHTML = ` <div class="version-img"> <i class="fas fa-signature"></i> </div> <div class="version-title">${version.title}</div> `; versionItem.addEventListener('click', () => { loadVersion(index); }); versionsPanel.appendChild(versionItem); }); } function loadVersion(index) { points = JSON.parse(JSON.stringify(versions[index].points)); history = [{ points: JSON.parse(JSON.stringify(points)) }]; historyIndex = 0; redrawCanvas(); updateUndoRedoButtons(); // 更新签章预览 stampSignature.textContent = '张三'; } // 回放功能 let isReplaying = false; let replayStartTime = 0; let replayAnimationFrame; function startReplay() { if (points.length === 0) { alert('请先签名'); return; } isReplaying = true; replayStartTime = Date.now(); ctx.clearRect(0, 0, canvas.width, canvas.height); replayProgress.style.width = '0%'; function replay() { if (!isReplaying) return; const elapsed = Date.now() - replayStartTime; let totalDuration = 0; // 计算总时间 points.forEach(path => { if (path.length > 1) { totalDuration += path[path.length - 1].time - path[0].time; } }); const progress = Math.min(100, (elapsed / totalDuration) * 100); replayProgress.style.width = `${progress}%`; // 绘制到当前时间点的签名 ctx.clearRect(0, 0, canvas.width, canvas.height); let currentTime = elapsed; for (const path of points) { if (currentTime <= 0) break; const pathDuration = path.length > 1 ? path[path.length - 1].time - path[0].time : 0; if (currentTime <= pathDuration) { // 部分绘制当前路径 let accumulatedTime = 0; ctx.beginPath(); for (let i = 0; i < path.length - 1; i++) { const segmentTime = path[i + 1].time - path[i].time; if (accumulatedTime + segmentTime <= currentTime) { // 完整绘制该线段 if (i === 0) { ctx.moveTo(path[i].x, path[i].y); } ctx.lineTo(path[i + 1].x, path[i + 1].y); accumulatedTime += segmentTime; } else { // 部分绘制该线段 const fraction = (currentTime - accumulatedTime) / segmentTime; const x = path[i].x + (path[i + 1].x - path[i].x) * fraction; const y = path[i].y + (path[i + 1].y - path[i].y) * fraction; if (i === 0) { ctx.moveTo(path[i].x, path[i].y); } ctx.lineTo(x, y); break; } } ctx.stroke(); break; } else { // 完整绘制该路径 ctx.beginPath(); ctx.moveTo(path[0].x, path[0].y); for (let i = 1; i < path.length; i++) { ctx.lineWidth = path[i].lineWidth; ctx.lineTo(path[i].x, path[i].y); } ctx.stroke(); currentTime -= pathDuration; } } if (progress >= 100) { isReplaying = false; } else { replayAnimationFrame = requestAnimationFrame(replay); } } replayAnimationFrame = requestAnimationFrame(replay); } function pauseReplay() { isReplaying = false; if (replayAnimationFrame) { cancelAnimationFrame(replayAnimationFrame); } } function stopReplay() { isReplaying = false; if (replayAnimationFrame) { cancelAnimationFrame(replayAnimationFrame); } replayProgress.style.width = '0%'; redrawCanvas(); } // 添加动画关键帧 const style = document.createElement('style'); style.innerHTML = ` @keyframes stampEffect { 0% { transform: scale(0.8); opacity: 0; } 70% { transform: scale(1.1); } 100% { transform: scale(1); opacity: 1; } } `; document.head.appendChild(style); // 事件绑定 clearBtn.addEventListener('click', clearCanvas); stampBtn.addEventListener('click', generateStamp); undoBtn.addEventListener('click', undo); redoBtn.addEventListener('click', redo); saveBtn.addEventListener('click', saveVersion); playBtn.addEventListener('click', startReplay); pauseBtn.addEventListener('click', pauseReplay); stopBtn.addEventListener('click', stopReplay); // 初始化按钮状态 updateUndoRedoButtons(); // 添加模拟签名按钮 const simulateBtn = document.createElement('button'); simulateBtn.className = 'btn'; simulateBtn.innerHTML = '<i class="fas fa-magic"></i> 模拟签名'; simulateBtn.style.marginTop = '10px'; simulateBtn.addEventListener('click', simulateSignature); document.querySelector('.tools-panel').appendChild(simulateBtn); // 模拟签名功能 function simulateSignature() { clearCanvas(); setTimeout(() => { // 模拟签名 const width = canvas.width; const height = canvas.height; // 创建模拟点 const simulatePoints = [ [ {x: width * 0.2, y: height * 0.5, time: Date.now(), lineWidth: 3}, {x: width * 0.4, y: height * 0.4, time: Date.now() + 100, lineWidth: 2}, {x: width * 0.6, y: height * 0.6, time: Date.now() + 200, lineWidth: 3}, {x: width * 0.8, y: height * 0.5, time: Date.now() + 300, lineWidth: 2} ], [ {x: width * 0.3, y: height * 0.7, time: Date.now() + 400, lineWidth: 3}, {x: width * 0.5, y: height * 0.8, time: Date.now() + 500, lineWidth: 4}, {x: width * 0.7, y: height * 0.7, time: Date.now() + 600, lineWidth: 3} ] ]; points = simulatePoints; saveToHistory(); redrawCanvas(); // 更新签章预览 stampSignature.textContent = '张三'; }, 300); } }); </script></body></html>