最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

通過(guò)滑動(dòng)翻頁(yè)效果實(shí)現(xiàn)和移動(dòng)端click事件問(wèn)題

 更新時(shí)間:2021年01月26日 10:06:46   作者:行舟客  
這篇文章主要介紹了滑動(dòng)翻頁(yè)效果實(shí)現(xiàn)和移動(dòng)端click事件問(wèn)題,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

前述

本文很短~
主要是為了總結(jié)和講述移動(dòng)端click和js事件機(jī)制導(dǎo)致的一個(gè)問(wèn)題。
(:咳咳,其實(shí)幾句話就能寫完的還要水一篇文章,不愧是我…


正文

最近做了一個(gè)小活動(dòng),里面要用到一個(gè)效果:滑動(dòng)翻頁(yè)。大概是這樣的:

demo-view

<!-- HTML代碼 -->
<div class="page-container">
	<div class="page" style="background: #dc3b26">1</div>
	<div class="page" style="background: #f3b03d">2</div>
	<div class="page" style="background: #44a2f8">3</div>
</div>

在css中,首先因?yàn)槭腔瑒?dòng)翻頁(yè),所以我們要保證“始終只有一屏”,這個(gè)可以放在全局樣式表里控制,然后是其中的“每一頁(yè)”都要占滿父元素 —— 這里其實(shí)用了“div是塊元素,無(wú)外力情況下豎直排列”的特性。

/** css樣式 */
html,
body{
	margin: 0;
	padding: 0;
	width: 100%;
	height: 100vh;
	overflow: hidden;
	font-size: 60px;
}
.page-container{
	width: 100%;
	height: 100%;
}
.page-container .page{
	width: 100%;
	height: 100%;
}

其JS實(shí)現(xiàn)也很簡(jiǎn)單:因?yàn)樵谝苿?dòng)端,所以使用了touchstarttouchmovetouchend事件來(lái)實(shí)現(xiàn)手勢(shì)滑動(dòng)功能:

  • start(剛按下)時(shí)記錄此時(shí)的手指位置——作為初始值;
  • 在move(觸摸滑動(dòng))時(shí)根據(jù)實(shí)時(shí)的手指位置和初始手指位置變量實(shí)現(xiàn)要求判斷,在本文場(chǎng)景為代表的場(chǎng)景下這一步一般還要求出“移動(dòng)距離”實(shí)時(shí)賦值;
  • 在end(手指離開)時(shí)(也有直接在move時(shí)進(jìn)行的)進(jìn)行收尾工作——比如:圖片滑動(dòng)完全劃過(guò)去、元素跑到結(jié)束位置、將事件監(jiān)聽(tīng)取消;
// 這里是控制全局js的文件
// 全局阻止瀏覽器默認(rèn)行為
document.addEventListener("touchstart",function(e){
	if(e.cancelable){
		e.preventDefault();
	}
},{passive: false})
// {passive: false}就是告訴前面可能有需要重置行為的代碼
document.addEventListener("touchmove",function(e){
	if(e.cancelable){
		e.preventDefault();
	}
},{passive: false})
// JavaScript代碼
let curPageIndex=0;
let pageContainer=document.querySelector(".page-container");
let pageNumber=pageContainer.children.length;  //頁(yè)面的數(shù)量
// 文檔的視窗高度(這里就是一屏的高度)
let cHeight=document.documentElement.clientHeight;
// 設(shè)置頁(yè)面容器的margin-top為合適的值,讓其顯示在視野中
function toPage(){
	pageContainer.style.transition="all .5s ease";
	pageContainer.style.marginTop=-curPageIndex*cHeight+"px";
	
	// 變化完成后去掉過(guò)渡效果 !
	pageContainer.addEventListener("transitionend",function(){
		pageContainer.style.transition="none";
	},{once:true})
}
toPage()

pageContainer.ontouchstart=function(e){
	let y=e.changedTouches[0].clientY;  //手指按下的縱坐標(biāo)
	pageContainer.ontouchmove=function(e){
		let dis=e.changedTouches[0].clientY-y;  //計(jì)算距離
		// 計(jì)算page-container的margin-top
		let mtop=-curPageIndex*cHeight+dis
		if(mtop>0){
			mtop=0;
		}else if(mtop<-(pageNumber-1)*cHeight){
			mtop=-(pageNumber-1)*cHeight;
		}
		// 實(shí)時(shí)改變位置
		pageContainer.style.marginTop=mtop+"px";
	}
	pageContainer.ontouchend=function(e){
		let dis=e.changedTouches[0].clientY-y;
		// 如果滑動(dòng)距離實(shí)在太短,就回到滑動(dòng)前的位置狀態(tài)
		if(Math.abs(dis)<=60){
			toPage()
		}else if(dis>0 && curPageIndex>0){
			curPageIndex--;
			toPage()
		}else if(dis<0 && curPageIndex<pageNumber-1){
			curPageIndex++;
			toPage()
		}
		
		// 手指離開后,取消監(jiān)聽(tīng)事件
		pageContainer.ontouchmove=null;
		pageContainer.ontouchend=null;
	}
}

至此,功能上似乎很完美。但這時(shí)候,我們?cè)诘谝粋€(gè)page里添加一個(gè)button:

