DEMOs

导航页

RSDCT首页,点击进入各成员博客

你的浏览器不支持canvas元素
下载图片
#fpDoodle {
  background-color: var(--bg);
}

.download {
  opacity: 0;

  &.download--active {
    opacity: 1;
  }
}
/* eslint max-classes-per-file:0 */

/**
 * Tetris Base Class
 */
class Tetris {
  /**
   * 俄罗斯方块O
   * @param {Object} ctx - canvas context
   * @param {string} color - 背景颜色
   */
  drawO(ctx, color = '#fe9805') {
    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(16, 0);
    ctx.lineTo(16, 16);
    ctx.lineTo(0, 16);
    ctx.closePath();

    this.constructor.drawBorder(ctx);
    this.constructor.drawBackground(ctx, color);
  }

  /**
   * 俄罗斯方块Z
   * @param {Object} ctx - canvas context
   * @param {string} color - 背景颜色
   */
  drawZ(ctx, color = '#5c8ad0') {
    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(16, 0);
    ctx.lineTo(16, 8);
    ctx.lineTo(24, 8);
    ctx.lineTo(24, 16);
    ctx.lineTo(8, 16);
    ctx.lineTo(8, 8);
    ctx.lineTo(0, 8);
    ctx.closePath();

    this.constructor.drawBorder(ctx);
    this.constructor.drawBackground(ctx, color);
  }

  /**
   * 俄罗斯方块T
   * @param {Object} ctx - canvas context
   * @param {string} color - 背景颜色
   */
  drawT(ctx, color = '#d33a2e') {
    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(24, 0);
    ctx.lineTo(24, 8);
    ctx.lineTo(16, 8);
    ctx.lineTo(16, 16);
    ctx.lineTo(8, 16);
    ctx.lineTo(8, 8);
    ctx.lineTo(0, 8);
    ctx.closePath();

    this.constructor.drawBorder(ctx);
    this.constructor.drawBackground(ctx, color);
  }

  /**
   * 俄罗斯方块I
   * @param {Object} ctx - canvas context
   * @param {string} color - 背景颜色
   */
  drawI(ctx, color = '#3e9336') {
    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(8, 0);
    ctx.lineTo(8, 32);
    ctx.lineTo(0, 32);
    ctx.closePath();

    this.constructor.drawBorder(ctx);
    this.constructor.drawBackground(ctx, color);
  }

  /**
   * 俄罗斯方块J
   * @param {Object} ctx - canvas context
   * @param {string} color - 背景颜色
   */
  drawJ(ctx, color = '#f6dc4b') {
    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(8, 0);
    ctx.lineTo(8, 24);
    ctx.lineTo(-8, 24);
    ctx.lineTo(-8, 16);
    ctx.lineTo(0, 16);
    ctx.closePath();

    this.constructor.drawBorder(ctx);
    this.constructor.drawBackground(ctx, color);
  }

  /**
   * 俄罗斯方块L
   * @param {Object} ctx - canvas context
   * @param {string} color - 背景颜色
   */
  drawL(ctx, color = '#f6dc4b') {
    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(16, 0);
    ctx.lineTo(16, 8);
    ctx.lineTo(8, 8);
    ctx.lineTo(8, 24);
    ctx.lineTo(0, 24);
    ctx.closePath();

    this.constructor.drawBorder(ctx);
    this.constructor.drawBackground(ctx, color);
  }

  /**
   * 绘制边框
   * @param {Object} ctx - canvas context
   */
  static drawBorder(ctx) {
    ctx.lineWidth = 1;
    ctx.strokeStyle = '#fff';
    ctx.stroke();
  }

  /**
   * 填充背景色
   * @param {Object} ctx - canvas context
   * @param {string} bgcolor - 背景颜色
   */
  static drawBackground(ctx, bgcolor) {
    ctx.fillStyle = bgcolor;
    ctx.fill();
  }

  /**
   * text样式
   * @param {Object} ctx - canvas context
   * @param {string} txt - text内容
   * @param {number} x - x轴偏移量
   * @param {number} y - y轴偏移量
   */
  static setText(ctx, txt, x, y) {
    ctx.font = '25px "Helvetica Neue", Helvetica, Arial, sans-serif';
    ctx.fillStyle = '#dfdfdf';
    ctx.fillText(txt, x, y);
  }
}

