一、视口相关
当我们写完的html代码用浏览器的移动端打开的时候,会发现字体变小了,很模糊,甚至看不清楚,所以我们需要加上meta视口标签的配置,来改变这种情况。
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no"/>
/**
width=device-width 表示的当前视口宽度等于当前设备的宽度
initial-scale=1表示的是当前缩放的是1,也就是没有缩放
user-scalable=no:表示的是用户是否可以进行缩放,no表示否
*/
我们来思考一个问题,我们如何在不同的设备上来实现不同的布局呢?
上面说的这个问题就是响应式布局,那么响应式布局如何实现呢?首先我们能够想到的就是媒体查询的方式
<header>
//必须要保证设置了viewport
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no"/>
</header>
<style>
.box {
width:400px;
height:400px;
background:#f1b0b7;
}
//媒体查询的方式
@media all and (min-width:400px ) and (max-width:1000px){
.box{
background:#000;
}
}
</style>
像素比
像素比:物理像素/逻辑像素
屏幕:我们的屏幕就是一个一个的发光二极管组成的,比如我们的电脑的最高的分辨率是1920x1080那么屏幕上的发光二极管的数量就是1920x1080个。
那么物理像素就是1920x1080;而逻辑像素则是当我们调整我们电脑的分辨率,比如我调整我的电脑到1366x768,他就会通过多个发光二极管去显示一个物理像素,所以逻辑像素就是1366x768。这两个数值的比值就是像素比。
适配
1.vw、vh适配
在页面中的元素,其实是占用固定的比例,不管手机多大多小,都能完整的显示页面,并且没有结构上的差异。
移动端主要通过vm,和vh来实现适配
1vw = 屏幕宽度的百分之一; 1vh= 屏幕高度的百分之一;所以50vw等于屏幕宽度的一半
实际项目使用
给我一张设计稿 宽度是750px像素的,然后我们要去适配它,我们应该怎么去实现不同设备的适配呢?
比如这个设计稿中,搜索栏的宽度和高度分别是;100% 和94px:
<div class=search></div>
/**
750px = 100vw 所以 1vw = 7.5px;
94px = ?vw ? = 94/7.5vw
*/
<style>
.search{
width:100vw;
height:calc(94vw/7.5);
background:#fff;
}
</style>
//通过上面的计算我们可以发现搜索栏的高度应该是94/7.5vw;这样就是实现适配了。我们当然也可以计算出具体的值,但是没有必要,因为太麻烦了.
这种方式存在一个问题就是会大量的换算公式,比较麻烦,我们可以通过scss文件来解决这个问题
//scss.css
$vw = 7.5;
//使用方式,可以直接使用 `/` 进行计算
.search{
width:100vw;
height:94vw/$vw;
background:#fff
}
2.em适配
em 相对于当前元素的font-size大小
看下面的例子:
<head>
<style>
.box{
font-size:20px;
}
.main{
//因为em是相对于自身的font-size来说的,但是自身的font-size也是em所以它会往上找;
font-size:2em;//40pxx
width:2em;//80px
height:3em;//120px
}
</style>
</head>
<div class="box">
<div class="main"></div>
</div>
3.rem适配
r:表示的是root 的意思,根元素,html;始终相对于根元素的font-size大小来计算;
rem 适配的基本原理: 是通过改变跟元素的font-size来实现的,我们来看下面的代码
<head>
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no"/>
<style>
html{
font-size:32px;
}
.box{
width:5rem;
height:3rem;
background:#103433;
}
</style>
<script>
//我们不可能每次设备改变了都去手动修改根元素font-size的值。但是我们可以通过js动态的去修改:
let rootEl = document.documentElement;
let viewWidth = window.innerWidth;
rootEl.style.fontSize = viewWidth/10 + 'px'
</script>
</head>
<body>
<div class="box"></div>
</body>
接下来我们模拟一下实际项目开发中的适配场景:
/**
首先我们假设我们把屏幕分成25rem ,也可以是其他rem 根据个人需要
1.我们把屏幕分成25份 : html-font-size : width/25 等于 100vw/25 = 4vw;
2.设计稿也要分成25份 : 750/25 = 30px 所以1rem = 30px
3.假设我们有一个元素.box 宽度是80px,我们该如何计算它的rem????
80px = ?rem 因为 1rem = 30px 所以 ? = 80/30rem;
4.同时我们还需要修改上面的js计算的font-size为分成25份的大小
let rootEl = document.documentElement;
let viewWidth = window.innerWidth;
rootEl.style.fontSize = viewWidth/25 + 'px'
5.我们在scss文件中设置元素的宽度:
$rem = 30;
.box{
width:80rem/$rem;
}
*/
4.flex布局
flex 布局很经典,主要是子组件身上的事件,现在先不记录,用的时候再说。
二、移动端事件
1.移动端的鼠标事件
大家都知道在pc端有鼠标事件,但是在移动端我们都是用手指点击,那么手指的点击事件肯定也有对应的方法,并且移动端同样具有pc端的鼠标点击事件:
pc端鼠标点击事件:
- mousedown:鼠标在元素身上按下;
- mousemove:鼠标在元素身上移动;
- mouseup:鼠标在元素身上抬起;
移动端手指点击事件:
- touchstart : 手指在元素身上按下;
- touchmove: 手指在屏幕中移动(在此之前,手指必须在元素身上按下,不管移动的时候手指是否在元素身上);
- touchend : 手指在屏幕中抬起(在此之前,手指必须在元素身上按下);
移动端也支持鼠标事件,但是鼠标事件的执行会被延迟一段时间:
移动端在点击元素的时候,会立即执行元素身上的touch事件,同时记录点击的坐标点等touch事件执行完毕之后,会再一次在坐标中查找元素,并且执行元素身上的mouse事件 300ms; mouse事件和touch事件可以不在同一个元素身上,只在乎这两个元素位置是否相同,最典型的bug就是会导致移动端的点透事件
什么是点透事件?
//点透事件就是点击一个div标签,然后会触发盒子里面的事件,下面我们看一下代码:
<div class='box'></div>
<a class='link' href='https://www.baidu.com'>百度</a>
<script>
let box = document.querySelector(".box");
/**
针对点透事件的解决方案:
1.尽量不要在移动端使用鼠标事件(包括a标签的使用)用js做跳转
2.延迟执行touch事件里面的代码;
3.阻止默认事件
*/
box.ontouched = function(ev){
setTimeout(()=>{
this.style.display = "none";
},300);
//ev.preventDefault();
}
</script>
2.其他事件
- changedTouches:[] 触发当前事件的手指列表;
- targetTouches:[] 当前元素身上的手指列表;
- touches:[] 当前屏幕中的手指列表;
实现下面一个需求:移动端拖拽的实现:
let box = document.querySelector('.box');
let startX,startY = 0;
box.ontouchstart = function(ev){
let info = box.getBoundingClientRect();
startX = info.left;
startY = info.top;
let touch = ev.changedTouches[0];
oldX = touch.pageX;
oldY = touch.pageY;
}
box.ontouchmove = functiono(ev){
let touch = ev.changeTouches[0];
let nowX = touch.pageX - oldX + startX;
let nowY = touch.pageY - oldY + startY;
box.style.transform = `translate(${nowX}px,${nowY}px)`;
ev.preventDefault();
}