如何实现react版模拟亚马逊人机交互菜单
发表于:2025-11-16 作者:千家信息网编辑
千家信息网最后更新 2025年11月16日,小编给大家分享一下如何实现react版模拟亚马逊人机交互菜单,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!需求介绍本文都是在web端的需求参考亚马逊和京东商城的首页左侧菜单效果,实现
千家信息网最后更新 2025年11月16日如何实现react版模拟亚马逊人机交互菜单
小编给大家分享一下如何实现react版模拟亚马逊人机交互菜单,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!
需求介绍
本文都是在web端的需求
参考亚马逊和京东商城的首页左侧菜单效果,实现一个react版本的组件,以供业务使用。
我们先看下亚马逊和京东商城的效果:
亚马逊商城
京东商城
从上面的效果得出我们的菜单效果需求点:
当我们的鼠标悬浮在左侧菜单的时候,右侧会对应展示它对应的子菜单项,
当我们的鼠标在左侧菜单上下移动时,左侧可以快速切换为对应的子菜单
当我们的鼠标移动以一定的倾斜角度移动到右侧的时候,鼠标虽然会经过其它的左侧菜单,但是不会执行切换。
到目前为止,我们就搞情况了我们的需求。接下来就要去实现我们的方案了。
实现方案
要实现我们的需求,复杂点主要是在如何实现上述的需求3。需求1和需求2 的基本切换效果我就不再说了,直接进入需求3
实现需求3
如果要实现这个需求,我们需要记录鼠标从左往右(从左侧菜单区域移动到右侧菜单区域)的移动轨迹,然后根据它的移动轨迹去判断它是否是在一个三角形的区域之内,如果在的话,就不让它切换菜单。
我们先看一张图:
P1:鼠标的起始位置
P2:左侧菜单的固定点1,鼠标在左侧区域的最大位移点
P3:左侧菜单的固定点2,鼠标在左侧区域的最大位移点
M:鼠标在左侧菜单移动的结束位置

