这个框架使用十分的简略,简略应用就 3 步,实用于用原生写 TV 端需要的前端,即便素来没开发过 TV 端的看完根本应用也能够把握, 十分好用!
github 链接:https://github.com/simpleRobort/TV-Focus.js (感觉不错的麻烦 github 给个 star,万分感激)
I. 根本应用
1. 事后写好页面,保障你所有可能获取焦点的 dom 元素领有一个对立结尾的 id 个别为 “item?”, 其中? 为数字,从 0 开始, 上不封顶
<!-- 保障元素领有定位 -->
<div class="dom" id="item0" style="position: absolute;left:200px;top:200px;width:150px;height:150px"> 这是第个 0dom</div>
<div class="dom" id="item1" style="position: absolute;left:400px;top:200px;width:150px;height:150px"> 这是第个 1dom</div>
<div class="dom" id="item2" style="position: absolute;left:600px;top:200px;width:150px;height:150px"> 这是第个 2dom</div>
<div class="dom" id="item3" style="position: absolute;left:200px;top:400px;width:150px;height:150px"> 这是第个 3dom</div>
<div class="dom" id="item4" style="position: absolute;left:400px;top:400px;width:150px;height:150px"> 这是第个 4dom</div>
<div class="dom" id="item5" style="position: absolute;left:600px;top:400px;width:150px;height:150px"> 这是第个 5dom</div>
对应 css:
.focus {border: 2px solid #0f0f0f; /* 这里就是获取焦点的实现原理了,Focus.js 会给获取焦点的元素增加一个名字叫做 focus 的 class 类 */}
2. 从源码里下载 focus.js( 点击下载 ),在你的 html 页面中引入
<script src="./focus.js"></script>
3. 在引入之后创立一个 script 标签,new 一个 FOCUS 对象并且传入参数
<script>
var vm = new FOCUS({
focusId: 'item3', // 页面首先获取焦点的 dom 元素的 Id, 不传默认 item0
event: {keyOkEvent: function (focusId) {console.log("点击了确认键,以后取得焦点的索引为:" + focusId)
switch (focusId) {
case 0:
break
}
},
keyBackEvent: function (focusId) {console.log("点击了返回键,以后取得焦点的索引为:" + focusId)
switch (focusId) {
case 6:
case 7:
break
}
}
}
})
</script>
到这里最简略的焦点挪动曾经被增加好了,你就能够关上页面看成果了
根本应用测试地址
II. 进阶应用
1. 应用后辈选择器显示暗藏图片与 dom 元素
根本应用里咱们只是简略的给 focus 增加了一个边框,十分的简便,然而当咱们须要通过焦点与否显示不同的图片的时候,只是简略的给 focus 增加边框并不够用,这时候就须要 css 的后辈选择器了
css:
.dom .select {
position: absolute; /* 须要增加定位,不然会被未选中显示的内容挤下去 */
display: none; /* 未被选中时暗藏选中才显示的内容 */
}
.dom .unselect {display: block; /* 未获取焦点时显示没被选中须要显示的内容 */}
.focus .select {display: block; /* 获取焦点时显示被选中的须要显示的内容 */}
.focus .unselect {visibility: hidden; /* 获取焦点时暗藏未被选中须要显示的内容 */}
html:
<!-- 以下图片为本地数据,如复制应用请批改 -->
<div id="bg">
<div class="dom" id="item0" style="position: absolute;left:890px;top:100px;width:150px;height:150px">
<div class="unselect"><img src="../image/unselect/gengduo.png" alt=""></div>
<div class="select" style="left:0px;top:0px;"><img src="../image/select/gengduo.png" alt=""></div>
</div>
<div class="dom" id="item1" style="position: absolute;left:200px;top:200px;width:150px;height:150px">
<div class="unselect"><img src="../image/unselect/1.png" alt=""></div>
<div class="select" style="left:0px;top:0px;"><img src="../image/select/1.png" alt=""></div>
</div>
<div class="dom" id="item2" style="position: absolute;left:500px;top:200px;width:150px;height:150px">
<div class="unselect"><img src="../image/unselect/2.png" alt=""></div>
<div class="select" style="left:0px;top:0px;"><img src="../image/select/2.png" alt=""></div>
</div>
<div class="dom" id="item3" style="position: absolute;left:800px;top:200px;width:150px;height:150px">
<div class="unselect"><img src="../image/unselect/3.png" alt=""></div>
<div class="select" style="left:0px;top:0px;"><img src="../image/select/3.png" alt=""></div>
</div>
<div class="dom" id="item4" style="position: absolute;left:200px;top:400px;width:150px;height:150px">
<div class="unselect"><img src="../image/unselect/4.png" alt=""></div>
<div class="select" style="left:0px;top:0px;"><img src="../image/select/4.png" alt=""></div>
</div>
<div class="dom" id="item5" style="position: absolute;left:500px;top:400px;width:150px;height:150px">
<div class="unselect"><img src="../image/unselect/5.png" alt=""></div>
<div class="select" style="left:0px;top:0px;"><img src="../image/select/5.png" alt=""></div>
</div>
<div class="dom" id="item6" style="position: absolute;left:800px;top:400px;width:150px;height:150px">
<div class="unselect"><img src="../image/unselect/5.png" alt=""></div>
<div class="select" style="left:0px;top:0px;"><img src="../image/select/5.png" alt=""></div>
</div>
</div>
js:
var vm = new FOCUS({
focusId: 'item3', // 页面首先获取焦点的 dom 元素的 Id
event: {keyOkEvent: function (focusId) {console.log("点击了确认键,以后取得焦点的索引为:" + focusId)
switch (focusId) {
case 0:
break
}
},
keyBackEvent: function (focusId) {console.log("点击了返回键,以后取得焦点的索引为:" + focusId)
switch (focusId) {
case 6:
case 7:
break
}
}
}
})
应用后辈选择器示例地址
2. 应用强制焦点变换 (forceMove)
实用的场景个别有两个:
1. 你须要这个元素按某一个方向键不切换焦点或者切换到本人想要的焦点(哪怕隔了一座山哈哈)
2. 你的 ui 设计稿十分的不法则(焦点默认的逻辑无奈满足需要,焦点默认挪动的逻辑是以 dom 的宽高地位发射一道射线,第一个触碰到的 dom 元素就会成为下一个焦点)
显然没有别的元素的话,这个两个元素无奈互相跳转,有人问我为什么不把断定范畴改大一点,我也试过,天然是解决了,然而有更多的问题呈现了,我这就不一一举例了哈哈,
回到正题,应用办法很简略,只须要在 new FOCUS 传入的对象里新增一个属性 focusMove 即可
var vm = new FOCUS({
focusId: 'item3',
forceMove: {// 须要被强制的焦点 id:[ 上,左,下,右]
item0: [-1,-1,"item1",-1],
item1: ["item0",-1,-1,-1],
}
})
forceMove 也是一个对象,须要传入属性,属性值为一个数组,顺次为方向键上左下右,参数有三种取值,如下
取值 | 形容 |
---|---|
-1 | 不做解决,随框架判断逻辑主动切换焦点 |
-2 | 禁止挪动,即便对应的方向有焦点 |
其余 dom 的 id | 强制挪动到对应的 dom |
3. 事件处理 (event)
tv 端除了上下左右方向键与数字键,还有其余的事件,这里也提供了 api
var vm = new FOCUS({
focusId: 'item3',
event: {keyOkEvent: function (focusId) {console.log("点击了确认键,以后取得焦点的索引为:" + focusId)
switch (focusId) {
case 0:
break
}
},
changeIndexBeforeFind: function (dir,focusId) {// 两个传参 (dir 代表方向:上左下右顺次为 0123, 以后焦点 id)
// Focus 会在主动寻找下一个焦点前触发这个事件,如果这个函数返回了一个指定索引
// 那么框架就不会浪费时间去寻找下一个焦点,间接应用你返回的索引
// 例:if (dir == 3 && focusId == 0) {return 2}
// 当在焦点索引为 0 的 dom 按下 右方向键,返回一个索引 2,框架会放弃计算
// 间接让索引为 2 的获取焦点
},
changeIndexAfterFind: function (dir,focusId,nextId) {// 三个传参 ( 前两个同上,nextId 为计算实现的焦点,如果没有适合的焦点就会返回 -1)
// Focus 会在寻找完焦点后触发这个事件,如果这个函数返回了一个指定索引
// 那么框架就摈弃原本应该成为焦点的 nextId,间接应用你返回的索引
},
}
})
事件名称 (都是函数, 如上) | 形容 |
---|---|
keyNumberEvent | 遥控器数字点击,有两个传参:(对应的数字,以后获取焦点的索引) |
keyOkEvent | 遥控器确认键,有一个传参 (以后获取焦点的索引) |
keyBackEvent | 遥控器返回键,有一个传参 (以后获取焦点的索引) |
focusEvent | 获取焦点后事件,有一个传参 (以后获取焦点的索引) |
unfocusEvent | 失去焦点后事件,有一个传参 (失去焦点的索引) |
darkFocusEvent | 获取暗焦点后事件,有一个传参 (失去焦点的索引) |
undarkFocusEvent | 失去暗焦点后事件,有一个传参 (失去焦点的索引) |
changeIndexBeforeFind | 按任意方向键后触发,详情见上图 |
changeIndexAfterFind | 按任意方向键后触发,详情见上图 |
4. 二级以上页面 (pageState)
当页面有若干个焦点是在触发某一个事件才可能被获取焦点的,在事件未触发时不应该被获取焦点,如果通过下面的强制事件频繁的增加 -2,那可太麻烦了,这时候就 pageState 就呈现了
应用办法:
var vm = new FOCUS({
pageState: {// 非凡焦点: 页面索引 ( 默认为 1)
item4: 2,
item5: 2
},
})
5. 办法 (methods)
为了尽量使页面的外围代码保留在 FOCUS 传参内,增加了相似 vue 的 methods 来不便代码治理
应用办法:
var vm = new FOCUS({
methods: {handleTest: function () {console.log("你点击了 methods")
}
},
event: {keyOkEvent: function (focusId) {this.handleTest()
}
}
})
传参时传入一个 methods 对象,用来保留办法,this 指向 Focus,也通过 this. 办法名来调用 methods 外部办法
methods 示例地址
5. 暗焦点 (darkFocus)
tv 端常常会有一个需要,页面上会有多个焦点,比如说一个节目,你可能会须要其余的焦点来示意以后所属于的分类,咱们称之为暗焦点
var vm = new FOCUS({darkFocus:[[1,0,2,3,4],[5,6,7,8]], // 暗焦点列表一个数组蕴含多个数组,参数为 id 后的索引,代表这几个 dom 为一块暗焦点,并且数组第一个索引为默认选中的暗焦点
darkGroup:[true,true], // 长度与 darkFocus 对应,代表每次进入暗焦点列表时,是否始终让这个列表的暗焦点被选中
darkClass: "active", // 暗焦点被增加的 class , 默认就是 active
event: {darkFocusEvent: function (id) {
// 你有可能会须要在焦点切换时依据以后的分类渲染新数据,// 咱们心愿你应用的是这个事件而不是 focusEvent
// 这是为了防抖, 在暗焦点没扭转时反复获焦不会反复触发这个事件
console.log("获取暗焦点",id)
},
undarkFocusEvent: function (id) {console.log("失落暗焦点",id)
},
focusEvent: function (id) {console.log("获取焦点",id)
},
unfocusEvent: function (id) {console.log("失落焦点",id)
},
}
})
6. 使用各 api 实现一个 tv 端常见 demo (demo)
tv 最多的就是多级栏目的需要,在焦点切换时,对应的子列表,子节目都要发生变化,本文章次要介绍框架的应用,
故具体内容可下载源码与 focus 文件理解
demo 地址
7. 生命周期 (生命周期)
按目前的需要引入了一个初始创立时的生命周期 created
应用形式:
var vm = new FOCUS({created: function (next) {this.addDiv()
next() // 必须调用,不调用无奈库就不执行初始化},
methods: {addDiv: function () {var div = document.createElement("div")
div.classList = "dom"
div.id = "item6"
var newContent = document.createTextNode("生命周期增加的 dom");
div.appendChild(newContent);
document.body.appendChild(div);
}
}
})
demo 地址
周期名称 | 传参 | 形容 |
---|---|---|
created | next | 提供一个 next 办法,在调用后库才会持续抓取页面的焦点并且初始化, 此时能拜访 methods 里的办法 |
III new FOCUS 传参
var vm = new FOCUS({})
传参为一个对象,其中对象外部的属性如下:
属性名称 | 类型 | 形容 |
---|---|---|
domIdName | string | 对立 id, 默认为 ”item”, 如心愿对立 id 为 (“focusDom0″、”focusDom1″…), 即该参数值为 “focusDom” |
focusId | string | 须要首先聚焦的 id,默认索引为 0 的元素 |
focusClass | string | 聚焦 dom 减少的 class, 默认为 ”focus” |
pageState | int | 设置页面等级,详情参考 II.4 |
forceMove | object | 批改 dom 的方向键逻辑,详情参考 II.2 |
event | object | 按键处理事件, 详情参考 II.3 |
methods | object | 办法保留,相似 vue 的 methods, 详情参考 II.5 |
darkFocus | array | 暗焦点,在焦点在别处时仍旧显示非凡款式, 每个数组第一个索引为默认选中的暗焦点, 详情参考 II.6 |
darkClass | string | 暗焦点被增加的 class , 默认就是 active, 详情参考 II.6 |
darkGroup | array | 长度与 darkFocus 对应,代表每次进入暗焦点列表时,是否始终让这个列表的暗焦点被选中, 详情参考 II.6 |
unFocusArr | array | 数组,数组能够有多个 id 索引,代表初始不容许被选中的焦点,之后可用上面介绍的 openFocus 解除禁止被选中 |
IV 框架的 Api
应用办法:
在实例外部应用: 示例:this.requireFocus(0)
在实例内部应用: 示例:vm.requireFocus(0) (vm 为实例对象)
var vm = new FOCUS({
event: {keyOkEvent: function (focusId) {this.requireFocus(6) // 在实例外部应用
}
}
})
vm.requireFocus(6) // 在实例内部应用
Api 名称 | 传参数量 | 传参 | 形容 |
---|---|---|---|
requireFocus | 1 | number | 使元素获取焦点,传参为索引值, 例 (使 id 为 ”item2″ 的元素获取焦点):this.requireFocus(2) |
log | 4(后三个参数可不传) | 打印内容,字体大小 (默认 16px), 文字色彩 (默认红色),背景色彩 (默认彩色) | tv 端无控制台,所以须要此 api 显示打印信息 |
getDom | 1 | int | 依据传参索引返回元素 |
getFocus | 0 | 无 | 返回以后焦点索引 |
getParam | 3 | 字段名: 字符串 默认值 地址: 默认以后地址 | 解析 url 传参 |
gotoPage | 1 | url 地址 | 单纯的跳转 url,可能会在须要跳转前发送申请而存在 |
getFocusDom | 0 | 无 | 返回以后焦点 dom 元素 |
stopFocus | 1 | 数组:内容为一个或多个 dom 索引 | 使数组内的焦点无奈被获取焦点 |
openFocus | 1 | 数组:内容为一个或多个 dom 索引 | 使数组内的焦点从 stopFocus 内移除,可能获取焦点 |
refresh | 0 | 无 | 调用后库会抛弃原来的焦点汇合,从新去抓取页面上的焦点 |
V 版本日志
版本号 | 更新内容 | 日期 |
---|---|---|
1.0.6 | 提供一个初始化的生命周期,为了适配页面初始化时要增加 dom 的需要 | 2022-5-19 |
1.0.5 | 增加焦点切换前后事件,动静批改焦点获取与否,减少框架的灵活性 | 2022-3-8 |
1.0.4 | 增加暗焦点相干事件,以及暗焦点防抖等解决 | 2022-3-7 |
1.0.3 | 增加 methods 传参,用来优化代码标准,增加 getparam 办法,获取 url 参数 | 2022-3-3 |
1.0.2 | 增加打印调试 api,以及 readme.md 排版更新,版本日志 | 2021-12-27 |
1.0.1 | 增加二级以上页面,失焦获焦事件 | 2021-12-21 |
1.0.0 | 具备 tv 端焦点框架根本需要 | 2021-12-20 |
其余
如果这个框架可能被很多应用到,我想我会十分的开心,如果你有什么感觉框架须要减少的好的倡议,我很荣幸可能晓得,这是我的联系方式,请表明来意, 心愿您能给我一个点赞,这是对我最大的激励
vx:DoubleU-_
QQ:1026990903