問題描述
在移動端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 = "";
}
});
}
});