检查是否正在使用视口元标记

问题描述 投票:0回答:9

我有一个画布,需要在调整浏览器窗口大小时调整大小,所以我有以下内容:

var resizeCanvas = function () {
    var ratio =  Math.max(window.devicePixelRatio || 1, 1);
    canvas.width = (canvas.offsetWidth || canvas.width) * ratio;
    canvas.height = (canvas.offsetHeight || canvas.height) * ratio;
    canvas.getContext('2d').scale(ratio, ratio);
}

window.addEventListener('resize', resizeCanvas);

这非常有效,除了在移动设备上滚动会触发 resize 事件

这是不希望的,因为调整画布大小会清除其内容,这意味着当移动用户滚动时,画布始终会被擦除。

感谢这个答案我想出了一个基于缓存宽度并仔细检查的解决方案,但根据我的设计,我实际上只需要解决受我的视口元标记影响的设备的问题:

<meta name="viewport" content="width=device-width, initial-scale=1">

有什么方法可以检查浏览器是否正在使用该元标记?我正在寻找类似的东西:

if(viewportMetaTagIsUsed){
    //For mobile browsers
    window.addEventListener("orientationchange", resizeCanvas);
} else {
    //For desktop browsers
    window.addEventListener('resize', resizeCanvas);
}
javascript html viewport meta-tags meta
9个回答
8
投票

据我所知,无法检测浏览器是否能够处理视口元标记。

以下是一些可供考虑的替代方案...


替代方案 1:浏览器嗅探

!function(a){var b=/iPhone/i,c=/iPod/i,d=/iPad/i,e=/(?=.*\bAndroid\b)(?=.*\bMobile\b)/i,f=/Android/i,g=/(?=.*\bAndroid\b)(?=.*\bSD4930UR\b)/i,h=/(?=.*\bAndroid\b)(?=.*\b(?:KFOT|KFTT|KFJWI|KFJWA|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|KFARWI|KFASWI|KFSAWI|KFSAWA)\b)/i,i=/IEMobile/i,j=/(?=.*\bWindows\b)(?=.*\bARM\b)/i,k=/BlackBerry/i,l=/BB10/i,m=/Opera Mini/i,n=/(CriOS|Chrome)(?=.*\bMobile\b)/i,o=/(?=.*\bFirefox\b)(?=.*\bMobile\b)/i,p=new RegExp("(?:Nexus 7|BNTV250|Kindle Fire|Silk|GT-P1000)","i"),q=function(a,b){return a.test(b)},r=function(a){var r=a||navigator.userAgent,s=r.split("[FBAN");return"undefined"!=typeof s[1]&&(r=s[0]),s=r.split("Twitter"),"undefined"!=typeof s[1]&&(r=s[0]),this.apple={phone:q(b,r),ipod:q(c,r),tablet:!q(b,r)&&q(d,r),device:q(b,r)||q(c,r)||q(d,r)},this.amazon={phone:q(g,r),tablet:!q(g,r)&&q(h,r),device:q(g,r)||q(h,r)},this.android={phone:q(g,r)||q(e,r),tablet:!q(g,r)&&!q(e,r)&&(q(h,r)||q(f,r)),device:q(g,r)||q(h,r)||q(e,r)||q(f,r)},this.windows={phone:q(i,r),tablet:q(j,r),device:q(i,r)||q(j,r)},this.other={blackberry:q(k,r),blackberry10:q(l,r),opera:q(m,r),firefox:q(o,r),chrome:q(n,r),device:q(k,r)||q(l,r)||q(m,r)||q(o,r)||q(n,r)},this.seven_inch=q(p,r),this.any=this.apple.device||this.android.device||this.windows.device||this.other.device||this.seven_inch,this.phone=this.apple.phone||this.android.phone||this.windows.phone,this.tablet=this.apple.tablet||this.android.tablet||this.windows.tablet,"undefined"==typeof window?this:void 0},s=function(){var a=new r;return a.Class=r,a};"undefined"!=typeof module&&module.exports&&"undefined"==typeof window?module.exports=r:"undefined"!=typeof module&&module.exports&&"undefined"!=typeof window?module.exports=s():"function"==typeof define&&define.amd?define("isMobile",[],a.isMobile=s()):a.isMobile=s()}(this);

alert(isMobile.any ? 'Mobile' : 'Not mobile');

这个特定的浏览器嗅探代码是 一个名为 isMobile 的库的代码。


替代方案 2:window.orientation

测试是

window.orientation
的定义:

alert(typeof window.orientation !== 'undefined' ? 'Mobile' : 'Not mobile');


3
投票

理想情况下,您应该将移动设备和台式机视为相同,因为界限非常模糊。带键盘支撑的平板电脑?带触摸屏的笔记本电脑?唯一的区别是 cpu 此时所在的位置。

