国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

轉(zhuǎn)盤(pán)抽獎(jiǎng)腳本自己擼

趙春朋 / 2638人閱讀

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

demo 效果

需求

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

書(shū)寫(xiě)偽代碼

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

實(shí)現(xiàn)一個(gè)類 class,只要傳入一個(gè)元素節(jié)點(diǎn),就可以控制轉(zhuǎn)動(dòng),

轉(zhuǎn)動(dòng)角度和時(shí)長(zhǎng)以及動(dòng)畫(huà)曲線 可 通過(guò)參數(shù)進(jìn)行配置

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

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

第二需要提供一個(gè) 開(kāi)啟動(dòng)畫(huà)的方法

第三,既然是動(dòng)畫(huà),脫不開(kāi)定時(shí)器功能,所以需要一個(gè)動(dòng)畫(huà)主循環(huán)

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

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

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

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

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

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) {}
}
實(shí)現(xiàn)一個(gè)設(shè)置元素樣式的方法

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

// 實(shí)現(xiàn)一個(gè)css3樣式,我們需要處理兼容性,確定瀏覽器類型,選擇對(duì)應(yīng)的屬性
// 這里添加一個(gè)輔助方法
/**
 * 判斷運(yùn)行環(huán)境支持的css,用作css制作動(dòng)畫(huà)
 */
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ù)里面增加一個(gè)屬性
this.supportedCSS = getSupportCSS();

然后 給類增加一個(gè) 設(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);
}

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




  
  
  
  Document
  


  
實(shí)現(xiàn)動(dòng)畫(huà)主循環(huán)

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

  _animateStart() {
    if (this._timer) {
      clearTimeout(this._timer);
    }
    this._animateStartTime = Date.now();
    this._animateStartAngle = this._angle;
    this._animate();
  }
  /**
   * 動(dòng)畫(huà)主循環(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)用緩動(dòng)函數(shù),獲取當(dāng)前時(shí)刻 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();
    }
  }

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

/**
 * 功能: 開(kāi)發(fā)一個(gè)旋轉(zhuǎn)插件,傳入一個(gè)元素節(jié)點(diǎn)即可控制旋轉(zhuǎn)
 * 轉(zhuǎn)動(dòng)角度和時(shí)長(zhǎng)以及動(dòng)畫(huà)曲線 可 通過(guò)參數(shù)進(jìn)行配置
 *
 * 參數(shù)列表:
 *  - dom 需要一個(gè)容器 必選
 *  - angle 初始角度   非必選
 *  - animateTo 結(jié)束角度  非必選
 *  - duration 動(dòng)畫(huà)時(shí)長(zhǎng)  非必選
 *  - easing 緩動(dòng)函數(shù)  非必選
 *  - step 角度每次更新調(diào)用  非必選
 *  - callback 動(dòng)畫(huà)結(jié)束回調(diào)  非必選
 */
class RotatePlate {
  constructor(options) {
    // 獲取當(dāng)前運(yùn)行環(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)前時(shí)刻角度
    this.init();
  }
  /**
   * 初始化操作
   */
  init(newOps = {}) {
    // 初始化參數(shù)
    this.setOptions(Object.assign({}, this.customOps, newOps));
    // 設(shè)置一次初始角度
    this._rotate(this._angle);
  }
  /**
   * 啟動(dòng)轉(zhuǎn)動(dòng)函數(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();
  }
  /**
   * 動(dòng)畫(huà)主循環(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);
    }
  }
}

/**
 * 判斷運(yùn)行環(huán)境支持的css,用作css制作動(dòng)畫(huà)
 */
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ǔ)充一個(gè) canvas 實(shí)現(xiàn)的動(dòng)畫(huà)方法:

  _rotateCanvas(angle) {
    // devicePixelRatio 是設(shè)備像素比,為了解決canvas模糊問(wèn)題設(shè)置的
    // 原理把 canvas畫(huà)布擴(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;
    // 解決模糊問(wèn)題
    this._cnv.scale(this.devicePixelRatio, this.devicePixelRatio);
    // 平移canvas原點(diǎn)
    this._cnv.translate(this.WIDTH / 2, this.HEIGHT / 2);
    // 平移后旋轉(zhuǎn)
    this._cnv.rotate(radian);
    // 移回 原點(diǎn)
    this._cnv.translate(-this.WIDTH / 2, -this.HEIGHT / 2);
    this._cnv.drawImage(this._img, 0, 0, this.WIDTH, this.HEIGHT);
  }
源碼下載

完整源碼請(qǐng)到 github 下載,查看

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/96919.html

相關(guān)文章

  • Vue+CSS3實(shí)現(xiàn)轉(zhuǎn)盤(pán)抽獎(jiǎng)

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

    mj 評(píng)論0 收藏0
  • 轉(zhuǎn)盤(pán)抽獎(jiǎng)-- 自己

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

    gaara 評(píng)論0 收藏0
  • canvas之轉(zhuǎn)盤(pán)抽獎(jiǎng)

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

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

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

    TesterHome 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<