Режим немедленного рисования в canvas

5 (100%) 6 vote[s]

Мы разобрались, как рисовать заполненные или каркасные прямоугольники. Как только вызывается метод ctx.strokeRect (x, y, width, height) или ctx.fillRect (x, y, width, height), прямоугольник действительно рисуется на холсте немедленно.  При рисовании прямоугольников с помощью strokeRect или fillRect, рисовании текста или рисунков, все эти фигуры будут отображаться сразу, что и называется «режим немедленного рисования«.

Другой режим, называемый «режим пути» («path mode«), или «режим с буферизацией», будет рассмотрен в следующей статье. С его помощью рисуются линии, кривые, дуги, а также прямоугольники.

Прямоугольники — это единственные фигуры, у которых есть режим немедленного рисования, и «режим пути/буферизации» («path/buffered mode«).

Таким образом, режим немедленного рисования — это графический контекст canvas HTML5 предоставляет несколько методов рисования. При вызове этих методов рисунки появляются на холсте, как только выполняются инструкции.

Рисование текста

API Canvas предоставляет два основных метода для рисования текста:

    • ctx.strokeText (message, x, y);
    • ctx.fillText (message, x, y) .

Он также предоставляет набор свойств контекста для установки шрифта и стиля символа, для разметки текста и т. д.

Типичное использование

Нарисуем текст «Hello, World!»:

Your browser does not support the canvas tag.

Просмотрите исходный код:

<!DOCTYPE html>
<html>
  <head>
  <meta charset="utf-8"/>
</head>
<body>

<canvas id="myCanvas" width=500 height=300>Your browser does not support the canvas tag.</canvas>

<script type="text/javascript">
    var canvas=document.getElementById('myCanvas');
    var context=canvas.getContext('2d');

    context.font = "60pt Calibri";
    context.lineWidth = 3;
    context.strokeStyle = "blue";
    context.fillStyle = "red";
  
    context.fillText("Hello World!", 10, 100);
    context.strokeText("Hello World!", 10, 100);

</script>

</body>
</html>

Попробуйте изменить позицию, в которой рисуется текст, изменить атрибуты шрифта и т. д.

Свойства context.font:

Можно нарисовать текст на холсте, используя свойство  font контекста, чтобы указать стиль шрифта (plain, bold, italic), size и font name. Другие свойства, такие как strokeStyle или fillStyle и т. д., также будут приняты во внимание.

Свойство font совместимо с CSS и принимает такие значения, как: 

[font style][font weight][font size][font face]

    • font style: normal, italic, oblique, inherit
    • font weight: normal, bold, bolder, lighter, auto, inherit, 100, 200, 300, 400, 500, 600, 700, 800, 900
    • font size: размер в пикселях или в точках, таких как 60pt, 20px, 36px, etc.
    • font face: Arial, Calibri, Times, Courier, etc. Некоторые font face шрифта могут работать не во всех браузерах.

fillText() или strokeText() методы

В fillText ( message, х, у) или strokeText ( message, х, у) методы из контекста прорисовывают текстовое сообщение в начале базового положения. В примере «Hello World» это расположено внизу левой ножки буквы «H».

Существует четвертый необязательный параметр maxWidth, который заставляет текст вписываться в заданную ширину, искажая его при необходимости:

context.strokeText("Hello World!", x, y [, maxWidth]);
context.fillText("Hello World!", x, y [, maxWidth]);

Пример использования параметра maxWidth методов strokeText() или fillText() :

Your browser does not support the canvas tag.

Просмотрите исходный код:

<!DOCTYPE html>
<html>
  <head>
  <meta charset="utf-8"/>
</head>
<body>
<canvas id="myCanvas" width=500 height=300>Your browser does not support the canvas tag.</canvas>

