如何实现react版模拟亚马逊人机交互菜单
发表于:2025-02-04 作者:千家信息网编辑
千家信息网最后更新 2025年02月04日,小编给大家分享一下如何实现react版模拟亚马逊人机交互菜单,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!需求介绍本文都是在web端的需求参考亚马逊和京东商城的首页左侧菜单效果,实现
千家信息网最后更新 2025年02月04日如何实现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安全错误
数据库的锁怎样保障安全
有房贷牌照互联网金融科技公司
软件开发未验收计入在建工程
个人网络安全注意事项清单
忻州软件开发分类
网络技术对教学管理的重要性
计算机网络技术必备知识网页
dell服务器esxi升级
数据库如何使用print语句
合肥服务器机柜企业
美国综合网络安全倡议
江油论坛网络技术男
拼多多搬家软件开发
网络安全与管理的英语
合肥fil服务器加盟
微信服务器ip
幽冥传奇数据库密码在哪改
北京华为服务器维修多少钱
软件开发不接受实施
浙江app软件开发的公司
ip网络技术+下载
web外贸云服务器
无线网络技术衰减失真
网络安全信息化办公室电话
软件开发平台 质保期
未转变者服务器没有
hp服务器故障查看
天使之战抖音专区哪个服务器好
无锡华为服务器维修地点
华为服务器最高能达到多少度
纸箱软件开发技术