JSFiddle - React, Tailwind, and code Playground

by VE_Amas

HTML

<textarea type="text" id="input" placeholder="只能输入英文|数字|空格 至少输入3个字符"></textarea>
<br/>
<input type="submit" id="submit">
<br/>
<canvas id="canvas"></canvas>

JavaScript

var $ = id => document.querySelector(id)
var canvas = $('#canvas');
var ctx = canvas.getContext('2d');
var input = $('#input');

var colors = {};
colors.bgc = '#181818';
colors.r = '#fc1a14';
colors.g = '#13ff11';
colors.b = '#131bf8';
colors.rg = '#fffb22';
colors.rb = '#fd13fc';
colors.gb = '#24fafc';
colors.rgb = '#ffffff';

var dotRadius = 8 * 2

$('#submit').addEventListener('click', generate);

function generate() {
  var str = input.value;
  if (!/^[A-Za-z0-9 ]*$/.test(str)) {
    alert('只能输入英文与数字!');
    return;
  }
  if (str.length < 3) {
    alert('至少输入3个字符!');
    return;
  }
  var len = Math.ceil(str.length / 3);
  str = str.split('').concat([' ', ' ']).slice(0, len * 3);
  var row = Math.round(Math.pow((len / 13), 0.5) * 8)
  while (len * 8 % row > 0) {
    row--;
  }
  var col = len * 8 / row;

  canvas.width = (col * 2 + 6) * dotRadius;
  canvas.height = (row * 2 + 6) * dotRadius;

  ctx.fillStyle = colors.bgc;
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  strs = new Array(3).join('.').split('.').map((v, i) => str.slice(i * len, (i + 1) * len).reverse().map(v => {
  	let s = '00000000' + v.charCodeAt(0).toString(2);
    return s.substr(s.length - 8, 8)
   }).join(''));
  strs = strs.map(v => {
    return new Array(row).join('.').split('.').map((u, i) => v.substr(col * i, col));
  })
  
  for (var i = 0; i < row; i++) {
    for (var j = 0; j < col; j++) {
      var vr = strs[2][i][j];
      var vg = strs[1][i][j];
      var vb = strs[0][i][j];
      var color = {
        '100': 'r',
        '010': 'g',
        '001': 'b',
        '110': 'rg',
        '101': 'rb',
        '011': 'gb',
        '111': 'rgb'
      }[vr + vg + vb] || 'bgc';
      ctx.fillStyle = colors[color];
      ctx.beginPath();
      ctx.arc((j * 2 + 3.5) * dotRadius, (i * 2 + 3.5) * dotRadius, dotRadius / 2, 0, 2 * Math.PI);
      ctx.fill();
    }
  }
}