掘金 人工智能 前天 14:19
Trae 设计电子签名工具,让每一个签名,都能体现你的风格
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

随着数字化时代的到来,电子签名已成为日常。Trae 电子签名生成器应运而生,它不仅提供多种签名风格、笔迹调节、导出格式,还具备手写优化、签名回放等细节处理,以及 Trae 交互体验。这款工具旨在帮助用户轻松设计出好看、专业且富有个性的电子签名,适用于各种场景,让签名成为个人风格的展现。

🖋️ 多样签名风格:Trae 提供多种签名风格,包括自然书写、优雅书法、艺术花体、极简签章风和街头涂鸦,满足不同场景需求,例如合同、简历或电子请柬。

🖌️ 灵活笔迹与画板调节:用户可以自定义笔触粗细、颜色、透明度,选择背景,模拟不同书写工具,并利用手写优化算法,实现流畅的签名效果。

📤 多种导出格式适配:支持 PNG、SVG、JPG 等多种导出格式,且支持透明背景、添加签章图、日期时间等功能,方便用户将签名嵌入到文档、简历等。

✍️ Trae 交互体验:通过 Trae 的语义识别功能,用户只需描述需求,例如“帮我签个好看的‘李晓晨’”,Trae 即可自动生成符合要求的签名。

🔄 手写体验的细节处理:Trae 提供了签名回放、签章印泥模拟器、撤回/重做、多版本存档等功能,以及移动端的延迟补偿和笔锋修正技术,增强手写签名体验。

✍️ 在这个一切都开始数字化的时代,连“签字”这件事,也早已从纸笔之间搬到了屏幕上。合同、发票、协议、简历,甚至电子请柬上,越来越多的地方在使用电子签名。

但问题也随之而来:

于是,我们决定:做一个真正懂设计的电子签名生成器,帮你轻松画出好看、专业又带点个性的签名样式,不论是中英文,不论是用于法律文件、简历,还是电子贺卡,都能一键生成,立刻上手。

🪄 电子签名,绝不是随便写写

传统印象里,电子签名不过是“在触摸板上画几个字”,但这背后,其实包含了不少设计细节:

而我们要做的,不是“一个板子画两笔”,而是一款带美学和实用性的电子签名设计工具

🎨 设计功能亮点

✏️ 多种签名风格

你可以选择生成不同风格的签名模板,也可以自己手写。我们支持以下几种样式:

🖌️ 笔迹与画板调节

💼 适配多种导出格式

🧠 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;">&copy; 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>

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

电子签名 签名设计 Trae 个性化签名
相关文章