美文网首页
京东大导航——预判用户行为(二)

京东大导航——预判用户行为(二)

作者: 如意同学Try | 来源:发表于2017-12-07 18:57 被阅读0次

在上篇京东大导航——预判用户行为(一)中讲到,我们对导航的切换操作设置了延时,解决了移入子菜单时不执行导航切换的问题。但同时引入了新的问题,即导航的延时造成了切换不流程。

如何才能做到,即保证用户进入子菜单的便捷,又能保证用户切换主导航的流程呢?


不防做这样的假设,如图

pic01.png

其中图中的O点为鼠标的起始位置。

若鼠标移动路径位于阴影内部,就认为用户想要移动到当前子菜单,如路径O->p1

若鼠标移动路径位于阴影外部,就认为用户想要切换菜单,如路径O->p2

于是问题就转化成了,判断鼠标移动的方向是否位于阴影部分内部,如何判断一个点位于一个三角形的内部(P点位于三角形0AB内部),具体实现则用到了数学上的向量积问题。

数学思路:判断一个点是否位于一个三角形的内部
pic02.png

同向法:沿着三角形三边走一圈A——>B——>C——>A,在AB边时,点P和C点在同侧;在BC边时,点P和A点在同侧;在CA边时,点P和B点在同侧;如果点P始终个第三个点保持同侧,则说明该点位于三角形内;若某一时刻两点位于两侧,那么该点在三角形外

那么问题又转化成了,判断两个点是否位于一条线段的同侧

这会儿就能使用向量积了。

pic03.png

如图,将向量PO和向量OA做叉乘,再将向量BO和OA做叉乘,如果两个叉乘的结果符号相同,说明两个点位于OA的同一侧

//向量积公式
 OA × PO = (p.x – a.x)(p.y – a.y) – (p.y – a.y)(p.x – a.x);

对三边都进行判断,判断函数

function flag(OA,PO,BO){
    var flag = -1;
    var a = OA × PO;
    var b = OA × BO;
    if(a*b< 0 ){
        //B,P两点不同向
        flag = -1;
    }else{
        //B,P两点同向
        flag = 1;
    }
        return flag
}
var x = flag(OA,PO,BO);
var y = flag(AB,PA,OA);
var z = flag(BO,PB,AB);
if(x == 1 && y == 1 && z == 1){
   //点在三角形内部
    //用户想进入子菜单
    //菜单切换延迟
}else{
    //点在三角形外部
    //用户想切换菜单
    //菜单切换不延迟
}

最终实现代码

//获取四个点的坐标
var topLeft = {
        x: sub-nav.offset().left,
        y: sub-nav.offset().top
    }
var bottomLeft = {
    x:sub-nav.offset().left,
    y:sub-nav.offset().top + sub-nav.height()
}
//O点为鼠标起始坐标,P点设置为鼠标移动后的第二个点
var mouseTrack = []; //跟踪鼠标坐标数组
$("#main-nav").on('mousemove', moveHanlder) //监听鼠标移动事件
var moveHanlder = function(e) {
    mouseTrack.push({
        x:  e.pageX,
        y:  e.pageY
    });
    if (mouseTrack.length > 3) {
        //取鼠标经过的2个点即可
        mouseTrack.shift(); 
    };
}
var O = mouseTrack[0];
var P = mouseTrack[1];

到目前为止已获取了四个点的坐标,下面就是对四个坐标进行各种数学运算

第一步:生成向量函数

function vector(a,b){
    //传入两个点,生成这两个点构成的向量
    return {
        x:a.x-b.x,
        y:a.y-b.y
    }
}

第二步:获取向量积函数

function vectorProduct(v1,v2){
    //传入两个向量,获取向量积
    var mul = v1.x * v2.y - v2.x * v1.y;
    return mul;
}

第三步:传入一条向量和两个点对向量积进行是否同向判断,在上文示例代码基础上改进

function flag(v,O,P){
    var flag = -1;
    var PA = vector(P,A);
    var OA = vector(O,A);
    var mul1 = vectorProduct(PA,v);
    var mul2 = vectorProduct(OA,v);
    if(mul1 * mul2< 0 ){
        //两点不同向
        flag = -1;
    }else{
        //两点同向
        flag = 1;
    }
        return flag
}

第四部:传入四个点,调用公式,判断是否需要延时

function needDelay(A,B,O,P){
    var V1 = vector(A,B);
    var V2 = vector(B,O);
    var V3 = vector(O,A);
    var x = flag(V1,O,P);
    var y = flag(V2,A,P);
    var z = flag(V3,B,P);
    if(x == 1 && y == 1 && z == 1){
        return true;
    }else{
         return false;
    }
}

再结合上篇京东大导航——预判用户行为(一)的代码,就能完成最终效果

if(needDelay){
    setTimeout(function(){
        //导航切换代码
    },500);
}else{
    //导航切换代码
}

效果图GIF:

最终效果

大功告成!

刺不刺激,惊不惊喜

源码见个人github地址

相关文章

网友评论

      本文标题:京东大导航——预判用户行为(二)

      本文链接:https://www.haomeiwen.com/subject/ooejixtx.html