Как сделать график на canvas

Объект Canvas

Объект Canvas является новым в HTML5.


Тег HTML5 <Canvas> используется для рисования графики на лету с помощью JavaScript.

Пример

var x = document.getElementById(«myCanvas»);

Пример

var x = document.createElement(«CANVAS»);

Примечание: Элемент <Canvas> не имеет собственных способностей рисования (это только контейнер для графики)-вы должны использовать скрипт, чтобы реально нарисовать графику.

Метод Context () возвращает объект, предоставляющий методы и свойства для рисования на холсте.

Эта ссылка будет охватывать свойства и методы объекта контекста («2D»), который может использоваться для рисования текста, линий, прямоугольников, кругов и других объектов на холсте.

Image pixel formats (experimental)

constcanvas=createCanvas(200,200)constctx=canvas.getContext('2d',{ pixelFormat'A8'})

These additional pixel formats have experimental support:

  • Like , but the 8 alpha bits are always opaque. This format is always used if the context attribute is set to false (i.e. ). This format can be faster than because transparency does not need to be calculated.
  • Each pixel is 16 bits, with red in the upper 5 bits, green in the middle 6 bits, and blue in the lower 5 bits, in native platform endianness. Some hardware devices and frame buffers use this format. Note that PNG does not support this format; when creating a PNG, the image will be converted to 24-bit RGB. This format is thus suboptimal for generating PNGs. instances for this mode use a instead of a .
  • Each pixel is 1 bit, and pixels are packed together into 32-bit quantities. The ordering of the bits matches the endianness of the platform: on a little-endian machine, the first pixel is the least-significant bit. This format can be used for creating single-color images. Support for this format is incomplete, see note below.
  • Each pixel is 30 bits, with red in the upper 10, green in the middle 10, and blue in the lower 10. (Requires Cairo 1.12 or later.) Support for this format is incomplete, see note below.

