1. 程式人生 > >H5移動端開發基礎(三)自定義滾動條、實戰-音悅臺

H5移動端開發基礎(三)自定義滾動條、實戰-音悅臺

自定義滾動條、實戰-音悅臺

自定義滾動條

*{margin: 0;padding: 0;}
body, html{height: 100%;overflow: hidden;}
#wrap{height: 100%;overflow: hidden;position: relative;}
#scrollBar
{position: absolute;right: 0;top: 0;width: 4px;height: 100%;background: rgba(0,0,0,.5);opacity: 0;transition: .3s opacity;}
<div id="wrap">
	<div id="scroll"></div>
	<div id="scrollBar"></div>
</div>
window.onload = function(){
	setInner();
	var wrap = document.querySelector
('#wrap'); var scroll = document.querySelector('#scroll'); var bar = document.querySelector('#scrollBar'); var scale = wrap.clientHeight/scroll.offsetHeight; bar.style.height = wrap.clientHeight*scale + 'px'; var callBack = { start: function(){ // console.log('滑動開始之前要執行的函式'); bar.style.opacity =
1; }, in: function(){ // console.log('滑動中執行的函式'); var top = -cssTransform(scroll, 'translateY')*scale; cssTransform(bar, 'translateY', top); }, over: function(){ // console.log('滑動結束之後要執行的函式'); bar.style.opacity = 0; } }; moveScroll(wrap, callBack); } function setInner(){ var scroll = document.querySelector('#scroll'); var inner = ''; for(var i=0; i<300; i++){ inner += '移動端事件互動' + i + '<br/>'; } scroll.innerHTML = inner; }

js封裝

transform.js

function cssTransform(el, attr, val){
  if(!el.transform){
    el.transform = {};
  }
  if(arguments.length>2){
    el.transform[attr] = val;
    // console.log(el.transform);
    var sVal = '';
    for(var s in el.transform){
      switch(s){
        case 'rotate':
        case 'rotateX':
        case 'rotateY':
        case 'rotateZ':
        case 'skewX':
        case 'skewY':
          sVal += s+'('+el.transform[s]+'deg) ';
          break;
        case 'translateX':
        case 'translateY':
        case 'translateZ':
          sVal += s+'('+el.transform[s]+'px) ';
          break;
        case 'scaleX':
        case 'scaleY':
        case 'scale':
          sVal += s+'('+el.transform[s]+') ';
          break;
      }
      // console.log(sVal);
      el.style.WebkitTransform = el.style.transform = sVal;
    }
  }else{
    var val = el.transform[attr];
    if(typeof val == 'undefined'){
      if(['scale', 'scaleX', 'scaleY'].indexOf(attr)>-1){
        val = 1;
      }else{
        val = 0;
      }
    }
    return val;
  }
}

tween.js

var Tween = (function(){
	return {
		/*
		t:當前次數
		b:起始值
		c:起始值和目標點之間的差值
		d:總次數
		*/
		easeOut: function(t, b, c, d){
			return -c*((t=t/d-1)*t*t*t-1) + b;
		},
		backOut: function(t, b, c, d, s){
			if(typeof s == 'undefined'){
				s = 2.70158;
			}
			return c*((t=t/d-1)*t*((s+1)*t+s)+1)+b;
		}
	}
})();

scrollBar.js

function moveScroll(wrap, callBack){
    var child = wrap.children[0];
    var startPoint = 0;
    var startY= 0;
    var minY = wrap.clientHeight - child.offsetHeight;
    var step = 1;
    var lastY = 0;
    var lastTime = 0;
    var lastDis = 0;
    var lastTimeDis = 1;
    var isMove = true;
    var isFirst = true;
    cssTransform(child, 'translateZ', 0.01);
    wrap.addEventListener('touchstart', function (e) {
      // child.style.transition = 'none';
      clearInterval(child.scroll);
      if(callBack && callBack.start){
      	callBack.start();
      }
      startPoint = {pageX: e.changedTouches[0].pageX, pageY: e.changedTouches[0].pageY};
      startY = cssTransform(child, 'translateY');
      step = 1;
      lastY = startPoint.pageY;
      lastTime = new Date().getTime();
      lastDis = 0;
      lastTimeDis = 1;
      isMove = true;
      isFirst = true;
    });
    wrap.addEventListener('touchmove', function (e) {
      if(!isMove){
        return;
      }
      var nowPoint = {pageX: e.changedTouches[0].pageX, pageY: e.changedTouches[0].pageY};
      var disX = nowPoint.pageX - startPoint.pageX;
      var disY = nowPoint.pageY - startPoint.pageY;
      var top = startY + disY;
      if(isFirst){
        isFirst = false;
        if(Math.abs(disY) < Math.abs(disX)){
          isMove = false;
          return;
        }
      }
      var nowTime = new Date().getTime();
      if (top > 0) {
        step = 1-top / wrap.clientHeight; 
        top = parseInt(top*step);
      }
      if (top < minY) {
        var over = minY - top; // 計算下超出值
        step = 1 - over / wrap.clientHeight; //根據超出值計算係數
        over = parseInt(over * step);
        top = minY - over;
      }
      // lastDis = top - lastY;
      lastDis = nowPoint.pageY - lastY;
      lastTimeDis = nowTime - lastTime;
      // lastY = top;
      lastY = nowPoint.pageY;
      lastTime = nowTime;
      cssTransform(child, 'translateY', top);
      if(callBack && callBack.in){
      	callBack.in();
      }
    });
    wrap.addEventListener('touchend', function (e) {
      var speed = (lastDis / lastTimeDis) * 200;
      speed = isNaN(speed) ? 0 : speed
      var top = cssTransform(child, 'translateY');
      var target = top + speed;
      // var type = 'cubic-bezier(.34, 0.92, .58, .9)';
      var type = 'easeOut';
      var time = Math.abs(speed * 1.2);
      time = time < 300 ? 300 : time;
      if (target > 0) {
        target = 0;
        // type = 'cubic-bezier(.68, 1.31, .92, 1.2)';
      	type = 'backOut';
      }
      if (target < minY) {
        target = minY;
        // type = 'cubic-bezier(.68, 1.31, .92, 1.2)';
        type = 'backOut';
      }
      // child.style.transition = time + 'ms ' + type;
      move(target, time, type);
      cssTransform(child, 'translateY', target);
    });
    function move(target, time, type){
		var t = 0;
		var b = cssTransform(child, 'translateY');
		var c = target - b;
		var d = Math.ceil(time/20);
		clearInterval(child.scroll);
		child.scroll = setInterval(function(){
			t++;
			if(t>d){
				clearInterval(child.scroll);
				if(callBack && callBack.over){
					callBack.over();
				}
			}else{
				var top = Tween[type](t, b, c, d);
				cssTransform(child, 'translateY', top);
				if(callBack && callBack.in){
					callBack.in();
				}
			}
		}, 20);
	}
}

音悅臺

適配

<meta name="viewport" content="width=device-width, user-scalable=no"/>
<script type="text/javascript">
  setRem();
  window.addEventListener('orientationchange', setRem);
  window.addEventListener("resize", setRem);
  function setRem() {
    var html = document.querySelector('html');
    var width = html.getBoundingClientRect().width;
    console.log(width)
    html.style.fontSize = width / 16 + 'px';
  }
</script>

樣式

body,h1,h2,h3,h4,h5,h6,p,dl,dd{margin:0;-webkit-text-size-adjust:100%;font-family:Helvetica;}
ul,ol{margin:0;padding:0;list-style:none;}
img{display:block;}
a{text-decoration:none;}
a,input,button{-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-appearance:none;outline:none;}
html,body{height:100%;position:relative;overflow:hidden;background:#eee;}
.wrap{height:100%;position:relative;overflow:hidden;}
#header{position:absolute;background:rgba(0,0,0,0.8);left:0;top:0;width:100%;z-index:2;}
.headerC{height:2rem;}
#logo{float:left;padding:0.38518519rem 0.25185185rem 0.31111111rem;}
#logo img{width:3.55555556rem;}
#menu-btn{float:left;width:1.91111111rem;height:2rem;background:url(../img/menuBtn.png) no-repeat;background-size:1.21481481rem 3.45185185rem;}
.menu-btn-show{background-position:center 0.23703704rem !important;}
.menu-btn-close{background-position:center -1.77777778rem !important;}
#btns{float:right;padding-top:0.31111111rem;}
#btns a{float:left;margin-right:0.22222222rem;width:1.64444444rem;height:1.15555556rem;background:#690;color:#ccc;font-size:0.59259259rem;line-height:1.15555556rem;text-align:center;border-radius:0.11851852rem;}
#btns .search-btn{font-weight:bold;color:#ffffff;margin-right:0.44444444rem;width:1.92592593rem;line-height:1.3037037rem;border-radius:0.14814815rem;}
.search{height:1.52592593rem;padding:0.23703704rem;}
.search input[type='search']{float:left;width:12.28148148rem;height:1.52592593rem;background:#999;padding:5px 10px;box-sizing:border-box;border:1px solid #5a5a5a;font-size:0.6rem;color:#333;border-radius:0.22222222rem 0 0 0.22222222rem;}
.search input[type='search']:focus{background:#fff;}
.search input[type='search']::-webkit-input-placeholder{color:#666;}
.search input[type='submit']{float:right;width:3.00740741rem;height:1.52592593rem;border:none;background:#414040;color:#fff;border-radius:0 0.22222222rem 0.22222222rem 0;font-size:0.77037037rem;}
#nav{position:absolute;width:100%;left:0;top:2rem;border-top:1px solid #414040;background:rgba(0,0,0,0.8);padding:0.14814815rem 0;display:none;}
#nav li{float:left;width:22.5%;line-height:2rem;font-size:0.8rem;text-align:center
            
           

相關推薦

H5移動開發基礎定義滾動實戰-

自定義滾動條、實戰-音悅臺 自定義滾動條 js封裝 transform.js tween.js scrollBar.js 音悅臺 適配 樣式 html

H5移動開發基礎多指操作案例-相簿

多指操作、案例-相簿 多指操作 旋轉 縮放 實現安卓多指事件 案例-相簿 多指操作 // gesturestart:手指觸碰元素,螢幕上有兩個或兩個以上的手指 oBox.addEventListener

H5移動開發基礎適配3Danimation

適配、3D、animation 適配 rem適配 getBoundingClientRect viewport適配 橫豎屏適配 方法一 方法二 3D

H5移動開發基礎事件基礎

事件基礎 移動端基礎事件 滑屏原理 transform 與 transition 無縫滑屏自動播放幻燈片 移動端基礎事件 手指按下:touchstart <==> mousedown 手指擡起:touchend <

大數據入門第二十二天——spark定義分區排序與查找

get buffer arr clas ron arm scala mut all 一、自定義分區   1.概述     默認的是Hash的分區策略,這點和Hadoop是類似的,具體的分區介紹,參見:https://blog.csdn.net/high2011/arti

微信公眾號開發整理--定義選單查詢刪除

1.查詢選單:get請求方式2.在工具類中新增訪問get請求常量URL建立查詢選單方法:public static int createMenu(String token,String menu) throws ParseException, IOException{int

Python自動化運維開發----基礎條件語句和迴圈語句

1.python中的條件和迴圈有哪些? python中的迴圈和其他程式語言一樣,條件有if,迴圈有while、for 2.條件語句 條件語句的格式(1)有一個條件 if  條件:     執行語句1 else:   &

從Android原生角度看移動html5開發APP之上拉載入

在mui框架中上拉載入其實很簡單了,框架已經幫助我們基本實現了。 mui的上拉載入和下拉重新整理類似,都屬於pullRefresh外掛,使用過程如下: 1、頁面滾動到底,顯示“正在載入...”提示(mui框架提供) 2、執行載入業務資料邏輯(開發者提供) 3、載入完畢,隱藏

Xamarin 跨移動開發系列01 -- 搭建環境編譯除錯部署執行

   (本文是基於老版本的VS和Xamarin,而VS2017已經集成了Xamarin,所以,本文已經過時,最新的Xamarin開發介紹請參見 使用 Xamarin開發手機聊天程式 。)    如果是.NET開發人員,想學習手機應用開發(Android和iOS),Xamarin 無疑是最好的選擇,編寫一次,

Windows客戶開發簡介

         之前的一篇文章裡,我簡單概要的介紹了一下介面庫的知識。既然是跟介面有關,那麼必然少不了很多關於繪製的內容。對於Windows開發而言,介面繪製使用的一類API就是所謂的“GDI”。          GDI這個東西可有歷史了,但是我們就不去追根朔源了。首先

Python 基礎——流程控制之break continue else

sim 流程 tin rime con python 基礎 完整 .py gpo break break 語句和 C 中的類似,用於跳出最近的一級 for 或 while 循環。 循環可以有一個 else 子句;它在循環叠代完整個列表(對於 for )或執行條件為 fals

flask web開發 定義錯誤頁面

#自定義錯誤頁面 @app.errorhandler(404)  #請求未知頁面或未知路由 def page_not_found(e):     return render_template('404.html'),404 @app.errorhandler(500

flume ng進擊之路 —— 定義source API開發

概述 關於flume ng的簡單介紹,可以參考flume ng進擊之路 (一)—— 入門,同時flume ng也提供了各種各樣的source和sink介面供我們在生成環境中使用,但是在生產環境中,我們常常需要定製的source或者sink來滿足我們的要求。

微信公眾平臺開發教程定義菜單

打開鏈接 delete toolbar 推送 優化 pcl reader 接口查詢 robot 應大家強烈要求,將自定義菜單功能課程提前。 一、概述: 如果只有輸入框,可能太簡單,感覺像命令行。自定義菜單,給我們提供了很大的靈活性,更符合用戶的操作習慣。在一個小小的微信對話

JS基礎定義函數

調用函數 pre 基礎 clas 自定義 語句 ... 全局 blog 作用:是為了讓重復使用的語句,方便進行調用。 定義格式: function 自定義函數名 (參數1, 參數2,...) { 執行的語句 } 函數的封裝:把語句放到函數中去的過程。 參數:通過

定義Realm

ssi 定義 try time public getname tid vax getc 引入依賴 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/

EL表達式定義 EL 表達式

abd sun title contain tld sta 參數 func lns 自定義EL函數(靜態方法): 編寫步驟: 1.編寫一個Java類,提供一個靜態方法 import java.util.List; public class GetLength {

架構探險定義類載入器

今天我們來談一談架構探險中自定義的類載入器,一般我們若想實現自定義的類載入器,可以繼承ClassLoader類,然後實現findClass方法即可,詳細介紹可以看以下連結: https://www.cnblogs.com/doit8791/p/5820037.html 本文

如何使hexo顯得自己更有逼格——定義與優化

部落格地址: 黑境​​​​ 優化策略 考慮到站點的穩定性和載入速度等,可以使用延遲載入圖片等方式提高響應速度。hexo還提供了一個最小化靜態檔案的外掛hexo-all-minifier可以壓縮html、css、js和影象檔案,刪除檔案中多餘的換行等。通過在

Unity動態編輯Terrain 定義筆刷

**** 程式碼我已經上傳到了我的Github上,需要的話可以直接去下載https://github.com/xdedzl/xdedzl,裡面有一個TerrainModilfyDemo的場景,我做了一個簡單的UI用來測試,工程版本是2018.3。注意編譯環境需要是.net4.x,用3.5會報錯。