在 canvas 上绘制像素并使用多个符号读取位置和颜色?

Draw pixels on canvas and read position and colors with a number of symbols?

我正在尝试在网站上为客户显示小像素图像。
虽然我现在取得了工作成果,但这并不是我想要的可靠解决方案。
我想知道对于纯 JavaScript 甚至 CSS.
的绘图过程是否有更好或更舒适的方法 我脑子里已经有了一个想法,这个想法似乎是我任务最舒适的解决方案,但经过一些尝试后,我仍然不确定如何正确处理它:
是否可以通过读取绘图信息-位置和颜色-
来绘制像素点 来自许多符号(类似于下面黄色框中的符号映射)并使用每个符号引用'#rrggbbaa'中的颜色值并使用额外的符号(如点或逗号)控制 canvas 上的位置?

//~ 1 ................  
//~ 2 ................  
//~ 3 ....B€2€M€2€....  
//~ 4 ..JJJJeeeennnn..  
//~ 5 .fff§§§§iiii333.  
//~ 6 ..xkxk....ikik..

let pp = ((s = '.dcanvas', A = document.querySelector(s), ctx =  A.getContext('2d'),  
id = ctx.createImageData(1, 1)) => (x, y, r, g, b, a)   => (id.data.set([r, g, b, a]),  
ctx.putImageData(id, x, y), A))()

//create points at y3, start at x5
pp(5, 3, 86, 212, 157, 250)   //~ B #45D38C
pp(6, 3, 255, 111, 1, 250)    //~ € #FF6F00
pp(7, 3, 75, 184, 136, 250)   //~ 2 #4BB888
pp(8, 3, 255, 111, 1, 250)    //~ € #FF6F00
pp(9, 3, 67, 164, 122, 250)   //~ M #43A47A
pp(10, 3, 255, 111, 1, 250)   //~ € #FF6F00
pp(11, 3, 75, 184, 136, 250)  //~ 2 #4BB888
pp(12, 3, 255, 111, 1, 250)   //~ € #FF6F00

//create points at y4, start at x3
pp(3, 4, 195, 69, 149, 250)   //~ J #C34595
pp(4, 4, 195, 69, 149, 250)   //~ J #C34595
pp(5, 4, 195, 69, 149, 250)   //~ J #C34595
pp(6, 4, 195, 69, 149, 250)   //~ J #C34595
pp(7, 4, 205, 88, 162, 250)   //~ e #CD58A2
pp(8, 4, 205, 88, 162, 250)   //~ e #CD58A2
pp(9, 4, 205, 88, 162, 250)   //~ e #CD58A2
pp(10, 4, 205, 88, 162, 250)  //~ e #CD58A2
pp(11, 4, 232, 104, 185, 250) //~ n #E868B9
pp(12, 4, 232, 104, 185, 250) //~ n #E868B9
pp(13, 4, 232, 104, 185, 250) //~ n #E868B9
pp(14, 4, 232, 104, 185, 250) //~ n #E868B9

//create points at y5, start at x2
pp(2, 5, 88, 222, 217, 250)   //~ f #58DED9
pp(3, 5, 88, 222, 217, 250)   //~ f #58DED9
pp(4, 5, 88, 222, 217, 250)   //~ f #58DED9
pp(5, 5, 170, 170, 170, 250)  //~ § #AAAAAA
pp(6, 5, 170, 170, 170, 250)  //~ § #AAAAAA
pp(7, 5, 170, 170, 170, 250)  //~ § #AAAAAA
pp(8, 5, 170, 170, 170, 250)  //~ § #AAAAAA
pp(9, 5, 165, 222, 133, 250)  //~ i #A5DE85
pp(10, 5, 165, 222, 133, 250) //~ i #A5DE85
pp(11, 5, 165, 222, 133, 250) //~ i #A5DE85
pp(12, 5, 165, 222, 133, 250) //~ i #A5DE85
pp(13, 5, 95, 181, 181, 250)  //~ 3 #5FB5B5
pp(14, 5, 95, 181, 181, 250)  //~ 3 #5FB5B5
pp(15, 5, 95, 181, 181, 250)  //~ 3 #5FB5B5

