92国产精品视频_亚洲a级在线观看_国产精品电影观看_国产精品免费观看在线_精品伊人久久97_亚洲人成在线观_尤物九九久久国产精品的特点_成人激情在线播放_成人黄色大片在线免费观看_亚洲成人精品久久久_久久免费视频在线观看_久久精品国产一区_国产一区二区三区18_亚洲欧美中文字幕在线一区_日韩美女中文字幕_日韩视频免费在线

首頁

canvas粒子效果

seo達人

如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    html, body {
      margin: 0;
      padding: 0;
      height: 100%;
      overflow: hidden;
    }
    .container {
      width: 100%;
      height: 100%;
    }
  </style>
</head>
<body>
  <div class="container">
    <canvas id="cs"></canvas>
  </div>
</body>
<script>
  function MoveBalls(element, opts) {
    var canvas = document.querySelector(element);
    this.canvas = canvas;
    this.ctx = canvas.getContext("2d");
    var defaultOpts = {
      total: 100,
      color: "#00D0FF",
      size: 1,
      width: this.canvas.parentNode.clientWidth,
      height: this.canvas.parentNode.clientHeight
    };
    var opts = opts || defaultOpts;
    for (var key in opts) {
        defaultOpts[key] = opts[key];
    };
    for (var key in defaultOpts) {
        this[key] = defaultOpts[key];
    };
    opts = null;
    defaultOpts = null;
    // 鼠標坐標
    this.coordinate = {
      x: null,
      y: null,
      max: 100
    };
    // 粒子
    this.dots = [];
    // 含鼠標坐標的粒子數組
    this.newDots = [];
    // 總數
    this.count = 0;
    // requestAnimationFrame兼容處理
    window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
          window.setTimeout(callback, 1000 / 60);
        };
    this.colorReg = /[rgba()]/g;
    this.init();
  };
  MoveBalls.prototype = {
    constructor: MoveBalls,
    init: function () {
      var _this = this;
      this.freshResize();
      this.mouseEvent();
      this.getDots();
      var timer = setTimeout(function () {
        clearTimeout(timer);
        _this.draw(_this)
      }, 300);
    },
    colorCheck: function () {
      this.canvas.style.color = this.color;
      var colorData = this.canvas.style.color;
      return colorData = colorData.replace(this.colorReg, "").split(",");
    },
    resize: function (self) {
      var _this = self || this;
      _this.canvas.width = _this.width;
      _this.canvas.height = _this.height;
    },
    freshResize: function () {
      this.resize();
      var _this = this;
      window.addEventListener("resize", function () {
        _this.resize(_this);
      });
    },
    mouseEvent: function () {
      var _this = this;
      _this.canvas.addEventListener("mousemove", function (e) {
        var e = e || winodw.event;
        _this.coordinate.x = e.offsetX ? e.offsetX : e.layerX;
        _this.coordinate.y = e.offsetY ? e.offsetY : e.layerY;
      });
      _this.canvas.addEventListener("mouseout", function () {
        _this.coordinate.x = null;
        _this.coordinate.y = null;
      })
    },
    getDots: function () {
      while(this.count < this.total) {
        var x = Math.random() * this.canvas.width;
        var y = Math.random() * this.canvas.height;
        var xMove = Math.random() * 2 - 1;
        var yMove = Math.random() * 2 - 1;
        this.dots.push({
          x: x,
          y: y,
          xMove: xMove,
          yMove: yMove,
          max: 100
        });
        this.count ++;
      }
    },
    draw: function (self) {
      var _this = self || this;
      var ctx = _this.ctx;
      ctx.clearRect(0, 0, _this.canvas.width, _this.canvas.height);
      _this.newDots = [_this.coordinate].concat(_this.dots);
      _this.dots.forEach(function (dot) {
        dot.xMove *= (dot.x > _this.canvas.width || dot.x < 0) ? -1 : 1;
        dot.yMove *= (dot.y > _this.canvas.height || dot.y < 0) ? -1 : 1;
        dot.x += dot.xMove;
        dot.y += dot.yMove;
        // 繪制點
        ctx.save();
        ctx.beginPath();
        ctx.arc(dot.x, dot.y, _this.size, 0, Math.PI * 5);
        ctx.fillStyle = _this.color;
        ctx.fill();
        ctx.restore();
        // 循環比對粒子間的距離
        for (var i = 0; i < _this.newDots.length; i ++) {
          var newDot = _this.newDots[i];
          // 如果是第一個點,則跳過
          if(newDot === dot || newDot.x === null || newDot.y === null) continue;
          var xDistance = dot.x - newDot.x;
          var yDistance = dot.y - newDot.y;
          var distance = Math.sqrt(Math.pow(xDistance, 2) + Math.pow(yDistance, 2));
          // 顏色深度
          var deep = 0;
          // 小于最小距離,則連線
          if (distance <= newDot.max) {
            // 附近的小球向鼠標位置移動
            if(newDot === _this.coordinate && distance > (newDot.max / 2)) {
              dot.x -= xDistance * 0.05;
              dot.y -= yDistance * 0.05;
            }
            // 距離越近---值越大---顏色越深
            deep = (newDot.max - distance) / newDot.max;
            // 畫線
            ctx.save();
            ctx.beginPath();
            ctx.lineWidth = deep / 2;
            var colorInfo = _this.colorCheck();
            ctx.strokeStyle = "rgba(" + colorInfo[0] + ", " + colorInfo[1] + ", " + colorInfo[2] + "," + (deep + 0.4) + ")";
            ctx.moveTo(dot.x, dot.y);
            ctx.lineTo(newDot.x, newDot.y);
            ctx.stroke();
            ctx.restore();
          }
        }
        // 將已經計算過的粒子刪除,減少遍歷的總數量
        _this.newDots.splice(_this.newDots.indexOf(dot), 1);
      });
      window.requestAnimationFrame(function (obj) {
        _this.draw(_this);
      });
    }
  }
  var moveBalls = new MoveBalls("#cs", {total: 66, color: "#00D0FF", size: 1});
</script>
</html>

藍藍設計m.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務


移動端web頁面開發

seo達人

如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

 字號

工作了有一段時間,基本上都在搞移動端的前端開發,工作的過程中遇到過很多問題,bug的解決方案,記錄下來,以便后用!?。热莶⒉皇呛苋?,以后每遇到一個問題都會總結在這里,分享給大家!

一、meta標簽相關知識

1、移動端頁面設置視口寬度等于設備寬度,并禁止縮放。

<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />

2、移動端頁面設置視口寬度等于定寬(如640px),并禁止縮放,常用于微信瀏覽器頁面。

<meta name="viewport" content="width=640,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />

3、禁止將頁面中的數字識別為電話號碼

<meta name="format-detection" content="telephone=no" />

4、忽略Android平臺中對郵箱地址的識別

<meta name="format-detection" content="email=no" />

5、當網站添加到主屏幕快速啟動方式,可隱藏地址欄,僅針對ios的safari


    
  1. <meta name="apple-mobile-web-app-capable" content="yes" />
  2. <!-- ios7.0版本以后,safari上已看不到效果 -->