<script type="text/javascript">
    var canvas=document.getElementById('myCanvas');
    var context=canvas.getContext('2d');

    context.font = "60pt Calibri";
    context.lineWidth = 3;
    context.strokeStyle = "blue";
    context.fillStyle = "red";
  
    context.fillText("Hello World!", 10, 100);
    context.strokeText("Hello World!", 10, 100);
  
    // Отрисовка текста с ограниченной шириной 250 пикселей
    context.fillText("Hello World!", 10, 160, 250);
    context.strokeText("Hello World!", 10, 160, 250);
   // Ограничить ширину до 150 пикселей
    context.fillText("Hello World!", 10, 220, 150);
    context.strokeText("Hello World!", 10, 220, 150);
</script>
</body>
</html>

Измерение ширины заданного текста (ограничительная рамка)

Метод ctx.measureText() можно использовать для получения текущей ширины в пикселях заданного текста, принимая во внимание различные свойства, такие как шрифт, размер, тень, lineWidth и т. д. Просмотрите пример:

Your browser does not support the canvas tag.

Исходный код:

<!DOCTYPE html>
<html>
  <head>
  <meta charset="utf-8"/>
</head>
<body>

<canvas id="myCanvas" width=500 height=300>Your browser does not support the canvas tag.</canvas>

<script type="text/javascript">
    var canvas=document.getElementById('myCanvas');
    var context=canvas.getContext('2d');

    context.font = "60pt Calibri";
    context.lineWidth = 3;
    context.strokeStyle = "blue";
    context.fillStyle = "red";
  
    context.fillText("Hello World!", 10, 100);
    context.strokeText("Hello World!", 10, 100);
  
    var textMetrics = context.measureText("Hello World!");
    var width = textMetrics.width;
  
    context.font = "20pt Arial";
    context.fillText("Width of previous text: " + width + "pixels", 10, 150);
  
    // Рисуем базовую линию заданной ширины
    context.moveTo(10, 100);
    context.lineTo(width+10, 100);
    context.stroke();

</script>
</body>
</html>

Свойство ctx.textbaseline : изменение способа горизонтального отображения текста

Текстовая базовая линия важна, поскольку она сообщает, как интерпретируется параметр y методов fillText («какой-то текст», x, y) и strokeText («какой-то текст», x, y).

Пример:

Your browser does not support the canvas tag.

Исходный код:

<!DOCTYPE html>
<html>
  <head>
  <meta charset="utf-8"/>
</head>
<body>

<canvas id="myCanvas3" width=500 height=300>Your browser does not support the canvas tag.</canvas>

<script type="text/javascript">
    var canvas=document.getElementById('myCanvas3');
    var context=canvas.getContext('2d');

   context.strokeStyle = "#000000";
context.lineWidth  = 1;
context.beginPath();
context.moveTo(  0, 75);
context.lineTo(500, 75);
context.stroke();
context.closePath();

context.font      = "16px Verdana";
context.fillStyle = "#000000";

context.textBaseline = "top";
context.fillText("top", 0, 75);

context.textBaseline = "hanging";
context.fillText("hanging", 40, 75);

context.textBaseline = "middle";
context.fillText("middle", 120, 75);

context.textBaseline = "alphabetic";
context.fillText("alphabetic", 200, 75);

context.textBaseline = "ideographic";
context.fillText("ideographic", 300, 75);

context.textBaseline = "bottom";
context.fillText("bottom-glyph", 400, 75);

</script>

</body>
</html>

Свойство textBaseline контекста используется для указания различных способов позиционирования базовой линии данного текста. В приведенном выше примере показаны различные возможные значения этого свойства и соответствующие результаты. Значение по умолчанию «буквенное » и соответствует тому, что использовалось в предыдущем примере «Hello World».

Возможные значения для свойства textBaseline:

top Текст выравнивается по верху самого высокого глифа в тексте.
hanging Текст выравнивается по строке, с которой кажется, что текст висит. Это почти идентично вершине, и во многих случаях вы не видите разницу.
middle Текст выравнивается по середине.
alphabetic Низ вертикально ориентированных глифов.
ideographic Низ горизонтально ориентированных глифов.
bottom Текст выравнивается по нижней части глифа в тексте, который распространяется дальше всего вниз по тексту.

