You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何保存含3D iframe的WordPress页面并留存用户设计内容?

解决方案

一、保存设计内容到WordPress站点(优先方案)

同域场景下,直接通过父子页面通信获取设计配置数据是最可靠的方案——比截图更精准,还能避免3D渲染相关的捕获问题。

1. 从3D iframe传递设计数据

  • 在iframe的3D页面中,监听用户完成设计的操作(比如点击“完成设计”按钮),将当前材质、变体等配置序列化为JSON后发送给父页面:
    // 3D页面内代码
    document.getElementById('finish-design').addEventListener('click', () => {
      const designConfig = {
        materials: currentMaterialSettings, // 你的3D库中当前材质数据
        variants: selectedVariantIds, // 用户选择的变体ID集合
        customParams: userCustomOptions // 其他自定义配置项
      };
      // 同域下直接传递数据
      window.parent.postMessage(JSON.stringify(designConfig), window.location.origin);
    });
    
  • 在WordPress产品配置页面(父页面),监听message事件接收数据并提交到后端:
    // WordPress页面内代码
    window.addEventListener('message', (event) => {
      // 验证同域,防止恶意数据
      if (event.origin !== window.location.origin) return;
      
      const designData = JSON.parse(event.data);
      // 调用WordPress AJAX接口保存数据
      fetch('/wp-admin/admin-ajax.php', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          'X-WP-Nonce': wpApiSettings.nonce // 用WP内置nonce防CSRF
        },
        body: new URLSearchParams({
          action: 'store_user_design',
          product_id: <?php echo get_the_ID(); ?>, // 当前产品ID
          design_content: JSON.stringify(designData)
        })
      })
      .then(res => res.json())
      .then(result => {
        if (result.success) {
          alert('你的设计已保存,我们会尽快查看');
        }
      });
    });
    

2. WordPress后端处理保存逻辑

在主题的functions.php中添加AJAX处理函数:

// 登录/未登录用户均可调用
add_action('wp_ajax_store_user_design', 'store_user_design');
add_action('wp_ajax_nopriv_store_user_design', 'store_user_design');

function store_user_design() {
    check_ajax_referer(); // 验证nonce有效性
    $product_id = intval($_POST['product_id']);
    $design_content = json_decode(stripslashes($_POST['design_content']), true);
    
    if (!is_array($design_content)) {
        wp_send_json_error('无效的设计数据');
    }
    
    // 方案1:保存为当前产品的自定义字段
    $user_id = get_current_user_id();
    $design_entry = [
        'id' => uniqid('design_'),
        'user_id' => $user_id,
        'created_time' => current_time('mysql'),
        'config' => $design_content
    ];
    
    // 追加到已有设计列表
    $existing_designs = get_post_meta($product_id, 'user_submitted_designs', true) ?: [];
    $existing_designs[] = $design_entry;
    update_post_meta($product_id, 'user_submitted_designs', $existing_designs);
    
    // 方案2:创建自定义文章类型单独管理(可选)
    // $design_post = wp_insert_post([
    //     'post_title' => '用户设计-' . uniqid(),
    //     'post_type' => 'user_design',
    //     'post_status' => 'private',
    //     'post_parent' => $product_id,
    //     'meta_input' => [
    //         'design_config' => $design_content,
    //         'submitter_id' => $user_id
    //     ]
    // ]);
    
    wp_send_json_success(['design_id' => $design_entry['id']]);
}

3. 查看用户提交的设计

  • 在WordPress后台编辑对应产品时,可在自定义字段user_submitted_designs中查看所有用户设计数据;如果用了自定义文章类型,直接在后台新增的“用户设计”栏目里查看。
  • 要预览设计,可在产品页添加预览功能,把保存的JSON配置重新传入3D iframe,让3D场景加载对应的参数。

二、用户下载设计后邮件发送方案

如果暂时不想开发后端保存逻辑,可以让用户导出设计数据或截图后通过邮件发送:

1. 导出设计配置为JSON文件

在父页面收到设计数据后,添加下载按钮:

// 父页面接收designData后执行
const downloadBtn = document.createElement('button');
downloadBtn.textContent = '下载设计配置文件';
downloadBtn.addEventListener('click', () => {
  const blob = new Blob([JSON.stringify(designData, null, 2)], {type: 'application/json'});
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = `产品设计-${Date.now()}.json`;
  a.click();
  URL.revokeObjectURL(url);
});
document.querySelector('.design-actions').appendChild(downloadBtn);

用户下载该文件后,可通过邮件发送给你,你将JSON导入3D页面即可还原设计。

2. 生成3D场景截图并下载

之前html2canvas生成空白PDF,核心原因是WebGL画布无法被默认捕获,可通过以下方式修正:

// 3D页面内获取WebGL画布截图
function capture3DScene() {
  const canvas = document.querySelector('canvas'); // 你的3D渲染画布
  return canvas.toDataURL('image/png');
}

// 完成设计时,将截图和配置一起传给父页面
document.getElementById('finish-design').addEventListener('click', () => {
  const sceneScreenshot = capture3DScene();
  const designData = {
    materials: currentMaterialSettings,
    variants: selectedVariantIds,
    screenshot: sceneScreenshot
  };
  window.parent.postMessage(JSON.stringify(designData), window.location.origin);
});

在父页面中,可直接让用户下载截图,或结合html2canvas生成PDF:

// 父页面接收数据后
const previewImg = document.createElement('img');
previewImg.src = designData.screenshot;
document.getElementById('design-preview').appendChild(previewImg);

// 生成PDF(需引入html2canvas和jsPDF)
document.getElementById('generate-pdf').addEventListener('click', async () => {
  const container = document.getElementById('design-preview');
  const canvas = await html2canvas(container, {
    allowTaint: true,
    logging: true // 开启日志排查问题
  });
  const pdf = new jsPDF('p', 'mm', 'a4');
  pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, 0, 210, 297);
  pdf.save('设计预览.pdf');
});

三、html2canvas空白问题的排查要点

  1. WebGL画布权限:确保3D画布未设置限制读取的crossOrigin属性,同域下保持默认即可。
  2. 渲染时机:等待3D场景渲染完成后再调用html2canvas,比如监听Three.js的render事件完成后执行。
  3. iframe状态:确保iframe完全加载后再操作,可监听iframe的load事件。
  4. 元素可见性:3D场景元素不能是display: none或在视口外,html2canvas无法捕获不可见元素。

内容的提问来源于stack exchange,提问作者Joe Bifano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 17:53:15