鼠标事件
、键盘事件
、资源加载事件
、动画事件
等事件为主。
click
在PC端
是点击事件
!手指事件
(单手指
和多手指
)、资源加载事件
、动画事件
等为主。
click
在移动端
是单击事件
。问题1:click事件
在移动端
存在300ms的延迟
。
click事件
在移动端
是单击事件
:
300ms
,看是否触发了第二次点击;
没有触发第二次点击
,则为单击操作
,触发click事件
。触发了第二次点击
,则为双击操作
,click事件
是不触发的!用touch事件模型
-即单手指事件模型
,来代替click事件
。
touchstart
:手指开始触摸。
touchmove
:手指移动。
touchend
:手指离开。
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>基于touch实现点击操作title>
<style>
.box {
position: absolute;
top: 20px;
left: 40px;
box-sizing: border-box;
width: 100px;
height: 100px;
border: 1px solid #000;
}
style>
head>
<body>
<div class="box">div>
<script>
// 基于touch事件模型模拟出“点击”的效果
const box = document.querySelector(".box");
// 简易的处理方法:只要手指离开盒子,则认为触发了点击操作「这样是不准确的,如果手指之前发了移动,则本操作不再是点击,而是滑动」
box.ontouchend = function () {
this.style.background = "pink";
};
script>
body>
html>
touchcancel
:因意外情况如手机没电,导致touch事件取消
了。
但是这种方式,如果需要自己去实现,太繁琐了!
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>基于touch实现点击操作title>
<style>
.box {
position: absolute;
top: 20px;
left: 40px;
box-sizing: border-box;
width: 100px;
height: 100px;
border: 1px solid #000;
}
style>
head>
<body>
<div class="box">div>
<script>
// 基于touch事件模型模拟出“点击”的效果
const box = document.querySelector(".box");
box.ontouchstart = function (ev) {
/*
手指按下的时候:记录手指起始的坐标位置
ev:TouchEvent
touches/targetTouches/changedTouches:都记录了手指位置的相关信息「伪数组」
我们平时都用changedTouches,因为其可以在 touchend 事件中,记录出手指离开屏幕时的坐标
*/
let finger = ev.changedTouches[0];
this.startX = finger.pageX;
this.startY = finger.pageY;
this.isMove = false;
};
box.ontouchmove = function (ev) {
/*
手指移动的时候:获取最新的手指坐标,减去起始坐标,计算出偏移的距离
在给定的误差值(一般都是10px)范围内,计算是否发生移动
*/
let finger = ev.changedTouches[0];
let changeX = finger.pageX - this.startX,
changeY = finger.pageY - this.startY;
if (Math.abs(changeX) > 10 || Math.abs(changeY) > 10)
this.isMove = true;
this.changeX = changeX;
this.changeY = changeY;
};
box.ontouchend = function (ev) {
/*
手指离开屏幕的时候:判断是移动还是点击操作
如果是移动操作,还可以基于偏移的距离算出移动的方向
*/
let { isMove, changeX, changeY } = this;
if (!isMove) {
console.log("当前是点击操作");
this.style.background = "pink";
return;
}
if (Math.abs(changeX) >= Math.abs(changeY)) {
// 是左右滑动
if (changeX >= 0) {
console.log("向右滑动");
} else {
console.log("向左滑动");
}
return;
}
// 是上下滑动
if (changeY >= 0) {
console.log("向下滑动");
} else {
console.log("向上滑动");
}
};
/*
移动端的常规操作,基本上都是基于 touchstart/touchmove/touchend 模拟出来的
+ 模拟点击
+ 模拟滑动「知道滑动方向」
+ 模拟单击/双击「300ms」
+ 模拟长按「750ms」
+ ...
对于一些需要多根手指进行的操作,可以基于 gesturestart/gesturechange/gestureend 模拟出来
+ 缩放
+ 旋转
+ ...
*/
script>
body>
html>
基于一些现有的封装好的事件库来解决。
fastclick.js 只能解决click事件
的300ms延迟
问题。
click事件
,只不过基于fastclick插件
,把其300ms延迟
处理掉即可!事件委托
,对页面中的click行为
做统一的处理
,核心还是基于touch事件模型
解决的!JS高级进阶/day0619_QQMusic/js/fastclick.js
JS高级进阶/day0619_QQMusic/touchDemo.html
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>基于touch实现点击操作title>
<style>
.box {
position: absolute;
top: 20px;
left: 40px;
box-sizing: border-box;
width: 100px;
height: 100px;
border: 1px solid #000;
}
style>
head>
<body>
<div class="box">div>
<script src="js/fastclick.js">script>
<script>
// 这样的处理在移动端会有300ms延迟问题
// 此时我们基于 fastclick 插件处理一下即可
FastClick.attach(document.body);
const box = document.querySelector(".box");
box.onclick = function () {
console.log(`fastclick`);
this.style.background = "pink";
};
script>
body>
html>
Zepto.js 被称为移动端的jQuery库
,语法和jQuery
非常类似,但是能够更好的支持移动端。
jQuery
来讲:
IE8
及IE8以下版本
的兼容
。jQuery
中最常用
、最核心
的方法
。
Zepto
比jQuery库
小很多。css3动画
。完善的移动端事件处理方案
。tap
点击。singleTap
单击。doubleTap
双击。longTap
长按。swipe
、swipeLeft
/swipeRight
/swipeDown
/swipeUp
滑动。pinchIn
/pinchOut
缩放。Zepto
和jQuery
一样,其大部分代码是用来操作DOM
的,已经不适用于当下的Vue开发
/React开发
了。JS高级进阶/day0619_QQMusic/js/zepto.min.js
JS高级进阶/day0619_QQMusic/touchDemo.html
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>基于touch实现点击操作title>
<style>
.box {
position: absolute;
top: 20px;
left: 40px;
box-sizing: border-box;
width: 100px;
height: 100px;
border: 1px solid #000;
}
style>
head>
<body>
<div class="box">div>
<script src="js/zepto.min.js">script>
<script>
$(".box").tap(function () {
console.log(`zepto-tap`);
$(this).css({
background: "pink",
});
});
script>
body>
html>
hammer.js 移动端专属的事件库
JS高级进阶/day0619_QQMusic/js/hammer.min.js
JS高级进阶/day0619_QQMusic/touchDemo.html
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>基于touch实现点击操作title>
<style>
.box {
position: absolute;
top: 20px;
left: 40px;
box-sizing: border-box;
width: 100px;
height: 100px;
border: 1px solid #000;
}
style>
head>
<body>
<div class="box">div>
<script src="js/hammer.min.js">script>
<script>
const box = document.querySelector(".box");
const instHammer = new Hammer(box);
instHammer.on("tap", function () {
console.log(`hammer-tap`);
box.style.background = "pink";
});
script>
body>
html>
问题2:事件穿透问题
该目标元素相同位置中其他元素
的鼠标点击click事件
。
问题3:keydown/up/press等事件在移动端用不了,统一基于input事件代替即可!
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>基于touch实现点击操作title>
<style>
.box {
position: absolute;
top: 20px;
left: 40px;
box-sizing: border-box;
width: 100px;
height: 100px;
border: 1px solid #ccc;
}
style>
head>
<body>
<div class="box">div>
body>
html>
<script>
const box = document.querySelector(".box");
// 这样的处理在移动端会有300ms延迟问题。
box.onclick = function () {
this.style.background = "pink";
};
script>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>基于touch实现点击操作title>
<style>
.box {
position: absolute;
top: 20px;
left: 40px;
box-sizing: border-box;
width: 100px;
height: 100px;
border: 1px solid #ccc;
}
style>
head>
<body>
<div class="box">div>
body>
html>
<script>
// 基于touch事件模型模拟出点击的效果。
const box = document.querySelector(".box");
// 简易的处理方法:只要手指离开盒子,则认为触发了点击操作。
// 这样是不准确的,如果手指之前发生了移动,则本操作不再是点击,而是滑动。
box.ontouchend = function () {
console.log(`touchend-->`);
this.style.background = "pink";
};
script>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>基于touch实现点击操作title>
<style>
.box {
position: absolute;
top: 20px;
left: 40px;
box-sizing: border-box;
width: 100px;
height: 100px;
border: 1px solid #ccc;
}
style>
head>
<body>
<div class="box">div>
body>
html>
<script>
// 基于touch事件模型模拟出点击的效果。
const box = document.querySelector(".box");
box.ontouchstart = function (ev) {
// 手指按下的时候:记录手指起始的坐标位置。
// ev:TouchEvent
// - touches/targetTouches/changedTouches:都记录了手指位置的相关信息,结果是一个伪数组。
// - 我们平时都用changedTouches,因为其可以在touchend事件中,记录出手指离开屏幕时的坐标。
// console.log(`ev-->`, ev);
let finger = ev.changedTouches[0];
// console.log(`finger-->`, finger);
this.startX = finger.pageX;
this.startY = finger.pageY;
this.isMove = false;
};
box.ontouchmove = function (ev) {
// 手指移动的时候:获取最新的手指坐标,减去起始坐标,计算出偏移的距离。
// 在给定的误差值(一般都是10px)范围内,计算是否发生移动。
let finger = ev.changedTouches[0];
// console.log(`finger-->`, finger);
let changeX = finger.pageX - this.startX;
let changeY = finger.pageY - this.startY;
if (Math.abs(changeX) > 10 || Math.abs(changeY) > 10) {
this.isMove = true;
}
this.changeX = changeX;
this.changeY = changeY;
};
box.ontouchend = function (ev) {
// 手指离开屏幕的时候:判断是移动还是点击操作。
// 如果是移动操作,还可以基于偏移的距离算出移动的方向。
let { isMove, changeX, changeY } = this;
if (!isMove) {
console.log(`当前是点击操作`);
this.style.background = "pink";
return;
}
if (Math.abs(changeX) >= Math.abs(changeY)) {
// 是左右滑动。
if (changeX >= 0) {
console.log(`向右滑动`);
} else {
console.log(`向左滑动`);
}
return
}
// 是上下滑动。
if (changeY >= 0) {
console.log(`向下滑动`);
} else {
console.log(`向上滑动`);
}
};
// - 移动端的常规操作,基本上都是基于touchstart/touchmove/touchend模拟出来的。
// - 模拟点击。
// - 模拟滑动-知道滑动方向。
// - 模拟单击/双击-300ms。
// - 模拟长按-750ms。
// - ...
// - 对于一些需要多根手指进行的操作,可以基于gesturestart/gesturechange/gestureend模拟出来。
// - 缩放。
// - 旋转。
// - ...
script>
技术方案:流式布局(外层容器的宽度按照百分比方式处理),基于@media进行结构和样式的调整。
@media all and (max-width:960px) {
.header{
//...
}
...
}
移动端响应式布局第一步:设置meta标签的viewport。
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
rem响应式布局方案
px物理像素,固定单位。
em相对单位,相对于父元素的字体大小。
一般用于段落首行缩进两个汉字之类的效果。
.box{
font-size:14px;//此时在该元素的子元素中1em=14px;
p{
text-indent:2em;//首行缩进两个字符。
}
}
rem(root em) 相对单位,相对于根元素(也就是html)的字体大小。
html{
font-size:20px;//1rem=20px。浏览器能识别的最小字体是12px。
}
.box1{
width:100px;
}
.box2{
width:5rem;
}
//目前box1和box2是一样大的。
//但是如果以后,把html的字体改为30px了,那么box1依然是100px,但是box2则自动变为150px了!
//也就是:只要修改根元素的字体大小,那么所有以rem为单位的样式,都会自动跟着等比缩放。
第一步:按照特定的尺寸(一般是设计稿的尺寸),设置rem和px的初始转换比例,然后把测量出来的像素值,全部按照这个比例,改为rem值,赋值给元素的样式!
设计稿的尺寸:一般都是750px的。
rem和px的初始转换比例:设置的值一定是方便计算的!
html{
font-size:16px;//1rem=100px ; 750px
}
量出来一个盒子大小是300px*260px。font-size为28px。
.box{
width:3rem;
height:2.6rem;
font-size:0.28rem;
}
第二步:获取当前设备的尺寸,计算出相比较于设计稿而言,缩放的比例。然后按照这个比例,去修改html的字体大小(也就是rem和px的换算比例)。
第三步:我们一般都会限制一个最大的缩放范围(比如:540),设备宽度即便超过这个范围,换算比例也不会再继续放大了,整个页面内容最宽540,左右两边预留空白即可。
logo.png
[email protected]
[email protected]
。webpack -> postcss
prefixfree.min.js
<script src="./js/prefixfree.min.js" async>script>
…