Горизонтальное выравнивание текста:

Свойство textAlign контекста сообщает, как будет использоваться параметр x при вызове strokeText («некоторый текст», x, y) и fillText («некоторый текст», x, y). Например, при  textAlign=»center» х параметр дает положение вертикального центра текста, а в  textAlign=»right» х соответствует крайнему правому положению текста. 

Пример:

Your browser does not support the canvas tag.

Исходный код:

<!DOCTYPE html>
<html>
  <head>
  <meta charset="utf-8"/>
</head>
<body>

<canvas id="myCanvas" width=500 height=120>Your browser does not support the canvas tag.</canvas>

<script type="text/javascript">
    var canvas=document.getElementById('myCanvas');
    var context=canvas.getContext('2d');

  context.stokeStyle = "#000000";
context.lineWidth  = 1;
context.beginPath();
context.moveTo( 250, 0);
context.lineTo( 250, 130);
context.stroke();
context.closePath();

context.font      = "16px Verdana";
context.fillStyle = "#000000";

context.textAlign = "center";
context.fillText("center", 250, 20);

context.textAlign = "start";
context.fillText("start", 250, 40);

context.textAlign = "end";
context.fillText("end", 250, 60);

context.textAlign = "left";
context.fillText("left", 250, 80);

context.textAlign = "right";
context.fillText("right", 250, 100);

</script>

</body>
</html>

Режим немедленного рисования изображений

Важно! Загружайте изображения в фоновом режиме, подождите, пока они загрузятся, прежде чем рисовать!

Работать с изображениями довольно просто, за исключением того, что нам нужно, чтобы изображения были полностью загружены в память перед их рисованием. Загрузка изображений — это асинхронный процесс. Работа с несколькими изображениями также может быть трудной для начинающих. Позже мы рассмотрим загрузчик нескольких изображений.

Также можно рисовать изображения из видеопотока, изображения, соответствующие другому содержимому холста, или изображения, которые определены HTML-элементами <img> на странице.

 Рассмотрим базовый пример:

Исходный код:

<!DOCTYPE HTML>
<html>
   <head>
      <meta charset="utf-8"/>
      <script>
         window.onload = function () {
// Необходимость запуска этого кода только после загрузки веб-страницы.
         var canvas = document.getElementById("myCanvas");
         var context = canvas.getContext("2d");
         var imageObj = new Image();
// функция обратного вызова, вызываемая строкой imageObj.src = ....
// расположен после этой функции
         imageObj.onload = function () {
// Рисуем изображение только тогда, когда у нас есть гарантия
// что оно было загружено
         context.drawImage(imageObj, 0, 0);
      };
 
// Вызывает функцию imageObj.onload асинхронно
      imageObj.src =
         "http://www.w3.org/html/logo/downloads/HTML5_Logo_512.png";
      };
      </script>
   </head>
   <body>
      <canvas id="myCanvas" width="512" height="512"></canvas>
   </body>
</html>

Пояснения:

    1. Мы должны создать объект JavaScript Image ( строка 10 ),
    2. Когда мы устанавливаем атрибут src этого объекта с URL-адресом файла изображения, то браузер отправляет в фоновом режиме асинхронный запрос . Загрузка большого изображения может занять некоторое время, поэтому остальная часть кода JavaScript продолжает работать. Вот почему мы называем это «асинхронным».
    3. Когда файл изображения загружен, браузер вызывает обратный вызов onload, связанный с изображением ( строка 13 ). 
    4. Мы рисуем изображение только из этого обратного вызова , в противном случае мы не можем гарантировать, что изображение было загружено и может быть использовано. Фактический рисунок здесь делается в строке 16 .

В строке 16 есть множество вариантов метода контекста drawImage (…) :

    • drawImage (img, x, y): рисует изображение в позиции x, y, сохраняя исходный размер изображения.
    • drawImage (img, x, y, sizeX, sizeY): то же, что и раньше, за исключением того, что размер нарисованного изображения изменяется.
    • drawImage (img, sx, sy, sw, sh, dx, dy, dw, dh): для рисования подизображений (sx, sy, sw, sh) определяют исходный прямоугольник, в то время как dx, dy, dw, sh определяют целевой прямоугольник. Если эти прямоугольники не имеют одинаковый размер, исходное изображение будет изменено.