Notes and caveats:

  • Using a non-default format can affect the behavior of APIs that involve pixel data:

    • The size of the array returned depends on the number of bit per pixel for the underlying image data format, per the above descriptions.
    • As above.
  • and do not yet support or . Have a use case and/or opinion on working with these formats? Open an issue and let us know! (See #935.)

  • , , and with shadow blurs may crash or not render properly.

  • The and constructors assume 4 bytes per pixel. To create an instance with a different number of bytes per pixel, use or .

5 последних уроков рубрики «HTML и DHTML»

  • При написании или отладки PHP скриптов мы частенько пользуемся функциями var_dump() и print_r() для вывода предварительных данных массив и объектов. В этом посте я бы хотел рассказать вам о функции var_export(), которая может преобразовать массив в формат, пригодный для PHP кода.


  • Парочка бесплатных шаблонов панелей администрирования.

  • Создание шаблона для письма не такое уж простое дело. Предлагаем вам подборку из 30 сайтов, где можно бесплатно скачать подобные шаблоны на любой вкус.

  • К примеру у вас есть поле поиска, которое обрабатывается при каждом нажатии клавиши клавиатуры. Если кто-то захочет написать слово Windows, AJAX запрос будет отправлен по следующим фрагментам: W, Wi, Win, Wind, Windo, Window, Windows. Проблема?.

JavaScript

JS Array concat() constructor copyWithin() entries() every() fill() filter() find() findIndex() forEach() from() includes() indexOf() isArray() join() keys() length lastIndexOf() map() pop() prototype push() reduce() reduceRight() reverse() shift() slice() some() sort() splice() toString() unshift() valueOf()

JS Boolean constructor prototype toString() valueOf()

JS Classes constructor() extends static super

JS Date constructor getDate() getDay() getFullYear() getHours() getMilliseconds() getMinutes() getMonth() getSeconds() getTime() getTimezoneOffset() getUTCDate() getUTCDay() getUTCFullYear() getUTCHours() getUTCMilliseconds() getUTCMinutes() getUTCMonth() getUTCSeconds() now() parse() prototype setDate() setFullYear() setHours() setMilliseconds() setMinutes() setMonth() setSeconds() setTime() setUTCDate() setUTCFullYear() setUTCHours() setUTCMilliseconds() setUTCMinutes() setUTCMonth() setUTCSeconds() toDateString() toISOString() toJSON() toLocaleDateString() toLocaleTimeString() toLocaleString() toString() toTimeString() toUTCString() UTC() valueOf()

JS Error name message

JS Global decodeURI() decodeURIComponent() encodeURI() encodeURIComponent() escape() eval() Infinity isFinite() isNaN() NaN Number() parseFloat() parseInt() String() undefined unescape()

JS JSON parse() stringify()

JS Math abs() acos() acosh() asin() asinh() atan() atan2() atanh() cbrt() ceil() cos() cosh() E exp() floor() LN2 LN10 log() LOG2E LOG10E max() min() PI pow() random() round() sin() sqrt() SQRT1_2 SQRT2 tan() tanh() trunc()

JS Number constructor isFinite() isInteger() isNaN() isSafeInteger() MAX_VALUE MIN_VALUE NEGATIVE_INFINITY NaN POSITIVE_INFINITY prototype toExponential() toFixed() toLocaleString() toPrecision() toString() valueOf()

JS OperatorsJS RegExp constructor compile() exec() g global i ignoreCase lastIndex m multiline n+ n* n? n{X} n{X,Y} n{X,} n$ ^n ?=n ?!n source test() toString() (x|y) . \w \W \d \D \s \S \b \B \0 \n \f \r \t \v \xxx \xdd \uxxxx

JS Statements break class continue debugger do…while for for…in for…of function if…else return switch throw try…catch var while

JS String charAt() charCodeAt() concat() constructor endsWith() fromCharCode() includes() indexOf() lastIndexOf() length localeCompare() match() prototype repeat() replace() search() slice() split() startsWith() substr() substring() toLocaleLowerCase() toLocaleUpperCase() toLowerCase() toString() toUpperCase() trim() valueOf()

Графические примитивы

Прямоугольники:

ctx.fillRect  (x,y, width,height);    // Рисует заполненный прямоугольник
ctx.strokeRect(x,y, width,height);    // Рисует границы прямоугольника
ctx.clearRect (x,y, width,height);    // Очищает заданную область и делает её полностью прозрачной

Настройки:

ctx.globalAlpha = 0.0                 // все сделать дальше прозрачным

ctx.fillStyle = "orange";             // разные способы задания цвета заливки
ctx.fillStyle = "#FFA500";
ctx.fillStyle = "rgb(255,165,0)";
ctx.fillStyle = "rgba(255,165,0,1)";

ctx.strokeStyle = "orange";           // аналогично для цвета линий
ctx.setLineDash();               // пунктирная линия с заданным параметром пунктира

ctx.lineWidth = 5;                    // толщина линии
сtx.lineCap   = "round";              // как оканчивать линию 

Линии:

beginPath();                          // начало рисования линии
...                                   // последовательность команд
closePath();                          // соединяет последнюю и первую точку (можно не делать)
stroke();                             // рисуем рамкой
fill();                               // и/или залитую фигуру
moveTo(x, y);                         // переместиться, ничего не рисуя
lineTo(x, y);                         // провести от последней точки линию
arc(x, y, radius, startAngle, endAngle, anticlockwise); // нарисовать дугу
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); // Безье кривые
var p = new Path2D("M 525,268 l 60,0  0,30 -60,0 0,-30 Z"); // кусок из svg-файла
ctx.stroke(p);                                              // M - move, L - сдвиг на
  • Для arc: x и y это координаты центра круга; startAngle и endAngle — точки начала и конца арки в радианах (углы от оси x). Параметр anticlockwise равен true, то дуга рисуется против часовой стрелки, иначе — по часовой. Угол отсчитывается от оси x в сторону оси y, которая направлена вниз (!!!)
  • Для bezierCurveTo: cp1x и cp1y — координаты первой точки контроля, а cp2x и cp2y — второй точки контроля, x и y — координаты конечной точки.
   ctx.beginPath();
   ctx.arc(200,  90, 5, 0, Math.PI*2, true);
   ctx.stroke();

   ctx.setLineDash();
   ctx.beginPath();
      ctx.moveTo(10,30);
      ctx.lineTo(200,90);
      ctx.lineTo(200,5);
   ctx.stroke();