6、將網站添加到主屏幕快速啟動方式,僅針對ios的safari頂端狀態條的樣式


    
  1. <meta name="apple-mobile-web-app-status-bar-style" content="black" />
  2. <!-- 可選default、black、black-translucent -->

viewport模板


    
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
  6. <meta content="yes" name="apple-mobile-web-app-capable">
  7. <meta content="black" name="apple-mobile-web-app-status-bar-style">
  8. <meta content="telephone=no" name="format-detection">
  9. <meta content="email=no" name="format-detection">
  10. <title>title</title>
  11. <link rel="stylesheet" href="index.css">
  12. </head>
  13. <body>
  14. content...
  15. </body>
  16. </html>

二、CSS樣式技巧

1、禁止ios和android用戶選中文字

.css{-webkit-user-select:none}

2、禁止ios長按時觸發系統的菜單,禁止ios&android長按時下載圖片

.css{-webkit-touch-callout: none}

3、webkit去除表單元素的默認樣式

.css{-webkit-appearance:none;}

4、修改webkit表單輸入框placeholder的樣式


    
  1. input::-webkit-input-placeholder{color:#AAAAAA;}
  2. input:focus::-webkit-input-placeholder{color:#EEEEEE;}

5、去除android a/button/input標簽被點擊時產生的邊框 & 去除ios a標簽被點擊時產生的半透明灰色背景

a,button,input{-webkit-tap-highlight-color:rgba(255,0,0,0);}

6、ios使用-webkit-text-size-adjust禁止調整字體大小

body{-webkit-text-size-adjust: 100%!important;}

7、android 上去掉語音輸入按鈕

input::-webkit-input-speech-button {display: none}

8、移動端定義字體,移動端沒有微軟雅黑字體


    
  1. /* 移動端定義字體的代碼 */
  2. body{font-family:Helvetica;}

三、其他技巧

1、手機拍照和上傳圖片


    
  1. <!-- 選擇照片 -->
  2. <input type=file accept="image/*">
  3. <!-- 選擇視頻 -->
  4. <input type=file accept="video/*">

2、取消input在ios下,輸入的時候英文首字母的默認大寫

<input autocapitalize="off" autocorrect="off" />

3、打電話和發短信


    
  1. <a href="tel:0755-10086">打電話給:0755-10086</a>
  2. <a href="sms:10086">發短信給: 10086</a>

四、CSS reset


    
  1. /* hcysun */
  2. @charset "utf-8";
  3. /* reset */
  4. html{
  5. -webkit-text-size-adjust:none;
  6. -webkit-user-select:none;
  7. -webkit-touch-callout: none
  8. font-family: Helvetica;
  9. }
  10. body{font-size:12px;}
  11. body,h1,h2,h3,h4,h5,h6,p,dl,dd,ul,ol,pre,form,input,textarea,th,td,select{margin:0; padding:0; font-weight: normal;text-indent: 0;}
  12. a,button,input,textarea,select{ background: none; -webkit-tap-highlight-color:rgba(255,0,0,0); outline:none; -webkit-appearance:none;}
  13. em{font-style:normal}
  14. li{list-style:none}
  15. a{text-decoration:none;}
  16. img{border:none; vertical-align:top;}
  17. table{border-collapse:collapse;}
  18. textarea{ resize:none; overflow:auto;}
  19. /* end reset */

五、常用公用CSS style


    
  1. /* public */
  2. /* 清除浮動 */
  3. .clear { zoom:1; }
  4. .clear:after { content:''; display:block; clear:both; }
  5. /* 定義盒模型為怪異和模型(寬高不受邊框影響) */
  6. .boxSiz{
  7. -webkit-box-sizing: border-box;
  8. -moz-box-sizing: border-box;
  9. -ms-box-sizing: border-box;
  10. -o-box-sizing: border-box;
  11. box-sizing: border-box;
  12. }
  13. /* 強制換行 */
  14. .toWrap{
  15. word-break: break-all; /* 只對英文起作用,以字母作為換行依據。 */
  16. word-wrap: break-word; /* 只對英文起作用,以單詞作為換行依據。*/
  17. white-space: pre-wrap; /* 只對中文起作用,強制換行。*/
  18. }
  19. /* 禁止換行 */
  20. .noWrap{
  21. white-space:nowrap;
  22. }
  23. /* 禁止換行,超出省略號 */
  24. .noWrapEllipsis{
  25. white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  26. }
  27. /* 文字兩端對齊 */
  28. .text-justify{
  29. text-align:justify;
  30. text-justify:inter-ideograph;
  31. }
  32. /* 定義盒模型為 flex布局兼容寫法并讓內容水平垂直居中 */
  33. .flex-center{
  34. display: -webkit-box;
  35. display: -moz-box;
  36. display: -ms-flexbox;
  37. display: -o-box;
  38. display: box;
  39. -webkit-box-pack: center;
  40. -moz-box-pack: center;
  41. -ms-flex-pack: center;
  42. -o-box-pack: center;
  43. box-pack: center;
  44. -webkit-box-align: center;
  45. -moz-box-align: center;
  46. -ms-flex-align: center;
  47. -o-box-align: center;
  48. box-align: center;
  49. }
  50. /* public end */

六、flex布局

1、定義彈性盒模型兼容寫法


    
  1. /*
  2. box
  3. inline-box
  4. */
  5. display: -webkit-box;
  6. display: -moz-box;
  7. display: -ms-flexbox;
  8. display: -o-box;
  9. display: box;

2、box-orient 定義盒模型內伸縮項目的布局方向


    
  1. /**
  2. * vertical column 垂直
  3. * horizontal row 水平 默認值
  4. */
  5. -webkit-box-orient: horizontal;
  6. -moz-box-orient: horizontal;
  7. -ms-flex-direction: row;
  8. -o-box-orient: horizontal;
  9. box-orient: horizontal;

3、box-direction 定義盒模型內伸縮項目的正序(normal默認值)、倒敘(reverse)


    
  1. /* Firefox */
  2. display:-moz-box;
  3. -moz-box-direction:reverse;
  4. /* Safari、Opera 以及 Chrome */
  5. display:-webkit-box;
  6. -webkit-box-direction:reverse;

4、box-pack 對盒子水平富??臻g的管理


    
  1. /*
  2. start
  3. end
  4. center
  5. justify
  6. */
  7. -webkit-box-pack: center;
  8. -moz-box-pack: center;
  9. -ms-flex-pack: center;
  10. -o-box-pack: center;
  11. box-pack: center;

5、box-pack 對盒子垂直方向富裕空間的管理


    
  1. /*
  2. start
  3. end
  4. center
  5. */
  6. /* box-align */
  7. -webkit-box-align: center;
  8. -moz-box-align: center;
  9. -ms-flex-align: center;
  10. -o-box-align: center;
  11. box-align: center;

6、定義伸縮項目的具體位置


    
  1. /*-moz-box-ordinal-group:1;*/ /* Firefox */
  2. /*-webkit-box-ordinal-group:1;*/ /* Safari 和 Chrome */
  3. .box div:nth-of-type(1){-webkit-box-ordinal-group:1;}
  4. .box div:nth-of-type(2){-webkit-box-ordinal-group:2;}
  5. .box div:nth-of-type(3){-webkit-box-ordinal-group:3;}
  6. .box div:nth-of-type(4){-webkit-box-ordinal-group:4;}
  7. .box div:nth-of-type(5){-webkit-box-ordinal-group:5;}

7、定義伸縮項目占空間的份數


    
  1. -moz-box-flex:2.0; /* Firefox */
  2. -webkit-box-flex:2.0; /* Safari 和 Chrome */
  3. .box div:nth-of-type(1){-webkit-box-flex:1;}
  4. .box div:nth-of-type(2){-webkit-box-flex:2;}
  5. .box div:nth-of-type(3){-webkit-box-flex:3;}
  6. .box div:nth-of-type(4){-webkit-box-flex:4;}
  7. .box div:nth-of-type(5){-webkit-box-flex:5;}

藍藍設計m.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務

原生JS實現ajax詳解

seo達人

如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

原生js寫ajax可以類比打電話

打電話分下面4步:
1.拿出手機
2.撥號
3.說話
4.聽對方說話

ajax也分下面4步:
1.創建ajax對象
2.連接到服務器
3.發送請求(告訴服務器我要什么文件)
4.接收返回值

下面是原生js寫ajax的具體寫法 :


    
  1. <script>
  2. window.onload=function()
  3. {
  4. var oBtn = document.getElementById("btn1");
  5. oBtn.onclick = function()
  6. {
  7. //1.創建ajax對象
  8. //只兼容非ie6的瀏覽器,在ie6瀏覽器上運行會提示沒有被定義
  9. //var oAjax = new XMLHttpRequest();//這才是ajax實際的請求
  10. //alert(oAjax);
  11. //ie6瀏覽器下按照下面方法寫,但是在別的瀏覽器中不能用,會報錯。
  12. //var oAjax = new ActiveXObject("Microsoft.XMLHTTP");
  13. //alert(oAjax);
  14. //鑒于上面出現的問題,可以采取下面的方法解決,用if判斷是否為IE6瀏覽器
  15. if(window.XMLHttpRequest)//如果有XMLHttpRequest,那就是非IE6瀏覽器。()里面加window的原因下面會有描述。
  16. {
  17. var oAjax = new XMLHttpRequest();//創建ajax對象
  18. }
  19. else//如果沒有XMLHttpRequest,那就是IE6瀏覽器
  20. {
  21. var oAjax = new ActiveXObject("Microsoft.XMLHTTP");//IE6瀏覽器創建ajax對象
  22. }
  23. //2.連接服務器
  24. //open(方法、文件名、異步傳輸)
  25. //方法:
  26. //傳輸方式是get方式還是post方式。
  27. //文件名
  28. //告訴服務器要讀哪個文件
  29. //異步傳輸
  30. //異步:多件事一件一件的做
  31. //同步:多件事情一起進行
  32. //但是js里面的同步和異步和現實的同步異步相反。
  33. //同步:多件事一件一件的做
  34. //異步:多件事情一起進行
  35. //ajax天生是用來做異步的
  36. oAjax.open("GET","a.txt?t='+new Date().getTime()",true);//加上t='+new Date().getTime()"的目的是為了消除緩存,每次的t的值不一樣。
  37. //3.發送請求
  38. oAjax.send();
  39. //4.接收返回
  40. //客戶端和服務器端有交互的時候會調用onreadystatechange
  41. oAjax.onreadystatechange=function()
  42. {
  43. //oAjax.readyState //瀏覽器和服務器,進行到哪一步了。
  44. //0->(未初始化):還沒有調用 open() 方法。
  45. //1->(載入):已調用 send() 方法,正在發送請求。
  46. //2->載入完成):send() 方法完成,已收到全部響應內容。
  47. //3->(解析):正在解析響應內容。
  48. //4->(完成):響應內容解析完成,可以在客戶端調用。
  49. if(oAjax.readyState==4)
  50. {
  51. if(oAjax.status==200)//判斷是否成功,如果是200,就代表成功
  52. {
  53. alert("成功"+oAjax.responseText);//讀取a.txt文件成功就彈出成功。后面加上oAjax.responseText會輸出a.txt文本的內容
  54. }
  55. else
  56. {
  57. alert("失敗");
  58. }
  59. }
  60. };
  61. }
  62. };
  63. /*//上面if里面需要些window的原因
  64. //js里面的變量和屬性
  65. var a = 12;
  66. alert(a);//頁面上彈出12很正常,而實際上輸出的是下面的寫法,是屬于window的,只是window能省就省了。
  67. alert(window.a);//輸出結果是一樣的
  68. window.alert(window.a);
  69. //想a這種全局變量實際上是winow的一個屬性。
  70. //如果不定義一個變量a直接像下面那樣輸出a
  71. alert(a)//系統會報錯,而不是undefind,因為沒有定義變量a。
  72. alert(window.a);//如果是這樣寫,系統就不會報錯了,會顯示undefind。
  73. //出現上面的原因是因為直接寫a從根上就找不到a,而前面加上window只是找不到window的屬性a了。*/
  74. </script>

但是,不能每次用ajax的時候都寫那么多代碼,要把這段ajax代碼封裝起來,方便使用。

封裝ajax代碼如下:


    
  1. //最后把代碼封裝起來,封裝起來以后,要給這個函數加上一個參數url.參數是為了替換要讀取的文件名
  2. function ajax(url,fnSucc)
  3. {
  4. if(window.XMLHttpRequest)
  5. {
  6. var oAjax = new XMLHttpRequest();
  7. }
  8. else
  9. {
  10. var oAjax = new ActiveXObject("Microsoft.XMLHTTP");//IE6瀏覽器創建ajax對象
  11. }
  12. oAjax.open("GET",url,true);//把要讀取的參數的傳過來。
  13. oAjax.send();
  14. oAjax.onreadystatechange=function()
  15. {
  16. if(oAjax.readyState==4)
  17. {
  18. if(oAjax.status==200)
  19. {
  20. fnSucc(oAjax.responseText);//成功的時候調用這個方法
  21. }
  22. else
  23. {
  24. if(fnfiled)
  25. {
  26. fnField(oAjax.status);
  27. }
  28. }
  29. }
  30. };
  31. }

將封裝的ajax調用:


    
  1. <script src="new_ajax.js"></script>//引用封裝的ajax文件
  2. <script>
  3. window.onload=function()
  4. {
  5. var oBtn = document.getElementById("btn1");
  6. oBtn.onclick = function()
  7. {
  8. ajax('a.txt',function(str){//讀取a.txt文件里面的內容
  9. alert(str);//將讀取的內容輸出
  10. })
  11. }
  12. };
  13. </script>
藍藍設計m.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務

遮罩層上滾動,使下方的列表隨之滾動

seo達人

如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

效果

這里寫圖片描述

遮罩層為一張邊框樣式圖(如下圖):

這里寫圖片描述

邊框樣式遮罩層顯示在最上方,然后是中間的列表,最下層是一個透明黑色遮罩層,滾動鼠標滾輪,能控制列表滾動

實現原理

注冊最上面遮罩層的滾動事件,拿到滾動滾動方向,然后控制列表滾動的方向和距離

上代碼

注冊事件 /**
 * 增加滾輪滾動事件(暫時只實現了chrome的滾動效果)
 * @param modalDomId 遮罩層domId
 * @param domId 需要滾動下層列表domId
 */ addMousewheelListener(modalDomId:string,domId:string){ //添加頁面監聽 let modalAwardPanel = document.getElementById(modalDomId);
  modalAwardPanel.addEventListener('mousewheel',function(e){
    let scrollContentDom = document.getElementById(domId); //向上滾 if (e.wheelDelta > 0){ if (scrollContentDom.scrollTop -20 >= 0){
        scrollContentDom.scrollTop = scrollContentDom.scrollTop - 20;
      } else{
        scrollContentDom.scrollTop = 0 ;
      }
    } //向下滾 else{ if(scrollContentDom.scrollTop + scrollContentDom.clientHeight < scrollContentDom.scrollHeight){
        scrollContentDom.scrollTop = scrollContentDom.scrollTop + 20;
      }
    }
  });
}