从上图我们可以得出:
如果鼠标的起始点是在 P1 的话,当鼠标移动到右侧区域,鼠标可能经过的三角形区域就是 P1-P2-P3所在的三角形,M点是鼠标的结束位置。所以我们判断鼠标的运动轨迹是否在三角形中就可以了。
部分逻辑代码
const [active, setActive] = useState(null) // 选中的菜单 const [showSub, setShowSub] = useState(false) // 是否显示子菜单 let timeout = useRef(null) // 设置延迟定时器,防止鼠标移到tab内容经过菜单时的切换 let mouseLocs = useRef([]) // 记录鼠标移动时的坐标数组 let firstSlope = useRef(null) // 菜单栏的固定点1, 根据菜单栏和内容的位置而改变 let secondSlope = useRef(null) // 菜单栏的固定点2, 根据菜单栏和内容的位置而改变 const refNavigation = useRef(null) const refNav = useRef(null) const refSubnav = useRef(null) /** * 根据内容栏相对于菜单栏的位置,判断移动过程中的点是否在三角形内 * @param {Object} p1 开始位置 * @param {Object} p2 菜单栏固定点1 * @param {Object} p3 菜单栏固定点2 * @param {Object} m 结束位置 * @return {*} */ function proPosInTriangle(p1, p2, p3, m) { // 结束时鼠标坐标位置 let x = m.x, y = m.y, // 开始鼠标坐标位置 x1 = p1.x, y1 = p1.y, // 菜单栏包裹层右上角坐标 x2 = p2.x, y2 = p2.y, // 右下角坐标 x3 = p3.x, y3 = p3.y, // (y2 - y1) / (x2 - x1)为两坐标连成直线的斜率 // 因为直线的公式为y=kx+b;当斜率相同时,只要比较 // b1和b2的差值就可以知道该点是在 // (x1,y1),(x2,y2)的直线的哪个方向 // 当r1大于0,说明该点在直线右侧,其它以此类推 r1 = y - y1 - ((y2 - y1) / (x2 - x1)) * (x - x1), r2 = y - y2 - ((y3 - y2) / (x3 - x2)) * (x - x2), r3 = y - y3 - ((y1 - y3) / (x1 - x3)) * (x - x3), compare compare = r1 * r2 * r3 < 0 && r1 > 0 // 返回是否在三角形内的结果 return compare } /** * 获取元素相对于浏览器左上角的坐标位置,为正值 * @param element * @return {{x: Number, y: Number}} * @constructor */ function LocFromdoc(element) { const { x, y, width, height } = element.getBoundingClientRect() return { x: x, y: y, width, height, } } /** * 记录元素的位置信息 * @param element * @return {{top: *, topAndHeight: number, left: *, leftAndWidth: number}} */ function getInfo(element) { const location = LocFromdoc(element) return { top: location.y, topAndHeight: location.y + element.offsetHeight, // offsetHeight 元素的像素高度, 高度包含该元素的垂直内边距和边框,且是一个整数 left: location.x, leftAndWidth: location.x + element.offsetWidth, } } /** * 根据内容栏相对于菜单栏的位置, 返回菜单栏的固定点1,和固定点2,保存在this.firstSlope和this.secondSlope对象里 * 即 左侧菜单栏的右上角和右下角的位置 */ function ensureTriangleDots() { // 获取菜单栏的位置 const info = getInfo(refNav.current) const x1 = info.leftAndWidth const y1 = info.top const x2 = x1 const y2 = info.topAndHeight firstSlope.current = { x: x1, y: y1, } secondSlope.current = { x: x2, y: y2, } } const onMouseOver = useCallback( obj => { let diff try { // 是否在指定三角形内 diff = proPosInTriangle( mouseLocs.current[0], firstSlope.current, secondSlope.current, mouseLocs.current[2] ) } catch (ex) {} // 是就启动延迟显示, // 否则不延迟 if (diff) { timeout.current = setTimeout(() => { setActive(obj.key) setShowSub(true) }, 300) } else { setActive(obj.key) setShowSub(true) } }, [mouseLocs, timeout] ) const onMouseEnter = () => { // 计算位置 if (refNav.current) { ensureTriangleDots() } setShowSub(true) } // 移出菜单所在区域 const onMouseLeave = () => { if (refSubnav.current) { setActive(null) setShowSub(false) } } // 记录鼠标在菜单栏中移动的最后三个坐标位置 const onMousemove = event => { mouseLocs.current.push({ x: event.pageX, y: event.pageY, }) if (mouseLocs.current.length > 3) { // 移除超过三项的数据 mouseLocs.current.shift() } } // 鼠标移出的时候,清除延时器 const onMouseout = () => { if (timeout.current) { clearTimeout(timeout.current) } }实现效果
看完了这篇文章,相信你对"如何实现react版模拟亚马逊人机交互菜单"有了一定的了解,如果想了解更多相关知识,欢迎关注行业资讯频道,感谢各位的阅读!
菜单
鼠标
位置
需求
移动
区域
固定点
坐标
三角形
三角
效果
亚马
亚马逊
内容
右侧
是在
切换
元素
商城
直线
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
交通广播服务器繁忙
数据库nosql特点
网络安全女工程师
国家网络安全防范
软件开发技术基础 土木
幼儿园国家网络安全宣传视频
图计算数据库
引文数据库有哪些特点
数据库代码用处
钢铁行业数据库备份技术原理
洛阳云端网络技术有限公司
零基础网络安全硕士
青岛御风启航网络技术
pg_ctl关闭数据库失败
专用软件开发功能清单
找回服务器的管理账号密码
网络技术零基础课程
王者荣耀服务器分很多区
网络安全活动方案学校
方腾网络技术有限公司
网络安全辩论赛四辩
控制网络技术
日常生活怎样做好网络安全
濡沫江湖官方服务器
云服务器需要搭配云安全产品吗
软件开发行业五行属金吗
数据库的jdbc怎样配置
软件开发 长期合同
数据库 路由器
网络技术零基础课程