文章目录
-
- 在当今数字化营销时代,视觉内容的重要性不言而喻。据统计,带有图片的社交媒体帖子比纯文本帖子获得更多的互动——平均高出2.3倍的参与度。对于网站运营者而言,为用户提供便捷的视觉内容创建工具,不仅能增强用户粘性,还能促进内容生成和分享。 然而,专业的图像设计软件如Photoshop学习成本高,而在线设计工具往往需要跳转到第三方网站,导致用户流失。将简易海报设计与宣传图生成工具直接集成到WordPress网站中,可以完美解决这一问题。用户无需离开您的网站即可创建吸引人的视觉内容,这不仅能提升用户体验,还能增加网站的功能价值和竞争力。 本文将详细指导您如何通过WordPress代码二次开发,将在线简易海报设计与宣传图生成工具集成到您的网站中,实现这一实用的互联网小工具功能。
-
- 在开始之前,我们需要确定合适的技术方案。目前主要有三种集成方式: 使用现有插件:如Canva的嵌入代码或类似设计工具的API 自定义开发简单设计器:基于HTML5 Canvas和JavaScript 混合方案:结合现有库和自定义功能 考虑到灵活性和控制度,我们将选择第二种方案,使用Fabric.js库构建一个轻量级但功能齐全的设计工具。Fabric.js是一个强大的Canvas库,专门用于处理图形和图像操作。
- 首先,确保您具备以下条件: 一个运行中的WordPress网站(版本5.0以上) 访问WordPress文件系统的权限(通过FTP或文件管理器) 基础的HTML、CSS、JavaScript和PHP知识 代码编辑器(如VS Code、Sublime Text等)
- 为了避免主题更新导致自定义代码丢失,我们将在子主题中进行开发: 在WordPress的wp-content/themes/目录下创建新文件夹,命名为my-design-tool-theme 在该文件夹中创建style.css文件,添加以下内容: /* Theme Name: My Design Tool Theme Template: your-parent-theme-folder-name Version: 1.0 Description: 子主题,用于集成海报设计工具 */ 创建functions.php文件,暂时留空 在WordPress后台启用这个子主题
-
- 在子主题的functions.php中添加以下代码,引入Fabric.js和其他必要的库: function design_tool_enqueue_scripts() { // 引入Fabric.js库 wp_enqueue_script('fabric-js', 'https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.5.0/fabric.min.js', array(), '4.5.0', true); // 引入html2canvas用于导出图片 wp_enqueue_script('html2canvas', 'https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js', array(), '1.4.1', true); // 引入我们的自定义脚本 wp_enqueue_script('design-tool-script', get_stylesheet_directory_uri() . '/js/design-tool.js', array('fabric-js', 'jquery'), '1.0', true); // 引入样式文件 wp_enqueue_style('design-tool-style', get_stylesheet_directory_uri() . '/css/design-tool.css', array(), '1.0'); // 本地化脚本,传递PHP变量到JavaScript wp_localize_script('design-tool-script', 'designToolAjax', array( 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('design_tool_nonce') )); } add_action('wp_enqueue_scripts', 'design_tool_enqueue_scripts');
- 在子主题目录下创建template-parts文件夹,然后创建design-tool-template.php文件: <?php /** * 海报设计工具模板 */ ?> <div class="design-tool-container"> <div class="design-tool-header"> <h1>简易海报设计工具</h1> <p>创建吸引人的宣传图、社交媒体图片和海报</p> </div> <div class="design-tool-wrapper"> <!-- 左侧工具栏 --> <div class="design-sidebar"> <div class="tool-section"> <h3>模板</h3> <div class="template-thumbnails"> <div class="template-item" data-template="social-media"> <img src="<?php echo get_stylesheet_directory_uri(); ?>/images/template-social.jpg" alt="社交媒体模板"> <span>社交媒体</span> </div> <div class="template-item" data-template="poster"> <img src="<?php echo get_stylesheet_directory_uri(); ?>/images/template-poster.jpg" alt="海报模板"> <span>海报</span> </div> <div class="template-item" data-template="banner"> <img src="<?php echo get_stylesheet_directory_uri(); ?>/images/template-banner.jpg" alt="横幅模板"> <span>横幅广告</span> </div> </div> </div> <div class="tool-section"> <h3>元素</h3> <button class="tool-btn" data-action="add-text">添加文本</button> <button class="tool-btn" data-action="add-image">添加图片</button> <button class="tool-btn" data-action="add-shape">添加形状</button> <button class="tool-btn" data-action="add-background">更改背景</button> </div> <div class="tool-section"> <h3>属性</h3> <div id="property-panel"> <p>选择元素以编辑属性</p> </div> </div> </div> <!-- 中间画布区域 --> <div class="design-main"> <div class="canvas-toolbar"> <button id="btn-undo" title="撤销">↶</button> <button id="btn-redo" title="重做">↷</button> <button id="btn-clear" title="清空画布">×</button> <select id="canvas-size"> <option value="800x600">800×600 (通用)</option> <option value="1200x628">1200×628 (Facebook)</option> <option value="1080x1080">1080×1080 (Instagram)</option> <option value="1500x500">1500×500 (Twitter横幅)</option> </select> </div> <div class="canvas-container"> <canvas id="design-canvas"></canvas> </div> <div class="canvas-footer"> <button id="btn-save-draft" class="btn-secondary">保存草稿</button> <button id="btn-export-png" class="btn-primary">导出为PNG</button> <button id="btn-export-jpg" class="btn-primary">导出为JPG</button> </div> </div> <!-- 右侧资源库 --> <div class="design-resources"> <div class="tool-section"> <h3>背景图片</h3> <div class="background-thumbnails"> <?php for($i=1; $i<=6; $i++): ?> <div class="bg-item" data-bg="<?php echo get_stylesheet_directory_uri(); ?>/images/bg<?php echo $i; ?>.jpg"> <img src="<?php echo get_stylesheet_directory_uri(); ?>/images/bg<?php echo $i; ?>.jpg" alt="背景<?php echo $i; ?>"> </div> <?php endfor; ?> </div> </div> <div class="tool-section"> <h3>字体选择</h3> <select id="font-selector"> <option value="Arial">Arial</option> <option value="Helvetica">Helvetica</option> <option value="Times New Roman">Times New Roman</option> <option value="Georgia">Georgia</option> <option value="Courier New">Courier New</option> </select> </div> <div class="tool-section"> <h3>颜色选择</h3> <div class="color-palette"> <div class="color-item" data-color="#FF0000" style="background-color:#FF0000;"></div> <div class="color-item" data-color="#00FF00" style="background-color:#00FF00;"></div> <div class="color-item" data-color="#0000FF" style="background-color:#0000FF;"></div> <div class="color-item" data-color="#FFFF00" style="background-color:#FFFF00;"></div> <div class="color-item" data-color="#FF00FF" style="background-color:#FF00FF;"></div> <div class="color-item" data-color="#00FFFF" style="background-color:#00FFFF;"></div> <div class="color-item" data-color="#000000" style="background-color:#000000;"></div> <div class="color-item" data-color="#FFFFFF" style="background-color:#FFFFFF; border:1px solid #ccc;"></div> </div> <input type="color" id="color-picker" value="#FF0000"> </div> </div> </div> <!-- 模态框 --> <div id="image-upload-modal" class="modal"> <div class="modal-content"> <span class="close-modal">×</span> <h3>上传图片</h3> <div class="upload-options"> <div class="upload-option"> <h4>从电脑上传</h4> <input type="file" id="file-upload" accept="image/*"> <button id="btn-upload">上传</button> </div> <div class="upload-option"> <h4>从URL添加</h4> <input type="text" id="image-url" placeholder="输入图片URL"> <button id="btn-add-url">添加</button> </div> </div> </div> </div> </div>
- 创建css/design-tool.css文件: /* 设计工具主容器 */ .design-tool-container { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; max-width: 1400px; margin: 0 auto; padding: 20px; background-color: #f5f7fa; min-height: 100vh; } .design-tool-header { text-align: center; margin-bottom: 30px; padding-bottom: 20px; border-bottom: 1px solid #e1e5eb; } .design-tool-header h1 { color: #2c3e50; margin-bottom: 10px; } .design-tool-header p { color: #7f8c8d; font-size: 1.1rem; } /* 设计工具布局 */ .design-tool-wrapper { display: flex; gap: 20px; background-color: white; border-radius: 10px; box-shadow: 0 5px 15px rgba(0,0,0,0.08); overflow: hidden; min-height: 700px; } .design-sidebar, .design-resources { width: 250px; padding: 20px; background-color: #f8f9fa; border-right: 1px solid #e9ecef; } .design-resources { border-right: none; border-left: 1px solid #e9ecef; } .design-main { flex: 1; display: flex; flex-direction: column; padding: 20px; } /* 工具栏样式 */ .tool-section { margin-bottom: 30px; } .tool-section h3 { color: #495057; font-size: 1.1rem; margin-bottom: 15px; padding-bottom: 8px; border-bottom: 1px solid #dee2e6; } .tool-btn { display: block; width: 100%; padding: 10px 15px; margin-bottom: 10px; background-color: #4dabf7; color: white; border: none; border-radius: 5px; cursor: pointer; transition: background-color 0.2s; font-size: 0.95rem; } .tool-btn:hover { background-color: #339af0; } /* 模板缩略图 */ .template-thumbnails { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } .template-item { border: 1px solid #dee2e6; border-radius: 5px; overflow: hidden; cursor: pointer; transition: transform 0.2s, box-shadow 0.2s; } .template-item:hover { transform: translateY(-3px); box-shadow: 0 5px 10px rgba(0,0,0,0.1); } .template-item img { width: 100%; height: 70px; object-fit: cover; } .template-item span { display: block; text-align: center; padding: 5px; font-size: 0.8rem; color: #495057; } /* 画布区域 */ .canvas-toolbar { display: flex; gap: 10px; margin-bottom: 20px; padding-bottom: 15px; border-bottom: 1px solid #e9ecef; } .canvas-toolbar button, .canvas-toolbar select { padding: 8px 15px; border: 1px solid #ced4da; border-radius: 5px; background-color: white; cursor: pointer; } .canvas-toolbar button:hover { background-color: #f8f9fa; } .canvas-container { flex: 1; display: flex; justify-content: center; align-items: center; border: 1px dashed #adb5bd; border-radius: 5px; background-color: #f8f9fa; margin-bottom: 20px; overflow: auto; } #design-canvas { background-color: white; box-shadow: 0 3px 10px rgba(0,0,0,0.1); } .canvas-footer { display: flex; justify-content: center; gap: 15px; padding-top: 20px; border-top: 1px solid #e9ecef; } .btn-primary, .btn-secondary { padding: 12px 25px; border: none; border-radius: 5px; cursor: pointer; font-size: 1rem; font-weight: 500; transition: all 0.2s; } .btn-primary { background-color: #40c057; color: white; } .btn-primary:hover { background-color: #37b24d; } .btn-secondary { background-color: #e9ecef; color: #495057; } .btn-secondary:hover { background-color: #dee2e6; } /* 资源库样式 */ .background-thumbnails { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } .bg-item { border: 1px solid #dee2e6; border-radius: 5px; overflow: hidden; cursor: pointer; height: 70px; } .bg-item img { width: 100%; height: 100%; object-fit: cover; } .color-palette { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-bottom: 15px; } .color-item { width: 30px; height: 30px; border-radius: 50%; cursor: pointer; border: 2px solid transparent; } .color-item:hover { border-color: #495057; } #color-picker { width: 100%; height: 40px; border: none; cursor: pointer; border-radius: 5px; overflow: hidden; } #font-selector { width: 100%; padding: 8px; border: 1px solid #ced4da; border-radius: 5px; } /* 模态框样式 */ .modal { display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.5); } .modal-content { background-color: white; margin: 10% auto; padding: 25px; width: 500px; border-radius: 10px; box-shadow: 0 5px 20px rgba(0,0,0,0.2); position: relative; } .close-modal { position: absolute; right: 20px; top: 15px; font-size: 28px; cursor: pointer; color: #7f8c8d; } .close-modal:hover { color: #2c3e50; } .upload-options { display: flex; gap: 20px; margin-top: 20px; } .upload-option { flex: 1; padding: 20px; border: 1px solid #e9ecef; border-radius: 5px; } .upload-option h4 { margin-top: 0; margin-bottom: 15px; color: #495057; } .upload-option input { width: 100%; padding: 8px; margin-bottom: 10px; border: 1px solid #ced4da; border-radius: 5px; } .upload-option button { padding: 8px 15px; background-color: #4dabf7; color: white; border: none; border-radius: 5px; cursor: pointer; } / 响应式设计 /@media (max-width: 1200px) { .design-tool-wrapper { flex-direction: column; } .design-sidebar, .design-resources { width: 100%; border-right: none; border-left: none; border-bottom: 1px solid #e9ecef; } .design-resources { border-top: 1px solid #e9ecef; } } / 属性面板样式 /
- background-color: white; padding: 15px; border-radius: 5px; border: 1px solid #e9ecef; min-height: 150px; } .property-group { margin-bottom: 15px; } .property-group label { display: block; margin-bottom: 5px; font-size: 0.9rem; color: #495057; } .property-group input,.property-group select { width: 100%; padding: 6px; border: 1px solid #ced4da; border-radius: 3px; } ## 第三部分:实现设计器核心功能 ### 3.1 初始化设计器JavaScript 创建`js/design-tool.js`文件,开始实现核心功能: jQuery(document).ready(function($) { // 初始化变量 let canvas, currentTool = 'select', history = [], historyIndex = -1; let selectedObject = null; // 初始化画布 function initCanvas(width = 800, height = 600) { canvas = new fabric.Canvas('design-canvas', { width: width, height: height, backgroundColor: '#ffffff', preserveObjectStacking: true }); // 添加默认文本 addDefaultText(); // 监听选择变化 canvas.on('selection:created', handleSelection); canvas.on('selection:updated', handleSelection); canvas.on('selection:cleared', clearSelection); // 监听对象修改 canvas.on('object:modified', saveState); canvas.on('object:added', saveState); canvas.on('object:removed', saveState); // 保存初始状态 saveState(); } // 添加默认文本 function addDefaultText() { const text = new fabric.Textbox('双击编辑文本', { left: 100, top: 100, width: 200, fontSize: 24, fill: '#333333', fontFamily: 'Arial' }); canvas.add(text); canvas.setActiveObject(text); } // 处理选择对象 function handleSelection(options) { selectedObject = canvas.getActiveObject(); updatePropertyPanel(); } // 清除选择 function clearSelection() { selectedObject = null; updatePropertyPanel(); } // 更新属性面板 function updatePropertyPanel() { const panel = $('#property-panel'); if (!selectedObject) { panel.html('<p>选择元素以编辑属性</p>'); return; } let html = '<div class="property-group">'; html += '<label>元素类型: ' + selectedObject.type + '</label>'; html += '</div>'; // 通用属性 html += '<div class="property-group">'; html += '<label>位置 X:</label>'; html += '<input type="number" id="prop-left" value="' + Math.round(selectedObject.left) + '">'; html += '</div>'; html += '<div class="property-group">'; html += '<label>位置 Y:</label>'; html += '<input type="number" id="prop-top" value="' + Math.round(selectedObject.top) + '">'; html += '</div>'; // 文本特定属性 if (selectedObject.type === 'textbox' || selectedObject.type === 'text') { html += '<div class="property-group">'; html += '<label>文本内容:</label>'; html += '<input type="text" id="prop-text" value="' + selectedObject.text + '">'; html += '</div>'; html += '<div class="property-group">'; html += '<label>字体大小:</label>'; html += '<input type="number" id="prop-font-size" value="' + selectedObject.fontSize + '">'; html += '</div>'; html += '<div class="property-group">'; html += '<label>字体:</label>'; html += '<select id="prop-font-family">'; html += '<option value="Arial"' + (selectedObject.fontFamily === 'Arial' ? ' selected' : '') + '>Arial</option>'; html += '<option value="Helvetica"' + (selectedObject.fontFamily === 'Helvetica' ? ' selected' : '') + '>Helvetica</option>'; html += '<option value="Times New Roman"' + (selectedObject.fontFamily === 'Times New Roman' ? ' selected' : '') + '>Times New Roman</option>'; html += '<option value="Georgia"' + (selectedObject.fontFamily === 'Georgia' ? ' selected' : '') + '>Georgia</option>'; html += '</select>'; html += '</div>'; html += '<div class="property-group">'; html += '<label>文本颜色:</label>'; html += '<input type="color" id="prop-fill" value="' + rgbToHex(selectedObject.fill) + '">'; html += '</div>'; } // 图像特定属性 if (selectedObject.type === 'image') { html += '<div class="property-group">'; html += '<label>透明度:</label>'; html += '<input type="range" id="prop-opacity" min="0" max="1" step="0.1" value="' + selectedObject.opacity + '">'; html += '</div>'; } panel.html(html); // 绑定属性变化事件 bindPropertyEvents(); } // 绑定属性变化事件 function bindPropertyEvents() { if (!selectedObject) return; // 位置属性 $('#prop-left').on('change', function() { selectedObject.set('left', parseInt($(this).val())); canvas.renderAll(); saveState(); }); $('#prop-top').on('change', function() { selectedObject.set('top', parseInt($(this).val())); canvas.renderAll(); saveState(); }); // 文本属性 $('#prop-text').on('change', function() { if (selectedObject.type === 'textbox' || selectedObject.type === 'text') { selectedObject.set('text', $(this).val()); canvas.renderAll(); saveState(); } }); $('#prop-font-size').on('change', function() { if (selectedObject.type === 'textbox' || selectedObject.type === 'text') { selectedObject.set('fontSize', parseInt($(this).val())); canvas.renderAll(); saveState(); } }); $('#prop-font-family').on('change', function() { if (selectedObject.type === 'textbox' || selectedObject.type === 'text') { selectedObject.set('fontFamily', $(this).val()); canvas.renderAll(); saveState(); } }); $('#prop-fill').on('change', function() { if (selectedObject.type === 'textbox' || selectedObject.type === 'text') { selectedObject.set('fill', $(this).val()); canvas.renderAll(); saveState(); } }); // 图像透明度 $('#prop-opacity').on('input', function() { if (selectedObject.type === 'image') { selectedObject.set('opacity', parseFloat($(this).val())); canvas.renderAll(); saveState(); } }); } // RGB转十六进制颜色 function rgbToHex(rgb) { if (!rgb) return '#000000'; if (rgb.startsWith('#')) return rgb; if (rgb.startsWith('rgb')) { const values = rgb.match(/d+/g); if (values && values.length >= 3) { const r = parseInt(values[0]).toString(16).padStart(2, '0'); const g = parseInt(values[1]).toString(16).padStart(2, '0'); const b = parseInt(values[2]).toString(16).padStart(2, '0'); return `#${r}${g}${b}`; } } return '#000000'; } // 保存状态到历史记录 function saveState() { // 只保留最近20个状态 if (history.length > 20) { history.shift(); } // 如果当前不是最新状态,移除后面的状态 if (historyIndex < history.length - 1) { history = history.slice(0, historyIndex + 1); } const state = JSON.stringify(canvas.toJSON()); history.push(state); historyIndex = history.length - 1; } // 撤销 function undo() { if (historyIndex > 0) { historyIndex--; loadState(history[historyIndex]); } } // 重做 function redo() { if (historyIndex < history.length - 1) { historyIndex++; loadState(history[historyIndex]); } } // 加载状态 function loadState(state) { canvas.loadFromJSON(state, function() { canvas.renderAll(); // 重新绑定事件 canvas.getObjects().forEach(function(obj) { obj.setCoords(); }); }); } // 添加文本 function addText() { const text = new fabric.Textbox('新文本', { left: 100, top: 100, width: 200, fontSize: 24, fill: $('#color-picker').val(), fontFamily: $('#font-selector').val() }); canvas.add(text); canvas.setActiveObject(text); updatePropertyPanel(); } // 添加形状 function addShape(shapeType = 'rect') { let shape; const color = $('#color-picker').val(); switch(shapeType) { case 'rect': shape = new fabric.Rect({ left: 150, top: 150, width: 100, height: 100, fill: color, strokeWidth: 2, stroke: '#333333' }); break; case 'circle': shape = new fabric.Circle({ left: 150, top: 150, radius: 50, fill: color, strokeWidth: 2, stroke: '#333333' }); break; case 'triangle': shape = new fabric.Triangle({ left: 150, top: 150, width: 100, height: 100, fill: color, strokeWidth: 2, stroke: '#333333' }); break; } canvas.add(shape); canvas.setActiveObject(shape); updatePropertyPanel(); } // 添加图片 function addImage(url) { fabric.Image.fromURL(url, function(img) { // 限制图片大小 const maxWidth = 400; const maxHeight = 400; let scale = 1; if (img.width > maxWidth) { scale = maxWidth / img.width; } if (img.height * scale > maxHeight) { scale = maxHeight / img.height; } img.scale(scale); img.set({ left: 200, top: 200 }); canvas.add(img); canvas.setActiveObject(img); updatePropertyPanel(); }); } // 更改背景 function changeBackground(type, value) { if (type === 'color') { canvas.setBackgroundColor(value, canvas.renderAll.bind(canvas)); } else if (type === 'image') { fabric.Image.fromURL(value, function(img) { canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), { scaleX: canvas.width / img.width, scaleY: canvas.height / img.height }); }); } saveState(); } // 更改画布尺寸 function changeCanvasSize(width, height) { canvas.setDimensions({width: width, height: height}); canvas.renderAll(); saveState(); } // 导出为图片 function exportImage(format = 'png', quality = 1.0) { const dataURL = canvas.toDataURL({ format: format, quality: quality }); // 创建下载链接 const link = document.createElement('a'); link.download = 'design-' + Date.now() + '.' + format; link.href = dataURL; document.body.appendChild(link); link.click(); document.body.removeChild(link); } // 保存草稿到服务器 function saveDraft() { const designData = JSON.stringify(canvas.toJSON()); $.ajax({ url: designToolAjax.ajax_url, type: 'POST', data: { action: 'save_design_draft', nonce: designToolAjax.nonce, design_data: designData }, success: function(response) { if (response.success) { alert('草稿保存成功!'); } else { alert('保存失败:' + response.data); } }, error: function() { alert('网络错误,请重试'); } }); } // 初始化事件监听 function initEventListeners() { // 工具栏按钮 $('[data-action="add-text"]').click(addText); $('[data-action="add-shape"]').click(function() { addShape('rect'); }); $('[data-action="add-image"]').click(function() { $('#image-upload-modal').show(); }); $('[data-action="add-background"]').click(function() { changeBackground('color', $('#color-picker').val()); }); // 模板选择 $('.template-item').click(function() { const template = $(this).data('template'); loadTemplate(template); }); // 背景选择 $('.bg-item').click(function() { const bgUrl = $(this).data('bg'); changeBackground('image', bgUrl); }); // 颜色选择 $('.color-item').click(function() { const color = $(this).data('color'); $('#color-picker').val(color); // 如果当前有选中对象,应用颜色 if (selectedObject && selectedObject.type === 'textbox') { selectedObject.set('fill', color); canvas.renderAll(); saveState(); updatePropertyPanel(); } }); $('#color-picker').change(function() { const color = $(this).val(); // 如果当前有选中文本对象,应用颜色 if (selectedObject && selectedObject.type === 'textbox') { selectedObject.set('fill', color); canvas.renderAll(); saveState(); updatePropertyPanel(); } }); // 字体选择 $('#font-selector').change(function() { const font = $(this).val(); // 如果当前有选中文本对象,应用字体 if (selectedObject && selectedObject.type === 'textbox') { selectedObject.set('fontFamily', font); canvas.renderAll(); saveState(); updatePropertyPanel(); } }); // 画布尺寸选择 $('#canvas-size').change(function() { const size = $(this).val().split('x'); const width = parseInt(size[0]); const height = parseInt(size[1]); changeCanvasSize(width, height); }); // 工具栏按钮 $('#btn-undo').click(undo); $('#btn-redo').click(redo); $('#btn-clear').click(function() { if (confirm('确定要清空画布吗?')) { canvas.clear(); addDefaultText(); saveState(); } }); // 导出按钮 $('#btn-export-png').click(function() { exportImage('png'); }); $('#btn-export-jpg').click(function() { exportImage('jpeg', 0.9); }); // 保存草稿 $('#btn-save-draft').click(saveDraft); // 图片上传模态框 $('.close-modal').click(function() { $('#image-upload-modal').hide(); }); $(window).click(function(event) { if ($(event.target).is('#image-upload-modal')) { $('#image-upload-modal').hide(); } }); // 上传图片 $('#btn-upload').click(function() { const fileInput = $('#file-upload')[0]; if (fileInput.files.length === 0) { alert('请选择图片文件'); return; } const file = fileInput.files[0]; const reader = new FileReader(); reader.onload = function(e) { addImage(e.target.result); $('#image-upload-modal').hide(); $('#file-upload').val(''); }; reader.readAsDataURL(file); }); // 从URL添加图片
在当今数字化营销时代,视觉内容的重要性不言而喻。据统计,带有图片的社交媒体帖子比纯文本帖子获得更多的互动——平均高出2.3倍的参与度。对于网站运营者而言,为用户提供便捷的视觉内容创建工具,不仅能增强用户粘性,还能促进内容生成和分享。
然而,专业的图像设计软件如Photoshop学习成本高,而在线设计工具往往需要跳转到第三方网站,导致用户流失。将简易海报设计与宣传图生成工具直接集成到WordPress网站中,可以完美解决这一问题。用户无需离开您的网站即可创建吸引人的视觉内容,这不仅能提升用户体验,还能增加网站的功能价值和竞争力。
本文将详细指导您如何通过WordPress代码二次开发,将在线简易海报设计与宣传图生成工具集成到您的网站中,实现这一实用的互联网小工具功能。
在开始之前,我们需要确定合适的技术方案。目前主要有三种集成方式:
- 使用现有插件:如Canva的嵌入代码或类似设计工具的API
- 自定义开发简单设计器:基于HTML5 Canvas和JavaScript
- 混合方案:结合现有库和自定义功能
考虑到灵活性和控制度,我们将选择第二种方案,使用Fabric.js库构建一个轻量级但功能齐全的设计工具。Fabric.js是一个强大的Canvas库,专门用于处理图形和图像操作。
首先,确保您具备以下条件:
- 一个运行中的WordPress网站(版本5.0以上)
- 访问WordPress文件系统的权限(通过FTP或文件管理器)
- 基础的HTML、CSS、JavaScript和PHP知识
- 代码编辑器(如VS Code、Sublime Text等)
为了避免主题更新导致自定义代码丢失,我们将在子主题中进行开发:
- 在WordPress的
wp-content/themes/目录下创建新文件夹,命名为my-design-tool-theme - 在该文件夹中创建
style.css文件,添加以下内容:
/*
Theme Name: My Design Tool Theme
Template: your-parent-theme-folder-name
Version: 1.0
Description: 子主题,用于集成海报设计工具
*/
- 创建
functions.php文件,暂时留空 - 在WordPress后台启用这个子主题
在子主题的functions.php中添加以下代码,引入Fabric.js和其他必要的库:
function design_tool_enqueue_scripts() {
// 引入Fabric.js库
wp_enqueue_script('fabric-js', 'https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.5.0/fabric.min.js', array(), '4.5.0', true);
// 引入html2canvas用于导出图片
wp_enqueue_script('html2canvas', 'https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js', array(), '1.4.1', true);
// 引入我们的自定义脚本
wp_enqueue_script('design-tool-script', get_stylesheet_directory_uri() . '/js/design-tool.js', array('fabric-js', 'jquery'), '1.0', true);
// 引入样式文件
wp_enqueue_style('design-tool-style', get_stylesheet_directory_uri() . '/css/design-tool.css', array(), '1.0');
// 本地化脚本,传递PHP变量到JavaScript
wp_localize_script('design-tool-script', 'designToolAjax', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('design_tool_nonce')
));
}
add_action('wp_enqueue_scripts', 'design_tool_enqueue_scripts');
在子主题目录下创建template-parts文件夹,然后创建design-tool-template.php文件:
<?php
/**
* 海报设计工具模板
*/
?>
<div class="design-tool-container">
<div class="design-tool-header">
<h1>简易海报设计工具</h1>
<p>创建吸引人的宣传图、社交媒体图片和海报</p>
</div>
<div class="design-tool-wrapper">
<!-- 左侧工具栏 -->
<div class="design-sidebar">
<div class="tool-section">
<h3>模板</h3>
<div class="template-thumbnails">
<div class="template-item" data-template="social-media">
<img src="<?php echo get_stylesheet_directory_uri(); ?>/images/template-social.jpg" alt="社交媒体模板">
<span>社交媒体</span>
</div>
<div class="template-item" data-template="poster">
<img src="<?php echo get_stylesheet_directory_uri(); ?>/images/template-poster.jpg" alt="海报模板">
<span>海报</span>
</div>
<div class="template-item" data-template="banner">
<img src="<?php echo get_stylesheet_directory_uri(); ?>/images/template-banner.jpg" alt="横幅模板">
<span>横幅广告</span>
</div>
</div>
</div>
<div class="tool-section">
<h3>元素</h3>
<button class="tool-btn" data-action="add-text">添加文本</button>
<button class="tool-btn" data-action="add-image">添加图片</button>
<button class="tool-btn" data-action="add-shape">添加形状</button>
<button class="tool-btn" data-action="add-background">更改背景</button>
</div>
<div class="tool-section">
<h3>属性</h3>
<div id="property-panel">
<p>选择元素以编辑属性</p>
</div>
</div>
</div>
<!-- 中间画布区域 -->
<div class="design-main">
<div class="canvas-toolbar">
<button id="btn-undo" title="撤销">↶</button>
<button id="btn-redo" title="重做">↷</button>
<button id="btn-clear" title="清空画布">×</button>
<select id="canvas-size">
<option value="800x600">800×600 (通用)</option>
<option value="1200x628">1200×628 (Facebook)</option>
<option value="1080x1080">1080×1080 (Instagram)</option>
<option value="1500x500">1500×500 (Twitter横幅)</option>
</select>
</div>
<div class="canvas-container">
<canvas id="design-canvas"></canvas>
</div>
<div class="canvas-footer">
<button id="btn-save-draft" class="btn-secondary">保存草稿</button>
<button id="btn-export-png" class="btn-primary">导出为PNG</button>
<button id="btn-export-jpg" class="btn-primary">导出为JPG</button>
</div>
</div>
<!-- 右侧资源库 -->
<div class="design-resources">
<div class="tool-section">
<h3>背景图片</h3>
<div class="background-thumbnails">
<?php for($i=1; $i<=6; $i++): ?>
<div class="bg-item" data-bg="<?php echo get_stylesheet_directory_uri(); ?>/images/bg<?php echo $i; ?>.jpg">
<img src="<?php echo get_stylesheet_directory_uri(); ?>/images/bg<?php echo $i; ?>.jpg" alt="背景<?php echo $i; ?>">
</div>
<?php endfor; ?>
</div>
</div>
<div class="tool-section">
<h3>字体选择</h3>
<select id="font-selector">
<option value="Arial">Arial</option>
<option value="Helvetica">Helvetica</option>
<option value="Times New Roman">Times New Roman</option>
<option value="Georgia">Georgia</option>
<option value="Courier New">Courier New</option>
</select>
</div>
<div class="tool-section">
<h3>颜色选择</h3>
<div class="color-palette">
<div class="color-item" data-color="#FF0000" style="background-color:#FF0000;"></div>
<div class="color-item" data-color="#00FF00" style="background-color:#00FF00;"></div>
<div class="color-item" data-color="#0000FF" style="background-color:#0000FF;"></div>
<div class="color-item" data-color="#FFFF00" style="background-color:#FFFF00;"></div>
<div class="color-item" data-color="#FF00FF" style="background-color:#FF00FF;"></div>
<div class="color-item" data-color="#00FFFF" style="background-color:#00FFFF;"></div>
<div class="color-item" data-color="#000000" style="background-color:#000000;"></div>
<div class="color-item" data-color="#FFFFFF" style="background-color:#FFFFFF; border:1px solid #ccc;"></div>
</div>
<input type="color" id="color-picker" value="#FF0000">
</div>
</div>
</div>
<!-- 模态框 -->
<div id="image-upload-modal" class="modal">
<div class="modal-content">
<span class="close-modal">×</span>
<h3>上传图片</h3>
<div class="upload-options">
<div class="upload-option">
<h4>从电脑上传</h4>
<input type="file" id="file-upload" accept="image/*">
<button id="btn-upload">上传</button>
</div>
<div class="upload-option">
<h4>从URL添加</h4>
<input type="text" id="image-url" placeholder="输入图片URL">
<button id="btn-add-url">添加</button>
</div>
</div>
</div>
</div>
</div>
创建css/design-tool.css文件:
/* 设计工具主容器 */
.design-tool-container {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
max-width: 1400px;
margin: 0 auto;
padding: 20px;
background-color: #f5f7fa;
min-height: 100vh;
}
.design-tool-header {
text-align: center;
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 1px solid #e1e5eb;
}
.design-tool-header h1 {
color: #2c3e50;
margin-bottom: 10px;
}
.design-tool-header p {
color: #7f8c8d;
font-size: 1.1rem;
}
/* 设计工具布局 */
.design-tool-wrapper {
display: flex;
gap: 20px;
background-color: white;
border-radius: 10px;
box-shadow: 0 5px 15px rgba(0,0,0,0.08);
overflow: hidden;
min-height: 700px;
}
.design-sidebar, .design-resources {
width: 250px;
padding: 20px;
background-color: #f8f9fa;
border-right: 1px solid #e9ecef;
}
.design-resources {
border-right: none;
border-left: 1px solid #e9ecef;
}
.design-main {
flex: 1;
display: flex;
flex-direction: column;
padding: 20px;
}
/* 工具栏样式 */
.tool-section {
margin-bottom: 30px;
}
.tool-section h3 {
color: #495057;
font-size: 1.1rem;
margin-bottom: 15px;
padding-bottom: 8px;
border-bottom: 1px solid #dee2e6;
}
.tool-btn {
display: block;
width: 100%;
padding: 10px 15px;
margin-bottom: 10px;
background-color: #4dabf7;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.2s;
font-size: 0.95rem;
}
.tool-btn:hover {
background-color: #339af0;
}
/* 模板缩略图 */
.template-thumbnails {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
.template-item {
border: 1px solid #dee2e6;
border-radius: 5px;
overflow: hidden;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
.template-item:hover {
transform: translateY(-3px);
box-shadow: 0 5px 10px rgba(0,0,0,0.1);
}
.template-item img {
width: 100%;
height: 70px;
object-fit: cover;
}
.template-item span {
display: block;
text-align: center;
padding: 5px;
font-size: 0.8rem;
color: #495057;
}
/* 画布区域 */
.canvas-toolbar {
display: flex;
gap: 10px;
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 1px solid #e9ecef;
}
.canvas-toolbar button, .canvas-toolbar select {
padding: 8px 15px;
border: 1px solid #ced4da;
border-radius: 5px;
background-color: white;
cursor: pointer;
}
.canvas-toolbar button:hover {
background-color: #f8f9fa;
}
.canvas-container {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
border: 1px dashed #adb5bd;
border-radius: 5px;
background-color: #f8f9fa;
margin-bottom: 20px;
overflow: auto;
}
#design-canvas {
background-color: white;
box-shadow: 0 3px 10px rgba(0,0,0,0.1);
}
.canvas-footer {
display: flex;
justify-content: center;
gap: 15px;
padding-top: 20px;
border-top: 1px solid #e9ecef;
}
.btn-primary, .btn-secondary {
padding: 12px 25px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 1rem;
font-weight: 500;
transition: all 0.2s;
}
.btn-primary {
background-color: #40c057;
color: white;
}
.btn-primary:hover {
background-color: #37b24d;
}
.btn-secondary {
background-color: #e9ecef;
color: #495057;
}
.btn-secondary:hover {
background-color: #dee2e6;
}
/* 资源库样式 */
.background-thumbnails {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
.bg-item {
border: 1px solid #dee2e6;
border-radius: 5px;
overflow: hidden;
cursor: pointer;
height: 70px;
}
.bg-item img {
width: 100%;
height: 100%;
object-fit: cover;
}
.color-palette {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 8px;
margin-bottom: 15px;
}
.color-item {
width: 30px;
height: 30px;
border-radius: 50%;
cursor: pointer;
border: 2px solid transparent;
}
.color-item:hover {
border-color: #495057;
}
#color-picker {
width: 100%;
height: 40px;
border: none;
cursor: pointer;
border-radius: 5px;
overflow: hidden;
}
#font-selector {
width: 100%;
padding: 8px;
border: 1px solid #ced4da;
border-radius: 5px;
}
/* 模态框样式 */
.modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
}
.modal-content {
background-color: white;
margin: 10% auto;
padding: 25px;
width: 500px;
border-radius: 10px;
box-shadow: 0 5px 20px rgba(0,0,0,0.2);
position: relative;
}
.close-modal {
position: absolute;
right: 20px;
top: 15px;
font-size: 28px;
cursor: pointer;
color: #7f8c8d;
}
.close-modal:hover {
color: #2c3e50;
}
.upload-options {
display: flex;
gap: 20px;
margin-top: 20px;
}
.upload-option {
flex: 1;
padding: 20px;
border: 1px solid #e9ecef;
border-radius: 5px;
}
.upload-option h4 {
margin-top: 0;
margin-bottom: 15px;
color: #495057;
}
.upload-option input {
width: 100%;
padding: 8px;
margin-bottom: 10px;
border: 1px solid #ced4da;
border-radius: 5px;
}
.upload-option button {
padding: 8px 15px;
background-color: #4dabf7;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
/ 响应式设计 /
@media (max-width: 1200px) {
.design-tool-wrapper {
flex-direction: column;
}
.design-sidebar, .design-resources {
width: 100%;
border-right: none;
border-left: none;
border-bottom: 1px solid #e9ecef;
}
.design-resources {
border-top: 1px solid #e9ecef;
}
}
/ 属性面板样式 /
background-color: white;
padding: 15px;
border-radius: 5px;
border: 1px solid #e9ecef;
min-height: 150px;
background-color: white;
padding: 15px;
border-radius: 5px;
border: 1px solid #e9ecef;
min-height: 150px;
}
.property-group {
margin-bottom: 15px;
}
.property-group label {
display: block;
margin-bottom: 5px;
font-size: 0.9rem;
color: #495057;
}
.property-group input,
.property-group select {
width: 100%;
padding: 6px;
border: 1px solid #ced4da;
border-radius: 3px;
}
## 第三部分:实现设计器核心功能
### 3.1 初始化设计器JavaScript
创建`js/design-tool.js`文件,开始实现核心功能:
jQuery(document).ready(function($) {
// 初始化变量
let canvas, currentTool = 'select', history = [], historyIndex = -1;
let selectedObject = null;
// 初始化画布
function initCanvas(width = 800, height = 600) {
canvas = new fabric.Canvas('design-canvas', {
width: width,
height: height,
backgroundColor: '#ffffff',
preserveObjectStacking: true
});
// 添加默认文本
addDefaultText();
// 监听选择变化
canvas.on('selection:created', handleSelection);
canvas.on('selection:updated', handleSelection);
canvas.on('selection:cleared', clearSelection);
// 监听对象修改
canvas.on('object:modified', saveState);
canvas.on('object:added', saveState);
canvas.on('object:removed', saveState);
// 保存初始状态
saveState();
}
// 添加默认文本
function addDefaultText() {
const text = new fabric.Textbox('双击编辑文本', {
left: 100,
top: 100,
width: 200,
fontSize: 24,
fill: '#333333',
fontFamily: 'Arial'
});
canvas.add(text);
canvas.setActiveObject(text);
}
// 处理选择对象
function handleSelection(options) {
selectedObject = canvas.getActiveObject();
updatePropertyPanel();
}
// 清除选择
function clearSelection() {
selectedObject = null;
updatePropertyPanel();
}
// 更新属性面板
function updatePropertyPanel() {
const panel = $('#property-panel');
if (!selectedObject) {
panel.html('<p>选择元素以编辑属性</p>');
return;
}
let html = '<div class="property-group">';
html += '<label>元素类型: ' + selectedObject.type + '</label>';
html += '</div>';
// 通用属性
html += '<div class="property-group">';
html += '<label>位置 X:</label>';
html += '<input type="number" id="prop-left" value="' + Math.round(selectedObject.left) + '">';
html += '</div>';
html += '<div class="property-group">';
html += '<label>位置 Y:</label>';
html += '<input type="number" id="prop-top" value="' + Math.round(selectedObject.top) + '">';
html += '</div>';
// 文本特定属性
if (selectedObject.type === 'textbox' || selectedObject.type === 'text') {
html += '<div class="property-group">';
html += '<label>文本内容:</label>';
html += '<input type="text" id="prop-text" value="' + selectedObject.text + '">';
html += '</div>';
html += '<div class="property-group">';
html += '<label>字体大小:</label>';
html += '<input type="number" id="prop-font-size" value="' + selectedObject.fontSize + '">';
html += '</div>';
html += '<div class="property-group">';
html += '<label>字体:</label>';
html += '<select id="prop-font-family">';
html += '<option value="Arial"' + (selectedObject.fontFamily === 'Arial' ? ' selected' : '') + '>Arial</option>';
html += '<option value="Helvetica"' + (selectedObject.fontFamily === 'Helvetica' ? ' selected' : '') + '>Helvetica</option>';
html += '<option value="Times New Roman"' + (selectedObject.fontFamily === 'Times New Roman' ? ' selected' : '') + '>Times New Roman</option>';
html += '<option value="Georgia"' + (selectedObject.fontFamily === 'Georgia' ? ' selected' : '') + '>Georgia</option>';
html += '</select>';
html += '</div>';
html += '<div class="property-group">';
html += '<label>文本颜色:</label>';
html += '<input type="color" id="prop-fill" value="' + rgbToHex(selectedObject.fill) + '">';
html += '</div>';
}
// 图像特定属性
if (selectedObject.type === 'image') {
html += '<div class="property-group">';
html += '<label>透明度:</label>';
html += '<input type="range" id="prop-opacity" min="0" max="1" step="0.1" value="' + selectedObject.opacity + '">';
html += '</div>';
}
panel.html(html);
// 绑定属性变化事件
bindPropertyEvents();
}
// 绑定属性变化事件
function bindPropertyEvents() {
if (!selectedObject) return;
// 位置属性
$('#prop-left').on('change', function() {
selectedObject.set('left', parseInt($(this).val()));
canvas.renderAll();
saveState();
});
$('#prop-top').on('change', function() {
selectedObject.set('top', parseInt($(this).val()));
canvas.renderAll();
saveState();
});
// 文本属性
$('#prop-text').on('change', function() {
if (selectedObject.type === 'textbox' || selectedObject.type === 'text') {
selectedObject.set('text', $(this).val());
canvas.renderAll();
saveState();
}
});
$('#prop-font-size').on('change', function() {
if (selectedObject.type === 'textbox' || selectedObject.type === 'text') {
selectedObject.set('fontSize', parseInt($(this).val()));
canvas.renderAll();
saveState();
}
});
$('#prop-font-family').on('change', function() {
if (selectedObject.type === 'textbox' || selectedObject.type === 'text') {
selectedObject.set('fontFamily', $(this).val());
canvas.renderAll();
saveState();
}
});
$('#prop-fill').on('change', function() {
if (selectedObject.type === 'textbox' || selectedObject.type === 'text') {
selectedObject.set('fill', $(this).val());
canvas.renderAll();
saveState();
}
});
// 图像透明度
$('#prop-opacity').on('input', function() {
if (selectedObject.type === 'image') {
selectedObject.set('opacity', parseFloat($(this).val()));
canvas.renderAll();
saveState();
}
});
}
// RGB转十六进制颜色
function rgbToHex(rgb) {
if (!rgb) return '#000000';
if (rgb.startsWith('#')) return rgb;
if (rgb.startsWith('rgb')) {
const values = rgb.match(/d+/g);
if (values && values.length >= 3) {
const r = parseInt(values[0]).toString(16).padStart(2, '0');
const g = parseInt(values[1]).toString(16).padStart(2, '0');
const b = parseInt(values[2]).toString(16).padStart(2, '0');
return `#${r}${g}${b}`;
}
}
return '#000000';
}
// 保存状态到历史记录
function saveState() {
// 只保留最近20个状态
if (history.length > 20) {
history.shift();
}
// 如果当前不是最新状态,移除后面的状态
if (historyIndex < history.length - 1) {
history = history.slice(0, historyIndex + 1);
}
const state = JSON.stringify(canvas.toJSON());
history.push(state);
historyIndex = history.length - 1;
}
// 撤销
function undo() {
if (historyIndex > 0) {
historyIndex--;
loadState(history[historyIndex]);
}
}
// 重做
function redo() {
if (historyIndex < history.length - 1) {
historyIndex++;
loadState(history[historyIndex]);
}
}
// 加载状态
function loadState(state) {
canvas.loadFromJSON(state, function() {
canvas.renderAll();
// 重新绑定事件
canvas.getObjects().forEach(function(obj) {
obj.setCoords();
});
});
}
// 添加文本
function addText() {
const text = new fabric.Textbox('新文本', {
left: 100,
top: 100,
width: 200,
fontSize: 24,
fill: $('#color-picker').val(),
fontFamily: $('#font-selector').val()
});
canvas.add(text);
canvas.setActiveObject(text);
updatePropertyPanel();
}
// 添加形状
function addShape(shapeType = 'rect') {
let shape;
const color = $('#color-picker').val();
switch(shapeType) {
case 'rect':
shape = new fabric.Rect({
left: 150,
top: 150,
width: 100,
height: 100,
fill: color,
strokeWidth: 2,
stroke: '#333333'
});
break;
case 'circle':
shape = new fabric.Circle({
left: 150,
top: 150,
radius: 50,
fill: color,
strokeWidth: 2,
stroke: '#333333'
});
break;
case 'triangle':
shape = new fabric.Triangle({
left: 150,
top: 150,
width: 100,
height: 100,
fill: color,
strokeWidth: 2,
stroke: '#333333'
});
break;
}
canvas.add(shape);
canvas.setActiveObject(shape);
updatePropertyPanel();
}
// 添加图片
function addImage(url) {
fabric.Image.fromURL(url, function(img) {
// 限制图片大小
const maxWidth = 400;
const maxHeight = 400;
let scale = 1;
if (img.width > maxWidth) {
scale = maxWidth / img.width;
}
if (img.height * scale > maxHeight) {
scale = maxHeight / img.height;
}
img.scale(scale);
img.set({
left: 200,
top: 200
});
canvas.add(img);
canvas.setActiveObject(img);
updatePropertyPanel();
});
}
// 更改背景
function changeBackground(type, value) {
if (type === 'color') {
canvas.setBackgroundColor(value, canvas.renderAll.bind(canvas));
} else if (type === 'image') {
fabric.Image.fromURL(value, function(img) {
canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), {
scaleX: canvas.width / img.width,
scaleY: canvas.height / img.height
});
});
}
saveState();
}
// 更改画布尺寸
function changeCanvasSize(width, height) {
canvas.setDimensions({width: width, height: height});
canvas.renderAll();
saveState();
}
// 导出为图片
function exportImage(format = 'png', quality = 1.0) {
const dataURL = canvas.toDataURL({
format: format,
quality: quality
});
// 创建下载链接
const link = document.createElement('a');
link.download = 'design-' + Date.now() + '.' + format;
link.href = dataURL;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
// 保存草稿到服务器
function saveDraft() {
const designData = JSON.stringify(canvas.toJSON());
$.ajax({
url: designToolAjax.ajax_url,
type: 'POST',
data: {
action: 'save_design_draft',
nonce: designToolAjax.nonce,
design_data: designData
},
success: function(response) {
if (response.success) {
alert('草稿保存成功!');
} else {
alert('保存失败:' + response.data);
}
},
error: function() {
alert('网络错误,请重试');
}
});
}
// 初始化事件监听
function initEventListeners() {
// 工具栏按钮
$('[data-action="add-text"]').click(addText);
$('[data-action="add-shape"]').click(function() {
addShape('rect');
});
$('[data-action="add-image"]').click(function() {
$('#image-upload-modal').show();
});
$('[data-action="add-background"]').click(function() {
changeBackground('color', $('#color-picker').val());
});
// 模板选择
$('.template-item').click(function() {
const template = $(this).data('template');
loadTemplate(template);
});
// 背景选择
$('.bg-item').click(function() {
const bgUrl = $(this).data('bg');
changeBackground('image', bgUrl);
});
// 颜色选择
$('.color-item').click(function() {
const color = $(this).data('color');
$('#color-picker').val(color);
// 如果当前有选中对象,应用颜色
if (selectedObject && selectedObject.type === 'textbox') {
selectedObject.set('fill', color);
canvas.renderAll();
saveState();
updatePropertyPanel();
}
});
$('#color-picker').change(function() {
const color = $(this).val();
// 如果当前有选中文本对象,应用颜色
if (selectedObject && selectedObject.type === 'textbox') {
selectedObject.set('fill', color);
canvas.renderAll();
saveState();
updatePropertyPanel();
}
});
// 字体选择
$('#font-selector').change(function() {
const font = $(this).val();
// 如果当前有选中文本对象,应用字体
if (selectedObject && selectedObject.type === 'textbox') {
selectedObject.set('fontFamily', font);
canvas.renderAll();
saveState();
updatePropertyPanel();
}
});
// 画布尺寸选择
$('#canvas-size').change(function() {
const size = $(this).val().split('x');
const width = parseInt(size[0]);
const height = parseInt(size[1]);
changeCanvasSize(width, height);
});
// 工具栏按钮
$('#btn-undo').click(undo);
$('#btn-redo').click(redo);
$('#btn-clear').click(function() {
if (confirm('确定要清空画布吗?')) {
canvas.clear();
addDefaultText();
saveState();
}
});
// 导出按钮
$('#btn-export-png').click(function() {
exportImage('png');
});
$('#btn-export-jpg').click(function() {
exportImage('jpeg', 0.9);
});
// 保存草稿
$('#btn-save-draft').click(saveDraft);
// 图片上传模态框
$('.close-modal').click(function() {
$('#image-upload-modal').hide();
});
$(window).click(function(event) {
if ($(event.target).is('#image-upload-modal')) {
$('#image-upload-modal').hide();
}
});
// 上传图片
$('#btn-upload').click(function() {
const fileInput = $('#file-upload')[0];
if (fileInput.files.length === 0) {
alert('请选择图片文件');
return;
}
const file = fileInput.files[0];
const reader = new FileReader();
reader.onload = function(e) {
addImage(e.target.result);
$('#image-upload-modal').hide();
$('#file-upload').val('');
};
reader.readAsDataURL(file);
});
// 从URL添加图片