組件調用: this.addMousewheelListener("你的最上方遮罩層id","你想要滾動的列表id");
藍藍設計m.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務

前端算法之彈幕設計

seo達人

如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

大家都說前端寫頁面較多,幾乎用不到算法。本文愿從彈幕設計這個場景來描述算法在前端中的應用,我們先來看下實現效果:

圖1.1 彈幕效果

 

開場之前我們先來描述彈幕開發的難度,再集中精力描述算法設計的思路。

* 如何保證不同字號的彈幕不碰撞
* 彈幕的位置計算
* 彈幕的速度控制及動畫實現
* 彈幕與視頻的同步

***如何保證不同字號的彈幕不碰撞***

如果彈幕采用相同的字號,碰撞的問題處理起來比較簡單,只要考慮相鄰彈幕的播放速度和偏移的位置就可以計算出來。然而使用不同字號的彈幕處理起來就麻煩了許多,彈幕的起始位置不可以線性的增加,比如第一行放了字幕,接下來的字幕可以按順序從上至下依次放置即可。

***彈幕的位置計算***

只有設計好彈幕的初始位置,才可以動態、的管理不同字號彈幕的碰撞問題。打個比方,我們通過接口獲取了2秒之內的彈幕數據1000條,每個字幕的長度、速度、字號都不同,怎么管理這些彈幕,示意圖如下:

圖2.1 彈幕管理示意圖

 

這是第一種情況,按照從上到啊的順序依次擺放以后會有幾個問題:
1. 彈幕五、六、七該怎么計算位置,按top值循環取模+累加嗎?
2. 當彈幕一或者彈幕三足夠長的時候,如何準時的跳過當前位置計算?
3. 當前屏幕的彈幕播放結束,如何再計算的時候利用空出來的位置
4. 空出的位置是否滿足當前彈幕的高度
5. ……

一系列問題就不統統列舉出來了,基于這個背景我們結合數學建模的思維方式,找到了彈幕場景相似度非常高的機場運營。我們可以把彈幕當做飛機,每個時間段播放多少彈幕和機場每個時間段放飛多少飛機一個道理。

首都國際機場一共有3條跑道,兩條4E級跑道、一條4F級跑道,2016年的吞吐量為9000萬人次。它的運行機制就是所有飛機通過搭臺有順序的共用3條跑道來完成運輸任務的。

同理,我們也設計了幾個個角色:一個是軌道(跑道)、一個是調度(塔臺)、一個是彈幕(飛機),我們為每個角色設計一個類分為為Track、Main、Bullet。

* 軌道
            
       軌道這個角色很重要,它可以解決彈幕位置計算、速度控制、碰撞檢測問題。
       首先,我們要來初始化軌道。通俗的說我們要修建幾個跑道呢,我們不是實物,可以動態調整軌道的                        數量,計算的原則:
        軌道數量 = 播放器有效高度 / 設備基準字號
    * 播放器有效高度:播放器的實際高度減去控制條的高度,因為彈幕不可以遮擋控制條。
    * 設備基準字號:移動端是10px,pc端是12px;
        為啥計算公式是這樣的?因為我們要支持不同字號的彈幕。試想不同的字號對物理空間的占用是不同的,然而如果要求軌道的尺寸是動態的,那就帶來很復雜的計算。本文提出“虛擬軌道”的概念,在交通管制中最常見的就是道路合并或者改向。我們也是采用將相鄰的物理軌道臨時合并為一條軌道。這樣就可以輕松的解決不同字號的軌道占用問題。原理圖如下:
        

圖2.2 軌道計算示意圖

其次我們來回憶下機場的工作流程:
1. 機長呼叫塔臺,CZ6132請求起飛
    * 目前跑道均被占用,請等待
        * N時刻后再次執行步驟1
    * 目前跑道 A1 空閑,準許進入
        * 執行步驟3
2. 塔臺查看跑道使用情況
3. 進入跑道,起飛完成
4. 機長通知塔臺,本次起飛完成,釋放跑道的占用
5. 其他飛機同樣執行上述步驟

按照這個思路,我們的彈幕工作流程:
    
1. 彈幕進入播放器
2. 軌道根據彈幕的播放速度、尺寸計算是否有合適的軌道提供
    * 沒有
        * 通知彈幕尚無合適軌道提供,請等待;同時,彈幕隊列中的其他彈幕依次執行步驟1
    * 有
        * 執行步驟3
3. 播放器加載彈幕DOM,開始播放,待播放完成
4. 播放完成通知軌道更新軌道占用情況
5. 其他彈幕同樣執行上述步驟

圖2.3 軌道可用性計算示意圖

 

關于軌道的基本原理我們整理清楚了,當然還有不少細節比如如何和調度通信、如何和彈幕通信以及虛擬軌道檢測算法等。有興趣的同學可以參考代碼吧。https://github.com/bytedance/xgplayer/blob/master/packages/xgplayer/src/control/makeBullet.js

* 彈幕
       彈幕基本是實現“飛機”的角色,我們要求它具有自身的屬性和方法。比如調度中心通過id能拿到它所有的基本信息,軌道控制也可以通過彈幕進行檢查和更新。當然彈幕也必須具備狀態自動更新、移動、播放結束通知、自動銷毀等功能。
* 調度
        調度就是搭臺的化身,承接著軌道、彈幕的控制,也保持著與播放器的步調一致。它的職責如下:
    1. 播放器交互控制
    2. 彈幕隊列控制
    3. 自身狀態更新
    4. 數據格式轉換
    5. 動畫執行
        還是直接用流程圖來描述更直接些:
        
       

圖2.4 彈幕運行機制流程圖

在彈幕啟動之后,首先要檢查本地是否已有緩存數據,沒有的話直接請求數據并緩存,然后執行數據讀取,首次過濾數據進入彈幕隊列,同時啟動定時器。彈幕隊列的數據會定期請求軌道,檢測隊列里的彈幕是否可以進入,一旦確認后軌道做好登記,彈幕就可以進入播放器開啟動畫播放了。定時器每隔2秒就會再次更新數據進入到彈幕隊列(這塊不同的業務可以定制不同的規則)。彈幕播放結束后會通知調度和軌道,調度會在彈幕隊列中移除該彈幕實例,軌道也會移除該彈幕實例的軌道占用。

藍藍設計m.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務