&nbsp&nbsp&nbsp
   ctx.beginPath();
      ctx.moveTo(10,130);
      ctx.bezierCurveTo(50,190, 159,70, 200,130);
      ctx.lineTo(200,190);
      ctx.lineTo(10,190);
   ctx.closePath();

   ctx.fillStyle = 'red';
   ctx.fill();               // заливаем

   ctx.lineWidth = 4;
   ctx.strokeStyle = 'green';
   ctx.stroke();             // делаем обводку
&nbsp&nbsp&nbsp
var grad = ctx.createLinearGradient(0,0,200,0);
grad.addColorStop(0, "white");
grad.addColorStop(0.5, "red");
grad.addColorStop(1, "black");
ctx.fillStyle = grad;
ctx.fillRect(0,0,400,50);
&nbsp&nbsp&nbsp

Матрицы

ctx.save();
ctx.translate(canvas.width/2, 0);  // сдвинули канвас вдоль оси Х
ctx.strokeStyle = "red";   ctx.strokeRect(0,0, 100,50);
ctx.rotate(30 * Math.PI / 180);    // поворачиваем
ctx.strokeStyle = "green"; ctx.strokeRect(0,0, 100,50);
ctx.scale(0.5,0.75);               // растягиваем
ctx.strokeStyle = "blue";  ctx.strokeRect(0,0, 100,50);
ctx.restore();
ctx.save();
ctx.translate(canvas.width/2, 0);  // сдвинули канвас вдоль оси Х
ctx.strokeStyle = "red";   ctx.strokeRect(0,0, 100,50);
ctx.scale(0.5,0.75);               // растягиваем
ctx.strokeStyle = "green"; ctx.strokeRect(0,0, 100,50);
ctx.rotate(30 * Math.PI / 180);    // поворачиваем
ctx.strokeStyle = "blue";  ctx.strokeRect(0,0, 100,50);
ctx.restore();

Пример: Крутилка

В центре канваса врашается линия на концах которой находятся также вращающиеся квадратики:

var canvas;                         // элемент id="canvas"
var ctx;                            // контекст рисования
var angle = 0, box1X=-50, box2X=50; // угол поворота и положения центров ящиков

/*******************************************************************************
 * запускается при загрузке страницы
 */
function run()
{
   canvas = document.getElementById('canvas');     // элемент id="canvas"
   ctx = canvas.getContext('2d');                  // контекст рисования
   setInterval(rotate, 100);                       // вызываем через 100ms
}
/*******************************************************************************
 * вызывается таймером каждые 100ms
 */
function rotate()
{
   ctx.clearRect(0,0, canvas.width,canvas.height);  // очищаем канвас

   ctx.save();
   ctx.translate(canvas.width/2, canvas.height/2);  // камеру в центр канваса
   ctx.strokeRect(-5,-5, 10, 10);                   // там (относит.центра) квадрат 10x10
   ctx.scale(2,2);                                  // увеличиваем всё дальше в 2 раза
   ctx.rotate(angle * Math.PI / 180);               // и поворачиваем на угол angle

   ctx.beginPath();                                 // линия, соединяющая ящики
   ctx.moveTo(box1X, 0);   ctx.lineTo(box2X, 0);    // она будет вращаться на угол angle
   ctx.closePath();                                 // вокруг центра канваса
   ctx.stroke();

   ctx.fillStyle = "blue";
   box(box1X, 0, 50, 10, 1,1, 10*angle);            // ящики вращаются с линией
   box(box2X, 0, 50, 10, 2,2, 10*angle);            // и ещё поворачиваются вокруг свомх осей

   ctx.restore();
   angle+=1;                                        // увеличиваем на 1 градус
}
/*******************************************************************************
 * Рисует прямоугольник шириной w и высотой h.
 * Его _центр_  находится в x,y относительно _родителя_
 * и повёрнут на угол "a" в градусах. Кроме этого отмаштабирован на sx, sy
 */
