解决IE中Resize事件重复提交多次的问题(转)

本文介绍了一个jQuery插件jquery.wresize.js,用于解决IE6下window.resize事件重复触发的问题。该插件能有效降低工作量,通过在事件处理中加入判断逻辑,避免事件的误触发。

最近项目中用到resize事件来控制页面的元素高度,相信这个功能并不少见。当问题就出现了,偶尔发现在IE6下,页面会等待比较久甚至出现假死状态。在DEBUG的过程中发现resize事件触发后,被重复执行了多次。在网上搜索了一下解决方案,分享下这个比较不错的解决办法。

 

PS:若项目是使用到jQuery的话,可以最大限度的降低工作量了。

 

-----------------------------以下是转载内容

 

 

作者:Andrea Ercolino

In IE the window resize event is fired multiple times per actual resize: it is a well known issue for IE6 and IE7, but they misbehave along different patterns. Actually it seems that IE6 is worse than IE7.

After quite a long session of R&D, I've got to a pretty good solution, in the form of a jQuery plugin:

jquery.wresize.js(作者网站的原插件地址在此)。

 

/*  
===============================================================================
WResize is the jQuery plugin for fixing the IE window resize bug
...............................................................................
                                               Copyright 2007 / Andrea Ercolino
-------------------------------------------------------------------------------
LICENSE: http://www.opensource.org/licenses/mit-license.php
WEBSITE: http://noteslog.com/
===============================================================================
*/
 
( function( $ ) 
{
	$.fn.wresize = function( f ) 
	{
		version = '1.1';
		wresize = {fired: false, width: 0};
 
		function resizeOnce() 
		{
			if ( $.browser.msie )
			{
				if ( ! wresize.fired )
				{
					wresize.fired = true;
				}
				else 
				{
					var version = parseInt( $.browser.version, 10 );
					wresize.fired = false;
					if ( version < 7 )
					{
						return false;
					}
					else if ( version == 7 )
					{
						//a vertical resize is fired once, an horizontal resize twice
						var width = $( window ).width();
						if ( width != wresize.width )
						{
							wresize.width = width;
							return false;
						}
					}
				}
			}
 
			return true;
		}
 
		function handleWResize( e ) 
		{
			if ( resizeOnce() )
			{
				return f.apply(this, [e]);
			}
		}
 
		this.each( function() 
		{
			if ( this == window )
			{
				$( this ).resize( handleWResize );
			}
			else
			{
				$( this ).resize( f );
			}
		} );
 
		return this;
	};
 
} ) ( jQuery );

 

If you want to try it, here is a test page, where a div is automatically resized when the window is resized.

 

 

 

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" style="overflow:hidden;"> 
 <head> 
  <title> test window resize </title> 
 
<script type="text/javascript" src="http://jquery.com/src/jquery-latest.pack.js"></script> 
<script type="text/javascript" src="jquery.wresize.js"></script> 
 
 
<script type="text/javascript"> 
jQuery( function( $ )  
{ 
    function content_resize()  
    { 
        var w = $( window ); 
        var H = w.height(); 
        var W = w.width(); 
        $( '#content' ).css( {width: W-20, height: H-20} ); 
    } 
 
    $( window ).wresize( content_resize ); 
 
    content_resize(); 
} ); 
</script> 
 
 </head> 
 
 <body> 
  
<div id="content" style="border: 1px dashed silver; position:absolute; overflow:auto;"> 
test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test  
</div> 
 
 </body> 
</html>
 

 

 

