如何实现react版模拟亚马逊人机交互菜单
发表于:2024-11-22 作者:千家信息网编辑
千家信息网最后更新 2024年11月22日,小编给大家分享一下如何实现react版模拟亚马逊人机交互菜单,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!需求介绍本文都是在web端的需求参考亚马逊和京东商城的首页左侧菜单效果,实现
千家信息网最后更新 2024年11月22日如何实现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安全错误
数据库的锁怎样保障安全
直销网络技术是什么
学习软件和服务器的设计
恒昌利通软件开发
30岁从事网络安全
数据库概论 期末
用io流实现数据库数据添加
excel服务器平台
网络安全的句子短
新田人民医院网络安全
软件开发技术企业发展情况
护苗 网络安全课堂
IBM服务器装lunx系统
软件开发商如何做生产
网络安全指数是什么意思
想要学软件开发报哪个专业
关于校园网络安全事件的新闻
广州楼控管理软件开发价位
统筹软件开发一般要多少钱
现代通信网络技术 ppt
win7如何建立服务器
手机淘宝服务器出错
斑马网络技术有限公司布局
四川电商软件开发哪家专业
服务器管理推荐什么软件
贾汪区网络营销软件开发常见问题
地信数据库
想要学软件开发报哪个专业
oracle数据库密码
数据库原理群
棋牌游戏软件开发员