一、背景:pdf预览
我司预览pdf时,pc端使用的是微软的在线预览,样式如下:
或者使用pdfjs预览:
这些预览插件在pc端表现不错,但是在移动端表现不尽如人意,尤其是在遇到不同的型号的浏览器时,兼容性问题层出不穷
为了统一解决pdf在h5端的预览,我找了个插件:pdfh5
,它可以很轻松的预览pdf,不挑机型,都显示这样
二、判断设备类型
由于pc和h5使用的插件不一样,那么肯定要判断设备类型,众所周知,navigator.userAgent
就是专门用来判断设备的,它可以识别出pc还是h5,识别出浏览器类型
谷歌:
火狐:
QQ浏览器:
我的vivo手机自带浏览器(可以看到Android、Mobile、VivoBrowser等关键信息):
于是我们可以封装一个函数,用来判断设备:
function getDeviceType(userAgent) {
userAgent = userAgent || navigator.userAgent
// 检查是否为移动设备
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent)
// 检查是否为平板设备
const isTablet =
/Tablet|iPad|PlayBook|Nexus 7|Nexus 10|Kindle|Silk|GT-P1000|GT-P1010|GT-P7500|GT-P7510|SCH-I800M|SHW-M180S|SM-T320|SM-T350|SM-T520|SM-T550|SM-T560|SM-T800|SM-T805|SM-T807|SM-T820|SM-T830|SM-T850|SM-T900|SM-T905|SM-T920|SM-T950|SM-T960|SM-T970|SM-T975|SM-T980|SM-T985|SM-T990|SM-T995|SM-T999|SM-T810|SM-T815|SM-T817|SM-T825|SM-T835|SM-T855|SM-T860|SM-T870|SM-T880|SM-T890|SM-T895|SM-T900|SM-T905|SM-T920|SM-T950|SM-T960|SM-T970|SM-T975|SM-T980|SM-T985|SM-T990|SM-T995|SM-T999/i.test(
userAgent
)
// 如果是移动设备但不是平板设备,则为手机
if ((isMobile || isHarmonyPhone) && !isTablet) {
return "Mobile"
} else if (isTablet) {
return "Tablet"
} else {
return "PC"
}
}
三、问题点
- 以上判断设置机型的方法,在绝大多数情况下,都是适用的;或者说在鸿蒙系统之前,在h5端都没问题
但是在华为的鸿蒙系统出来后,判断设备时,它有自己的一些特殊标识,需要将鸿蒙系统考虑进去
- 此外,在老版的鸿蒙系统中,自带的浏览器打印出来的userAgent竟然和pc端一样
询问AI,这是什么骚操作
所以我们封装的方法在这个浏览器上无法区分出来是pc还是h5,好在最新版的鸿蒙已不存在此问题,只需要在识别设备时将鸿蒙考虑进去即可
最终的方法(参考):
function getDeviceType(userAgent) {
userAgent = userAgent || navigator.userAgent
// 检查是否为移动设备
const isMobile =
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
userAgent
)
// 检查是否为鸿蒙手机端
const isHarmonyPhone = /Harmony/i.test(navigator.userAgent) && /Mobile|Phone/i.test(navigator.userAgent)
// 检查是否为平板设备
const isTablet =
/Tablet|iPad|PlayBook|Nexus 7|Nexus 10|Kindle|Silk|GT-P1000|GT-P1010|GT-P7500|GT-P7510|SCH-I800M|SHW-M180S|SM-T320|SM-T350|SM-T520|SM-T550|SM-T560|SM-T800|SM-T805|SM-T807|SM-T820|SM-T830|SM-T850|SM-T900|SM-T905|SM-T920|SM-T950|SM-T960|SM-T970|SM-T975|SM-T980|SM-T985|SM-T990|SM-T995|SM-T999|SM-T810|SM-T815|SM-T817|SM-T825|SM-T835|SM-T855|SM-T860|SM-T870|SM-T880|SM-T890|SM-T895|SM-T900|SM-T905|SM-T920|SM-T950|SM-T960|SM-T970|SM-T975|SM-T980|SM-T985|SM-T990|SM-T995|SM-T999/i.test(
userAgent
)
// 如果是移动设备但不是平板设备,则为手机
if ((isMobile || isHarmonyPhone) && !isTablet) {
return "Mobile"
} else if (isTablet) {
return "Tablet"
} else {
const isSmallScreen = 'ontouchstart' in window || navigator.maxTouchPoints >= 2 || window.screen.width <= 960
return isSmallScreen ? "Mobile": "PC"
}
}
如果你的项目比较早,鸿蒙系统发布后,用户使用鸿蒙设备访问,可能会有个线上bug哦,自检
四、扩展
pdfh5自带的download方法进行下载,在手机端各个浏览器表现不一致
例如:
- 谷歌:支持设置pdf文件名,但文件超过8M时,下载不了
- vivo浏览器:不支持设置pdf文件名
- QQ浏览器:不支持设置pdf文件名 ...
通过创建a元素实现下载,实测几个浏览器都没问题,苹果手机也支持,鸿蒙也支持
function downloadUrl(url,fileName){
let title = fileName;
let urlName = url.split('/'),
urlNameLen = urlName.length-1;
if(!title){
title = urlName[urlNameLen]
}
fetch(url)
// 获取 blob 对象
.then(res=>res.blob())
.then(blob=>{
var link = document.createElement('a');
link.style.display = 'none';
document.body.appendChild(link);
var url = window.URL.createObjectURL(blob);
link.href = url;
link.download = title;
link.click();
//下载完成后清理URL对象和a标签
window.URL.revokeObjectURL(url);
document.body.removeChild(link);
})
}
如果你觉得这篇文章对你有用,可以看看作者封装的库xtt-utils,里面封装了非常实用的js方法。如果你也是vue开发者,那更好了,除了常用的api,还有大量的基于element-ui组件库二次封装的使用方法和自定义指令等,帮你提升开发效率。不定期更新,欢迎交流~