防止跨浏览器缩放

70
对于类似地图的工具,我想要禁用浏览器的缩放功能。(我知道这通常是不好的想法,但对于某些特定的网站,这是必需的。)
我通过监听键盘快捷键CTRL + / CTRL -并添加e.preventDefault()等内容已经成功实现了它。但是这不能防止从浏览器的缩放菜单更改缩放。
我尝试过:
- 使用CSS:zoom: reset; 它适用于Chrome(请参见这个页面以查看一个有效的示例),但在Firefox上根本不起作用。 - 在各种问题/答案中,我还发现了 ``` ``` 但这似乎只适用于移动设备。
如何在各种浏览器中防止缩放?

@Skoua:可以覆盖这些快捷键。我成功地使用了(window.onkeydowne.preventDefault())。 我的问题是:如何防止浏览器菜单(查看>缩放设置等)中的缩放。 - Basj
1
如果这是在Flash上,那就另当别论了。不过,我一直在尝试构建一个脚本,检测浏览器的缩放级别,并使用zoom应用相反的效果,但比我想象的要困难得多。(使用http://tombigel.github.io/detect-zoom/) - chdltest
1
@Basj:千万不要这样做。说真的,你的应用程序部分现状下几乎无法阅读,对于老年人和疲惫的眼睛来说更是如此。禁用缩放除了让用户感到恼怒之外没有任何意义。(而且,说实话,覆盖滚动以使事物放大和缩小非常尴尬,以至于我试图使用它并迷失在其中后,你的网站最终变成了一个无用的白屏幕。) - Denis de Bernardy
@Basj,我看到你的演示中禁用了缩放,至少在导航栏上是这样。而且它似乎甚至在Firefox桌面版上也被禁用了。你最终是如何解决的? - Yash Capoor
也许可以通过检测缩放(detecting zoom)并相应地调整元素的大小来解决这个问题。 - Samie Bencherif
显示剩余12条评论
14个回答

45

我并没有找到一个“权威”的答案,也就是说,没有浏览器开发者明确的声明。然而,我找到的所有类似问题的答案(比如这个那个)都表明同样的事情——浏览器的缩放功能存在是为了用户的利益,一些浏览器(比如Firefox)根本不允许你作为网站创建者禁用这个选项。


这份文档或许可以解释为什么在移动设备上允许作者禁用缩放是个好主意,但在台式机上不是。

简而言之,如果你知道移动设备的自动缩放会导致显示不当,你可能需要阻止它。 在台式机上,没有自动缩放,所以当用户访问你的网站时,他们会看到它应该呈现的样子。 如果他们决定需要缩放页面,没有必要阻止他们这样做。


关于您列出的解决方案:


1
你在问题评论中提供的应用程序与缩放有关,这使得我的回答对于你的特定情况不太相关。不过,它可能在一般情况下还是有帮助的,我猜。 - hon2a
检查我的答案是否正确,只需在添加addEventListener时添加{passive: false}。 window.addEventListener("wheel", handleWheel, {passive: false});https://dev59.com/4V4d5IYBdhLWcg3wJvsp#69709413 - Jian Zhong

39

使用此代码,您可以在浏览器中禁用使用 Ctrl + +Ctrl + -Ctrl + 鼠标滚轮向上Ctrl + 鼠标滚轮向下 进行缩放。

$(document).keydown(function(event) {
if (event.ctrlKey==true && (event.which == '61' || event.which == '107' || event.which == '173' || event.which == '109'  || event.which == '187'  || event.which == '189'  ) ) {
        event.preventDefault();
     }
    // 107 Num Key  +
    // 109 Num Key  -
    // 173 Min Key  hyphen/underscore key
    // 61 Plus key  +/= key
});

$(window).bind('mousewheel DOMMouseScroll', function (event) {
       if (event.ctrlKey == true) {
       event.preventDefault();
       }
});

点击此处查看演示:JSFiddle


5
Ctrl和+可以放大页面。 - Shanu Shaji
是的,它在Chrome浏览器中进行了缩放,现在请再次检查,我已经更新了条件。 - Vijay Dhanvai
11
截至2020年,在我测试的所有浏览器中,这种方法已经失效。 - 10 Replies
Chrome的解决方法可能是将滚轮事件附加到某个div包装器上,而不是附加到窗口/文档/主体本身,https://chromestatus.com/feature/6662647093133312。 - Kasheftin

11

将以下内容插入您的 HTML 代码:

针对移动设备,请将其插入在 '< head>...< /head>' 标签之间。

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">

适用于桌面浏览器:在“<body>…”标签后立即插入。

<script>
  document.body.addEventListener("wheel", e=>{
    if(e.ctrlKey)
      e.preventDefault();//prevent zoom
  });
</script>

9
我认为您可以监听浏览器缩放事件(ctrl + “+”),然后检查window.devicePixelRatio。然后,根据比例在body元素上应用HTML5缩放变换以相同的比例缩小。因此,基本上您无法防止功能,但可以使用相同的大小应用负面效果。
POC代码:
 <body style="position: absolute;margin: 0px;">
        <div style="width: 300px; height: 200px; border: 1px solid black;">
            Something is written here
        </div>
        <script>
            var keyIncrease = [17, 61];
            var keyDecrease = [17, 173];
            var keyDefault = [17, 48];
            var listenMultiKeypress = function(keys, callback){
                var keyOn = [];
                for(var i=0; i<keys.length; i++){
                    keyOn[i] = false;
                }
                addEventListener('keydown', function(e){
                    var keyCode = e.which;
                    console.log(keyCode);
                    var idx = keys.indexOf(keyCode);
                    if(idx!=-1){
                        keyOn[idx] = true;
                    }
                    console.log(keyOn);
                    for(var i=0; i<keyOn.length; i++){
                        if(!keyOn[i]){
                            return;
                        }
                    }
                    setTimeout(callback, 100);
                });
                addEventListener('keyup', function(e){
                    var keyCode = e.which;
                    var idx = keys.indexOf(keyCode);
                    if(idx!=-1){
                        keyOn[idx] = false;
                    }
                    console.log(keyOn);
                });
            };
            var previousScale = 1;
            var previousDevicePixelRatio;
            var neutralizeZoom = function(){
                //alert('caught');
                var scale = 1/window.devicePixelRatio;

                document.body.style.transform = 'scale('+(1/previousScale)+')';
                document.body.style.transform = 'scale('+scale+')';
                var widthDiff = parseInt(getComputedStyle(window.document.body).width)*(scale-1);
                var heightDiff = parseInt(getComputedStyle(window.document.body).height)*(scale-1);
                document.body.style.left = widthDiff/2 + 'px';
                document.body.style.top = heightDiff/2 + 'px';
                previousScale = scale;
            };

            listenMultiKeypress(keyIncrease, neutralizeZoom);
            listenMultiKeypress(keyDecrease, neutralizeZoom);
            listenMultiKeypress(keyDefault, neutralizeZoom);
            neutralizeZoom();
        </script>
    </body>
</html>

6
因此,正如先前提到的那样,这是不可能的。然而,你仍然可以采取一些方法来更加聪明地处理它。
五个主要浏览器中的三个都允许您查看浏览器的缩放级别,此外,如果浏览器被缩放,将触发window.onresize事件。
IE:      event.view.devicePixelRatio           OR window.view.devicePixelRatio
Chrome:  event.currentTarget.devicePixelRatio  OR window.devicePixelRatio
Firefox: event.originalTarget.devicePixelRatio OR window.devicePixelRatio
Safari:  /* Not possible */
Opera:   /* Not possible */

我认为OR之后的东西基于我的一些发现。我知道的前面几个至少在每个版本中都可以工作。请注意,Safari和Opera都有devicePixelRatio,但是两者都不会更改。它总是1

如果你不太关心,上述内容是你的简单方法。如果你很在意,那么你可以尝试使用detect-zoom脚本,我是在寻找解决Safari和Opera问题时发现的。

现在,你可以获取缩放级别,然后抵消你的缩放,使其不做任何事情。所以,如果我强制浏览器缩放为50%,你只需要设置为200%。因此,没有变化。当然,这可能会更加复杂,你需要存储上一次的浏览器缩放、新的浏览器缩放,并进行一些稍微复杂的数学计算,但基于你已经拥有的内容,这应该很容易。

另一个想法可能是只监听大小调整事件,然后根据新的可见大小进行计算,但如果窗口只是被调整大小,可能会引起问题。我认为上述方案可能是你最好的选择,如果需要,可以设置一个回退alert来提醒用户不要缩放。


这可能是最好的方法,覆盖了所有情况。而且 detect-zoom 脚本在新版本的 Chrome 和 Firefox 中不起作用。但正如所述,Safari 和 Opera 得到支持。 - stackErr
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Basj
@Basj,本帖提到的方法依赖于您的设计。这些属性是只读的,所以您能做的最好的事情就是抵消它们。例如,如果您处于223%缩放状态,并且用户将其更改为150%缩放,则会读取该值,并在代码中转到1.486%缩放(如果我算得对的话:223/150)。如果用户再次更改,则您将假装150%100%,并根据此进行计算。像您提供的页面一样,纯文本,因此无法使用该方法。此外,您不希望阻止该类型页面的缩放。 - David

4

我更新了Vijay的代码:

$(document).ready(function(){
 var keyCodes = [61, 107, 173, 109, 187, 189];

 $(document).keydown(function(event) {   
   if (event.ctrlKey==true && (keyCodes.indexOf(event.which) != -1)) {
     alert('disabling zooming'); 
     event.preventDefault();
    }
 });

 $(window).bind('mousewheel DOMMouseScroll', function (event) {
    if (event.ctrlKey == true) {
      alert('disabling zooming'); 
      event.preventDefault();
    }
  });
});

这个解决方案适用于桌面浏览器,跨平台(操作系统/Windows)。


我将你的代码粘贴到jsfiddle.net上,我仍然可以在Mac上使用Command +缩放。 - PioneerMan
@NestMan,我认为您忘记在末尾放置});。 - Andrii Gordiichuk
这样可以防止缩放,做得很好,但是如果你真的尝试滚动缩放它,在Chrome上仍然会缩放。 - user8458667
在我的MacBook上,我用触控板捏住(同时将两个手指从触控板上分开)- 浏览器调用“鼠标滚轮”事件,但脚本无法工作,因为未按下crtlKey键(也没有Cmd键)。 - Maxim Georgievskiy

