亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

轉(zhuǎn)盤抽獎腳本自己擼

趙春朋 / 2696人閱讀

摘要:效果需求很多場景都需要做各種活動,抽獎最是司空見慣了,跑馬燈的,轉(zhuǎn)盤的,下面先花幾分鐘擼出一個轉(zhuǎn)盤的吧,當(dāng)然網(wǎng)上至少有一打的可供參考。但是我們只差一個定時器循環(huán)了接下里實現(xiàn)這個主循環(huán),不斷更新值就可以了。

demo 效果

需求

很多場景都需要做各種活動,抽獎最是司空見慣了,跑馬燈的,轉(zhuǎn)盤的,下面先花幾分鐘擼出一個轉(zhuǎn)盤的吧,當(dāng)然網(wǎng)上至少有一打的 demo 可供參考。
真的只需要一點點時間而已。

書寫偽代碼

實現(xiàn)一個東西,一般都先寫偽代碼,這里也不例外。
初步想法功能主要有兩點:

實現(xiàn)一個類 class,只要傳入一個元素節(jié)點,就可以控制轉(zhuǎn)動,

轉(zhuǎn)動角度和時長以及動畫曲線 可 通過參數(shù)進(jìn)行配置

考慮一下,這個類需要什么方法功能?
根據(jù)上面的兩個需求,

第一 需要一個 設(shè)置參數(shù)的 方法

第二需要提供一個 開啟動畫的方法

第三,既然是動畫,脫不開定時器功能,所以需要一個動畫主循環(huán)

這里再提供一個 init 方法用作初始化操作,比如設(shè)置參數(shù)或者還有其他處理,增加兼容性。
下面是偽代碼

class RotatePlate {
  constructor(options) {
    this.init();
  }
  /**
   * 初始化操作
   */
  init() {
    this.setOptions();
  }
  /**
   * 啟動轉(zhuǎn)動函數(shù)
   */
  rotate() {}
  /**
   * 設(shè)置配置參數(shù)
   */
  setOptions() {}
  /**
   * 動畫主循環(huán)
   */
  _animate() {}
}
實現(xiàn)參數(shù) options 配置方法

為了方便使用和兼容處理,我們開發(fā)者常用的做法就是配置默認(rèn)參數(shù),然后用 調(diào)用者的參數(shù)去覆蓋默認(rèn)參數(shù)。所以,先給類增加一些默認(rèn)配置,如下:

constructor(options) {
    // 緩存用戶數(shù)據(jù)參數(shù),稍后會進(jìn)行默認(rèn)參數(shù)覆蓋,之后再做重復(fù)初始化也會很方便
    this.customOps = options;
    // 默認(rèn)參數(shù)配置
    this._parameters = {
      angle: 0, // 元素初始角度設(shè)置
      animateTo: 0, // 目標(biāo)角度
      step: null, // 旋轉(zhuǎn)過程中 回調(diào)函數(shù)
      easing: function(t, b, c, d) {
        return -c * ((t = t / d - 1) * t * t * t - 1) + b;
      }, // 緩動曲線,關(guān)于動畫 緩動函數(shù)不太懂得可以自行搜索
      duration: 3000, // 動畫旋轉(zhuǎn)時間
      callback: () => {}, // 旋轉(zhuǎn)完成回調(diào)
    };
    this._angle = 0; // 維護(hù)一個當(dāng)前時刻角度的私有變量,下面setOptions就知道如何使用了
  }
  this.init(); // 調(diào)用初始化方法

接下來實現(xiàn) setOptions 方法,并且在 init 方法中進(jìn)行調(diào)用,這個方法實現(xiàn)沒什么難度,就是對象合并操作

init() {
  // 初始化參數(shù)
  this.setOptions(Object.assign({}, this.customOps));
}

/**
  * 設(shè)置配置參數(shù)
  */
setOptions(parameters) {
  try {
    // 獲取容器元素
    if (typeof parameters.el === "string") {
      this.el = document.querySelector(parameters.el);
    } else {
      this.el = parameters.el;
    }
    // 獲取初始角度
    if (typeof parameters.angle === "number") this._angle = parameters.angle;
    // 合并參數(shù)
    Object.assign(this._parameters, parameters);
  } catch (err) {}
}
實現(xiàn)一個設(shè)置元素樣式的方法

