大屏可视化的自适应处理,除了要懂得前端的基本布局以外,还需要了解各个场景下的自适应方案选型,这里提供三种自适应处理大屏的方案,每一种方案同时提供原生JS项目中的使用方式以及vue项目中的使用方式
这里介绍的这几种方案只要是web页面都适用,不限于是不是大屏的项目哦~
在写一些自适应页面的时候推荐使用百分比布局、Flex布局、Grid布局
方案一:使用传统的rem/vw进行适配(不推荐)
rem处理
1. js项目中
(function(doc, win) {
var docEl = doc.documentElement,
isIOS = navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/),
dpr = isIOS ? Math.min(win.devicePixelRatio, 3) : 1,
dpr = window.top === window.self ? dpr : 1, //被iframe引用时,禁止缩放
dpr = 1,
scale = 1 / dpr,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
docEl.dataset.dpr = dpr;
var metaEl = doc.createElement('meta');
metaEl.name = 'viewport';
metaEl.content = 'initial-scale=' + scale + ',maximum-scale=' + scale + ', minimum-scale=' + scale;
docEl.firstElementChild.appendChild(metaEl);
var recalc = function() {
var width = docEl.clientWidth;
if (width / dpr > 750) {
width = 750 * dpr;
}
// 乘以100,px : rem = 100 : 1
docEl.style.fontSize = 100 * (width / 750) + 'px';
};
recalc()
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
})(document, window);
2. vue项目中
安装lib-flexible和postcss-px2rem
npm install lib-flexible --save
npm install postcss-px2rem --save
在main.js中引入lib-flexible
import 'lib-flexible'
以vue-cli4工程为例,package.json同级目录下新建vue.config.js文件,在文件中写入以下代码
module.exports = {
css: {
loaderOptions: {
css: {},
postcss: {
plugins: [
require('postcss-px2rem')({
remUnit: 37.5 //根据设计图
//375的图就给37.5,也就是1rem=37.5px
})
]
}
}
},
}
vw处理
1.js项目中
在项目根目录创建package.json文件
{
"devDependencies": {
"gulp": "^3.9.1",
"gulp-cssnano": "^2.1.3",
"gulp-postcss": "^7.0.1",
"gulp-rename": "^1.2.2",
"gulp-sass": "^4.0.1",
"gulp-sourcemaps": "^2.6.4",
"postcss-assets": "^5.0.0",
"postcss-cssnext": "^3.1.0",
"postcss-px-to-viewport": "^0.0.3",
"postcss-short": "^4.1.0",
"postcss-short-color": "^3.0.0",
"postcss-viewport-units": "^0.1.6",
"postcss-write-svg": "github:jonathantneal/postcss-write-svg"
},
"dependencies": {
"autoprefixer": "^9.4.10",
"postcss-aspect-ratio-mini": "^0.0.2"
}
}
新建gulp.js并配置
var gulp=require('gulp');
var postcss=require('gulp-postcss');
var sass=require('gulp-sass');
var shortColor = require('postcss-short-color');
var autoprefixer = require('autoprefixer');
var cssnext = require('postcss-cssnext');
var shortcss = require('postcss-short');
var pxtoviewport = require('postcss-px-to-viewport');
var sourcemaps=require('gulp-sourcemaps');
var rename=require('gulp-rename');
var cssnano=require('gulp-cssnano');
gulp.task('css',function(){
var processors=[
require('postcss-short-color'),
shortcss,
cssnext,
autoprefixer({browsers: ['> 1%'], cascade: false}),
pxtoviewport({
viewportWidth: 750, // 视窗的宽度,对应的是我们设计稿的宽度,一般是750
viewportHeight: 1334, // 视窗的高度,根据750设备的宽度来指定,一般指定1334,也可以不配置
unitPrecision: 3, // 指定`px`转换为视窗单位值的小数位数(很多时候无法整除)
viewportUnit: 'vw', // 指定需要转换成的视窗单位,建议使用vw
selectorBlackList: ['.ignore', '.hairlines'], // 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名
minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也可以设置为你想要的值
mediaQuery: false // 允许在媒体查询中转换`px`著作权归作者所有。
}),
require('postcss-write-svg'),
require('postcss-aspect-ratio-mini'),
require('postcss-viewport-units'),
];
return gulp.src('./src/css/*.scss').pipe(sass().on('error',sass.logError))
.pipe(postcss(processors))
.pipe(gulp.dest('./dest'));
});
gulp.task('rename',['css'],function(){
return gulp.src('dest/style.css')
.pipe(postcss([cssnano]))
.pipe(rename('style.min.css'))
.pipe(sourcemaps.init())
.pipe(sourcemaps.write('maps/'))
.pipe(gulp.dest('./dest'))
});
gulp.task('default',['css','rename']);
// 监听功能
var watcher=gulp.watch('src/*.css',['default']);
watcher.on('change',function(event){
console.log('File'+event.path+'was'+event.type+',running tasking ...');
});
2.vue项目中
这里以vue-cli4工程为例,安装相关依赖包
npm i cssnano postcss-aspect-ratio-mini postcss-cssnext postcss-px-to-viewport postcss-viewport-units postcss-write-svg -S
npm i cssnano-preset-advanced -D
npm i postcss-import postcss-url autoprefixer -D
在postcss.config.js添加以下配置
module.exports = {
"plugins": {
"postcss-import": {},
"postcss-url": {},
"postcss-aspect-ratio-mini": {},
"postcss-write-svg": {
utf8: false
},
"postcss-cssnext": {},
"postcss-px-to-viewport": {
viewportWidth: 750, // 视窗的宽度,对应的是我们设计稿的宽度,一般是750
viewportHeight: 1334, // 视窗的高度,根据750设备的宽度来指定,一般指定1334,也可以不配置
unitPrecision: 3, // 指定`px`转换为视窗单位值的小数位数(很多时候无法整除)
viewportUnit: 'vw', // 指定需要转换成的视窗单位,建议使用vw
selectorBlackList: ['.ignore', '.hairlines'], // 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名
minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也可以设置为你想要的值
mediaQuery: false // 允许在媒体查询中转换`px`
},
"postcss-viewport-units":{},
"cssnano": {
preset: "advanced",
autoprefixer: false,
"postcss-zindex": false
},
}
}
在public文件夹下的index.html添加以下内容
<script
src="//g.alicdn.com/fdilab/lib3rd/viewport-units-buggyfill/0.6.2/??viewport-units-buggyfill.hacks.min.js,viewport-units-buggyfill.min.js"></script>
<script>
window.onload = function () {
window.viewportUnitsBuggyfill.init({
hacks: window.viewportUnitsBuggyfillHacks
});
}
</script>
方案二:zoom缩放(推荐)
1.js项目中
$(window).resize(function() {
$("body").css("zoom", $(window).width() / 1920);
});
$("body").css("zoom", $(window).width() / 1920);
2.vue项目中
window.onload = function() {
document.body.style.zoom = "normal"; //避免zoom尺寸叠加
let scale = document.body.clientWidth / 1920;
document.body.style.zoom = scale;
};
//防抖,避免resize占用过多资源
(function() {
var throttle = function(type, name, obj) {
obj = obj || window;
var running = false;
var func = function() {
if (running) {
return;
}
running = true;
requestAnimationFrame(function() {
obj.dispatchEvent(new CustomEvent(name));
running = false;
});
};
obj.addEventListener(type, func);
};
throttle("resize", "optimizedResize");
})();
window.addEventListener("optimizedResize", function() {
document.body.style.zoom = "normal";
let scale = document.body.clientWidth / 1920;
document.body.style.zoom = scale;
});
方案三:scale缩放(推荐)
1.js项目中
function screenSize(editorDom) {
let screenWidth = document.body.clientWidth || document.documentElement.clientWidth;
let screenHeight = document.body.clientHeight || document.documentElement.clientHeight;
let defWidth = 1920;
let defHeight = 1080;
let xScale = screenWidth / defWidth;
let yScale = screenHeight / defHeight;
document.getElementById(editorDom).style.cssText += ';transform: scale(' + xScale + ',' + yScale + ')';
$(window).resize(() => {
let screenWidth = document.body.clientWidth || document.documentElement.clientWidth;
let screenHeight = document.body.clientHeight || document.documentElement.clientHeight;
xScale = screenWidth / defWidth;
yScale = screenHeight / defHeight;
document.getElementById(editorDom).style.cssText += ';transform: scale(' + xScale + ',' + yScale + ')';
})
}
2.vue项目中
export function screenSize(editorDom) {
let screenWidth = document.body.clientWidth || document.documentElement.clientWidth;
let screenHeight = document.body.clientHeight || document.documentElement.clientHeight;
let defWidth = 1920;
let defHeight = 1080;
let xScale = screenWidth / defWidth;
let yScale = screenHeight / defHeight;
editorDom.style.cssText += ';transform: scale(' + xScale + ',' + yScale + ')';
$(window).resize(() => {
let screenWidth = document.body.clientWidth || document.documentElement.clientWidth;
let screenHeight = document.body.clientHeight || document.documentElement.clientHeight;
xScale = screenWidth / defWidth;
yScale = screenHeight / defHeight;
editorDom.style.cssText += ';transform: scale(' + xScale + ',' + yScale + ')';
})
}