RSDCT首页,点击进入各成员博客
#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);