上面設(shè)置完了參數(shù),我們還沒辦法驗證參數(shù)是否正確。
為了實現(xiàn)旋轉(zhuǎn)效果,我們有兩種方式可供選擇,第一種,利用 css3 的 transform,第二種利用 canvas 繪圖。其實兩種方法都比較簡單,這里先選擇 css3 實現(xiàn)一版,結(jié)尾再附上 canvas 版本的。

// 實現(xiàn)一個css3樣式,我們需要處理兼容性,確定瀏覽器類型,選擇對應(yīng)的屬性
// 這里添加一個輔助方法
/**
 * 判斷運行環(huán)境支持的css,用作css制作動畫
 */
function getSupportCSS() {
  let supportedCSS = null;
  const styles = document.getElementsByTagName("head")[0].style;
  const toCheck = "transformProperty WebkitTransform OTransform msTransform MozTransform".split(
    " "
  );
  for (var a = 0; a < toCheck.length; a++) {
    if (styles[toCheck[a]] !== undefined) {
      supportedCSS = toCheck[a];
      break;
    }
  }
  return supportedCSS;
}
// 在constructor構(gòu)造函數(shù)里面增加一個屬性
this.supportedCSS = getSupportCSS();

然后 給類增加一個 設(shè)置樣式的方法_rotate

_rotate(angle) {
    const el = this.el;
    this._angle = angle; // 更新當(dāng)前角度
    el.style[this.supportedCSS] = `rotate3d(0,0,1,${angle % 360}deg)`;
}
// 在 init里面增加 _rotate方法,初始化元素 初始角度
init() {
  // 初始化參數(shù)
  this.setOptions(Object.assign({}, this.customOps));
  // 設(shè)置一次初始角度
  this._rotate(this._angle);
}

在這里,就可以寫一個 demo,進(jìn)行測試了,當(dāng)然還么有動畫,只能測試初始角度 angle 設(shè)置
demo 代碼,順便看看我們的腳本代碼變成了什么樣子:




  
  
  
  Document
  


  
實現(xiàn)動畫主循環(huán)

寫到這里,雖然說了一大推話,但是代碼去掉注釋,真的還沒有幾行。
但是我們只差一個定時器循環(huán)了,接下里實現(xiàn)這個主循環(huán),不斷更新 angle 值就可以了。
說起定時器,我們需要計算動畫時間來 判斷是否應(yīng)該取消定時器等等,一些附加操作,所以增加一個_animateStart 方法清理和計時, 下面直接上代碼,

  _animateStart() {
    if (this._timer) {
      clearTimeout(this._timer);
    }
    this._animateStartTime = Date.now();
    this._animateStartAngle = this._angle;
    this._animate();
  }
  /**
   * 動畫主循環(huán)
   */
  _animate() {
    const actualTime = Date.now();
    const checkEnd =
      actualTime - this._animateStartTime > this._parameters.duration;
      // 判斷是否應(yīng)該 結(jié)束
    if (checkEnd) {
      clearTimeout(this._timer);
    } else {
      if (this.el) {
        // 調(diào)用緩動函數(shù),獲取當(dāng)前時刻 angle值
        var angle = this._parameters.easing(
          actualTime - this._animateStartTime,
          this._animateStartAngle,
          this._parameters.animateTo - this._animateStartAngle,
          this._parameters.duration
        );
        // 設(shè)置 el 元素的樣式
        this._rotate(~~(angle * 10) / 10);
      }
      if (this._parameters.step) {
        this._parameters.step.call(this, this._angle);
      }
      // 循環(huán)調(diào)用
      this._timer = setTimeout(() => {
        this._animate();
      }, 10);
    }
    // 完成回調(diào)
    if (this._parameters.callback && checkEnd) {
      this._angle = this._parameters.animateTo;
      this._rotate(this._angle);
      this._parameters.callback.call(this);
    }
  }

然后再 rotate 方法調(diào)用_animateStart 就好了

  rotate() {
    if (this._angle === this._parameters.animateTo) {
      this._rotate(this._angle);
    } else {
      this._animateStart();
    }
  }

至此,一個利用 css3 實現(xiàn)的腳本就完成了,有木有很簡單,下面貼上完整代碼.

