db-lgtv-focus-engine
Version:
the Best TV focus engine
78 lines (76 loc) • 2.9 kB
JavaScript
function throttle(fn, wait) {
var pre = Date.now();
return function () {
var context = this;
var args = arguments;
var now = Date.now();
if (now - pre >= wait) {
fn.apply(context, args);
pre = Date.now();
}
};
}
export function bindKeydownListener(focus_engine) {
let throttle_key_down = throttle((e) => {
focus_engine.last_key_down = e
if (window['焦点框架-loading-加载中']) return
let focused_leaf = focus_engine.findFocusedLeaf()
if (!focused_leaf) return
let code_enum = {}
for (let key in focus_engine.options.KEYS) {
for (let code of focus_engine.options.KEYS[key]) {
code_enum[code] = key
}
}
let _e = new Event("keydown")
let _default = true
_e.code = e.which
_e.preventDefault = () => {
_default = false
}
focused_leaf.el.dispatchEvent(_e)
if (!_default) return
if (!code_enum[e.which]) return
e.preventDefault()
switch (code_enum[e.which]) {
case 'left':
case 'right':
case 'top':
case 'bottom': {
focused_leaf.el.dispatchEvent(new Event(code_enum[e.which]))
let will_focus_leaf = focused_leaf[code_enum[e.which]]
if (!will_focus_leaf) {
// 找不到邻居 => 重新定位 => 避免落焦误差
focus_engine.leaf_pool.forEach(leaf => leaf.rect = leaf.el.getBoundingClientRect())
focus_engine.trunk_pool.forEach(trunk => trunk.rect = trunk.el.getBoundingClientRect())
focused_leaf.findAllNeighbor()
will_focus_leaf = focused_leaf[code_enum[e.which]]
if (!will_focus_leaf) break
}
if (will_focus_leaf.parent && will_focus_leaf.parent !== focused_leaf.parent) {
if (will_focus_leaf.parent.cacheable && will_focus_leaf.parent.cache) {
// 若命中父元素缓存 则不需要聚焦叶子
will_focus_leaf.parent.cache.focus()
} else {
// 父元素无缓存
will_focus_leaf.focus()
}
} else {
will_focus_leaf.focus()
}
break
}
case 'ok': {
setTimeout(() => {
if (focus_engine.options.KEY_TYPE !== 'down') return
focused_leaf.ok()
}, 0)
break
}
}
}, focus_engine.options.KEY_SPEED)
document.onkeydown = throttle_key_down
}
export function unbindKeydownListener(focus_engine) {
document.onkeydown = (e) => {}
}