嵌入Fancybox的TikTok视频在弹窗中自动消失问题求助
Fancybox嵌入TikTok视频后打开立即消失的解决办法
问题情况
使用@fancyapps/ui": "^5.0.17"实现多平台视频嵌入,YouTube和VK视频显示正常,但TikTok视频放入Fancybox后,打开会立即消失:
- 浏览器元素检查可见视频仍在DOM结构中
- 打开视频后刷新页面,视频可正常观看
- 快速点开视频也能查看,但关闭Fancybox后视频会消失
现有代码
后端获取TikTok数据(PHP)
$apiUrl = "https://www.tiktok.com/oembed?url={$link}"; try { $response = $client->get($apiUrl); $jsonResponse = json_decode($response->getBody(), true); $html = $jsonResponse['html']; $preview = $jsonResponse['thumbnail_url']; } catch(Exception $exception) { $html = false; $preview = ''; } return view('widgets.index_iframe_tik_tok_widget', [ 'html' => $html, 'masterJob' => $this->config['index'], 'key' => $this->config['key'], 'preview' => $preview ]);
TikTok oEmbed返回的HTML内容
<blockquote class="tiktok-embed" cite="https://www.tiktok.com/@world_walkerz/video/7218998983937625349" data-video-id="7218998983937625349" data-embed-from="oembed" style="max-width: 605px;min-width: 325px;" id="v62804243901872250"> </blockquote> <script async="" src="https://www.tiktok.com/embed.js"></script>
前端Blade视图代码
@if($html) <div> <span data-thumb="{{ $preview }}" data-fancybox="{{ $index->id }}" data-src="#dialog-content-{{ $index->id }}-{{ $key }}"></span> <div style="display: none" id="dialog-content-{{ $index->id }}-{{ $key }}"> {!! $html !!} </div> </div> @endif
问题原因
TikTok的embed.js是异步加载脚本,仅在页面初始加载时扫描tiktok-embed块完成渲染。但Fancybox打开时会将目标DOM元素移至自身容器,加上初始元素为display: none,导致脚本无法正确识别元素;同时Fancybox的动画过程也可能干扰TikTok的渲染逻辑,最终造成视频显示后消失。
解决方法
方法1:Fancybox打开后动态加载TikTok脚本
移除后端返回HTML中的自带脚本,改为在Fancybox打开后加载脚本并触发渲染:
- 修改视图代码,剔除自带的script标签:
@if($html) <div> <span data-thumb="{{ $preview }}" data-fancybox="{{ $index->id }}" data-src="#dialog-content-{{ $index->id }}-{{ $key }}" class="tiktok-fancybox-trigger"></span> <div style="display: none" id="dialog-content-{{ $index->id }}-{{ $key }}"> {!! str_replace('<script async="" src="https://www.tiktok.com/embed.js"></script>', '', $html) !!} </div> </div> @endif
- 添加JS监听Fancybox事件:
// 绑定TikTok触发元素的Fancybox事件 Fancybox.bind('.tiktok-fancybox-trigger', { onDone: (fancybox, slide) => { // 检查脚本是否已加载 let tiktokScript = document.querySelector('script[src="https://www.tiktok.com/embed.js"]'); if (!tiktokScript) { tiktokScript = document.createElement('script'); tiktokScript.src = 'https://www.tiktok.com/embed.js'; tiktokScript.async = true; document.body.appendChild(tiktokScript); } else { // 脚本已加载则手动触发渲染 if (window.tiktokEmbed) { window.tiktokEmbed.render(); } } }, onClose: (fancybox) => { // 关闭时移除iframe,避免下次打开冲突 const tiktokIframe = fancybox.container.querySelector('iframe.tiktok-embed'); if (tiktokIframe) { tiktokIframe.remove(); } } });
方法2:直接使用Fancybox的iframe模式加载TikTok
绕开blockquote渲染逻辑,让Fancybox直接加载TikTok嵌入页面:
- 后端提取视频ID并构造嵌入URL:
// 从oEmbed返回的html中提取视频ID preg_match('/data-video-id="(\d+)"/', $jsonResponse['html'], $matches); $videoId = $matches[1] ?? ''; // 构造直接嵌入的URL $embedUrl = "https://www.tiktok.com/embed/v2/{$videoId}";
- 修改视图代码,使用Fancybox的iframe类型:
@if($embedUrl) <span data-thumb="{{ $preview }}" data-fancybox="{{ $index->id }}" data-src="{{ $embedUrl }}" data-type="iframe" data-width="605" data-height="auto"></span> @endif
此方法无需处理DOM移动问题,实现更简洁。
方法3:临时禁用Fancybox动画
若上述方法无效,可先关闭Fancybox入场动画,给TikTok脚本足够渲染时间:
Fancybox.bind('[data-fancybox]', { animationEffect: "none" });
内容的提问来源于stack exchange,提问作者REssh
相关产品推荐
相关产品推荐

