原生js实现 兼容常规pc、大屏、移动端 适配方案
项目背景:1、设计稿1)pc设计稿为19201080的可视化大屏,16:9比例设计2)大屏设计稿35841152的可视化大屏,28:9比例设计3)移动端设计稿 宽750的可视化大屏2、适配不同屏幕1)pc要兼容不同分辨率下的屏幕,注意这里说的是往下兼容 兼容1k以下的 不能出现滚动条 使用scale2)大屏比例为28:9,在项目开发中,可以按照1680:540 达到28:9的效果 不能出现滚动条
1、设计稿
1)pc设计稿为19201080的可视化大屏,16:9比例设计
2)大屏设计稿35841152的可视化大屏,28:9比例设计
3)移动端设计稿 宽750的可视化大屏
2、适配不同屏幕
1)pc要兼容不同分辨率下的屏幕,注意这里说的是往下兼容 兼容1k以下的 不能出现滚动条 使用scale
2)大屏比例为28:9,在项目开发中,可以按照1680:540 达到28:9的效果 不能出现滚动条 使用rem
3)移动端兼容,以750为标准实现适配 使用rem
3、实现思路:
1)pc可以根据vw、vh去实现
<style scoped lang="scss">
@function vw($px) {
@return ($px/1920) * 100vw;
}
body {
width:vw(1920)
}
</<style>
问题:在echats中,当在小屏幕的时候,图表的字体会比ui稿上的大,这时候你又要把字体在js里面再进行一步转换
// 字体转换
function toFontSize(px){
let vw = px / 1920;
let htmlWidth = document.documentElement.clientWidth || document.body.clientWidth;
return htmlWidth * vw
}
2)rem
rem (font size of the root element), 是 css3 的引入的一个大小单位。即相对于根元素的 font-size 值的大小。所谓根元素在网页里一般就是 html。
问题:在echats中,当在小屏幕的时候,图表的字体会比ui稿上的大,这时候你又要把字体在js里面再进行一步转换
3)缩放scale
浏览器body设置为设计稿宽高即1920*1080, 动态根据实际宽高对body的width,height进行缩放,从而实现内容缩放
采用scale方案,字体不受浏览器最小字体限制,可以自由绽放到该分辨率下对应比例
4)根据不同屏幕切换显示 不同页面
pc和大屏的页面布局结构一致,所以更换className去实现切换
移动端与pc、大屏的页面布局都不一致,所以根据js判断当前是否为移动设备进行显示切换
4、简单实现代码
<!DOCTYPE html>
<html>
<head><meta name="viewport" content="width=device-width,initial-scale=1.0,maixmum-scale=1.0,minimum-scale=1.0,user-scalable=no"></head>
<body>
<!-- 大屏 + pc 页面 -->
<div class="pc" id="main">
<div class="column">
<div class="bk"></div>
<div class="bk"></div>
<div class="bk"></div>
</div>
<div class="column">
<div class="big-bk"></div>
<div class="big-bk"></div>
</div>
<div class="column">
<div class="bk"></div>
<div class="bk"></div>
<div class="bk"></div>
</div>
</div>
<!-- 移动端页面 -->
<div class="mobile">
<div class="column">
<div class="bk"></div>
<div class="bk"></div>
<div class="bk"></div>
<div class="bk"></div>
</div>
</div>
</body>
<script>
var bodyStyle = document.createElement('style')
var docWidth,docHeight;
var designWidth,designHeight;
// 屏幕缩放实现
function refreshScale(){
bodyStyle.innerHTML=`body{width:${designWidth}px; height:${designHeight}px!important;}`
document.documentElement.firstElementChild.appendChild(bodyStyle)
document.getElementById('main').style='display:flex'
document.getElementsByClassName('mobile')[0].style='display:none'
var widthRatio = docWidth / designWidth,
heightRatio = docHeight / designHeight;
document.body.style = `transform:scale(${widthRatio},${heightRatio});transform-origin:left top;`;
// 应对浏览器全屏切换前后窗口因短暂滚动条问题出现未占满情况
setTimeout(function(){
var lateWidth= document.documentElement.clientWidth,
lateHeight = document.documentElement.clientHeight;
if( lateWidth === docWidth ) return;
widthRatio = lateWidth / designWidth
heightRatio = lateHeight / designHeight
document.body.style = "transform:scale(" + widthRatio + "," + heightRatio + ");transform-origin:left top;"
},0)
}
// 清除scale
function clearScale(){
// 清除pc样式
bodyStyle.innerHTML=``
document.documentElement.firstElementChild.appendChild(bodyStyle)
document.body.style="transform:none;transform-origin:none"
}
// 初始化
function init(){
// 获取当前屏幕可视区域大小
docWidth = document.documentElement.clientWidth;
docHeight = document.documentElement.clientHeight;
// 判断是否是移动设备
if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i.test(navigator.userAgent)){
mobilePage();
}else{
let mainClass = document.getElementById('main').classList;
if(docWidth == 1680 || docWidth == 3584){ // 模拟大屏
designWidth = docWidth;
designHeight = docWidth / 28 *9;
mainClass.add('large');
mainClass.remove('pc');
largePage();
}else{ // pc
designWidth = 1920;
designHeight = 1080;
mainClass.add('pc');
mainClass.remove('large');
refreshScale()
}
}
}
// 大屏设置 rem 函数
function setRem (designSize) {
// 基准大小
baseSize = 100;
let basePc = baseSize / designSize; // 表示1680的设计图,使用100PX的默认值
let vW = window.innerWidth; // 当前窗口的宽度
let rem = vW * basePc; // 以默认比例值乘以当前窗口宽度,得到该宽度下的相应font-size值
document.documentElement.style.fontSize = rem + "px";
}
// 大屏页面
function largePage(){
clearScale();
document.getElementById('main').style='display:flex'
document.getElementsByClassName('mobile')[0].style='display:none'
// 大屏 设置 rem 函数
let designSize = 1680;
setRem(designSize);
}
// 移动端页面
function mobilePage(){
clearScale()
// 是移动设备 展示移动设备页
document.getElementById('main').style='display:none'
document.getElementsByClassName('mobile')[0].style='display:flex'
// mobile 设置 rem 函数
let designSize = 750;
setRem(designSize);
}
// 初始化
init();
// 监听前进/后退以及load事件触发
window.addEventListener("pageshow", function (e) {
if (e.persisted) { // 浏览器后退的时候重新计算
init()
}
}, false);
// 监听屏幕缩放
window.addEventListener("resize",function(){
init()
}, false);
</script>
</html>
<style>
html {
width: 100%;
height: 100%;
}
body{
margin:0px;
transform: translate3d(0,0,0)
}
/* pc */
.pc {
width: 1860px;
height: 1020px;
display: flex;
flex-direction: row;
justify-content: space-between;
padding:30px;
}
.pc .column {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.pc .bk {
width: 450px;
height: 350px;
border: #000 solid 1px;
margin-top: 30px;
}
.bk:first-child{
margin-top: 0px;
}
.pc .big-bk {
width: 850px;
height: 550px;
border: #000 solid 1px;
margin: 30px 30px 0px 30px;
}
.big-bk:first-child {
margin-top: 0px;
}
/* 移动端 */
.mobile {
display: flex;
flex-direction: column;
align-items: center;
}
.mobile .bk {
width: 6.9rem;
height: 2rem;
border: #000 solid 0.01rem;
margin-top: 0.3rem;
}
/* 大屏 */
.large {
width: 16.2rem;
height: 4.6rem;
display: flex;
flex-direction: row;
justify-content: space-between;
padding:0.3rem;
}
.large .column {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.large .bk {
width: 4.5rem;
height: 1.5rem;
border: #000 solid 1px;
margin-top: 0.3rem;
}
.large .big-bk {
width: 6.5rem;
height: 2.5rem;
border: #000 solid 1px;
margin: 0.3rem 0.3rem 0rem 0.3rem;
}
</style>
pc兼容 参考:https://blog.csdn.net/sophie_u/article/details/109582687
更多推荐
所有评论(0)