Рисовать пиксели на холсте и читать положение и цвета с количеством символов? - PullRequest
1 голос
/ 12 июля 2019

Я пытаюсь отобразить крошечные пиксельные изображения на веб-сайте для клиента.
Хотя я достиг рабочего результата сейчас, это не надёжное решение, к которому я стремился.
Я задаюсь вопросом, может ли быть лучший или довольно удобный подход, который вы знаете для процесса рисования с использованием чистого JavaScript или даже CSS.
У меня уже была одна концепция в моей голове, и эта идея кажется наиболее удобным решением для моей задачи, но после некоторых попыток я все еще не совсем уверен, как правильно ее решить:
Можно ли нарисовать пиксели, прочитав информацию о чертеже - положение и цвет -
из числа символов (аналогично карте символов в желтом поле ниже) и ссылки на значения цвета в '#rrggbbaa' с каждым символом и управляйте положением на холсте с помощью дополнительного символа, такого как точка или запятая?

//~ 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">

1 Ответ

1 голос
/ 12 июля 2019

Есть много возможных решений, но вот одно.Создайте массив ваших данных пикселей и карту ваших цветов.Затем переберите свои пиксели и выведите их один за другим.

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().) Вам также необходимо преобразовать свои шестнадцатеричные значения в 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">
...