/**
 * 功能: 開發(fā)一個旋轉(zhuǎn)插件,傳入一個元素節(jié)點即可控制旋轉(zhuǎn)
 * 轉(zhuǎn)動角度和時長以及動畫曲線 可 通過參數(shù)進(jìn)行配置
 *
 * 參數(shù)列表:
 *  - dom 需要一個容器 必選
 *  - angle 初始角度   非必選
 *  - animateTo 結(jié)束角度  非必選
 *  - duration 動畫時長  非必選
 *  - easing 緩動函數(shù)  非必選
 *  - step 角度每次更新調(diào)用  非必選
 *  - callback 動畫結(jié)束回調(diào)  非必選
 */
class RotatePlate {
  constructor(options) {
    // 獲取當(dāng)前運行環(huán)境支持的樣式屬性
    this.supportedCSS = getSupportCSS();
    // 緩存用戶數(shù)據(jù)
    this.customOps = options;
    // 私有參數(shù)
    this._parameters = {
      angle: 0,
      animateTo: 0,
      step: null,
      easing: function(t, b, c, d) {
        return -c * ((t = t / d - 1) * t * t * t - 1) + b;
      },
      duration: 3000,
      callback: () => {},
    };
    this._angle = 0; // 當(dāng)前時刻角度
    this.init();
  }
  /**
   * 初始化操作
   */
  init(newOps = {}) {
    // 初始化參數(shù)
    this.setOptions(Object.assign({}, this.customOps, newOps));
    // 設(shè)置一次初始角度
    this._rotate(this._angle);
  }
  /**
   * 啟動轉(zhuǎn)動函數(shù)
   */
  rotate() {
    if (this._angle === this._parameters.animateTo) {
      this._rotate(this._angle);
    } else {
      this._animateStart();
    }
  }
  /**
   * 設(shè)置配置參數(shù)
   */
  setOptions(parameters) {
    try {
      // 獲取容器元素
      if (typeof parameters.el === "string") {
        this.el = document.querySelector(parameters.el);
      } else {
        this.el = parameters.el;
      }
      // 獲取初始角度
      if (typeof parameters.angle === "number") this._angle = parameters.angle;
      // 合并參數(shù)
      Object.assign(this._parameters, parameters);
    } catch (err) {}
  }
  _rotate(angle) {
    const el = this.el;
    this._angle = angle; // 更新當(dāng)前角度
    el.style[this.supportedCSS] = `rotate3d(0,0,1,${angle % 360}deg)`;
  }
  _animateStart() {
    if (this._timer) {
      clearTimeout(this._timer);
    }
    this._animateStartTime = Date.now();
    this._animateStartAngle = this._angle;
    this._animate();
  }
  /**
   * 動畫主循環(huán)
   */
  _animate() {
    const actualTime = Date.now();
    const checkEnd =
      actualTime - this._animateStartTime > this._parameters.duration;
    if (checkEnd) {
      clearTimeout(this._timer);
    } else {
      if (this.el) {
        var angle = this._parameters.easing(
          actualTime - this._animateStartTime,
          this._animateStartAngle,
          this._parameters.animateTo - this._animateStartAngle,
          this._parameters.duration
        );
        this._rotate(~~(angle * 10) / 10);
      }
      if (this._parameters.step) {
        this._parameters.step.call(this, this._angle);
      }
      this._timer = setTimeout(() => {
        this._animate();
      }, 10);
    }
    if (this._parameters.callback && checkEnd) {
      this._angle = this._parameters.animateTo;
      this._rotate(this._angle);
      this._parameters.callback.call(this);
    }
  }
}

/**
 * 判斷運行環(huán)境支持的css,用作css制作動畫
 */
function getSupportCSS() {
  let supportedCSS = null;
  const styles = document.getElementsByTagName("head")[0].style;
  const toCheck = "transformProperty WebkitTransform OTransform msTransform MozTransform".split(
    " "
  );
  for (var a = 0; a < toCheck.length; a++) {
    if (styles[toCheck[a]] !== undefined) {
      supportedCSS = toCheck[a];
      break;
    }
  }
  return supportedCSS;
}

