使用canvas实现刮刮乐功能

// 画布宽-屏幕宽
const canvasWidth=window.screen.width;
// 画布高
const canvasHeight=window.screen.height;
// 圆形/巨型配置
let setting={}
  // 圆形/巨型配置
const guideNewConfig={
	type: 'circle',
    dom: '#targetCity',
    radius: 65
}
const stepClear=0.2;
/**
 * @description 获取元素中心点
 * @param {Document} element dom元素
 * @returns {Object}
 */
function getElePositionCenter(element) {
  const data = element.getBoundingClientRect();
  return {
    x: parseInt(data.left + data.width / 2, 10),
    y: parseInt(data.top + data.height / 2, 10)
  };
}

// 获取dom,获取dom相关位置信息
function initDom() {
      const {
        dom, // 目标元素
        type, // 圆还是长方形
        radius, // 圆角
        width, // 宽
        height// 高
      } = guideNewConfig;// 传入的一些配置项
      // 获取dom
      setTimeout(() => {
        const ballEle = document.querySelector(dom);
        if (!ballEle) return;
        const ballPos = getElePositionCenter(ballEle);

        const { x, y } = ballPos || {};
        const set = {
        // 如果是在蒙层中画个圆
          circle: {
            radius,
            srcPx: x,
            srcPy: y,
          },
          // 如果是在蒙层中画个矩形
          round: {
            srcPx: x
            srcPy: y,
            width,
            height
          }
        };
		// 自定义调整位置
        let left = x + 25;
        let top = y + 25;
        
        // 忽略这段代码 为了增加一些dom元素的样式
        handEle.setAttribute('style', `
            left: ${left}px;
            top: ${top}px;
          `);
		// 忽略这段代码  为了增加一些dom元素的样式
        tipEle.setAttribute('style', `
            left: ${tipl}px;
            top: ${tipt}px;
            background-image:url(${this.tipUrl});
          `);
         
        setting = set[type];
        initCanvas();
      }, 0);

  // 获取canvas
   function initCanvas() {
      const canvas = document.querySelector('#guideCanvas');
      const context = canvas.getContext('2d');
      canvas.width = canvasWidth;
      canvas.height = canvasHeight;
      drawRect(context);
    }
    
    /**
     * @description: 绘制图形蒙层和透明区域
     * @param {*} ctx context
     * @return {*}
     */
    function drawRect(ctx) {
      // 绘制黑色蒙层
      ctx.fillStyle = 'rgba(0, 0, 0, 0.68)';
      ctx.fillRect(0, 0, canvasWidth, canvasHeight);

      // 画透明圆形区域
      const { radius, srcPx, srcPy } = setting;

      const {
        type, // 圆还是长方形
        width, // 宽
        height// 高
      } = guideNewConfig;
      // 画圆
      if (type === 'circle') {
        clearCircle(ctx, srcPx, srcPy, radius);

        // 画圆环减弱锯齿
        ctx.beginPath();
        ctx.strokeStyle = 'rgba(157, 157, 161, 1)';
        ctx.arc(srcPx, srcPy, radius, 0, 2 * Math.PI);
        ctx.stroke();
      } else {
        // 画矩形
        drawRound(ctx, srcPx, srcPy, width, height, 10);
      }
    },

	/**
     * @description: 画透明圆形区域方法,主要使用 canvas 的 clearRect 方法
     * @param {*} ctx context
     * @param {Number} srcPx 起点x
     * @param {Number} srcPy 起点y
     * @param {Number} radius 圆半径
     * @return {*}
     */
    function clearCircle(ctx, srcPx, srcPy, radius) {
      const calcWidth = radius - stepClear;
      const calcHeight = Math.sqrt(radius * radius - calcWidth * calcWidth);
      const posX = srcPx - calcWidth;
      const posY = srcPy - calcHeight;
      const widthX = 2 * calcWidth;
      const heightY = 2 * calcHeight;
      if (stepClear <= radius) {
        ctx.clearRect(posX, posY, widthX, heightY);
        stepClear += 1;
        clearCircle(ctx, srcPx, srcPy, radius);
      }
    },
  // 画圆角矩形
   function  drawRound(ctx, x, y, w, h, r) {
      if (w < 2 * r) r = w / 2;
      if (h < 2 * r) r = h / 2;
      ctx.beginPath();
      ctx.moveTo(x + r, y);
      ctx.arcTo(x + w, y, x + w, y + h, r);
      ctx.arcTo(x + w, y + h, x, y + h, r);
      ctx.arcTo(x, y + h, x, y, r);
      ctx.arcTo(x, y, x + w, y, r);
      ctx.closePath();
      ctx.lineWidth = 2;
      ctx.strokeStyle = 'rgba(157, 157, 161, 1)';
      ctx.stroke();
      clearDrawEound(ctx);
      ctx.fill();
    },
	    
  // 清楚圆角矩形
   function clearDrawEound(ctx) {
      ctx.globalCompositeOperation = 'destination-out';
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值