function box(x,y, w, h, sx, sy,  a)
{
   ctx.save();                                       // сохраняем параметры канваса
   ctx.translate(x,y);                               // перемещаем камеру в x,y
   ctx.scale(sx, sy);
   ctx.rotate(a*Math.PI/180);                        // поворачиваем на угол 10*angle
   ctx.fillRect(-w/2, -h/2, w, h);                   // помещаем центр в x,y
   ctx.restore();                                    // восстанавливаем параметры канваса
}

License

(The MIT License)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Supported CSS Tags

  • margin (shorthand and expanded) px only
  • padding (shorthand and expanded);
  • font (shorthand and expanded) ‘shorthand’ thanks to canvas font support
  • color
  • background-color
  • width
  • em and % text sizing.
body{font-familyArial;font-size14px;padding5px;background-colorrgba(0,0,0);color#fff;}p{padding-toppx;padding-left5px;padding-bottom5px;}strong, b{font-weightbold;}em, i, var{font-styleitalic;}code, samp, kbd{font-familymonospace;}center {text-aligncenter;}
  • text-decoration
  • background (shorthand and expanded)
  • border (shorthand and expanded)
  • transform
  • box-shadow
  • position
  • margin: auto
  • float: left, right, clear: both

Цвета, стили, тени¶

Свойства:

Устанавливает/возвращает цвет, градиент или шаблон, используемый для заливки графического объекта
Устанавливает/возвращает уровень размытости для теней
Устанавливает/возвращает цвет для теней
Устанавливает/возвращает горизонтальное расстояние тени от фигуры
Устанавливает/возвращает вертикальное расстояние тени от фигуры
Устанавливает/возвращает цвет, градиент или шаблон, используемый для обводки фигуры

Методы:

Определяет цвета и позицию остановки в объекте градиента
Создает линейный градиент (для использования с содержимым элемента )
Размножает заданный элемент в заданном направлении
Создает радиальный/круговой градиент (для использования на содержимом элемента )

Кривые линии

Чтобы рисовать что-то более сложное, чем линии и прямоугольники, нужно изучить следующие четыре метода: arc(), arcTo(), bezierCurveTo() и quadraticCurveTo(). Все эти методы рисуют кривые линии, и хотя каждый делает это по-своему, все они требуют хотя бы небольших (а некоторые и больших) знаний математики.

Изо всех этих методов самый простой — метод arc(), который рисует дугу. Чтобы нарисовать дугу, нужно сначала представить себе в уме полный круг, а потом решить, какую часть его окружности вы хотите рисовать:

Дуга выглядит достаточно простой фигурой, но чтобы полностью ее описать, требуется несколько единиц информации. Сначала нужно нарисовать воображаемый круг. Для этого надо знать координаты центра (1) и радиуса (2), который определяет размер круга. Далее следует описать длину дуги на окружности, для чего требуется угол начала дуги (3) и угол ее окончания (4). Значения углов должны быть в радианах, которые выражаются через число π. Угол всей окружности равен 2π, половины — 1π и т.д.

Собрав все необходимые данные, передаем их методу arc():

Дугу можно закрыть, соединив ее концы прямой линией. Для этого нужно вызвать метод closePath() перед тем, как вызывать метод stroke(). Кстати, окружность — это та же дуга, просто с углом 2π. Рисуется окружность следующим образом:


Метод arc() нельзя применять для рисования овала (вытянутого круга). Для этого нужно использовать либо более сложные методы для рисования кривых, либо применить трансформации.

Три других метода рисования кривых — arcTo(), bezierCurveTo() и quadraticCurveTo() — могут быть несколько посложнее для тех, кто не в ладах с геометрией. Они основаны на принципе контрольных точек, т.е. точек, которые сами не являются частью кривой, но управляют ее формой. Наиболее известным типом таких кривых являются кривые Безье, которые используются практически в каждой программе рисования. Причиной популярности этого метода является, его способность создавать плавные кривые, независимо от их размера.

Кривая Безье создается следующим кодом:

Контур сложной фигуры часто состоит из ряда дуг и кривых, соединяющихся друг с другом. По окончанию рисования всех составляющих можно вызвать метод closePath(), чтобы обвести или закрасить всю фигуру. Чтобы побольше узнать о кривых Безье, лучше поэкспериментировать с ними, а хорошую игровую площадку для этого можно найти на этой странице: Canvas Bézier Curve Example.

Преимущества API Canvas

Перечисленные недостатки Canvas-приложений создают довольно неприглядную картину. Однако у них есть ряд своих преимуществ. Главное из них ― высокая производительность при обработке графики и возможность согласованного представления информации на разных устройствах.

Производительность при обработке графики

Существуют задачи, которые может решить и HTML, и Canvas, такие как визуализация изображений, текста и анимации.

Так как Canvas не обременен накладными расходами, связанными с анализом HTML и поддержанием иерархической модели документов, в Canvas эти задачи неизменно решаются быстрее.

В HTML-приложениях главный враг производительности ― это добавление, удаление и обновление узла. Эти изменения модели документа часто заставляют браузер заново обрабатывать или перекомпоновывать всю страницу, что может быть очень ресурсоёмким процессом. Обновление модели документа много раз в секунду, необходимое в приложении реального времени, может сильно замедлить работу браузера.

Когда скорость имеет первостепенное значение, переход от HTML-ориентированной архитектуры на Canvas-ориентированную может быть залогом достижения максимальной производительности. За высокую производительность приходится платить низкоуровневым API вместо мощного языка разметки HTML и гибкости CSS.

Согласованность между устройствами

Согласованное, кроссплатформенное представление всегда трудно давалось традиционной модели HTML/CSS из-за разницы в механизмах макетирования браузеров. Хотя Web-страницы на разных платформах могут выглядеть очень похожими, трудно достичь согласованного дизайна «с точностью до пиксела».

Графические построения Canvas устраняет эти проблемы. Canvas позволяет контролировать внешний вид графики и текста на уровне пикселей и гарантировать, что результат будет абсолютно одинаковым на всех платформах.

Создание объектов на сцене

  • Geometry — описывает форму (положения вершин, грани, радиус и т.д)
  • Material — описывает внешний вид объектов (цвет, текстура, прозрачность и т.д.)

headbody

  • угол зрения или FOV, в нашем случае это стандартный угол 75;
  • второй параметр — соотношение сторон или aspect ratio;
  • третьим и четвертым параметром идут минимальное и максимальное расстояние от камеры, которое попадет в рендеринг.

canvasbody

BoxGeometry

  • width: ширина куба, размер сторон по оси X
  • height: высота куба, т.е. размер сторон по оси Y
  • depth: глубина куба, т.е. размер сторон по оси Z

MeshBasicMaterial0x00ff00{ wireframe: true }Mesh

Meshscene.add()

requestAnimationFrame

SphereGeometry

  • радиус (значение по умолчанию равно 1)
  • widthSegments — количество горизонтальных сегментов (треугольников). Минимальное значение равно 3, значение по умолчанию 8
  • heightSegments — количество вертикальных сегментов. Минимальное значение равно 2, значение по умолчанию 6

MeshNormalMaterial


MeshPhongMaterialSpotLight

SpotLightintensity, distance, angle, penumbra, decay

TorusGeometry

  • радиус, по умолчанию 1;
  • диаметр трубы, по умолчанию 0.4;
  • radialSegments или количество сегментов-треугольников, по умолчанию 8;
  • tubularSegments или количество сегментов-граней, по умолчанию 6

specular0x111111

Изменение цветов

Итак, всё что мы рисовали до сих пор, будь то прямоугольник или треугольник, окрашивалось в чёрный цвет. Круто! Однако, существует множество функций в JavaScript API, которые позволят вам с лёгкостью изменить цвет фигуры, которую вы рисуете. Вашему вниманию представляю fillStyle и strokeStyle.

Объявлять тут в принципе нечего, поэтому давайте сразу же применим их на практике:

ctx.fillStyle = "rgb(255, 0, 0)";
ctx.fillRect(50, 50, 100, 100);

Данный код окрасит квадрат в красный цвет:

Или вы можете изменить цвет рамки квадрата:

ctx.strokeStyle = "rgb(255, 0, 0)";
ctx.strokeRect(50, 50, 100, 100);

Вот вы и научились применять данные методы:

Методы fillStyle и strokeStyle удобны тем, что они используют те же цвета, что и в привычном вам CSS. Это значит, что вы можете использовать RGB, RGBA, HSA, специальные слова (“red”) и шестнадцатеричные значения.

Сразу стоит отметить, что изменение цвета не приводит к преобразованию уже существующего содержания элемента canvas. К примеру, если вы нарисовали черный прямоугольник, затем создали наполнитель для красного цвета, а потом нарисовали ещё один прямоугольник, то первая фигура останется чёрной.

Рисование на холсте для тех, кто ненавидит математику

Если вы планируете создавать на холсте захватывающую графику, но не желаете углубленно изучать геометрию, вам, может быть, придется немного разочароваться. К счастью, существует несколько способов, которые могут помочь вам рисовать требуемые фигуры, не беспокоясь о математических принципах в их основе:

Использовать библиотеку рисования

Зачем набивать себе шишки на лбу, если можно использовать готовую библиотеку для рисования кругов, треугольников, овалов и многоугольников за один прием? Идея простая — вызывается метод высшего уровня (скажем, fillEllipse(), которому передаются соответствующие координаты), и библиотека JavaScript преобразует все это в требуемую операцию на холсте. В качестве двух хороших примеров такой библиотеки можно назвать CanvasPlus и Artisan JS. Но эти, и другие, библиотеки продолжают развиваться, поэтому еще рано говорить, какие из них выживут и окажутся пригодными для профессионального применения.

Рисовать растровые изображения

Вместо того чтобы кропотливо рисовать каждую требуемую фигуру самому, можно скопировать в холст уже готовую графику. Например, изображение круга, сохраненное в файле формата PNG, можно вставить в холст. Но этот подход не позволит использовать гибкость при манипулировании изображением, например растягивать его, перемещать или удалять его части и т.п.

Использовать профессиональный инструмент

Для того чтобы манипулировать сложной графикой на холсте или сделать ее интерактивной, фиксированного растрового изображения будет недостаточно. Решением этой проблемы может быть средство преобразования, которое способно исследовать вашу графику и сгенерировать правильный код для применения с холстом.

В этом отношении представляет интерес одно из таких средств — модуль Ai->Canvas для Adobe Illustrator. Данный модуль преобразует созданную в Adobe Illustrator графику в страницу HTML с кодом JavaScript, который воспроизводит эту графику на холсте.

Caveats

  • simple flow engine, no div floating, all elements are either a new line or a line element.
  • Treats all elements as div’s except for tags the following tags
    • span, strong, em, code, samp, kbd, var, b
    • This can be expanded on via options.lineTags:
  • font*, text*, color are the only style tags that get applied to children elements.
  • fetch is required for downloading images. a polyfill (whatwg-fetch) for unsupported browsers and for node support it needs to be passed as an option.fetch: fetch.
  • font-size and font-family must be defined on any parent element for text to render.
  • for webpack you need to add the following to config for it to compile
{"node"{"fs""empty"}}

С этим читают