Здравейте Днес научих как да работя с текстови елементи с помощта на канава и библиотека със скици на канава.

Крайният резултат изглежда така:

Както обикновено, къде можете да намерите този урок:

Това е раздел 6 от курса Креативно кодиране: създаване на визуални елементи с JavaScript от Бруно Имбризи.

Този модул изследва типа скица и работата с текстови елементи с помощта на канава.

Ето няколко извода от този модул:

  1. Използване на canvas fillText() и други методи, свързани с текста, включително добавяне на семейство шрифтове и размер на шрифта чрез свойства на canvas.

Можете да се запознаете с методите тук.

Научих това да виждам текста, нарисуван върху платното; трябва да използвате свойството textBaseline, което определя как се изчертава текстът.

Центриране на текста върху платното:

В предишните проекти използвахме метод translate() за подравняване на елементите в средата на блока на платното; обаче, когато работим с текст, ще трябва също да използваме свойството textAlign и да го зададем на center.

Изглежда, че добавянето на това свойство е помогнало; текстът обаче все още не изглеждаше центриран, което, както обяснява Бруно, се дължи на сложността на шрифтовите структури.

Как може да бъде разрешен този проблем?

Научих, че едно от възможните решения е да се добави метод, наречен measureText, който на теория би върнал ширината на посочения текст и други свойства; можете да разгледате документацията тук - https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics.

По-долу е даден пример за свойство meassureText()

let text = 'A'
const metrics = context.meassureText(text)
console.log (metrics) 

Използвайки това, можете да видите свойствата на този метод:

След това присвояване на тези стойности в кода:

const metrics  = typeContext.measureText(text)
//metric x
const mx = metrics.actualBoundingBoxLeft * -1
//metric y
const my = metrics.actualBoundingBoxAscent * -1
// metric width
const mw = metrics.actualBoundingBoxLeft + metrics.actualBoundingBoxRight
//metric height
const mh = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent

И накрая, начертайте ги върху платното, за да видите ограничителната кутия на елемента

typeContext.beginPath();
typeContext.rect(mx, my, mw, mh);
typeContext.stroke();

Подравняването на типа вече може да се визуализира малко по-лесно; следователно можем да използваме подобни методи за подравняване на обекта:

const x = (width - mw)  * 0.5 - mx
const y = (height - mh) * 0.5 - my
context.translate(x, y)

2. Актуализиране на буквите на екрана с помощта на клавишите на клавиатурата

Бруно използва keyup слушател на събития, който се задейства при освобождаване на ключ. Изглежда нещо като по-долу и приема два параметъра; едната е функцията за събитие на клавиатурата, а другата е функция, която се задейства при събитието на клавиатурата.

//declared outside the function call
let manager

//declared inside the function call
//update the key and render it again
const onKeyUp = (e) => {
text = e.key.toUpperCase()
manager.render()
};
document.addEventListener('keyup', onKeyUp)
//update of canvas-sketch function
const start  = async () => {
manager = await canvasSketch(sketch, settings)
};
start()

Тук Бруно обяснява концепциите за работа с асинхронната функция като библиотека за скици на платно, която се използва като асинхронна функция и включва набор от асинхронни функции, които можете да използвате. В този случай manager. render() е извикване на функция, което можете да използвате, за да задействате повторно изобразяване на текущия кадър.

Бруно обяснява концепцията на извикванията на асинхронна функция много добре; ако обаче се интересувате да научите малко повече, предлагам да разгледате видеоклипа и статията тук.

3. Растерно изображение

Растерното изображение се използва за четене на цветови стойности от пикселите върху платното, така че да можем да имаме повече гъвкавост при модифициране на съдържанието на буквата и да можем да рисуваме други фигури във формата на буква.

Бележка от Бруно е, че самото платно е растерно изображение, където всеки пиксел се състои от четири канала R, G, B, A.

Също така е важно да се определи местоположението на пиксела въз основа на оста x и y.

Бруно започва със създаването на отделно платно, наречено typeCanvas, което може да се използва за справка и четене на данните от него; можете да го създадете извън функцията за скица.

След като типовото платно е настроено, то ще се появи в горния ляв ъгъл на екрана.

За да прочетем пикселни данни от него, трябва да използваме метода canvas, наречен getImageData(). Изглежда по-долу и можем да го добавим в извикването на функцията sketch:

const typeData = typeContext.getImageData(0,0,cols,rows).data

След като това е настроено, можете да получите достъп до стойностите на пикселите за всеки канал. Това може да се постигне с помощта на цикъл for. С помощта на цикъла можем да намерим колоните и редовете в решетката, както и RGB стойностите за всеки канал.

4. Глифове

В този раздел Бруно показва как да рисувате глифове вместо примитивни форми. Bruno използва функция за генериране на различни видове глифове въз основа на яркостта на стойностите на пикселите.

const getGlyph =  (v) => {
if (v < 50) return '';
if (v < 100) return '.';
if (v < 50) return '';
if (v < 150) return '-';
if (v < 200) return '^';
const glyphs = '_= /'.split('');
return random.pick(glyphs);
return text;
}

Крайният резултат изглежда готин и ми харесва, че можете да натискате различни клавиши, за да генерирате различни глифове.

Резюме

Не наблегнах на преминаването през самия код, тъй като това е много добре обяснено в урока.

Чувствам, че този път беше по-лесно да разбера много понятия, включени в предишните уроци. Все още обаче се боря с няколко математически понятия и намирането на правилните координати. Вярвам, че това изисква много повече практика; обаче урокът беше много изчерпателен.

Това е последната част от курса, но има опция да създадете свой собствен проект в края на курса.