3
以下代码可以防止鼠标、键盘手势进行所有类型的缩放。
document.addEventListener(
    "wheel",
    function touchHandler(e) {
      if (e.ctrlKey) {
        e.preventDefault();
      }
    }, { passive: false } );

对于移动设备,只需要添加以下代码行:<meta name='viewport' content='width=device-width,initial-scale=1,user-scalable=no, maximum-scale=1.0, shrink-to-fit=no'>

好的答案简单明了,人类可读性很重要。谢谢。尽管描述可以更好,但这并不影响键盘的+和-缩放。对我来说没关系,只需要禁用ctrl +滚动即可,这个答案就完美了。 - ThaJay

2

通过键盘防止浏览器缩放与上面的许多答案相同。

window.addEventListener('keydown', function (e) {
    if ((e.ctrlKey || e.metaKey) && (e.which === 61 || e.which === 107 || e.which === 173 || e.which === 109 || e.which === 187 || e.which === 189)) {
        e.preventDefault();
    }
}, false);

但是现代浏览器中通过鼠标滚轮禁止缩放的方法有所不同。 Chrome的新策略需要你显式地使用passive = false。

{passive: false}

如果不这样做,event.preventDefault()无法停止鼠标滚轮事件导致的默认浏览器缩放行为,请检查。
const handleWheel = function(e) {
    if(e.ctrlKey || e.metaKey)
        e.preventDefault();
};
window.addEventListener("wheel", handleWheel, {passive: false});

