核心问题是, 如何将设计图还原到不同屏幕宽度的设备上
需要解决如下问题:
-
- 配置样式预处理语言(scss)
-
- 将设计图还原到不同屏幕宽度的设备上
-
- 1px或者0.5px实现
-
- 图片展示模糊问题解决
配置样式预处理语言(scss)
使用vue-cli3配置
1. 安装依赖包
此处的sass-loader默认安装的是11以上的版本, 在vue3.0上会报错, 需要降级,尝试安装10.1.1后没问题了
npm install -D sass-loader sass
1. 配置自动化导入公共样式
(1) 使用了 style-resources-loader
npm install -D style-resources-loader
(2) 配置
在vue.config.js中, 配置chainWebpack属性; 这样全局会加入./src/styles/imports.scss下的公共样式, 省略了每个vue文件样式内手动引入.
const path = require('path');
module.exports = {
chainWebpack: config => {
const types = ['vue-modules', 'vue', 'normal-modules', 'normal']
types.forEach(type => addStyleResource(config.module.rule('scss').oneOf(type)))
},
}
function addStyleResource (rule) {
rule.use('style-resource')
.loader('style-resources-loader')
.options({
patterns: [
path.resolve(__dirname, './src/styles/imports.scss'),
],
})
}
解决问题2,3,4
-
- 将设计图还原到不同屏幕宽度的设备上
-
- 1px或者0.5px实现
-
- 图片展示模糊问题解决
方案一: flexible方案
核心思想:
-
- 使用rem, 根据屏幕宽度动态设置根元素font-size
-
- 动态设置meta标签内的scale值, 根据dpr动态缩放屏幕,已达到理想效果 淘宝的讲解文章
方案二: viewport方案
使用vue-cli3配置, 不支持的设备实用Viewport Units Buggyfill兼容(现在不支持的很少了) 方案核心思想: 100vw等于页面的宽度, 任何设备,只要支持vw, 页面宽度就是100vw, 这样就能根据设计图转化为vw渲染页面, 从而保证设计图在不同设备的还原.
1. 安装包依赖
npm install -D postcss-px-to-viewport
2. 配置
- 根目录下创建postcss.config.js
- 根据设计图配置viewportWidth属性值, 一般设计图是以iphone6宽度设计的, 所以此处设计750.
- 横屏宽度landscapeWidth为1334,也是iphone6的横屏宽度
- selectorBlackList配置.如需部分选择器不转换单位,可以配置此属性([/^.ingore_/g]此正则会匹配所有以.ingore_开头的选择器, 比较实用)
module.exports = {
plugins: {
// 配置px to vw
'postcss-px-to-viewport': {
unitToConvert: 'px', // 需要转换的单位
viewportWidth: 750, // 设计图视口宽度
unitPrecision: 5, // 小数保留位数
propList: ['*'], // 支持转换的css属性名称
viewportUnit: 'vw', // 转为为vw宽度单位
fontViewportUnit: 'vw', // 字体单位
selectorBlackList: [], // 选择器黑名单,转换时不会转换符合此处的选择器
minPixelValue: 1, // 最小的转换数值
mediaQuery: false, // 媒体查询里面的是否转换
replace: true, // 是否直接替换属性值而不是添加备用属性
exclude: undefined, // 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
include: undefined, // 设置此处值, 则只转换include内的文件
landscape: false, // 是否添加根据 landscapeWidth 生成的媒体查询条件 @media (orientation: landscape)
landscapeUnit: 'vw', // 横屏时使用的单位
landscapeWidth: 1334 // 横屏时使用的视口宽度
}
}
}
3. 1px问题解决
伪元素 + transform scale方案(sass版本)
@mixin border-1px($width: 1px, $color: #ccc, $radius: 0px, $direction: all) {
position: relative;
&::after {
content: "";
pointer-events: none;
display: block;
position: absolute;
border-radius: $radius;
box-sizing: border-box;
width: 100%;
height: 100%;
left: 0;
top: 0;
transform-origin: 0 0;
@if($direction == all) {
border: $width solid $color;
} @else {
border-#{$direction}: $width solid $color;
}
@media only screen and (-webkit-min-device-pixel-ratio:2) {
width: 200%;
height: 200%;
border-radius: $radius * 2;
transform: scale(.5);
}
@media only screen and (-webkit-min-device-pixel-ratio:3) {
width: 300%;
height: 300%;
border-radius: $radius * 3;
transform: scale(.333);
}
}
}
使用
.box-1px {
width: 200px;
height: 200px;
margin-top: 10px;
@include border-1px(0.5px);
}
4. 图片展示模糊问题解决
图片模糊的根本原因是: 在高倍屏上, 1个css像素会被大于1个的物理像素渲染, 例如2倍屏上,图片一个像素点会被4个物理像素渲染,每个物理像素只能取临近的色值,所以就会模糊. 图片上一个像素对应于一个物理像素就不会产生模糊问题, 所以解决问题最终要朝这个方向努力.
以下也有几种方式解决:
(1)img标签推荐srcset,sizes的方式
作为原生的解决方案, 无疑是体验最好的, 也是最省力的.
srcset,sizes会根据屏幕宽度,设备像素比自动选择合适的图片渲染出来.
如下例子:
在小于360px宽度的屏幕上,
dpr=1的屏幕上, 实际渲染宽度128 * 1 = 128, 所以会渲染mm-width-128px.jpg;
dpr=2的屏幕上, 实际渲染宽度 128 * 2 = 256, 所以会渲染mm-width-256px.jpg;
在大于360px宽度的屏幕上,
dpr=1的屏幕上, 实际渲染宽度256 * 1 = 256, 所以会渲染mm-width-256px.jpg;
dpr=2的屏幕上, 实际渲染宽度 256 * 2 = 512, 所以会渲染mm-width-512px.jpg;
<img class="ingore_img" src="https://www.zhangxinxu.com/study/201410/mm-width-128px.jpg"
srcset="https://www.zhangxinxu.com/study/201410/mm-width-128px.jpg 128w, https://www.zhangxinxu.com/study/201410/mm-width-256px.jpg 256w, https://www.zhangxinxu.com/study/201410/mm-width-512px.jpg 512w"
sizes="(max-width: 360px) 128px, 256px" alt="图片模糊解决">
(2)背景图片推荐image-set()
浏览器会根据dpr, 选择1倍图,或者2倍图展示, 单属性兼容性差
background-image: image-set( url(https://www.zhangxinxu.com/study/201410/mm-width-128px.jpg) 1x, url(https://www.zhangxinxu.com/study/201410/mm-width-256px.jpg) 2x, url(https://www.zhangxinxu.com/study/201410/mm-width-128px.jpg) 600dpi);
(3) 媒体查询方式
.avatar{
background-image: url(conardLi_1x.png);
}
@media only screen and (-webkit-min-device-pixel-ratio:2){
.avatar{
background-image: url(conardLi_2x.png);
}
}
@media only screen and (-webkit-min-device-pixel-ratio:3){
.avatar{
background-image: url(conardLi_3x.png);
}
}
(4) svg
svg无论放多大,都不会失真