坚持你正在做的事情:缓存宽度并检查它是否发生变化。不要尝试确定设备是移动设备还是桌面设备,因为您有时会失败。


2
投票

你尝试过吗:

var viewportMetaTag = document.querySelector('meta[name="viewport"]');
var viewportMetaTagIsUsed = viewportMetaTag && viewportMetaTag.hasAttribute('content') ? true : false;

MDN 上的文档:


2
投票

您可以检查orientationchange事件是否存在,并根据该事件分配功能。像下面的代码

if("onorientationchange" in window) {
  //For mobile browsers
  window.addEventListener("orientationchange", resizeCanvas);
} else{
  //For desktop browsers
  window.addEventListener('resize', resizeCanvas);
}

检测事件支持的代码片段取自下面的线程

检测对给定 JavaScript 事件的支持?


2
投票

试试这个:

//mobile detection
    var isDevice = false;
    if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
        isDevice = true;
        // your code ...
    }

或:

if ($('meta[name="viewport"]').size() > 0) {
      // your code ...
}

或:

if ($('meta[name="viewport"]').attr('content').indexOf('device-width') - 1) {
      // your code ...
}

1
投票

我认为你想要的不一定是检测视口标签的使用,而是检测你是否在移动浏览器中运行。

这个答案我们可以找到一个检测大多数移动浏览器的功能:

window.mobilecheck = function() {
    var check = false;
    (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
    return check;
}

然后你可以用它来做你想做的事:

if(window.mobilecheck()){
    //For mobile browsers
    window.addEventListener("orientationchange", resizeCanvas);
} else {
    //For desktop browsers
    window.addEventListener('resize', resizeCanvas);
}

1
投票

您可以通过js更改meta标签的内容(例如将其设置为

width=123
)。现在,您的页面中必须有这样一个元素,它肯定会因此改变其大小(也许是
div@width:100%
?)。之后,您恢复元的原始值,但已经知道它对浏览器是否意味着什么。

如果你这样做,过程的结果应该保存到localStorage或cookie,这样你就只会弄乱页面一次。


0
投票

试试这个:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=0.1">
<script>
    var width=$(window).width();
    $('meta[name=viewport]').attr('content','width=device-width, initial-scale=1');
    var newWidth=$(window).width();
    var viewportMetaTagIsUsed=width!=newWidth;
    alert(viewportMetaTagIsUsed?'using meta viewport':'not using meta viewport');
</script>

或更封装:

	function usesViewport() {
		var meta=$('meta[name=viewport]');
		var content=meta.attr('content');
		if (!meta.length) {
			meta=$('<meta name="viewport" content="width=device-width, initial-scale=1" />').appendTo('head');
			console.log(meta.parent());
		}
		$('meta[name=viewport]').attr('content','width=device-width, initial-scale=1');
		var width1=$(window).width();
		$('meta[name=viewport]').attr('content','width=device-width, initial-scale=0.1');
		var width2=$(window).width();
		if (content) {
			$('meta[name=viewport]').attr('content',content);
		} else {
			meta.remove();
		}
		var result=width1!=width2;
		return result;
	}
	$(function() {
		alert(usesViewport()?'Uses viewport':'Doesn\'t use viewport');
	});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

我不知道为什么它在这里不起作用,可能与脚本的沙箱有关,但是,我仍然将其复制并粘贴到维基百科的控制台中,并且它可以工作。


0
投票

您可以通过重新配置视口来检查视口元标记的有效性。 请参阅下面的代码,该代码已在 iOS Safari、Android Chrome、Android Firefox 上测试。

function checkIfViewportMetaEffective() {
  return new Promise((resolve, reject) => {
    let meta = document.querySelector('meta[name="viewport"]');
    if (!meta) {
      reject(new Error('No viewport meta tag found'));
      return;
    }
    let content = meta.content;
    let root = document.documentElement;
    let tempWidth = root.clientWidth + 3;
    let resolved = false;
    let isApproxmate = (a, b, epsilon = 1) => {
      return a > b - epsilon && a < b + epsilon;
    };
    let resizeHandler = (e) => {
      resolved = true;
      visualViewport.removeEventListener('resize', resizeHandler);
      console.log(root.clientWidth, tempWidth);
      resolve(isApproxmate(root.clientWidth, tempWidth, 1));
      // reset viewport and trigger repaint again
      meta.content = content;
      div.remove();
    };
    visualViewport.addEventListener('resize', resizeHandler);
    setTimeout(() => { if (!resolved) resizeHandler(); }, 50);
    // reconfigure viewport and trigger repaint
    meta.content = content.replace('device-width', tempWidth);
    let div = document.body.appendChild(document.createElement('div'));
  });
}
queueMicrotask(async () => {
  let text = 'is viewport meta effective? ' + await checkIfViewportMetaEffective();
  console.log(text);
});
© www.soinside.com 2019 - 2024. All rights reserved.