下面再補(bǔ)充一個 canvas 實現(xiàn)的動畫方法:

  _rotateCanvas(angle) {
    // devicePixelRatio 是設(shè)備像素比,為了解決canvas模糊問題設(shè)置的
    // 原理把 canvas畫布擴(kuò)大,然后縮小顯示在屏幕
    this._angle = angle;
    const radian = ((angle % 360) * Math.PI) / 180;
    this._canvas.width = this.WIDTH * this.devicePixelRatio;
    this._canvas.height = this.HEIGHT * this.devicePixelRatio;
    // 解決模糊問題
    this._cnv.scale(this.devicePixelRatio, this.devicePixelRatio);
    // 平移canvas原點
    this._cnv.translate(this.WIDTH / 2, this.HEIGHT / 2);
    // 平移后旋轉(zhuǎn)
    this._cnv.rotate(radian);
    // 移回 原點
    this._cnv.translate(-this.WIDTH / 2, -this.HEIGHT / 2);
    this._cnv.drawImage(this._img, 0, 0, this.WIDTH, this.HEIGHT);
  }
源碼下載

完整源碼請到 github 下載,查看

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/96919.html

相關(guān)文章

  • Vue+CSS3實現(xiàn)轉(zhuǎn)盤抽獎

    摘要:最近有個轉(zhuǎn)盤抽獎的需求,搜了一下現(xiàn)有的輪子,有的是用的動畫函數(shù)實現(xiàn)的,有的是用繪圖然后再用高頻率的調(diào)用旋轉(zhuǎn)方法,前者太老了沒法簡單移植到項目,后者感覺性能表現(xiàn)可能不會太好。核心思路是用以及實現(xiàn)旋轉(zhuǎn)動畫,使用和繪制出定位較為精確的輪盤獎項。 最近有個轉(zhuǎn)盤抽獎的需求,搜了一下現(xiàn)有的輪子,有的是用jQuery的動畫函數(shù)實現(xiàn)的,有的是用canvas繪圖然后再用高頻率的setTimeout調(diào)用旋...

    mj 評論0 收藏0
  • 轉(zhuǎn)盤抽獎-- 自己

    摘要:自己很菜,不可否認(rèn)。所以上周日試試水,看看自己能否寫個圓盤抽獎的。效果圖代碼外部圓內(nèi)部園請輸入外數(shù)字開始基礎(chǔ)旋轉(zhuǎn)的圓以自己的寬度的一半為,以父盒子的高度一半為,作為旋轉(zhuǎn)點。 自己很菜,不可否認(rèn)。所以上周日試試水,看看自己能否寫個圓盤抽獎的demo。// github L6zt開發(fā)思路 布局 css rotate 布局; 抽獎過渡效果,采用css3 transition; 動態(tài)計算抽獎...

    gaara 評論0 收藏0
  • canvas之轉(zhuǎn)盤抽獎

    摘要:最近工作中重構(gòu)了抽獎轉(zhuǎn)盤,給大家提供一個開發(fā)轉(zhuǎn)盤抽獎的思路需求轉(zhuǎn)盤根據(jù)獎品數(shù)量不同而有變化目錄結(jié)構(gòu)由于業(yè)務(wù)需要所以開發(fā)了兩個版本抽獎,和,不過部分只能替換圖片,沒有功能邏輯。 最近工作中重構(gòu)了抽獎轉(zhuǎn)盤,給大家提供一個開發(fā)轉(zhuǎn)盤抽獎的思路 需求 1、轉(zhuǎn)盤根據(jù)獎品數(shù)量不同而有變化 2、canvas 目錄結(jié)構(gòu) showImg(https://segmentfault.com/img/bVbwL...

    _ang 評論0 收藏0
  • 小程序制作大轉(zhuǎn)盤抽獎功能,巨簡約的代碼??!

    摘要:公司說要做個活動,迎接雙十一。。大概的思路就是頁面有個轉(zhuǎn)盤,然后轉(zhuǎn)盤是一個背景。轉(zhuǎn)盤的指針也是用圖片。如下圖然后第二步,翻查小程序文檔。最后根據(jù)小程序文檔說,這個參數(shù)需要輸出。為真的時候運行正常旋轉(zhuǎn)的方法,為假的時候。 公司說要做個活動,迎接雙十一。。然后最怕的事情出現(xiàn)了,就是做轉(zhuǎn)盤。以前沒怎么寫過動畫,特別怕這些東西。。。好了,廢話不說。直入正題。 首先,先構(gòu)圖。大概的思路就是頁面...

    TesterHome 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<