输入框聚焦时将其滚动到可视区域(v-scroll-safe-area指令)

文章目录

    • 问题描述
    • 涉及方法
    • 指令核心

问题描述

在移动端web开发的时候,输入框聚焦时会出现键盘弹出遮挡的情况,v-scroll-safe-area指令就是让键盘弹出时能让输入框布局滚动到可视区域
输入框聚焦时将其滚动到可视区域(v-scroll-safe-area指令)_第1张图片


涉及方法

//判断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 = "";
      }
    });
  }
});

你可能感兴趣的:(框架/工具)