/**
 * Draw Tetris Class extends Tetris Class
 */
class DrawTetris extends Tetris {
  /**
   * 绘制整幅图像
   * @param {Object} ctx - canvas context
   */
  drawAll(ctx) {
    // 主要图像距容器边线10px,加上5px的border
    ctx.save();
    ctx.translate(95, 95);
    ctx.scale(10, 10);
    this.drawO(ctx);
    ctx.restore();

    ctx.save();
    ctx.translate(335, 15);
    ctx.scale(10, 10);
    this.drawZ(ctx);
    ctx.restore();

    ctx.save();
    ctx.translate(255, 495);
    ctx.rotate(Math.PI); // (1 * PI)rad = 180deg
    ctx.scale(10, 10);
    this.drawT(ctx);
    ctx.restore();

    ctx.save();
    ctx.translate(415, 215);
    ctx.scale(10, 10);
    this.drawI(ctx);
    ctx.restore();

    ctx.save();
    ctx.translate(295, 135);
    ctx.scale(10, 10);
    this.drawJ(ctx);
    ctx.restore();
  }

  /**
   * 缩放方块
   * @param {Object} canvas - canvas object
   * @param {Object} ctx - canvas context
   * @param {number} x - x轴偏移
   * @param {number} y - y轴偏移
   */
  drawTransform(canvas, ctx, x, y) {
    const s = 10.6;

    if (x > 95 && x < 255 && y > 95 && y < 255) {
      ctx.save();
      ctx.translate(90, 90);
      ctx.scale(s, s);
      this.drawO(ctx);
      ctx.restore();

      this.constructor.tetrisAct(canvas, 'www');
    } else if ((x > 335 && x < 495 && y > 15 && y < 95)
               || (x > 415 && x < 575 && y > 95 && y < 175)) {
      ctx.save();
      ctx.translate(328, 10);
      ctx.scale(s, s);
      this.drawZ(ctx);
      ctx.restore();

      this.constructor.tetrisAct(canvas, 'lxl');
    } else if ((x > 95 && x < 175 && y > 335 && y < 415)
               || (x > 15 && x < 255 && y > 415 && y < 495)) {
      ctx.save();
      ctx.translate(263, 500);
      ctx.save();
      ctx.rotate(Math.PI); // (1 * PI)rad = 180deg
      ctx.scale(s, s);
      this.drawT(ctx);
      ctx.restore();
      ctx.restore();

      this.constructor.tetrisAct(canvas, 'xia');
    } else if (x > 415 && x < 495 && y > 215 && y < 535) {
      ctx.save();
      ctx.translate(413, 205);
      ctx.scale(s, s);
      this.drawI(ctx);
      ctx.restore();

      this.constructor.tetrisAct(canvas, 'zp');
    } else if ((x > 215 && x < 295 && y > 295 && y < 375)
               || (x > 295 && x < 375 && y > 135 && y < 375)) {
      ctx.save();
      ctx.translate(292, 126);
      ctx.scale(s, s);
      this.drawJ(ctx);
      ctx.restore();

      this.constructor.tetrisAct(canvas, 'dii');
    } else {
      ctx.clearRect(0, 0, 590, 550);
      this.drawAll(ctx);

      canvas.onclick = null;
      canvas.style.cursor = '';
    }
  }

  /**
   * 点击动作
   * @param {Object} canvas - canvas objec
   * @param {string} lct - 方块名称
   */
  static tetrisAct(canvas, lct) {
    canvas.onclick = () => {
      // window.open(`http://${lct}.rensidiaochaotian.com/`);
      console.log(lct);
    };

    canvas.style.cursor = 'pointer';
  }
}

const buildDownload = (dataURL) => {
  const download = document.querySelector('.download');

  download.href = dataURL;
  download.classList.add('download--active');
};

window.addEventListener('load', () => {
  const canvas = document.querySelector('#fpDoodle');
  const ctx = canvas.getContext('2d');
  const tetris = new DrawTetris();

  tetris.drawAll(ctx);

  canvas.onmousemove = (e) => {
    const t = e.currentTarget;
    const x = e.pageX - t.offsetLeft;
    const y = e.pageY - t.offsetTop;

    tetris.drawTransform(t, ctx, x, y);
  };

  buildDownload(canvas.toDataURL('image/png'));
}, false);