//create points at y6, start at x3
pp(3, 6, 11, 122, 229, 250)   // ~ x #0B7AE5
pp(4, 6, 232, 199, 17, 250)   // ~ k #E8C711
pp(5, 6, 11, 122, 229, 250)   // ~ x #0B7AE5
pp(6, 6, 232, 199, 17, 250)   // ~ k #E8C711
                              // ~ .
                              // ~ .
                              // ~ .
                              // ~ .
pp(11, 6, 165, 222, 133, 250) // ~ i #A5DE85
pp(12, 6, 232, 199, 17, 250)  // ~ k #E8C711
pp(13, 6, 165, 222, 133, 250) // ~ i #A5DE85
pp(14, 6, 232, 199, 17, 250)  // ~ k #E8C711

//color reader
let A = rp(50, 80);
<canvas class="dcanvas" width=48 height=48 style="background: #383838">

有很多可能的解决方案,但这里有一个。创建一个 array of your pixel data, and a map 你的颜色。然后遍历你的像素,一个一个输出。

const pixels = [
  '................',
  '................',
  '....B€2€M€2€....',
  '..JJJJeeeennnn..',
  '.fff§§§§iiii333.',
  '..xkxk....ikik..',
];

const colors = new Map([
  ['B', '#45D38C'],
  ['€', '#FF6F00'],
  ['2', '#4BB888'],
  ['M', '#43A47A'],
  ['J', '#C34595'],
  ['e', '#CD58A2'],
  ['n', '#E868B9'],
  ['f', '#58DED9'],
  ['§', '#AAAAAA'],
  ['i', '#A5DE85'],
  ['3', '#5FB5B5'],
  ['x', '#0B7AE5'],
  ['k', '#E8C711'],
  ['i', '#A5DE85'],
]);

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

pixels.forEach((row, y) => {
  row.split('').forEach((pixel, x) => {
    if (colors.has(pixel)) {
      ctx.fillStyle = colors.get(pixel);
      ctx.fillRect(x, y, 1, 1);
    }
  });
});
<canvas id="canvas" width=48 height=48 style="background: #383838">

更快的选择:

您可能已经猜到了,如果要绘制很多像素,您会希望使用 ImageData 对象。 (它会比简单的 fillRect() 方法更快。)You'll also need to convert your hex values to RGB. 以下是您可以这样做的方法:

const pixels = [
  '................',
  '................',
  '....B€2€M€2€....',
  '..JJJJeeeennnn..',
  '.fff§§§§iiii333.',
  '..xkxk....ikik..',
];

const colors = new Map([
  ['B', '#45D38C'],
  ['€', '#FF6F00'],
  ['2', '#4BB888'],
  ['M', '#43A47A'],
  ['J', '#C34595'],
  ['e', '#CD58A2'],
  ['n', '#E868B9'],
  ['f', '#58DED9'],
  ['§', '#AAAAAA'],
  ['i', '#A5DE85'],
  ['3', '#5FB5B5'],
  ['x', '#0B7AE5'],
  ['k', '#E8C711'],
  ['i', '#A5DE85'],
]);

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const imageData = ctx.createImageData(canvas.width, canvas.height);

pixels.forEach((row, y) => {
  row.split('').forEach((pixel, x) => {
    const hex = colors.get(pixel);

    if (hex) {
      const px = x * 4;
      const py = y * canvas.width * 4;
      const rgb = hexToRgb(hex);

      imageData.data[py + px + 0] = rgb[0]; // R value
      imageData.data[py + px + 1] = rgb[1]; // G value
      imageData.data[py + px + 2] = rgb[2]; // B value
      imageData.data[py + px + 3] = 255;    // A value
    }
  });
});

ctx.putImageData(imageData, 0, 0);

function hexToRgb(hex) {
  hex = hex.replace('#', '');
  const bigint = parseInt(hex, 16);
  const r = (bigint >> 16) & 255;
  const g = (bigint >> 8) & 255;
  const b = bigint & 255;
  return [r, g, b];
}
<canvas id="canvas" width=48 height=48 style="background: #383838">