久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長(zhǎng)資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      HTML5 Canvas實(shí)戰(zhàn)之刮獎(jiǎng)效果的實(shí)例詳情

      近年來由于移動(dòng)設(shè)備對(duì)HTML5的較好支持,經(jīng)常有活動(dòng)用刮獎(jiǎng)的效果,最近也在看H5方面的內(nèi)容,就自己實(shí)現(xiàn)了一個(gè),現(xiàn)分享出來跟大家交流。

      1、效果

      2、原理

      原理很簡(jiǎn)單,就是在刮獎(jiǎng)區(qū)添加兩個(gè)canvas,第一個(gè)canvas用于顯示刮開后顯示的內(nèi)容,可以是一張圖片或一個(gè)字符串,第二個(gè)canvas用于顯示涂層,可以用一張圖片或用純色填充,第二個(gè)canvas覆蓋在第一個(gè)canvas上面。

      當(dāng)在第二個(gè)canvas上點(diǎn)擊或涂抹(點(diǎn)擊然后拖動(dòng)鼠標(biāo))時(shí),把點(diǎn)擊區(qū)域變?yōu)橥该?,這樣就可以看到第一個(gè)canvas上的內(nèi)容,即實(shí)現(xiàn)了刮獎(jiǎng)效果。

      3、實(shí)現(xiàn)

      (1)定義Lottery類

      function Lottery(id, cover, coverType, width, height, drawPercentCallback) {      this.conId = id;      this.conNode = document.getElementById(this.conId);      this.cover = cover || '#CCC';      this.coverType = coverType || 'color';      this.background = null;      this.backCtx = null;      this.mask = null;      this.maskCtx = null;      this.lottery = null;      this.lotteryType = 'image';      this.width = width || 300;      this.height = height || 100;      this.clientRect = null;      this.drawPercentCallback = drawPercentCallback;  }

      對(duì)參數(shù)解釋一下:

      • id:刮獎(jiǎng)容器的id

      • cover:涂層內(nèi)容,可以為圖片地址或顏色值,可空,默認(rèn)為 #ccc

      • coverType:涂層類型,值為 image 或 color,可空,默認(rèn)為 color

      • width:刮獎(jiǎng)區(qū)域?qū)挾龋J(rèn)為300px,可空

      • height:刮獎(jiǎng)區(qū)域高度,默認(rèn)為100px,可空

      • drawPercentCallback:刮開的區(qū)域百分比回調(diào),可空

      然后還定義了幾個(gè)需要用到的變量:

      • background:第一個(gè)canvas元素

      • backCtx:background元素的2d上下文(context)

      • mask:第二個(gè)canvas元素

      • maskCtx:mask元素的2d上下文(context)

      • lottery:刮開后顯示的內(nèi)容,可以為圖片地址或字符串

      • lotteryType:刮開后顯示的內(nèi)容類型,值為 image 或 text,要跟lottery匹配

      • clientRect:用于記錄mask元素的 getBoundingClientRect() 值

      (2)添加二個(gè)canvas到刮獎(jiǎng)容器,并獲取2d上下文

      this.background = this.background || this.createElement('canvas', {      style: 'position:absolute;left:0;top:0;'  });  this.mask = this.mask || this.createElement('canvas', {      style: 'position:absolute;left:0;top:0;'  });    if (!this.conNode.innerHTML.replace(/[wW]| /g, '')) {      this.conNode.appendChild(this.background);      this.conNode.appendChild(this.mask);      this.clientRect = this.conNode ? this.conNode.getBoundingClientRect() : null;      this.bindEvent();  }    this.backCtx = this.backCtx || this.background.getContext('2d');  this.maskCtx = this.maskCtx || this.mask.getContext('2d');

      這里用于了createElement工具方法,另外還綁定了事件,后面介紹。

      (3)繪制第一個(gè)canvas

      第一個(gè)canvas分兩種類型,image 和 string,如果是圖片直接用canvas的drawImage就可以了,如果是string,要先用白色填充,然后在上下左右居中的地方繪制字符串,代碼如下:

      if (this.lotteryType == 'image') {      var image = new Image(),          _this = this;      image.onload = function () {          _this.width = this.width;          _this.height = this.height;          _this.resizeCanvas(_this.background, this.width, this.height);          _this.backCtx.drawImage(this, 0, 0);      }      image.src = this.lottery;  } else if (this.lotteryType == 'text') {      this.width = this.width;      this.height = this.height;      this.resizeCanvas(this.background, this.width, this.height);      this.backCtx.save();      this.backCtx.fillStyle = '#FFF';      this.backCtx.fillRect(0, 0, this.width, this.height);      this.backCtx.restore();      this.backCtx.save();      var fontSize = 30;      this.backCtx.font = 'Bold ' + fontSize + 'px Arial';      this.backCtx.textAlign = 'center';      this.backCtx.fillStyle = '#F60';      this.backCtx.fillText(this.lottery, this.width / 2, this.height / 2 + fontSize / 2);      this.backCtx.restore();  }

      (4)繪制第二個(gè)canvas

      第二個(gè)canvas也分 image 或 color 填充兩種情況。

      這里有一個(gè)難點(diǎn),就是如何把鼠標(biāo)點(diǎn)擊區(qū)域變成透明的呢?答案在這里:developer.mozilla.org/en/docs/Web/Guide/HTML/Canvas_tutorial/Compositing

      即我們要把 maskCtx的 globalCompositeOperation 設(shè)置為 destination-out ,詳細(xì)的用法請(qǐng)參考上面給出的鏈接。

      因此,繪制第二個(gè)canvas的代碼如下:

      this.resizeCanvas(this.mask, this.width, this.height);  if (this.coverType == 'color') {      this.maskCtx.fillStyle = this.cover;      this.maskCtx.fillRect(0, 0, this.width, this.height);      this.maskCtx.globalCompositeOperation = 'destination-out';  } else if (this.coverType == 'image'){    var image = new Image(),          _this = this;      image.onload = function () {          _this.maskCtx.drawImage(this, 0, 0);          _this.maskCtx.globalCompositeOperation = 'destination-out';      }      image.src = this.cover;  }

      這里resizeCanvas是改變canvas大小的工具方法。

      (5)綁定事件

      繪制完成后,要給第二個(gè)canvas綁定事件。這里分了移動(dòng)設(shè)備和PC-WEB兩處情況。移動(dòng)設(shè)備是 touchstart 和 touchmove 事件,對(duì)應(yīng)的PC-WEB是keydown 和 mousemove事件,另外PC-WEB方式下,要給document綁定一個(gè)mouseup事件,用來判斷鼠標(biāo)是否按下。代碼如下:

      bindEvent: function () {      var _this = this;      var device = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));      var clickEvtName = device ? 'touchstart' : 'mousedown';      var moveEvtName = device? 'touchmove': 'mousemove';      if (!device) {          var isMouseDown = false;          document.addEventListener('mouseup', function(e) {              isMouseDown = false;          }, false);      }      this.mask.addEventListener(clickEvtName, function (e) {          isMouseDown = true;          var docEle = document.documentElement;          if (!_this.clientRect) {              _this.clientRect = {                  left: 0,                  top:0              };          }          var x = (device ? e.touches[0].clientX : e.clientX) - _this.clientRect.left + docEle.scrollLeft - docEle.clientLeft;          var y = (device ? e.touches[0].clientY : e.clientY) - _this.clientRect.top + docEle.scrollTop - docEle.clientTop;          _this.drawPoint(x, y);      }, false);        this.mask.addEventListener(moveEvtName, function (e) {          if (!device && !isMouseDown) {              return false;          }          var docEle = document.documentElement;          if (!_this.clientRect) {              _this.clientRect = {                  left: 0,                  top:0              };          }          var x = (device ? e.touches[0].clientX : e.clientX) - _this.clientRect.left + docEle.scrollLeft - docEle.clientLeft;          var y = (device ? e.touches[0].clientY : e.clientY) - _this.clientRect.top + docEle.scrollTop - docEle.clientTop;          _this.drawPoint(x, y);      }, false);  }

      這里在事件中取出了鼠標(biāo)坐標(biāo),調(diào)用了drawPoint進(jìn)行了繪制,下面會(huì)講到。

      (6)繪制點(diǎn)擊和涂抹區(qū)域

      這里用到了canvas的徑向漸變,在鼠標(biāo)從標(biāo)處繪制一個(gè)圓形,代碼如下:

      drawPoint: function (x, y) {      this.maskCtx.beginPath();      var radgrad = this.maskCtx.createRadialGradient(x, y, 0, x, y, 30);      radgrad.addColorStop(0, 'rgba(0,0,0,0.6)');      radgrad.addColorStop(1, 'rgba(255, 255, 255, 0)');      this.maskCtx.fillStyle = radgrad;      this.maskCtx.arc(x, y, 30, 0, Math.PI * 2, true);      this.maskCtx.fill();      if (this.drawPercentCallback) {          this.drawPercentCallback.call(null, this.getTransparentPercent(this.maskCtx, this.width, this.height));      }  }

      (7)涂抹區(qū)域百分比

      在很多時(shí)候,我們還需要知道用戶涂抹了多少然后進(jìn)行下一步交互,如當(dāng)用戶涂抹了80%后,才允許下一張顯示。

      這個(gè)百分比如何計(jì)算呢?其實(shí)很簡(jiǎn)單,我們可以用getImageData方法到畫布上指定矩形的像素?cái)?shù)據(jù),由于每個(gè)像素都是用rgba表示的,而涂抹過的區(qū)域是透明的,所以我們只需要判斷alpha通道的值就可以知道是否透明。代碼如下:

      getTransparentPercent: function(ctx, width, height) {      var imgData = ctx.getImageData(0, 0, width, height),          pixles = imgData.data,          transPixs = [];      for (var i = 0, j = pixles.length; i < j; i += 4) {          var a = pixles[i + 3];          if (a < 128) {              transPixs.push(i);          }      }      return (transPixs.length / (pixles.length / 4) * 100).toFixed(2);  }

      (8)調(diào)用入口init

      最后再提供一個(gè)入口用來進(jìn)行繪制和重置,代碼如下:

      init: function (lottery, lotteryType) {      this.lottery = lottery;      this.lotteryType = lotteryType || 'image';      this.drawLottery();  }

      至此,關(guān)鍵代碼全部講解完了。

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)