H5移动端-解决点击输入框时页面自动放大的问题

2,978 阅读3分钟

问题

在移动端项目,我们常遇到的一个问题:用户点击输入框时,页面会不期望地发生自动缩放,这既打断了用户的输入流程,也影响了整体的用户体验。

我们的目标是优化这一行为,确保用户在点击输入框时,页面能够保持稳定,仅允许用户专注于内容的输入,从而提升产品的可用性和满意度。

解决前后效果对比

微信图片_20240903110833.jpg

微信图片_20240903110817.jpg

方案

针对移动端点击输入框导致页面自动缩放的问题,我们需要根据不同操作系统(主要是安卓与iOS)采取差异化的解决方案。

安卓:通常可以通过在HTML文档头部设置viewportmeta标签,并明确指定minimum-scalemaximum-scaleuser-scalable属性的值来有效防止页面缩放。这种方法能够确保用户输入时,页面保持稳定的视图比例。

iOS:仅仅依靠设置meta标签的某些值往往不足以解决问题。iOS的Safari浏览器有其独特的页面缩放行为,尤其是在处理输入框时。

为了解决这个问题,我们可以采用JavaScript编写一个封装函数,该函数在页面加载完成后自动执行。该函数的核心逻辑可以是通过监听输入框的聚焦(focus)和失焦(blur)事件,动态地调整页面的缩放级别或利用CSS样式来阻止不必要的缩放行为,从而实现在iOS环境下用户输入时页面保持稳定的用户体验。

安卓解决方式:

<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0,user-scalable=no"/>
//在移动浏览器上页面渲染是在一个叫viewport的页面绘制区域内
<meta name="viewport"

// 设置layout viewport 的宽度,为一个正整数,使用字符串”width-device”表示设备宽度
 content="width=device-width,

// 设置页面的初始缩放值,为一个数字,设置值为1.0
 initial-scale=1.0,

//允许用户的最小缩放值,为一个数字,设置值为1.0

 minimum-scale=1.0,

//允许用户的最大缩放值,为一个数字,设置值为1.0
 maximum-scale=1.0,

//是否允许用户进行缩放,值为”no”或”yes”, no 代表不允许,yes代表允许
user-scalable=no"/>

iOS解决方式:

<script>
    // 当页面加载完成后触发该函数
    window.onload = function () {

        // e.preventDefault()  ===    阻止默认事件

        // 当一个手指放在屏幕上时,会触发 touchstart 事件。如果另一个手指又放在了屏幕上,则会先触发 gesturestart 事件
        document.addEventListener('gesturestart', function (e) {
            e.preventDefault();
        });

        // 在单个元素上单击两次 ===  dblclick
        document.addEventListener('dblclick', function (e) {
            e.preventDefault();
        });

        // 一个手指放在屏幕上时,会触发 touchstart 事件
        document.addEventListener('touchstart', function (event) {
            if (event.touches.length > 1) {
                event.preventDefault();
            }
        });

        // 如果一个或两个手指在屏幕上滑动,将会触发 gesturechange 事件
        // 但只要有一个手指移开, 就会触发 gestureend 事件,紧接着又会触发基于该手指的 touchend 事件
        var lastTouchEnd = 0;
        document.addEventListener('touchend', function (event) {
            var now = (new Date()).getTime();
            // 如果在300ms内触发两次touchend,就阻止默认事件
            if (now - lastTouchEnd <= 300) {
                event.preventDefault();
            }
            lastTouchEnd = now;
        }, false);
    };

</script>

注意

如果是web-view渲染的H5,经测试用第一种方式就行,两端都可以兼容。