快速開發一個自己的微信小程序

seo達人

如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

一.寫在前面

小程序學習資料

1.為什么要學小程序開發?

對于前端開發而言,微信小程序因為其簡單快速、開發成本低、用戶流量巨大等特點,也就成了前端開發工程師必會的一個技能。

2.開發準備:

(1)有人開玩笑說,會vue小程序根本都不用學:

微信小程序雖然是騰訊自己搞的,但是核心的思想跟vue等框架是一樣一樣的哦~

(2)善于搜集精美的小組件: “我們不生產代碼,我們只是代碼的搬運工”,善于找到想要的組件并把他們巧妙優雅的組裝成一個大項目,也算是程序員一項基本技能了。

具體怎么找到想要的小程序demo,篇末會給大家推薦小程序的資源,有很多大神的項目哦

擼起袖子開干了

一.注冊小程序賬號,下載IDE

1.官網注冊https://mp.weixin.qq.com/,并下載IDE。

2.官方文檔一向都是最好的學習資料。

注意:

(1)注冊賬號之后會有一個appid,新建項目的時候需要填上,不然很多功能是用不了的,比如不能預覽,不能上傳代碼等等。

(2)如果你注冊過微信公眾號的話,一定要注意,微信公眾號和小程序是兩個賬號,二者的appid也是不同,小程序開發必須使用小程序的appid哦。

二.小程序框架介紹和運行機制

1.我們建立了“普通快速啟動模板”,然后整個項目目錄如下:

2.app.js

整個項目的啟動文件,如注釋寫的onlaunch方法有三大功能,瀏覽器緩存進行存和取數據;用登陸成功的回調;獲取用戶信息。

globalData是定義整個項目的全局變量或者常量哦。

3.app.json

整個項目的配置文件,比如注冊頁面,配置tab頁,設置整個項目的樣式,頁面標題等等;

!注意:小程序啟動默認的第一個頁面,就是app.json的pages中的第一個頁面哦。

4.pages

小程序的頁面組件,有幾個頁面就會有幾個子文件夾。比如快速啟動模板,就有兩個頁面,index和logs

5.打開index目錄

可以看到有三個文件,其實和我們web開發的文件是一一對應的。

index.wxml對應index.html;

index.wxss對應index.css;

index.js就是js文件哦。

一般我們還會給每個頁面組件添加一個.json文件,作為該頁面組件的配置文件,設置頁面標題等功能

6.雙擊index.js文件

(1)var app = getApp();

引入整個項目的app.js文件,用來取期中的公共變量等信息。

如果要使用util.js工具庫中的某個方法,在util.js中module.exports導出,然后在需要的頁面中require即可得到哦。

(2)比如,我們要獲取豆瓣電影的時候,我們需要調用豆瓣的api;我們先在app.js中的gloabData中定義doubanBase

然后在index.js中使用app.globaData.doubanBase即可取到這個值。

當然這些常量你也可以在頁面需要的時候,再用寫死的值,但是為了整個項目的維護,還是建議把這種公用參數統一寫在配置文件中哦。

(3)接下來在整個page({})中,第一個data,就是本頁面組件的內部數據,會渲染到該頁面的wxml文件中,類似于vue、react哦~

通過setData修改data數據,驅動頁面渲染

(4)一些生命周期函數

比如onload(), onready(), onshow(), onhide()等等,監聽頁面加載、頁面初次渲染、頁面顯示、頁面隱藏等等

更多的可以查官網API哦。其中用的最多的就是onload()方法,和onShareAppMessage()方法(設置頁面分享的信息)

7 .wxml模板的使用。

比如本項目電影頁面,就是以最小的星級評價組件wxml當做模板,star到movie到movie-list,一級一級的嵌套使用。

star-template.wxml頁面寫好name屬性;然后import引入的時候通過name獲得即可

8.常用的wxml標簽

view,text,icon,swiper,block,scroll-view等等,這些標簽直接查官網文檔即可

三.小程序框架、各個頁面以及發布上線的注意點

1.整個框架中的一些注意點

(1)整個wxml頁面,最底層的標簽是哦。

(2) 每個頁面頂部導航欄的顏色,title在本頁面的json中配置,如果沒有配置的話,取app.json中的總配置哦。

(3)json中不能寫注釋哦,不然會報錯的。

(4)路由相關

1)使用wx.SwitchTab跳轉tab頁的話,在app.json中除了注冊pages頁面,還需要在tabBar中注冊tab頁,才能生效哦。

注意:tab最多5個,也就是我們說的頭部或者底部最多5個菜單。其他的頁面只能通過其他路由方法打開哦。

2)navigateTo是跳到某個非tab頁,比如歡迎頁,電影詳情頁,城市選擇頁;在app.json中注冊后,不能在tabBar里注冊哦,不然同樣也是不能跳轉的哦。

3)reLaunch跳轉,新開的頁面左上角是沒有退回按鈕的,本項目只用了一次,切換城市的時候哦。

(5)頁面之間傳遞參數

參數寫在跳轉的url之中,然后另一個頁面在onload方法中的傳參option接收到。如下傳遞和獲取id

(6)data-開頭的自定義屬性的使用

比如wxml中我們怎么寫

點擊的事件對象可以這么取,var postId = event.currentTarget.dataset.postid;

注意: 大寫會轉換成小寫,帶_符號會轉成駝峰形式

(7)事件對象event,event.target和event.currentTarget的區別:

target指的是當前點擊的組件 和currentTarget 指的是事件捕獲的組件。

比如,輪播圖組件,點擊事件應該要綁定到swiper上,這樣才能監控任意一張圖片是否被點擊,

這時target這里指的是image(因為點擊的是圖片),而currentTarget指的是swiper(因為綁定點擊事件在swiper上)

(8)使用免費的網絡接口:

本項目中用到了 和風天氣api,騰訊地圖api,百度地圖api,豆瓣電影api,聚合頭條新聞api等,具體用法可以看各自官網的接口文檔哦,很詳細的

注意:免費接口是有訪問限制的,所以如果用別人的組件用了這種接口的話,最好還是自己注冊一個新的key替換上哦

附上一個免費接口大全:

https://github.com/jokermonn/-Api

!!另外還要注意,要把這些接口的域名配置到小程序的合法域名中,不然也是訪問不了的

(8)wxss有一個坑:無法讀取本地資源,比如背景圖片用本地就會報錯哦。

把本地圖片弄成網絡圖片的幾種方式: 上傳到個人網站;QQ空間相冊等等也是可以的哦

2.切換城市頁面:

(1)首頁使用navigateTo跳轉到切換城市頁,由于首頁并沒有關閉,導致切換了城市返回來,天氣信息還是舊的。

正確的處理邏輯如下:

1)使用reLaunch跳轉到切換城市頁面,實質是關閉所有頁面打開新的頁面哦。

2)切換城市頁面,更新公共變量中城市信息為手動切換的城區,再switchTab回到首頁,觸發首頁重新加載。

3)首頁獲取城市信息的時候加一個判斷,全局沒有才取定位的,全局有(比如剛才設置了)就用全局的哦。

(2)城市列表的滾動和回到頂部