Разные варианты drawImage (…)

Пример:

Исходный код:

<!DOCTYPE HTML>
<html>
    <head>
       <meta charset="utf-8"/>
        
    <script>
      window.onload = function() {
        var canvas = document.getElementById("myCanvas");
        var context = canvas.getContext("2d");
        
        var imageObj = new Image();

        imageObj.onload = function() {
           // Оригинал, большое изображение
           // context.drawImage (imageObj, 0, 10);
          
           // Исходное изображение, нарисованное с размером = 100x100 пикселей
          context.drawImage(imageObj, 0, 10, 100, 100);
          // with size = 150x150
          context.drawImage(imageObj, 80, 10, 150, 150);
          // with size = 200x200
          context.drawImage(imageObj, 210, 10, 200, 200);

          // рисуем вспомогательное изображение в 0, 0, ширина = 512, высота = 100
           // в позиции 100, 250, шириной 256 и высотой 50
          context.drawImage(imageObj, 0, 0, 512, 100, 100, 250, 256, 50);

        };
        imageObj.src = "http://www.w3.org/html/logo/downloads/HTML5_Logo_512.png";
      };

    </script>
	<style>
	#myCanvas {
  border:1px solid black;
}
	</style>
  </head>
  <body>
    <canvas id="myCanvas" width="512" height="512"></canvas>
  </body>
</html>

Рисование изображения, определенного на странице элементом <img src = «…»>

Иногда вам может понадобиться нарисовать изображение, которое уже объявлено в документе HTML как элемент <img src = «…»>. Помните, что когда вы добавляете <img> в документ, браузер начинает загружать его в фоновом режиме. 

НЕПРАВИЛЬНО => вы, конечно, можете попробовать нарисовать его, используя такой код:

<body>
<canvas id="myCanvas" width="512" height="512"></canvas>
<p>Original image as an <img> element:</p>
<img id="logo"
src="http://fc07.deviantart.net/fs70/f/2013/149/b/8/texture_85_by_voyager168-d670m68.jpg">
<script>
     canvas = document.getElementById("myCanvas");
     var ctx = canvas.getContext("2d");
     var logo = document.querySelector("#logo");
     ctx.drawImage(logo, 0, 0, 100, 100);
</script>
</body>

Хотя вы найдете много примеров в Интернете, которые делают это таким образом, они будут работать в большинстве случаев только с небольшими изображениями или с изображениями, которые находятся в кеше браузера. Помните, что вы не можете нарисовать изображение, которое не было полностью загружено!

Если вы попытаетесь нарисовать изображение, которое не загружено или загружено частично, вы получите неожиданные результаты!

Лучшая практика: рисовать только изображение, которое полностью загружено, используя OnLoad обратного вызова!

ПРАВИЛЬНО => правильный способ сделать это показан в этом примере, который начинает рисовать только из функции обратного вызова onload:

С большими файлами изображений это не слетит и не даст неожиданных результатов.

В спецификации DOM Level 2 говорится:

Событие load происходит, когда реализация DOM завершает загрузку  всего содержимого в документе, всех кадров в пределах FRAMESET или элемента OBJECT.

Режим немедленного рисования изображений из видеопотока

Функция drawImage (…) может принимать элемент видео в качестве первого параметра. Изображение, которое будет нарисовано, является тем, которое в данный момент воспроизводится видеопотоком. Это можно сделать с частотой видео на большинстве современных компьютеров или мобильных устройств.

Пример использования смотрите в «Видеопоток: GetUserMedia API, запись, загрузка«

Читайте больше по теме:

Подписаться
Уведомление о
guest
0 Комментарий
Inline Feedbacks
View all comments
Просмотры: 215

Популярные записи