问题描述
在移动端web开发的时候,输入框聚焦时会出现键盘弹出遮挡的情况,v-scroll-safe-area指令就是让键盘弹出时能让输入框布局滚动到可视区域
涉及方法
//判断ios或android系统
function getOS () {
let ua = navigator.userAgent.toLowerCase()
let isIOS = /iphone/.test(ua)
if (isIOS) {
return 'ios'
} else {
return 'android'
}
}
//兼容性添加监听
export function addEvent(element, type, callback, evCatch = false) {
if (element.addEventListener) {
element.addEventListener(type, callback, evCatch);
} else if (element.attachEvent) {
element.attachEvent("on" + type, callback);
}
}
//获取最近一个可以滚动的元素
export function getLatelyScrollElem(elem) {
let parentElem = elem.parentElement;
if (parentElem.nodeName.toLocaleLowerCase() !== "body") {
if (hasScrollbar(parentElem)) {
return parentElem;
} else {
return getLatelyScrollElem(parentElem);
}
} else {
return window;
}
}
//是否有滚动条
export function hasScrollbar(elem) {
return elem.scrollHeight > elem.clientHeight + 50;
}
//根据target的位置滚动
export function scrollSafeAreaByElem(scrollElem, target) {
if (scrollElem) {
var gsr = parseInt(window.screen.height * 0.382);
var y = parseInt(scrollElem.scrollTop + getTop(target) - gsr + 30);
scrollElem.scrollTo(0, y);
}
}
function getTop(e) {
//30是一个相对于黄金分割点的系数 建议在30-50之间
var offset = e.offsetTop;
while (e.offsetParent) {
e = e.offsetParent;
offset += e.offsetTop;
}
offset = offset - document.documentElement.scrollTop + 30;
return offset;
}
指令核心
import Vue from "vue";
//监听页面里所有的输入框,并将其滚动到可视区域
Vue.directive("scroll-safe-area", {
inserted(el, binding) {
let inputElem = "";
//记录最近一个可滚动的区域
let scrollElem = "";
const os = getOS();
if (os === "android") {
addEvent(
el,
"focus",
ev => {
var event = ev || window.ev;
var target = ev.target || ev.srcElement;
if (target.nodeName.toLocaleLowerCase() == "input") {
inputElem = target;
scrollSafeAreaByElem(scrollElem, inputElem);
}
},
true
);
}
addEvent(
el,
"blur",
event => {
inputElem = "";
if (os === "ios") {
if (document.documentElement) {
document.documentElement.scrollTop =
document.documentElement.scrollTop;
} else {
document.body.scrollTop = document.body.scrollTop;
}
}
},
true
);
const originHeight =
document.documentElement.clientHeight || document.body.clientHeight;
addEvent(window, "resize", event => {
const resizeHeight =
document.documentElement.clientHeight || document.body.clientHeight;
if (resizeHeight < originHeight) {
// 键盘弹起
if (inputElem) {
scrollElem = getLatelyScrollElem(inputElem);
scrollSafeAreaByElem(scrollElem, inputElem);
}
} else {
//键盘收起
if (os === "android") {
inputElem.blur();
}
scrollElem = "";
inputElem = "";
}
});
}
});