import React, { useEffect, useRef, useState, useCallback, forwardRef, useImperativeHandle } from 'react'; import videojs from 'video.js'; import 'video.js/dist/video-js.css'; import 'videojs-playlist'; import './PlaylistButton'; import './index.scss'; // 扩展videojs类型 declare global { interface Window { videojs: any; } } // 循环播放模式枚举 export enum LoopMode { NONE = 'none', // 不循环 SINGLE = 'single', // 单视频循环 SEQUENCE = 'sequence', // 顺序循环整个播放列表 SHUFFLE = 'shuffle', // 随机循环整个播放列表 } // 视频项接口 export interface VideoItem { sources: Array<{ src: string; type: string; }>; poster?: string; title?: string; summary?: string; } // 组件属性接口 interface MifcVideoProps { videoList: VideoItem[]; autoplay?: boolean; loop?: boolean | LoopMode; // 支持布尔值或循环模式 width?: string | number; height?: string | number; onVideoChange?: (index: number, isAutoPlay?: boolean) => void; onPlay?: () => void; onPause?: () => void; onEnded?: () => void; onRef?: (ref: MifcVideoRef) => void; children?: React.ReactNode; } // 组件引用接口 export interface MifcVideoRef { playByUrl: (videoUrl: string) => void; } const MifcVideo = forwardRef<MifcVideoRef, MifcVideoProps>( ( { videoList, autoplay = false, loop = LoopMode.SEQUENCE, // 默认顺序循环 width = '100%', height = '100%', onVideoChange, onPlay, onPause, onEnded, onRef, children, }, ref, ) => { const videoRef = useRef<HTMLVideoElement>(null); const playlistRef = useRef<HTMLDivElement>(null); const playerRef = useRef<any>(null); const hideTimeoutRef = useRef<NodeJS.Timeout | null>(null); const originalPlaylistRef = useRef<VideoItem[]>([]); const [isPlaylistVisible, setIsPlaylistVisible] = useState(false); const isPlaylistVisibleRef = useRef(isPlaylistVisible); const [currentVideoIndex, setCurrentVideoIndex] = useState(0); const [isPlaying, setIsPlaying] = useState(false); const [autoplayBlocked, setAutoplayBlocked] = useState(false); const [isPlaylistScrollable, setIsPlaylistScrollable] = useState(false); const [isMouseNearLeftEdge, setIsMouseNearLeftEdge] = useState(false); const [showControls, setShowControls] = useState(false); const controlsTimeoutRef = useRef<NodeJS.Timeout | null>(null); const [isMobile, setIsMobile] = useState(false); const isAutoPlayingRef = useRef(false); const touchStartRef = useRef({ x: 0, y: 0 }); const [isFullscreen, setIsFullscreen] = useState(false); // 新增:跟踪全屏状态 // 暴露方法给父组件 useImperativeHandle(ref, () => ({ playByUrl: (videoUrl: string) => { if (playerRef.current) { // 设置自动播放标记 isAutoPlayingRef.current = true; // 创建临时视频项 const tempVideo: VideoItem = { sources: [{ src: videoUrl, type: 'video/mp4' }], title: 'AI推荐视频', summary: '正在播放AI推荐的视频', }; // 将临时视频添加到播放列表并播放 const currentPlaylist = (playerRef.current as any).playlist(); const videoIndex = currentPlaylist.findIndex((video: VideoItem) => video.sources.some((source) => source.src === videoUrl), ); if (videoIndex >= 0) { // 如果视频已在播放列表中,直接切换到该视频 switchVideo(videoIndex); // onVideoChange 会通过 playlistitem 事件自动触发 } else { // 如果视频不在播放列表中,添加到列表并播放 const newPlaylist = [...currentPlaylist, tempVideo]; (playerRef.current as any).playlist(newPlaylist, newPlaylist.length - 1); // onVideoChange 会通过 playlistitem 事件自动触发 } // 尝试播放 const playPromise = playerRef.current.play(); if (playPromise !== undefined) { playPromise.catch((error: any) => { console.warn('播放视频失败:', error); }); } } }, })); // 检测是否为移动端 const checkMobile = () => { const userAgent = navigator.userAgent.toLowerCase(); const isMobileDevice = /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent); const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0; const isMobileResult = isMobileDevice || isTouchDevice; setIsMobile(isMobileResult); return isMobileResult; }; useEffect(() => { checkMobile(); window.addEventListener('resize', checkMobile); return () => window.removeEventListener('resize', checkMobile); }, []); // 显示控制器 const showControlsWithTimeout = useCallback(() => { setShowControls(true); // 清除之前的定时器 if (controlsTimeoutRef.current) { clearTimeout(controlsTimeoutRef.current); } // 3秒后自动隐藏控制器 controlsTimeoutRef.current = setTimeout(() => { setShowControls(false); }, 3000); }, []); // 隐藏控制器 const hideControls = useCallback(() => { setShowControls(false); if (controlsTimeoutRef.current) { clearTimeout(controlsTimeoutRef.current); controlsTimeoutRef.current = null; } }, []); // 自定义setter函数,同时更新状态和ref const setIsPlaylistVisibleWithRef = useCallback((value: boolean) => { setIsPlaylistVisible(value); isPlaylistVisibleRef.current = value; // 立即更新ref }, []); // 显示播放列表 //showPlaylist`函数不能添加isMobile为依赖项,因为当前函数被用作useEffect的依赖项,而该useEffect用于初始化播放器。当`isMobile`状态改变时,`showPlaylist`函数会重新创建,导致`useEffect`依赖项变化,从而重新初始化播放器。在移动端,可能由于重新初始化播放器时自动播放被阻止,导致黑屏 const showPlaylist = useCallback(() => { const currentVisible = isPlaylistVisibleRef.current; const mobileIsNo = checkMobile(); if (mobileIsNo) { if (currentVisible) { setIsPlaylistVisibleWithRef(false); } else { setIsPlaylistVisibleWithRef(true); } } else { setIsPlaylistVisible(true); } // 清除之前的定时器 if (hideTimeoutRef.current) { clearTimeout(hideTimeoutRef.current); } if (!mobileIsNo) { // 1.5秒后自动隐藏 hideTimeoutRef.current = setTimeout(() => { setIsPlaylistVisible(false); }, 1500); } }, []); // 隐藏播放列表 const hidePlaylist = useCallback((e?: React.MouseEvent | React.TouchEvent) => { // 阻止事件冒泡到父元素,避免触发视频播放/暂停 if (e) { e.stopPropagation(); e.preventDefault(); // 阻止默认行为 } const mobileIsNo = checkMobile(); if (mobileIsNo) { setIsPlaylistVisibleWithRef(false); } else { setIsPlaylistVisible(false); } if (hideTimeoutRef.current) { clearTimeout(hideTimeoutRef.current); hideTimeoutRef.current = null; } }, []); // 切换视频 const switchVideo = useCallback((index: number) => { if (playerRef.current && playerRef.current.playlist) { playerRef.current.playlist.currentItem(index); const mobileIsNo = checkMobile(); // setCurrentVideoIndex 和 onVideoChange 会通过 playlistitem 事件自动触发 // 不需要在这里重复调用 // 重置隐藏定时器 if (hideTimeoutRef.current) { clearTimeout(hideTimeoutRef.current); } hideTimeoutRef.current = setTimeout(() => { if (mobileIsNo) { setIsPlaylistVisibleWithRef(false); } else { setIsPlaylistVisible(false); } }, 1000); } }, []); // 设置循环播放模式 const setLoopMode = useCallback((mode: LoopMode) => { if (!playerRef.current) return; switch (mode) { case LoopMode.NONE: // 不循环播放 (playerRef.current as any).playlist.repeat(false); (playerRef.current as any).playlist.autoadvance(0); break; case LoopMode.SINGLE: // 单视频循环 (playerRef.current as any).playlist.repeat(false); (playerRef.current as any).playlist.autoadvance(0); // 设置videojs的loop属性 playerRef.current.loop(true); break; case LoopMode.SEQUENCE: // 顺序循环整个播放列表 (playerRef.current as any).playlist.repeat(true); (playerRef.current as any).playlist.autoadvance(0); playerRef.current.loop(false); break; case LoopMode.SHUFFLE: // 随机循环整个播放列表 (playerRef.current as any).playlist.repeat(false); (playerRef.current as any).playlist.autoadvance(0); playerRef.current.loop(false); // 启用随机播放 (playerRef.current as any).playlist.shuffle({ rest: false }); break; } }, []); // 初始化播放器 useEffect(() => { if (!videoRef.current || !videoList.length) return; // 保存原始播放列表 originalPlaylistRef.current = [...videoList]; // 初始化videojs播放器 const player = videojs(videoRef.current, { controls: true, autoplay, loop: false, // 初始不设置循环,由循环模式控制 fluid: true, responsive: true, playbackRates: [0.5, 1, 1.25, 1.5, 2], playsinline: true, // 防止移动端自动全屏 controlBar: { children: [ 'playToggle', { name: 'volumePanel', inline: false, }, 'currentTimeDisplay', 'timeDivider', 'durationDisplay', 'progressControl', 'playbackRateMenuButton', 'playlistButton', 'fullscreenToggle', ], }, }); playerRef.current = player; // 添加播放列表组件 playerRef.current.addChild('Component', { el: playlistRef.current, }); // 等待播放器准备就绪后初始化播放列表 player.ready(() => { // 使用正确的播放列表API初始化 (player as any).playlist(videoList, 0); // 设置循环播放模式 const loopMode = typeof loop === 'boolean' ? (loop ? LoopMode.SEQUENCE : LoopMode.NONE) : loop; setLoopMode(loopMode); // 设置自动播放 if (autoplay) { // 确保播放列表已加载 setTimeout(() => { try { (player as any).playlist.first(); const playPromise = player.play(); // 处理自动播放可能被浏览器阻止的情况 if (playPromise !== undefined) { playPromise.catch((error: any) => { console.warn('自动播放被阻止:', error); setAutoplayBlocked(true); }); } } catch (error) { console.warn('自动播放失败:', error); setAutoplayBlocked(true); } }, 100); } }); // 设置事件监听器 player.on('play', () => { setIsPlaying(true); // showPlaylist(); onPlay?.(); }); player.on('pause', () => { setIsPlaying(false); onPause?.(); }); player.on('ended', () => { setIsPlaying(false); onEnded?.(); isAutoPlayingRef.current = false; }); player.on('timeupdate', () => { const currentTime = player.currentTime(); const duration = player.duration(); // 在视频即将结束时显示播放列表(剩余3秒) if (duration && currentTime && currentTime > 0 && duration - currentTime <= 3) { // 注释掉这里,因为会触发多次,直接播放完下一个播放就行不需要展开播放列表 // showPlaylist(); } }); // 播放列表项变化事件 player.on('playlistitem', (event: any, data: any) => { const currentIndex = (player as any).playlist.currentItem(); setCurrentVideoIndex(currentIndex); onVideoChange?.(currentIndex, isAutoPlayingRef.current); // 根据自动播放标记传递参数 // // 重置自动播放标记 // isAutoPlayingRef.current = false; }); // 播放列表按钮点击事件 player.on('playlistButtonClick', (e?: React.MouseEvent | React.TouchEvent) => { // 彻底阻止事件传播 if (e) { e.stopPropagation(); e.preventDefault(); } showPlaylist(); }); // 监听全屏变化事件 player.on('fullscreenchange', () => { setIsFullscreen(player?.isFullscreen() || false); }); // 清理函数 return () => { if (player) { player.dispose(); } if (hideTimeoutRef.current) { clearTimeout(hideTimeoutRef.current); } if (playerRef.current) { playerRef.current.dispose(); playerRef.current = null; } }; }, [videoList, autoplay, loop, showPlaylist, onVideoChange, onPlay, onPause, onEnded, setLoopMode]); // 播放列表点击事件处理 const handlePlaylistItemClick = useCallback( (index: number, e?: React.MouseEvent | React.TouchEvent) => { if (e) { e.stopPropagation(); // 阻止事件冒泡 e.preventDefault(); // 阻止默认行为 } switchVideo(index); isAutoPlayingRef.current = false; }, [switchVideo], ); // 播放列表项的触摸事件处理 const handlePlaylistItemTouchStart = useCallback((e: React.TouchEvent, index: number) => { // 记录触摸起始位置 const touch = e.touches[0]; touchStartRef.current = { x: touch.clientX, y: touch.clientY, }; e.stopPropagation(); }, []); // 播放列表项的触结束事件处理 const handlePlaylistItemTouchEnd = useCallback( (e: React.TouchEvent, index: number) => { // 计算触摸移动距离 const touch = e.changedTouches[0]; const deltaX = Math.abs(touch.clientX - touchStartRef.current.x); const deltaY = Math.abs(touch.clientY - touchStartRef.current.y); // 只有在移动距离小于阈值时才触发点击事件 // 这样可以防止滑动时误触发点击 if (deltaX < 10 && deltaY < 10) { handlePlaylistItemClick(index, e); } e.stopPropagation(); }, [handlePlaylistItemClick], ); // 播放列表浮层的点击处理 const handlePlaylistOverlayClick = useCallback((e: React.MouseEvent | React.TouchEvent) => { e.stopPropagation(); }, []); // 播放列表鼠标进入事件 const handlePlaylistMouseEnter = useCallback(() => { if (hideTimeoutRef.current) { clearTimeout(hideTimeoutRef.current); hideTimeoutRef.current = null; } // 在播放列表区域时保持控制器显示 showControlsWithTimeout(); }, [showControlsWithTimeout]); // 播放列表鼠标离开事件 const handlePlaylistMouseLeave = useCallback(() => { // 只有在鼠标不在左侧边缘时才启动自动隐藏定时器 const mobileIsNo = checkMobile(); if (!isMouseNearLeftEdge) { hideTimeoutRef.current = setTimeout(() => { if (mobileIsNo) { setIsPlaylistVisibleWithRef(false); } else { setIsPlaylistVisible(false); } }, 1000); } }, [isMouseNearLeftEdge]); // 处理用户交互开始播放 const handleUserInteraction = useCallback(() => { if (autoplayBlocked && playerRef.current) { setAutoplayBlocked(false); const playPromise = playerRef.current.play(); if (playPromise !== undefined) { playPromise.catch((error: any) => { console.warn('播放失败:', error); }); } } }, [autoplayBlocked]); // 检测播放列表内容是否可滚动 const checkPlaylistScrollable = useCallback(() => { const playlistContent = document.querySelector('.playlist-content'); if (playlistContent) { const isScrollable = playlistContent.scrollHeight > playlistContent.clientHeight; setIsPlaylistScrollable(isScrollable); } }, []); // 处理播放器点击事件 const handlePlayerClick = useCallback( (event?: React.MouseEvent | React.TouchEvent) => { // 如果是移动端且是触摸事件,不处理点击(由触摸事件处理) if (isMobile && event && 'touches' in event) { return; } // 检查触摸目标是否是播放列表按钮或相关元素 const target = event?.target as Element; const isPlaylistButton = target?.closest('.vjs-playlist-button'); if (playerRef.current && !isPlaylistButton) { if (isPlaying) { playerRef.current.pause(); } else { playerRef.current.play(); } } }, [isPlaying, isMobile], ); // 处理触摸开始事件(移动端) const handleTouchStart = useCallback( (event: React.TouchEvent) => { // 显示控制器 showControlsWithTimeout(); // 检查触摸目标是否是播放列表按钮或相关元素 const target = event.target as Element; const isPlaylistButton = target.closest('.vjs-playlist-button') || target.closest('.playlist-toggle-btn') || target.closest('.playlist-overlay'); // 在移动端触摸播放视频时关闭侧边栏,但排除播放列表相关元素 if (isMobile && !isPlaylistButton) { hidePlaylist(); } }, [showControlsWithTimeout, isMobile], ); // 处理触摸结束事件(移动端) const handleTouchEnd = useCallback( (event: React.TouchEvent) => { // 检查是否在播放器区域点击(非控制栏区域) const touch = event.changedTouches[0]; const container = event.currentTarget; const rect = container.getBoundingClientRect(); const touchY = touch.clientY - rect.top; // 检查是否点击在控制栏区域(底部20%区域) const isInControlBarArea = touchY > rect.height * 0.8; // 只有在非控制栏区域点击时才触发播放/暂停 if (!isInControlBarArea) { handlePlayerClick(); } }, [handlePlayerClick], ); // 处理触摸移动事件(移动端) const handleTouchMove = useCallback((event: React.TouchEvent) => { // 移动端不需要处理触摸移动事件 }, []); // 处理鼠标移动到左侧边缘(仅桌面端) const handleMouseMove = useCallback( (event: React.MouseEvent) => { const container = event.currentTarget; const rect = container.getBoundingClientRect(); const mouseX = event.clientX - rect.left; const edgeThreshold = 50; // 左侧边缘检测区域宽度 // 显示控制器 showControlsWithTimeout(); // 仅在桌面端处理左侧边缘检测 if (!isMobile) { if (mouseX <= edgeThreshold) { setIsMouseNearLeftEdge(true); // 只有在播放列表未显示且不在播放列表区域内时才显示 if (!isPlaylistVisible) { showPlaylist(); } } else { setIsMouseNearLeftEdge(false); } } }, [isPlaylistVisible, showPlaylist, showControlsWithTimeout, isMobile], ); // 处理鼠标离开容器(仅桌面端) const handleMouseLeave = useCallback( (event: React.MouseEvent) => { // 仅在桌面端处理鼠标离开事件 if (!isMobile) { setIsMouseNearLeftEdge(false); hideControls(); } }, [hideControls, isMobile], ); // 检测播放列表可滚动状态 useEffect(() => { if (isPlaylistVisible) { // 延迟检测,确保DOM已更新 setTimeout(checkPlaylistScrollable, 100); // 监听窗口大小变化 window.addEventListener('resize', checkPlaylistScrollable); return () => window.removeEventListener('resize', checkPlaylistScrollable); } }, [isPlaylistVisible, videoList, checkPlaylistScrollable]); // 控制videojs控制器的显示/隐藏 useEffect(() => { if (playerRef.current) { const controlBar = playerRef.current.controlBar; if (controlBar) { if (showControls) { controlBar.el().classList.add('vjs-control-bar-visible'); } else { controlBar.el().classList.remove('vjs-control-bar-visible'); } } } }, [showControls]); // 组件卸载时清理定时器 useEffect(() => { return () => { if (controlsTimeoutRef.current) { clearTimeout(controlsTimeoutRef.current); } }; }, []); return ( <div className={`mifc-video-container ${isFullscreen ? 'fullscreen-mode' : ''}`} style={{ width, height }} onMouseMove={handleMouseMove} onMouseLeave={handleMouseLeave} onTouchStart={handleTouchStart} onTouchEnd={handleTouchEnd} onTouchMove={handleTouchMove} onContextMenu={(e) => e.preventDefault()}> {/* 视频播放器 */} <div className={`video-player-wrapper ${!isMobile && isMouseNearLeftEdge ? 'edge-hover' : ''}`} onClick={handlePlayerClick} style={{ touchAction: 'manipulation' }}> <video ref={videoRef} className="video-js vjs-default-skin" data-setup="{}" muted={autoplay} playsInline onContextMenu={(e) => e.preventDefault()} style={{ pointerEvents: 'auto' }} /> {/* 自动播放被阻止时的提示 */} {autoplayBlocked && ( <div className="autoplay-blocked-overlay" onClick={handleUserInteraction}> <div className="autoplay-blocked-content"> <div className="autoplay-icon">▶️</div> <div className="autoplay-text"> <h3>点击开始播放</h3> <p>浏览器阻止了自动播放,请点击此处开始播放</p> </div> </div> </div> )} {/* 暂停时显示的播放按钮 {!isPlaying && !autoplayBlocked && ( <div className="play-button-overlay" onClick={handlePlayerClick}> <div className="play-button"> <svg width="80" height="80" viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="40" cy="40" r="40" fill="rgba(0, 0, 0, 0.7)"/> <path d="M32 24L56 40L32 56V24Z" fill="white"/> </svg> </div> </div> )} */} </div> {/* 播放列表浮层 */} <div ref={playlistRef} className={`playlist-overlay ${isPlaylistVisible && !isFullscreen ? 'visible' : ''} ${isFullscreen ? 'fullscreen' : ''} ${isPlaylistVisible && isFullscreen ? 'fullscreen-visible' : ''}`} onMouseEnter={handlePlaylistMouseEnter} onMouseLeave={handlePlaylistMouseLeave} onClick={handlePlaylistOverlayClick} // 阻止播放列表浮层的点击事件冒泡 onTouchStart={handlePlaylistOverlayClick} // 阻止触摸事件冒泡 onTouchEnd={handlePlaylistOverlayClick} // 添加触摸结束处理 > <div className={`playlist-content ${isPlaylistScrollable ? 'scrollable' : ''}`} onClick={handlePlaylistOverlayClick} // 内容区域也阻止点击 onTouchStart={handlePlaylistOverlayClick} // 内容区域也阻止触摸 > {videoList.map((video, index) => ( <div key={index} className={`playlist-item ${index === currentVideoIndex ? 'active' : ''}`} onClick={(e) => handlePlaylistItemClick(index, e)} onTouchStart={(e) => handlePlaylistItemTouchStart(e, index)} // 添加触摸开始处理 onTouchEnd={(e) => handlePlaylistItemTouchEnd(e, index)} // 添加触摸结束处理 > <div className="playlist-item-content"> <div className="playlist-item-title">{video.title || `视频 ${index + 1}`}</div> <div className="playlist-item-summary">{video.summary || '点击播放视频'}</div> </div> </div> ))} </div> {/* 右侧收起按钮 */} <div className="playlist-toggle-btn" onClick={hidePlaylist} onTouchEnd={hidePlaylist} // 添加触摸事件处理 ></div> </div> </div> ); }, ); export default MifcVideo; 当前代码中的showPlaylist函数在pc中会触发两次
08-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值