嵌入YouTube视频30秒后显示领取奖励按钮问题求助
问题:YouTube视频观看满30秒后未显示Claim Reward按钮
我嵌入了YouTube视频,希望用户观看满30秒后显示Claim Reward按钮,后续逻辑交由Livewire处理。但目前观看满30秒后按钮仍未显示,请求帮助:
原代码
HTML部分
<div class="p-3"> <div class="space-y-3"> <h2 class="font-bold">{{$video->title}}</h2> <div class="relative rounded-lg overflow-hidden" style="padding-bottom: 56.25%;"> <iframe id="videoFrame" class="absolute top-0 left-0 w-full h-full rounded-lg" src="https://www.youtube.com/embed/{{$video->embed_code}}" frameborder="0" allowfullscreen></iframe> </div> <div id="claimButton" style="display: none;"> @if (!$claimed) <button wire:click="claimReward" class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"> Claim Reward </button> @else <div class="mt-2 text-green-500">Reward claimed</div> @endif </div> </div> </div>
JS部分
<script> // Initialize YouTube Player API var player; // Function to initialize the player function onYouTubeIframeAPIReady() { player = new YT.Player('videoFrame', { events: { 'onStateChange': onPlayerStateChange } }); } // Function to handle player state change function onPlayerStateChange(event) { if (event.data == YT.PlayerState.PLAYING) { // Video has started playing, start tracking time startTime = Date.now(); } else if (event.data == YT.PlayerState.ENDED) { // Video has ended, check if user can claim reward checkWatchTime(); } } // Function to check watch time and show the "Claim Reward" button function checkWatchTime() { const currentTime = Date.now(); const elapsedTime = (currentTime - startTime) / 1000; // Convert to seconds if (elapsedTime >= 30 && !claimed) { document.getElementById('claimButton').style.display = 'block'; } } </script> <script src="https://www.youtube.com/iframe_api"></script>
问题分析
- YouTube API未启用:iframe的URL缺少
enablejsapi=1参数,导致Player API无法正常控制视频,状态监听失效。 - 变量作用域错误:
startTime未声明为全局变量,在checkWatchTime函数中无法访问,会引发未定义错误。 - Livewire变量无法直接访问:JS中的
!claimed是PHP后端变量,前端JS无法直接读取,需要将其传递到前端。 - 检查逻辑不完善:仅在视频结束时检查时长,用户未看完视频但已观看满30秒时,不会触发按钮显示;且用系统时间差计算时长不准确(用户可能暂停、快进)。
修复方案
步骤1:修改iframe的src,启用YouTube API
在iframe的URL中添加enablejsapi=1参数,确保API能正常工作:
<iframe id="videoFrame" class="absolute top-0 left-0 w-full h-full rounded-lg" src="https://www.youtube.com/embed/{{$video->embed_code}}?enablejsapi=1" frameborder="0" allowfullscreen></iframe>
步骤2:传递Livewire的claimed变量到前端
在HTML中添加一个隐藏元素存储claimed值:
<!-- 添加隐藏元素存储claimed状态 --> <input type="hidden" id="claimedStatus" value="{{ $claimed ? 'true' : 'false' }}">
步骤3:修正JS逻辑,准确跟踪观看时长
使用YouTube API的getCurrentTime()获取视频实际播放进度,并且在播放过程中定时检查,确保满足条件时立即显示按钮:
<script> var player; var watchTimer; // 从隐藏元素获取claimed状态 const isClaimed = document.getElementById('claimedStatus').value === 'true'; function onYouTubeIframeAPIReady() { player = new YT.Player('videoFrame', { events: { 'onStateChange': onPlayerStateChange } }); } function onPlayerStateChange(event) { if (event.data === YT.PlayerState.PLAYING) { // 播放时启动定时检查 watchTimer = setInterval(checkWatchTime, 1000); } else { // 暂停、结束时清除定时器 clearInterval(watchTimer); } } function checkWatchTime() { const claimButton = document.getElementById('claimButton'); // 已显示按钮或已领取奖励则不再检查 if (claimButton.style.display === 'block' || isClaimed) { clearInterval(watchTimer); return; } // 获取视频当前播放进度(秒) const currentVideoTime = player.getCurrentTime(); if (currentVideoTime >= 30) { claimButton.style.display = 'block'; clearInterval(watchTimer); } } </script> <script src="https://www.youtube.com/iframe_api"></script>
步骤4:优化按钮显示逻辑(可选)
如果用户已经领取过奖励,直接让按钮区域显示“Reward claimed”而不是隐藏:
<div id="claimButton" style="display: {{ $claimed ? 'block' : 'none' }};"> @if (!$claimed) <button wire:click="claimReward" class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"> Claim Reward </button> @else <div class="mt-2 text-green-500">Reward claimed</div> @endif </div>
这样修改后,用户观看视频满30秒(无论是否看完),按钮都会自动显示;同时避免了快进、暂停等情况导致的时长计算错误,也解决了API无法正常工作的问题。
内容的提问来源于stack exchange,提问作者Niffey Dovie
相关产品推荐
相关产品推荐