基于scroll-view組件的scroll-top屬性,初始就是0,滾動就會增加的;點擊回到頂部給它置為0即可回到頂部

3.天氣頁

(1)初始化頁面,天氣顯示的邏輯

首先調用小程序的wx.getLocation方法獲得當前的經緯度,然后調用騰訊地圖獲得當前的城市名稱和區縣名稱,并存到公共變量中,

再調用查詢天氣和空氣質量的方法哦。

(2)容錯處理

城市的名稱長短不一,有點名字特別長,比如巴彥淖爾市這種,需要動態的獲取完整的城市名稱;

有些偏僻的城市暫時沒有天氣信息,我們需要對返回的結果進行判斷,沒有信息的需要給用戶一個良好的提示信息。

4.周邊-地圖服務頁面

(1)調用百度地圖的各種服務,查詢酒店,美食,生活服務三種信息,更多信息可以看百度地圖的文檔

(2)點擊時給被點中的圖標加個邊框,數據驅動視圖,所以使用一個長度為3的數組保存三個圖標當前是否被點中的狀態

然后wxml再根據數據來動態添加class,增加邊框樣式

5.豆瓣電影頁

(1)電影詳情頁的預覽圖片,用小程序本身的previewImage實現。

(2)詳情頁使用onReachBottom()方法,監控用戶上拉觸底事件,然后發送請求繼續獲得數據,實現懶加載的效果

(3)用戶體驗方面的優化,js中將整數評分比如7分統一改為7.0分,然后wxml模板再判斷分數是否為0顯示“暫無評分”

(4)搜索之后清空搜索框

因為小程序中不能使用getelementbyId這種方式獲得元素,只能用數據來控制了

在data中加一個屬性searchText來保存搜索框的內容并和 input的value屬性綁定,搜索完成或者點擊X時,searchText變量清空即可實現清空輸入框的效果哦。

6.新聞頁面

(1)聚合頭條新聞的免費接口,只返回了新聞的基本信息,新聞的主體內容是沒有的哦。

我找了好多新聞類的接口,好像都是沒有新聞主體內容的。如果誰知道更好的接口歡迎留言告訴我哈~

(2)當然,也可以自己去爬新聞網站的數據哦

7.更多頁面

(1)小程序目前開放外鏈的功能只是給公司組織的小程序開放了,個人開發還是不能使用外鏈的哦。

(2)彩蛋頁面,獲得用戶信息

通過 wx.setStorageSync('userInfos', userInfos); 可以獲得登陸小程序的用戶的個人信息,可以發送給后臺存到數據庫中,方便對用戶進行分析

我這里只是存儲到瀏覽器緩存中哦,最大應該是10M緩存;如果用戶把這個小程序從小程序列表中刪除掉,就會清空這個緩存。

8.發布注意

(1) 新版本小程序發布的限制為2M,一般都是圖片最占空間,所以盡量使用網絡圖片

具體怎么把本地圖片變成網絡圖片,上面有講哦。

(2)在開發者工具上預覽測試沒問題,點擊上傳;網頁版小程序個的人中心的左側“開發管理”菜單,第三塊--開發版本就有了內容。

(3)點擊提交,填寫小程序相關信息,就可以提交審核了哦。

注意:分類最好填寫準確,這樣才能更快的通過審核哦。我這個小程序一天半時間過審上線的

至此,我就把兩天開發內碰到的坑和注意點都過了一遍,據說還有更多的坑,等之后更深入的開發再繼續研究咯。

藍藍設計m.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務

mongoose中save無法獲取回調函數值的解決方法

seo達人

如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

mongoose保存數據:

const save = new Model(data).save()
    
  • 1

如果成功,則可以獲取到保存在數據庫的值,但是如果保存數據失敗,則會拋出異常,好在save可以傳入一個回調函數,用法如下:

const save = new Model(data).save((err, result)=>{ if(err){ // 保存失敗執行的操作
    }else { // 保存成功執行的操作
    }

})
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

我們希望根據結果獲取到不同的值,但是此時save返回的是undefined,因為save中的回調函數是一個異步操作

解決方法:

使用try catch:

try{
    const save = await new Model(data).save();
    // 保存成功執行的操作 return ... }catch(err){
    // 保存失敗執行的操作 return ... }
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

注意:在async函數中才可以這么使用,因為await只能用在async函數中

示例:(注冊功能)

user.model.js

const mongoose  = require("mongoose"); const port      = process.env.PORT || "8899"; const UserSchema = mongoose.Schema({
    userName: {
        type: String,
        unique: true },
    passWord: String,
    createTime: {
        type: Date, default: Date.now()
    },
    updateTime: {
        type: Date, default: Date.now()
    }
}, {
    timestamps: {
        createAt: "createTime",
        updateTime: "updateTime" }
});

module.exports = mongoose.model("USER", UserSchema);
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

service.js

const User = require("./user.model);
class User{
    async login(user){
            try{
                const result = await new User(user).save();
                // 其他操作,如發送注冊郵件
                return { success: true }
            }catch(err){
                return { success: false, message: "用戶名或密碼錯誤" }
            }
   }
}
moduel.exports = new User();
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

controller.js

const server = require("./server); async login(){ // 首先獲取請求中攜帶的用戶信息 const result = await server.login(user);
    if(result.success){ // 注冊成功執行的操作 }else { // 注冊失敗執行的操作 }
}
藍藍設計m.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務

HTML-圖片標簽img

seo達人

如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

圖片標簽

圖片標簽<img src=路徑屬性 alt:加載失敗后顯示的文本  width:指定圖片寬度  height:指定圖片高度>  單位: px

路徑屬性

絕對路徑
        E:\ruanjian\軟件\環境\images
相對路徑:相對于主文件位置的路徑
        引用文件方式:

        同級:直接寫文件名.后綴名
        上級:../文件名.后綴名   ../返回上一級文件夾
        下級:文件夾/文件名.后綴名


    
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title></title>
  6. </head>
  7. <body>
  8. <h1>這是一個圖片</h1>
  9. <!-- 圖片標簽<img src=路徑屬性 alt:加載失敗后顯示的文本 width:指定圖片寬度 height:指定圖片高度 單位:px>
  10. 路徑屬性:
  11. 絕對路徑
  12. E:\ruanjian\軟件\環境\images
  13. 相對路徑:相對于主文件位置的路徑
  14. 同級:直接寫文件名.后綴名
  15. 上級:../文件名.后綴名 ../返回上一級文件夾
  16. 下級:文件夾/文件名.后綴名
  17. -->
  18. <img src="../img/ad.jpg" alt="加載中" width="1000px" height="500px">
  19. <img src="../img/1.jpg" alt="加載中"><br><br><br><br><br><br><br><br><br><br><br>
  20. <img src="../footer.jpg" ><br>
  21. </body>
  22. </html>

<br>標簽:換行   <img>標簽為內聯標簽所以不換行,所以添加<br>標簽換行。

頁面是這樣的:

藍藍設計m.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務


前端性能優化之Lazyload

seo達人

如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

前端性能優化之Lazyload

@(Mob前端-冬晨)[JavaScript|技術分享|懶加載]


Lazyload 簡介

前端工作中,界面和效果正在變得越來越狂拽炫酷,與此同時性能也是不得不提的問題。有些項目,頁面長,圖片多,內容豐富。像商城頁面。如果同步加載時一次性加載完畢,那肯定是要等到花都謝了,loading轉的人都崩潰~。今天分享的是Lazyload技術 是一種延遲加載技術。讓頁面加載速度快到飛起、減輕服務器壓力、節約流量、提升用戶體驗。

一、實現思路

頁面較長,屏幕的可視區域有限。 
不設置頁面中img標簽src屬性值或者將其指向同一個占位圖。 
圖片的實際地址存在img標簽自定義的一個屬性中,如:“data-url”。 
監聽scroll,滾動到某個位置時,動態的將url替換成實際的“data-url”。

二、上代碼

  • html部分(簡單示意下結構)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Lazyload</title> <style type="text/css"> .mob-wrap li{list-style: none;width: 100%;height: 345px;} </style> </head> <body> <ul class="mob-wrap"> <li"> <img class="tamp-img" alt="loading" data-src="http://mob.com/public/images/index/sharesdk-logo.jpg"><p>ShareSDK輕松實現社會化功能</p> </li> <li"> <img class="tamp-img" alt="loading" data-src="http://mob.com/public/images/index/sms-logo.jpg"><p>短信驗證碼SDK</p> </li> <li"> <img class="tamp-img" alt="loading" data-src="http://mob.com/public/images/index/rec-logo.jpg"><p>MobLink實現Web與App的無縫鏈接</p> </li> </ul> </body> </html>
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

簡要流程

Start監聽滾動事件距頂部高度<scrollTop么?將url替換成data-urlEndyesno
  • js部分
var aImg = [
  {"src":"http://mob.com/public/images/index/sharesdk-logo.jpg","txt":"ShareSDK輕松實現社會化功能"},
  {"src":"http://mob.com/public/images/index/sms-logo.jpg","txt":"短信驗證碼SDK"},
  {"src":"http://mob.com/public/images/index/rec-logo.jpg","txt":"MobLink實現Web與App的無縫鏈接"}
]; var sLi = '';
document.getElementsByClassName("mob-wrap")[0].innerHTML=""; for(let i = 0;i<10;i++){
  sLi = document.createElement("li");
  sLi.innerHTML = `<img class="tamp-img" alt="loading" src="./zwt.gif" data-src="${aImg[i%3].src}"><p>${aImg[i%3].txt}</p>`;
  document.getElementsByClassName("mob-wrap")[0].appendChild(sLi);
};

window.onscroll = function () {
  var bodyScrollHeight =  document.documentElement.scrollTop;// body滾動高度
  var windowHeight = window.innerHeight;// 視窗高度
  var imgs = document.getElementsByClassName('tamp-img');
  for (var i =0; i < imgs.length; i++) { var imgHeight = imgs[i].offsetTop;// 圖片距離頂部高度 if (imgHeight < windowHeight + bodyScrollHeight - 340) { imgs[i].src = imgs[i].getAttribute('data-src'); imgs[i].className = imgs[i].className.replace('tamp-img','');
    }
  }
};
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25




謝謝觀看,搞定收工0.0~~~這樣草草了事總是不好的

三、再優化

不做任何處理直接監聽scroll必然導致在滾動鼠標滾輪的時候,過于頻繁的觸發處理函數。 
如果剛巧在處理函數中有大量的操作dom等消耗性能的行為,引發大量操作,導致頁面變卡變慢, 
甚至瀏覽器崩潰無響應。 
處理這種問題的思路是節流和防抖。 
節流函數的概念有一個很形象的比喻:在接咖啡的時候,按了一次按鈕會出咖啡, 
緊跟著再按幾次按鈕接到的還是那一杯咖啡,相當于后面幾次按的沒有起作用。


常規的節流在這里就不多說了,下面介紹的是一種每隔least時間內至少執行一次的節流函數。

//節流函數 _throttle = (fn, delay, least) => { var timeout = null,
  startTime = new Date();
    fn(); return function() { var curTime = new Date();
    clearTimeout(timeout); if(curTime - startTime >= least) {
        fn();
        startTime = curTime;
    }else {
        timeout = setTimeout(fn, delay);
    }
    }
}
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

使用節流函數

function compare () { var bodyScrollHeight =  document.documentElement.scrollTop;// body滾動高度 console.log(bodyScrollHeight+"替換src方法") var windowHeight = window.innerHeight;// 視窗高度 var imgs = document.getElementsByClassName('tamp-img'); for (var i =0; i < imgs.length; i++) { var imgHeight = imgs[i].offsetTop;// 圖片距離頂部高度  if (imgHeight < windowHeight + bodyScrollHeight - 340) {
       imgs[i].src = imgs[i].getAttribute('data-src');
       imgs[i].className = imgs[i].className.replace('tamp-img','');
    }
  }
}
window.onscroll = _throttle(compare, 350,600);
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

滾動時間least長于600,調用compare,否則延遲350ms執行。 
這樣相對于直接onscroll性能得到更進一步提升,在功能上也沒有什么問題。 
不同的業務場景調整一下delay和least就可以。


結語:歷史潮流浩浩蕩蕩,前端技術的發展也是日新月異。 
不斷通過一個個小的技術點深入探究,以加深自己對js這門語言的理解。 
溫故知新,回顧舊的內容,學習新的內容和特性,更好的適應工作中的需求。

藍藍設計m.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務



跨瀏覽器問題

seo達人

如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

寫在前面的話

關于跨瀏覽器問題一直是一個大問題, 所以我決定在此做一個記錄, 當然不可能把跨瀏覽器問題一下子都搞定, 所以該文章將是一個長期的過程, 當coding時遇到了, 就會完善該文。

添加事件