<div class="page" style="background: #dc3b26">
	<button onclick="alert('哈哈哈')" class="but">click me!</button>
	1
</div>

然后到頁(yè)面上查看效果:

error-view

無(wú)效!

這是因?yàn)樵谏戏饺謏s文件里我們加了“阻止瀏覽器默認(rèn)事件”的代碼。
——在移動(dòng)端瀏覽器中,click事件和mousestart事件是同時(shí)被觸發(fā)的。因?yàn)?strong>移動(dòng)端瀏覽器是沒(méi)有click事件的,它是由mouse事件模擬的! :也正是這個(gè)原因,才有了所謂的“移動(dòng)端瀏覽器300ms延遲”的問(wèn)題 1 。
——還有就是,在微信自帶的瀏覽器中,有一個(gè)“觸頂下拉回彈”的操作,這其實(shí)是不應(yīng)該的。它也屬于瀏覽器默認(rèn)事件。
所以一般我們需要禁止掉這些東西。

但是如上面所示,全部禁止掉總會(huì)造成一些困擾,怎么辦?
H5提供了“自定義屬性”,針對(duì)本文方法,我們完全可以 —— 在全局事件里檢測(cè)當(dāng)前觸發(fā)的元素有沒(méi)有某一個(gè)自定義屬性,如果有,就什么也不攔截;否則就執(zhí)行禁止默認(rèn)行為的代碼:
比如

<button data-default="true" onclick="alert('哈哈哈')" class="but">click me!</button>

將上面“控制全局js的文件”內(nèi)容改為如下:

// 全局阻止瀏覽器默認(rèn)行為
document.addEventListener("touchstart",function(e){
	if(e.target.dataset.default){
		return;
	}
	if(e.cancelable){
		e.preventDefault();
	}
},{passive: false})
document.addEventListener("touchmove",function(e){
	if(e.target.dataset.default){
		return;
	}
	if(e.cancelable){
		e.preventDefault();
	}
},{passive: false})

就OK了:

success-view


其實(shí)還有另一種“解法”:既然上面說(shuō)了,移動(dòng)端click實(shí)際上是通過(guò)mouse事件模擬的,那么我們可以從mousestart事件入手;又因?yàn)閎utton元素是“第一個(gè)頁(yè)面”內(nèi)的(子)元素,所以可以用阻止事件冒泡

<!-- button就是普通的button -->
<button class="but">click me!</button>
document.querySelector(".but").addEventListener("touchstart",function(e){
	e.stopPropagation();
	alert('噶哈哈');
},false)

complete-view

關(guān)于捕獲和冒泡→

我們首先要知道的是:當(dāng)我們鼠標(biāo)按下一個(gè)按鈕時(shí),并不是“點(diǎn)擊了一個(gè)按鈕”,而是在這個(gè)區(qū)域內(nèi),鼠標(biāo)(上的按鍵)被按下,操作系統(tǒng)和瀏覽器把這個(gè)信息對(duì)應(yīng)到了“按鈕”所在區(qū)域并觸發(fā)其邏輯。
事實(shí)上鼠標(biāo)點(diǎn)擊并沒(méi)有位置信息,是操作系統(tǒng)一直在監(jiān)聽(tīng)鼠標(biāo)移動(dòng),根據(jù)累積的位移計(jì)算出來(lái)的坐標(biāo),將其傳給瀏覽器。
那么,把這個(gè)坐標(biāo)轉(zhuǎn)換為具體的元素上的事件的過(guò)程,就可稱作“捕獲”。那“冒泡”呢?這個(gè)不好解釋,但有一點(diǎn)想必你是明白的:當(dāng)你按下電視開關(guān)時(shí),你也按到了電視!
這就是很多文章會(huì)講到的“冒泡過(guò)程由內(nèi)向外,捕獲過(guò)程由外向內(nèi)”,或者說(shuō)是“洋蔥模型”。
還有一點(diǎn)就是:事件addEventListener的第三個(gè)參數(shù) true/false ,即為“是捕獲/冒泡”。(別多想,這只是瀏覽器提供的事件模型之一。無(wú)論是否監(jiān)聽(tīng),在一個(gè)事件發(fā)生時(shí),捕獲和冒泡總是先后發(fā)生的)

到此這篇關(guān)于滑動(dòng)翻頁(yè)效果實(shí)現(xiàn)和移動(dòng)端click事件問(wèn)題的文章就介紹到這了,更多相關(guān)滑動(dòng)翻頁(yè)效果內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • window.print()局部打印三種方式(小結(jié))

    window.print()局部打印三種方式(小結(jié))

    本文主要介紹了window.print()局部打印三種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • 最新評(píng)論

    偃师市| 麟游县| 中西区| 永安市| 通江县| 万州区| 鹤山市| 河东区| 西盟| 海林市| 松溪县| 梅州市| 商水县| 仁怀市| 永春县| 镶黄旗| 岗巴县| 文山县| 漾濞| 明光市| 久治县| 靖州| 嵩明县| 大石桥市| 贵阳市| 喀喇沁旗| 东兴市| 新巴尔虎右旗| 水城县| 龙泉市| 贵港市| 霸州市| 即墨市| 黄大仙区| 广德县| 华宁县| 抚顺县| 屏山县| 平安县| 公安县| 区。|