但是我们无法防止从浏览器菜单点击缩放。


请完整阅读问题。它不是关于响应鼠标滚轮事件的问题。 - hon2a
2
是的,你说得对。有些人说它在现代浏览器上不再起作用了。我几天前通过鼠标滚轮事件解决了缩放问题。也许对某些人有帮助。 我还提到过,这段代码无法防止由浏览器菜单触发的缩放。 - Jian Zhong

1
$(document).ready(function () {
      $(document).keydown(function (event) {
          if (event.ctrlKey == true && (event.which == '107' || event.which == '109' || event.which == '187' || event.which == '189'))
           {
               event.preventDefault();
           }
       });

           $(window).bind('mousewheel DOMMouseScroll', function (event) {
               if (event.ctrlKey == true) {
                   event.preventDefault();
               }

      });
  })

1
你尝试过吗…
$("body").css({
     "-moz-transform":"scale(1)",
     "-webkit-transform":"scale(1)",
     "-o-transform":"scale(1)",
     "-ms-transform":"scale(1)"
});

我使用这种代码来设置或重新设置比例尺。


1
这个不起作用。 - Binh Ho
考虑到这个答案是八年前的,我并不感到惊讶。这些是非常具体的、针对性强的 jQuery 转换,使用了一种我今天不会尝试的模式。我们当时必须做一些奇怪的事情。简单地看一下,一个 CSS body { transform: scale(1); } 可能会起作用。 - rfornal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接