var EventUtil = { /*
     *添加事件
    */ addHandler: function(element, type, handler) { if(element.addEventListener){ element.addEventListener(type, handler, false)
        }else if(element.attachEvent){ element.attachEvent('on'+type, handler)
        }else{ element['on'+type] = handler
        }
    }, /*
     *刪除事件
    */ removeHandler: function(element, type, handler){ if(element.removeEventListener){ element.removeEventListener(type, handler, false)
        }else if(element.detachEvent){ element.detachEvent('on'+type, handler)
        }else { element['on'+type] = null }
    }, /*
     *獲得事件對象
    */ getEvent: function(event){ return event ? event : window.event  //ie瀏覽器的事件對象是window對象的屬性, 所以需要window.event來獲取。 }, /*
     *獲得事件對象的事件目標(觸發事件的事件目標)
    */ getTarget: function(event){ return event.target || event.srcElement //這是||符號的另一種用法, 遇到true就返回。 }, /*
     *阻止默認事件
    */ preventDefault: function(event){ if(event.preventDefault){
            event.preventDefault
        }else{
            event.returnValue = false }
    }, /*
     *阻止事件冒泡
    */ stopPropagation: function(event){ if(event.stopPropagation){
            event.stopPropagation()
        }else {
            event.cancelBubble = true }
    }

}  // stopPropagation()方法既可以阻止事件冒泡,也可以阻止事件捕獲,也可以阻止處于目標階段。
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

ajax事件

關于xhr對象, ie7需要之前的需要使用ActiveXObject對象來實現, 而且存在三個不同的版本。 雖然現在已經不用兼容ie7以前的瀏覽器了, 還是可以了解一下: 
//適用于IE7之前的版本

function createXHR(){ if(typeof arguments.callee.activeXString != 'string'){ var versions = ['MSXML2.XMLHttp.6.0', 'MSXML2.XMLHttp.3.0', 'MSXML2.XMLHttp'],
        i,
        len; for(i = 0; len = version.length; i++){ try{ new ActiveXObject(veersions[i]); arguments.callee.activeXString = versions[i] break }catch(ex){ //跳過 }
        }
    } return new ActiveXObject(arguments.callee.activeXString)
}
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

//最終版本

function createXHR(){ if(typeof XMLHttpRequest != 'undefined'){ return new XMLHttpRequest()
    }else if(typeof ActiveXObject != 'undefined'){ if(typeof arguments.callee.activeXString != 'string'){ var versions = ['MSXML2.XMLHttp.6.0', 'MSXML2.XMLHttp.3.0', 'MSXML2.XMLHttp'],
        i,
        len; for(i = 0; len = version.length; i++){ try{ new ActiveXObject(veersions[i]); arguments.callee.activeXString = versions[i] break }catch(ex){ //跳過 }
        }
    } return new ActiveXObject(arguments.callee.activeXString)
    }else { throw new Error("NO XHR object availabel")
    }
}
藍藍設計m.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務

日歷

鏈接

個人資料

藍藍設計的小編 http://m.skdbbs.com

存檔

92国产精品视频_亚洲a级在线观看_国产精品电影观看_国产精品免费观看在线_精品伊人久久97_亚洲人成在线观_尤物九九久久国产精品的特点_成人激情在线播放_成人黄色大片在线免费观看_亚洲成人精品久久久_久久免费视频在线观看_久久精品国产一区_国产一区二区三区18_亚洲欧美中文字幕在线一区_日韩美女中文字幕_日韩视频免费在线
欧美www在线| 自拍视频亚洲| 欧美在线观看一二区| 国产ts一区| 欧美精品一区二区三区久久久竹菊| av有声小说一区二区三区| 在线观看日韩av电影| 久久色精品视频| 欧美mv日韩mv国产网站app| 麻豆视频在线观看免费网站| 欧美黄色一区二区| yw视频在线观看| 欧美va天堂va视频va在线| 综合激情网站| 国产一区二区三区欧美| 不卡一区二区三区视频| 国产不卡一区二区在线播放| 精品肉辣文txt下载| 亚洲激情图片一区| 久久久精品国产**网站| 成人激情综合网| 久久青青视频| 97在线超碰| 欧美日本在线视频中文字字幕| 国内毛片久久| 日韩三区在线| 欧美探花视频资源| 最新国产拍偷乱拍精品| 五月天丁香综合久久国产| 日韩精品中文字幕一区二区三区| 中文字幕这里只有精品| 欧美色道久久88综合亚洲精品| 欧美在线视频播放| 日韩福利视频导航| 国产不卡网站| 亚洲综合偷拍欧美一区色| 免费国产在线精品一区二区三区| 国产精品一区二区三区毛片淫片| 成人黄色在线免费| 在线观看a级片| 美女av一区二区三区| 成人高清免费观看| 久久这里只有| 奇米影视亚洲狠狠色| 色一情一乱一区二区| 亚洲国产另类 国产精品国产免费| 国产日本欧美一区二区三区| 亚洲一区国产一区| 久久久久国产精品免费网站| 日韩av高清| 国产精品对白一区二区三区| 99在线精品视频在线观看| 亚洲xxx拳头交| 国产亚洲成av人在线观看导航| 丝袜连裤袜欧美激情日韩| 综合久久av| 国产成人中文字幕| 欧美日韩成人一区| 免费亚洲电影在线| 欧美日韩中文在线| 欧美黄网免费在线观看| 亚洲一区在线视频观看| 精品电影一区| 欧美成人69| 国产精品二区一区二区aⅴ污介绍| 最新成人av在线| 精品亚洲永久免费精品| 国内精品视频在线播放| 精品无人乱码一区二区三区的优势| 97se亚洲综合| 成人午夜888| 国产欧美日韩丝袜精品一区| 亚洲第一精品电影| 国产经典一区二区三区| 永久免费毛片在线播放不卡| 久久久综合精品| 欧洲乱码伦视频免费| 免费高清在线观看| 婷婷视频在线| 亚洲国产综合人成综合网站| 欧洲精品毛片网站| 伊人影院久久| 午夜视频一区二区三区| 天堂一区二区在线免费观看| 日韩欧美国产综合一区| 日韩精品成人一区二区在线观看| 久久99精品久久久久久久久久| 亚洲视频自拍| 7878成人国产在线观看| 97超级在线观看免费高清完整版电视剧| 日本黄色一区二区| 精品一区二区综合| 精品一区二区三区中文字幕在线| 精品无码三级在线观看视频| 免费一区视频| 日本老师69xxx| 精品久久久久久久大神国产| 香蕉视频成人在线观看| 国产精品露脸av在线| 欧美色精品天天在线观看视频| 国产一区二区导航在线播放| 欧美日韩无遮挡| 国产精品久久久久aaaa樱花| 一区二区三区在线影院| 国内精品在线一区| 国产精品一区二区日韩| 天天做天天摸天天爽国产一区| 久久久中精品2020中文| 午夜av一区二区| 99riav视频在线观看| 欧美色成人综合| 懂色av一区二区三区蜜臀| 国产乱视频在线观看| 亚洲高清不卡一区| 污片在线免费观看| 欧美精品日韩一区| 精品国产乱码久久久久久樱花| 红杏一区二区三区| 色哟哟网站入口亚洲精品| 97在线免费观看| 亚洲在线黄色| 极品美女销魂一区二区三区免费| 亚洲色图视频免费播放| 蜜桃伊人久久| 欧美性淫爽ww久久久久无| 欧美一区二区在线免费观看| 日韩中文一区二区三区| 高清在线观看av| av网址在线| 欧美视频第一页| 日韩av在线最新| 日韩精品电影网站| 99久久综合狠狠综合久久aⅴ| 欧美激情在线观看| 国产精品一二三在线| 欧美高清性xxxxhdvideosex| 色综合天天爱| 日韩亚洲精品在线| 久久99精品久久久久| 波多野结衣一区二区三区在线观看| 久久天天躁狠狠躁老女人| 欧洲成人午夜免费大片| 999热视频在线观看| 国产精品久久久久四虎| 日韩欧美精品网站| 国产91在线观看| 亚洲一级免费视频| 精品久久香蕉国产线看观看亚洲| 成人激情电影在线| 亚洲无线看天堂av| 日韩一区二区免费高清| 国产欧美日韩| 欧美日韩在线视频一区二区| 久久国产精品久久精品国产| 色偷偷噜噜噜亚洲男人的天堂| 色婷婷av一区二区| 国产suv精品一区二区6| 久久久精彩视频| 成人性生交大片免费| 4438全国亚洲精品在线观看视频| 91免费看网站| 亚洲天天影视| 91免费国产网站| 国产喂奶挤奶一区二区三区|