美文网首页
电视EPG(WEB)页面上的焦点导航方案

电视EPG(WEB)页面上的焦点导航方案

作者: fengfancky | 来源:发表于2019-04-18 11:46 被阅读0次

    使用HTML、JS等相关Web前端技术基于Android机顶盒开发电视EPG页面。由于电视端使用遥控器进行焦点控制,我们需要对焦点导航进行处理,使用户进行便捷 的交互。

    在Android开发中有一个默认的导航规则,开发者设置好相关属性之后可以通过遥控器导航。在操作遥控器后,它会使当前元素的目标方向上的最近元素获取焦点。web没有这样的规则,我们需要建立一个类似的规则。对当前获得焦点元素在使用遥控器操作(上、下、左、右键)时,使当前元素在上、下、左、右方向对应的元素获得焦点。

    准备

    1.设置元素的tabindex属性值为-1

    <div tabindex=-1 class="item" id="nav_item1" >首页</div>
    

    tabIndex属性可以设置键盘中的TAB键在页面元素中的移动顺序,即焦点的顺序。默认情况下,普通元素无法获取焦点,只有链接、表单等元素可以获取焦点。所以普通元素需要设置tabindex属性,再使用foucs()方法即可。当tabindex的值 >= 0时,可以通过Tab键获取焦点,而tabindex = -1时Tab键不能获取焦点,只能通过JS获取。当tabindex的值不为-1的时候,使用遥控器操作时焦点获取位置不符合预期。

    注:给元素添加样式 outline: none; 用于去除默认样式。

    给需要获取焦点的元素都添加一个相同的类名,如 class="item",将需要获取焦点的元素都筛选出来。

    2.获取焦点

    完成上诉步骤后,通过调用focus()方法给目标元素设置焦点。如:

    view.focus();
    

    3.获取当前焦点元素

    通过 document.activeElement 可以得到当前界面正获得焦点的元素,十分重要,在建立导航规则后,我们需要通过该元素得到它在各个方向上对应的元素。

    建立导航规则

    我们需要建立这样一个规则:当用户按左键时,由当前焦点元素的左边(合适)元素获取焦点。同理,按上、右、下键时,都有对应方向上合适的元素获得焦点。
    原理:首先获取当前焦点元素的位置,在与页面中所有元素的位置进行比较,获取各个方向上最合适的元素。

    1.获取所有需要获取焦点的元素集合

    var className = ".item";//默认值
    var list = document.querySelectorAll(className);
    

    可通过下面方法设置或修改,需和html中的class保持一致

    setClassName:function(name){
        if(name !=null & name != ""){
           className = name;
        }   
    }
    

    2.获取元素在页面中的位置

    /**
     * 获取当前焦点元素在页面中的绝对位置
     * @param {当前获取的焦点的元素} e 
     */
    function getPosition(e){
        var x=0,y=0;
        while(e!=null){
            x += e.offsetLeft;
            y += e.offsetTop;
            e =  e.offsetParent;        
        }
        return {x:x,y:y};
    
    }
    

    3.遍历焦点元素集合找出当前焦点元素在目标方向上最合适的元素

    以左方向为例

    /**
     * 寻找所需方向上最近或最合适的元素
     * @param {按键方向} direction 
     * @param {所有需要获取焦点元素的集合} list 
     */
    function findFocusId(direction,list){
               
        var currentEle = document.activeElement; //当前焦点元素
        var currentLoc = getPosition(currentEle);   //当前焦点元素位置
        var locele = null;
        var minDistance = 99999999;
    
        switch(direction){
            case "left":
    
                for(var i=0;i<list.length;i++){ //遍历集合中的所有元素
                    var loc = getPosition(list[i]); //获取每个元素的位置
                    if(currentLoc.x >= (loc.x+list[i].offsetWidth)){ //目标元素必须在当前元素的左边
    
                       //计算当前元素的左上角到目标元素右上角的距离
                        var d1 = Math.sqrt(Math.pow(Math.abs(currentLoc.x-loc.x-list[i].offsetWidth),2) +Math.pow(Math.abs(currentLoc.y-loc.y),2));
                        //计算当前元素的左下角到目标元素的右下角的距离平方
                        var d2 = Math.sqrt(Math.pow(Math.abs(currentLoc.x-loc.x-list[i].offsetWidth),2) +Math.pow(Math.abs(currentLoc.y+currentEle.offsetHeight-loc.y-list[i].offsetHeight),2));
                       
                        //记录最小距离和最小距离元素。
                        var mind = d1<d2 ? d1 : d2;//取最小值
                        locele = mind < minDistance ? list[i] : locele ;  
                        minDistance = mind < minDistance ? mind : minDistance; 
                    }
                }
                break;
        }
    
        if(locele != null){
            return locele.id;
        }else{
            return null;
        }
        
    }
    

    4.添加特殊导航操作

    添加自定义属性:
    nextLeftFocusId 当前元素方向上指定的下一个焦点元素的id
    nextUpFocusId 当前元素方向上指定的下一个焦点元素的id
    nextRightFocusId 当前元素方向上指定的下一个焦点元素的id
    nextDownFocusId 当前元素方向上指定的下一个焦点元素的id

    在HTML中这样设置:

        <img tabindex=-1 id="img9" class="item" nextUpFocusId="nav_item1" nextRightFocusId="img4" >
    

    当该元素获取焦点时,按上键由id为 "nav_item1" 的元素获取焦点,按右键由id为 "img4" 的元素获取焦点。具体实现如下:

     var leftFocus = currentEle.getAttribute("nextLeftFocusId");//在html中指定特殊方向的下一个获取焦点元素的id
     if(leftFocus!=null&leftFocus != ""){
             return leftFocus;
     }
    

    在遍历计算之前提前返回。

    case "left":
                var leftFocus = currentEle.getAttribute("nextLeftFocusId");//在html中指定特殊方向的下一个获取焦点元素的id
                if(leftFocus!=null&leftFocus != ""){
                    return leftFocus;
                }
                
                for(var i=0;i<list.length;i++){
                    var loc = getPosition(list[i]);
                    if(currentLoc.x >= (loc.x+list[i].offsetWidth)){
    
                        //左上角到右上角
                        var d1 = Math.sqrt(Math.pow(Math.abs(currentLoc.x-loc.x-list[i].offsetWidth),2) +Math.pow(Math.abs(currentLoc.y-loc.y),2));
                        //左下角到右下角
                        var d2 = Math.sqrt(Math.pow(Math.abs(currentLoc.x-loc.x-list[i].offsetWidth),2) +Math.pow(Math.abs(currentLoc.y+currentEle.offsetHeight-loc.y-list[i].offsetHeight),2));
                       
                        var mind = d1<d2 ? d1 : d2;//取最小值
                        locele = mind < minDistance ? list[i] : locele ;  
                        minDistance = mind < minDistance ? mind : minDistance;                 
                   }
                }
               
                break;
    

    设置焦点样式

    当元素获取焦点时,我们需要改变它的显示样式,来表示它获取了焦点。

    1.使用onfocus和onblur

    onfocus :获得焦点
    onblur:失去焦点
    如:

    <div tabindex = "-1" class="item" id="area0_div_0" onfocus="search_focus()" onblur="search_blur()" >
        <div class="pic pic01" id="area0_pic0"></div>
        <div class="txt" id="area0_txt0">搜索</div>
    </div>
    

    再实现search_focus和search_blur两个方法,可以分别处理获得焦点和失去焦点的两种样式。

         function search_focus(){
            document.getElementById("area0_pic0").style.backgroundImage  = "url(../images/portal/serach.png)";
            document.getElementById("area0_pic0").style.backgroundRepeat = "no-repeat";
            document.getElementById("area0_pic0").style.backgroundPosition = "-1px -3px";
            document.getElementById("area0_txt0").style.color = "#fff";
        }
        function search_blur(){
            document.getElementById("area0_pic0").style.backgroundImage  = "url(../images/portal/serach_dark.png)";
            document.getElementById("area0_pic0").style.backgroundPosition = "0px 0px";
            document.getElementById("area0_txt0").style.color = "#778796";
        }
    

    2.使用:focus伪类

    设置未获取焦点的正常状态样式:

    .content .item{
            outline: none;//去除默认样式
            border: 2px solid transparent;
            transition: all .5s ease-out;
            -webkit-transition: all .5s ease-out;
     } 
    

    设置获得焦点后的样式:

     .content .item:focus{
        z-index: 9;
        border-radius: 10px;
        box-shadow:white 0px 0px 10px ;
        border: 2px solid white;
        transition: all .4s ease-out;
        -webkit-transition: all .4s;
        transform: scale(1.2);
        -ms-transform:scale(1.2);
        -moz-transform:scale(1.2);
        -webkit-transform:scale(1.2);
        -o-transform:scale(1.2);
    }
    

    DEMO

    见:https://github.com/fengfancky/WebEPG

    相关文章

      网友评论

          本文标题:电视EPG(WEB)页面上的焦点导航方案

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