总结一些h5出现的问题及解决方案
1、ios的webview中滑动不流畅。(原因:ios5.0以后的版本,滑动定义有两个值auto和touch。默认值为auto)
-webkit-overflow-scrolling: touch; /* 当手指从触摸屏上移开,会保持一段时间的滚动 */ -webkit-overflow-scrolling: auto; /* 当手指从触摸屏上移开,滚动会立即停止 */
解决方案:
①、在滚动容器上增加滚动touch方法
.wrapper {
-webkit-overflow-scrolling: touch;
}
②、设置滚动条隐藏:
.container ::-webkit-scrollbar {display: none;}
可能会导致使用position:fixed;固定定位的元素,随着页面一起滚动
③、设置overflow
body { overflow-y: hidden; } .wrapper { overflow-y: auto; }
设置之后,就会出现一个问题,ios上拉边界下拉出现白色空白
产生原因:在ios中,手指按住屏幕上下拖动,会触发touchmove事件。这个时间触发的对象是整个view容器,容器自然会被拖动,剩下的部分会成空白。
解决方案:
①、监听事件禁止滚动
通过监听touchmove,让需要滑动的地方滑动,不需要滑动的地方禁止滑动(值得注意的是我们要过滤掉具有滚动容器的元素)。
document.body.addEventListener('touchmove', function(e) { if(e._isScroller) return; // 阻止默认事件 e.preventDefault(); }, { passive: false });
2、滚动拖鞋填充空白,装饰城其他功能(比如:下拉后刷新页面)
HTML 中meta元标签标准中有个viewport属性,用来控制页面的缩放,一般用于移动端,如下图:
移动端常规写法:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
因此我们可以设置maximum-scale、minimum-scale与user-scalable=no用来避免这个问题
<meta name=viewport
content="width=device-width, initial-scale=1.0, minimum-scale=1.0 maximum-scale=1.0, user-scalable=no">
3、软键盘将页面顶起来、收起未回落问题
原理与解决方案:
软键盘将页面顶起来的解决方案,主要是通过监听页面高度变化,强制恢复成弹出前的高度。
// 记录原有的视口高度 const originalHeight = document.body.clientHeight || document.documentElement.clientHeight; window.onresize = function(){ var resizeHeight = document.documentElement.clientHeight || document.body.clientHeight; if(resizeHeight < originalHeight ){ // 恢复内容区域高度 // const container = document.getElementById("container") // 例如 container.style.height = originalHeight; } }
键盘不能回落问题出现在ios 12+和wechat6.7.4+中,而在微信h5开发中是比较常见额bug
兼容原理,判断版本类型,更改滚动的可视区域
const isWechat = window.navigator.userAgent.match(/MicroMessenger\/([\d\.]+)/i); if (!isWechat) return; const wechatVersion = wechatInfo[1]; const version = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/); // 如果设备类型为iOS 12+ 和wechat 6.7.4+,恢复成原来的视口 if (+wechatVersion.replace(/\./g, '') >= 674 && +version[1] >= 12) { window.scrollTo(0, Math.max(document.body.clientHeight, document.documentElement.clientHeight)); }
注意:window.scrollTo(x-coord, y-coord),其中window.scrollTo(0, clientHeight)恢复成原来的视口
4、iphone X系列安全区域适配问题
产生的原因iphone X以及它以上的系列,都采用刘海屏设计和全面屏手势。头部、底部、侧边都需要做特殊处理。才能适配iPhone X的特殊情况。
解决方案:
①、设置安全区域,填充危险区域,危险区域不做操作和内容展示
②、viewport-fit meta标签设置问cover,获取所有区域填充。判断设备是否属于iPhone X,给头部底部增加适配层
viewport-fit 有 3 个值分别为:
auto:此值不影响初始布局视图端口,并且整个web页面都是可查看的。
contain:视图端口按比例缩放,以适合显示内嵌的最大矩形。
cover:视图端口被缩放以填充设备显示。强烈建议使用 safe area inset 变量,以确保重要内容不会出现在显示之外。
设置viewport-fit为cover
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes, viewport-fit=cover">
添加适配层,使用 safe area inset变量
/* 适配 iPhone X 顶部填充*/ @supports (top: env(safe-area-inset-top)){ body, .header{ padding-top: constant(safe-area-inset-top, 40px); padding-top: env(safe-area-inset-top, 40px); padding-top: var(safe-area-inset-top, 40px); } } /* 判断iPhoneX 将 footer 的 padding-bottom 填充到最底部 */ @supports (bottom: env(safe-area-inset-bottom)){ body, .footer{ padding-bottom: constant(safe-area-inset-bottom, 20px); padding-bottom: env(safe-area-inset-bottom, 20px); padding-top: var(safe-area-inset-bottom, 20px); } }
注意:safe-area-inset-top
, safe-area-inset-right
, safe-area-inset-bottom
, safe-area-inset-left
safe-area-inset-*
由四个定义了视口边缘内矩形的 top
, right
, bottom
和 left
的环境变量组成,这样可以安全地放入内容,而不会有被非矩形的显示切断的风险。对于矩形视口,例如普通的笔记本电脑显示器,其值等于零。对于非矩形显示器(如圆形表盘,iPhoneX
屏幕),在用户代理设置的四个值形成的矩形内,所有内容均可见。
其中 env()
用法为 env( <custom-ident> , <declaration-value>? )
,第一个参数为自定义的区域,第二个为备用值。
其中 var()
用法为 var( <custom-property-name> , <declaration-value>? )
,作用是在 env()
不生效的情况下,给出一个备用值。
constant()
被 css
2017-2018 年为草稿阶段,是否已被标准化未知。而其他iOS 浏览器版本中是否有此函数未知,作为兼容处理而添加进去。
5、页面生成为图片和二维码问题
①、使用QRCode生成二维码
import QRCode from 'qrcode'; // 使用 async 生成图片 const options = {}; const url = window.location.href; async url => { try { console.log(await QRCode.toDataURL(url, options)) } catch (err) { console.error(err); } }
将 await QRCode.toDataURL(url, options)
赋值给 图片 url
即可
②、生成图片:
主要是使用 htmlToCanvas
生成 canvas
画布
import html2canvas from 'html2canvas'; html2canvas(document.body).then(function(canvas) { document.body.appendChild(canvas); });
但是不单单在此处就完了,由于是 canvas
的原因。移动端生成出来的图片比较模糊。
我们使用一个新的 canvas
方法多倍生成,放入一倍容器里面,达到更加清晰的效果,通过超链接下载图片 下载文件简单实现,更完整的实现方式之后更新
const scaleSize = 2; const newCanvas = document.createElement("canvas"); const target = document.querySelector('div'); const width = parseInt(window.getComputedStyle(target).width); const height = parseInt(window.getComputedStyle(target).height); newCanvas.width = width * scaleSize; newCanvas.height = widthh * scaleSize; newCanvas.style.width = width + "px"; newCanvas.style.height =width + "px"; const context = newCanvas.getContext("2d"); context.scale(scaleSize, scaleSize); html2canvas(document.querySelector('.demo'), { canvas: newCanvas }).then(function(canvas) { // 简单的通过超链接设置下载功能 document.querySelector(".btn").setAttribute('href', canvas.toDataURL()); }
根据需要设置 scaleSize
大小