Знакомство с новым элементом
Первый пример
Настройки цвета и размера
Прямоугольники
Линии и дуги
Окружности
Закруглённые углы
Кривые Безье
Функция clip() - ограничиваем область рисования
Тени
Градиенты
Прозрачность
Используем шаблоны
Треугольник Серпинского
Рисование изображений
Рисование текста
Комбинирование наложений
Canvas - это новый элемент HTML5, который предназначен для создания растрового изображения при помощи JavaScript. Само слово canvas переводится как холст или канва. Текст внутри тега будет проигнорирован браузером с поддержкой canvas и показан в браузере без поддержки canvas.
<canvas id="test" width="500" height="500">
Здесь можно указать текст для тех,
у кого не поддерживается тег canvas
</canvas>
У тега есть два атрибута — width (ширина) и height (высота). Если размеры не указать, то по умолчанию размер холста будет равен 300х150 пикселей. Canvas создаёт область фиксированного размера, содержимым которого управляют контексты. Атрибуты не имеют отношения к CSS, они обозначают ширину и высоту canvas в пикселях не на экране, а на координатной плоскости холста.
Не рекомендуется использовать CSS для установки высоты и ширины холста, так как в этом случае canvas подвергнется масштабированию. Задавайте размеры в элементе.
Требуется установить обязательный идентификатор для обращению к элементу в JavaScript.
Также можно применить стиль, например, сделаем рамку вокруг холста и не будем устанавливать размеры, чтобы увидеть ширину и высоту по умолчанию.
<canvas id="border" style = "border:2px solid black">Canvas</canvas>
Сейчас все современные браузеры поддерживают canvas. Если такой уверенности нет, то можно устроить небольшую проверку.
var canvas = document.getElementById('my_canvas');
if (canvas.getContext){
var context = canvas.getContext('2d');
}else{
// Сделать что-то для вывода скрытого содержимого
// или позволить браузеру вывести текст элемента canvas
}
Мы находим элемент canvas по идентификатору, а затем вызываем метод getContext() с единственным параметром - строкой 2d. Если getContext() возвращает ответ, мы получаем 2D-контекст холста для добавления объектов.
Размер холста можно вычислить программно через свойства canvas.width и canvas.height.
<canvas height='320' width='480' id='first_example'>Пример</canvas>
<script>
var canvas = document.getElementById("first_example");
var context = canvas.getContext('2d');
context.fillRect(0, 0, canvas.width, canvas.height);
</script>
Если открыть созданный пример браузером, то увидим область с чёрным прямоугольником. Это и есть тот самый холст, на котором нарисован прямоугольник, размеры которого равны размерам элемента canvas. Если бы мы не рисовали чёрный прямоугольник, то у нас был бы прозрачный холст. Размеры задаются в пикселях, а отсчёт идёт от верхнего левого угла. На холсте можно рисовать различные фигуры. Можно указать отрицательные значения для координат, ошибки не произойдёт, но смысла в этом нет - фигуры не будут видны на экране.
Стили для заливки и обводки имеют глобальный параметр. Если вы задали какое-то свойство, то оно применится для всех элементов, если не был после этого изменен. Например, мы сначала задали зелёный цвет для заливки и синий для обводки. Если после этого мы нарисуем несколько фигур, то они все будут иметь зелёный фон и синюю обводку.
За заливку отвечает свойство fillStyle. По умолчанию для заливки используется чёрный цвет. За цвет и стиль обводки отвечает свойство strokeStyle.
Цвет задается точно так же как и в CSS (четыре способа)
// все четыре строки задают оранжевый цвет заливки
context.fillStyle = "orange";
context.fillStyle = "#FFA500";
context.fillStyle = "rgb(255,165,0)";
context.fillStyle = "rgba(255,165,0,1)"
Есть ещё редко используемый способ через HSL - hsl(219, 58%, 93%).
Установим желаемые настройки - укажем, что мы хотим красный цвет (#FF0000) и толщину в 3 пиксела для обводки и зеленый цвет (#00FF00) для заливки:
context.strokeStyle = '#FF0000'; // Цвет обводки
context.lineWidth = 3; // Ширина линии
context.fillStyle = '#00FF00'; // Цвет заливки
Начнем с прямоугольника. В canvas есть два вида прямоугольников — залитые и незалитые (обводка). Предусмотрены три функции для рисования прямоугольников.
Функция clearRect() как бы вырезает кусок фигуры, за которым можно увидеть холст.
context.clearRect(10, 10, 200, 200); // Очистка области указанного размера и положения
context.clearRect(0, 0, canvas.width, canvas.height); // Очистка всего холста
Нарисуем два вида прямоугольников.
var canvas = document.getElementById("rectangles");
var context = canvas.getContext('2d');
context.strokeStyle = '#FF0000'; // Цвет обводки
context.lineWidth = 3; // Ширина линии
context.fillStyle = '#00FF00'; // Цвет заливки
context.fillRect(10, 10, 390, 100);
context.strokeRect(40, 130, 200, 150);
Попробуйте нарисовать ещё один закрашенный прямоугольник и вырезать из него прямоугольник меньшего размера.
Каждая добавляемая фигура размещается на отдельном уровне; следующий фрагмент кода создаёт три прямоугольника со смещением в 15 пикселей, чтобы они частично наложились друг на друга.
<canvas id='rects'>Наложение прямоугольников</canvas>
<script>
var canvas = document.getElementById("rects");
var context = canvas.getContext('2d');
canvas.height = 200;
canvas.width = 300;
context.fillStyle = "rgb(200, 0, 0)";
context.fillRect(15, 15, 100, 100);
context.fillStyle = "rgb(0, 200, 0)";
context.fillRect(30, 30, 100, 100);
context.fillStyle = "rgb(0, 0, 200)";
context.fillRect(45, 45, 100, 100);
</script>
<canvas id='chessboard'>Шахматная доска</canvas>
<script>
var canvas = document.getElementById("chessboard");
var context = canvas.getContext('2d');
// Размеры холста
canvas.width = 300;
canvas.height = 300;
// Внешняя рамка для доски
context.strokeRect(15, 15, 266, 266);
// Внутренняя рамка для доски
context.strokeRect(18, 18, 260, 260);
// Закрашиваем внутреннюю область черным цветом
context.fillRect(20, 20, 256, 256);
for (i = 0; i < 8; i += 2)
for (j = 0; j < 8; j += 2) {
context.clearRect(20 + i * 32, 20 + j * 32, 32, 32);
context.clearRect(20 + (i + 1) * 32, 20 + (j + 1) * 32, 32, 32);
}
</script>
В этом примере мы установили размер холста 300 на 300 пикселей. Далее мы нарисовали два пустых прямоугольника, которые формируют рамку вокруг нашей «шахматной доски». Далее закрашиваем внутреннюю часть рамки прямоугольником черного цвета, а затем в цикле делаем в них своеобразные квадратные "дырки", чтобы через них просвечивал белый цвет. В итоге у нас получится красивая шахматная доска.
<canvas id='color_chessboard'>Цветная шахматная доска</canvas>
<script>
var canvas = document.getElementById("color_chessboard");
var context = canvas.getContext('2d');
canvas.width = 300;
canvas.height = 300;
context.strokeStyle = '#B70A02'; // меняем цвет рамки
context.strokeRect(15, 15, 266, 266);
context.strokeRect(18, 18, 260, 260);
context.fillStyle = '#AF5200'; // меняем цвет клеток
context.fillRect(20, 20, 256, 256);
for (i = 0; i < 8; i += 2)
for (j = 0; j < 8; j += 2) {
context.clearRect(20 + i * 32, 20 + j * 32, 32, 32);
context.clearRect(20 + (i + 1) * 32, 20 + (j + 1) * 32, 32, 32);
}
</script>
Мы можем рисовать прямые и изогнутые линии, окружности и другие фигуры. Замкнутые линии можно заливать цветом. В отличии от рисования прямоугольников, рисование линий это не одна команда, а их последовательность. Так, сначала надо объявить начало новой линии с помощью beginPath(), а в конце сказать от том, что рисование линии заканчивается с помощью closePath(). У каждого отрезка линии есть начало и конец.
beginPath используется что бы «начать» серию действий описывающих отрисовку фигуры. Каждый новый вызов этого метода сбрасывает все действия предыдущего и начинает «рисовать» снова.
closePath является не обязательным действием и по сути оно пытается завершить рисование проведя линию от текущей позиции к позиции с которой начали рисовать.
Завершающий шаг - это вызов методов stroke или fill. stroke обводит фигуру линиями, а fill заливает фигуру сплошным цветом.
Также существуют такие методы как,
Давайте нарисуем ломаную, состоящую из двух отрезков:
context.beginPath();
context.moveTo(10, 10); // Начало линии
context.lineTo(100, 100); // Узел линии
context.lineTo(150, 100); // Конец линии
context.closePath();
Если набор отрезков будет замкнут, то у нас получится полигон, который можно залить цветом. Создадим и зальём треугольник с помощью функции fill().
context.beginPath();
context.moveTo(50, 50);
context.lineTo(50, 250);
context.lineTo(250, 250);
context.closePath();
context.fill();
Значение ширины линии хранится в свойстве lineWidth контекста canvas и одна единица соответствует одному пикселю. Значение по умолчанию естественно 1.0
Стиль верхушки линии хранится в свойстве lineCap и для него существуют три возможных значения:
Стиль соединения линий хранится в свойстве lineJoin и может принимать три возможных значения:
Мы можем ограничить длину огромного хвоста miter с помощью свойства miteLimit, которое по умолчанию принимает значение 10.
<canvas id='crown'>Корона</canvas>
<script>
var canvas = document.getElementById("crown");
var context = canvas.getcanvas('2d');
canvas.height = 200;
canvas.width = 200;
context.beginPath();
context.arc(80, 100, 56, 3/4 * Math.PI, 1/4 * Math.PI, true);
//Заливаем дугу
context.fill();
context.moveTo(40, 140);
context.lineTo(20, 40);
context.lineTo(60, 100);
context.lineTo(80, 20);
context.lineTo(100, 100);
context.lineTo(140, 40);
context.lineTo(120, 140);
// Обводим контур короны
context.stroke();
</script>
Окружности рисуются с помощью команды arc(ox, oy, radius, startAngle, endAngle, antiClockWise), где ox и oy — координаты центра, radius — радиус окружности, startAngle и endAngle — начальный и конечный углы (в радианах) для отрисовки окружности, а antiClockWise — направление движения при отрисовке (true для против часовой стрелке, false — против). С помощью arc() можно рисовать как круги и окружности, так и дуги и части окружности.
Окружность с радиусом в 100 пикселей:
context.beginPath();
context.arc(250, 250, 100, 0, Math.PI * 2, false);
context.closePath();
context.fill(); // Заливка окружности
Нарисуем разноцветный круг:
Код нарисует круг, состоящий из 6 сегментов с произвольными цветами, которые будут меняться при обновлении страницы
<canvas id="color_circle" width="300" height="200"></canvas>
<script>
canvas = document.getElementById("color_circle");
context = canvas.getContext("2d");
for(var i = 0; i < 6;i++){
context.fillStyle = 'rgb(' + Math.round(Math.random()*255) + ',' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random()*255) +')'
context.beginPath();
context.arc(100, 100, 70, Math.PI/3 * i, Math.PI/3 * (i + 1), false)
context.lineTo(100, 100);
context.fill();
}
</script>
Нарисуем дольки апельсина или арбуза, а также другие варианты с использованием собственной процедуры.
<canvas id='arc_demo'>Дольки</canvas>
<script>
var canvas = document.getElementById("arc_demo");
var context = canvas.getContext('2d');
canvas.height = 200;
canvas.width = 500;
function drawArc(xPos, yPos, radius, startAngle, endAngle, anticlockwise, lineColor, fillColor)
{
var startAngle = startAngle * (Math.PI/180);
var endAngle = endAngle * (Math.PI/180);
var radius = radius;
context.strokeStyle = lineColor;
context.fillStyle = fillColor;
context.lineWidth = 8;
context.beginPath();
context.arc(xPos, yPos, radius, startAngle, endAngle, anticlockwise);
context.fill();
context.stroke();
}
drawArc(50, 15, 40, 0, 180, false, "aqua", "yellow");
drawArc(150, 15, 50, 350, 170, false, "green", "pink");
drawArc(270, 70, 60, 0, 100, true, "red", "white");
drawArc(400, 60, 50, 350, 20, true, "blue", "purple");
</script>
Теперь нарисуем круги из этих же фигур.
<canvas id='circles_demo'>Дольки</canvas>
<script>
var canvas = document.getElementById("circles_demo");
var context = canvas.getContext('2d');
canvas.height = 200;
canvas.width = 500;
function drawCircle(xPos, yPos, radius, lineColor, fillColor)
{
var startAngle = 0 * (Math.PI/180);
var endAngle = 360 * (Math.PI/180);
var radius = radius;
context.strokeStyle = lineColor;
context.fillStyle = fillColor;
context.lineWidth = 8;
context.beginPath();
context.arc(xPos, yPos, radius, startAngle, endAngle, false);
context.fill();
context.stroke();
}
drawCircle(50, 45, 40, "aqua", "yellow");
drawCircle(150, 55, 50, "green", "pink");
drawCircle(270, 70, 60, "red", "white");
drawCircle(400, 65, 50, "blue", "purple");
</script>
Нарисуем частично залитую окружность.
<canvas id='part_circle'>Частично залитая окружность</canvas>
<script>
var canvas = document.getElementById("part_circle");
var context = canvas.getContext('2d');
canvas.height = 400;
canvas.width = 400;
context.beginPath();
context.arc(200, 200, 100, 0, Math.PI * 0.85, false)
context.stroke();
context.beginPath();
context.arc(200, 200, 100, 0, Math.PI * 0.85, true);
context.fill();
</script>
Нарисуем круги в случайном порядке.
<canvas id='random_circle'>круги в случайном порядке</canvas>
<script>
var canvas = document.getElementById("random_circle");
var context = canvas.getContext('2d');
canvas.height = 400;
canvas.width = 400;
var numCircles = 500;
var maxRadius = 20;
var minRadius = 3;
var colors =
["aqua", "black", "blue", "fuchsia", "green", "cyan", "lime", "maroon",
"navy", "olive", "purple", "red", "silver", "teal", "yellow", "azure",
"gold", "bisque", "pink", "orange"];
var numColors = colors.length;
// в цикле создаём круги
for(var n = 0; n < numCircles; n++)
{
// в случайном порядке установим характеристики
var xPos = Math.random() * canvas.width;
var yPos = Math.random() * canvas.height;
var radius = minRadius + (Math.random() * (maxRadius-minRadius));
var colorIndex = Math.random() * (numColors - 1);
colorIndex = Math.round(colorIndex);
var color = colors[colorIndex];
drawCircle(context, xPos, yPos, radius, color);
}
// функция для рисования круга
function drawCircle(context, xPos, yPos, radius, color)
{
var startAngle = (Math.PI / 180) * 0;
var endAngle = (Math.PI / 180) * 360;
context.shadowColor = "gray";
context.shadowOffsetX = 1;
context.shadowOffsetY = 1;
context.shadowBlur = 5;
context.beginPath();
context.arc(xPos, yPos, radius, startAngle, endAngle, false);
context.fillStyle = color;
context.fill();
}
</script>
Закруглённые углы рисуются при помощи функции arcto(), который содержит пять параметров.
<canvas id='arcto'>Закруглённые углы</canvas>
<script>
var canvas = document.getElementById("arcto");
var context = canvas.getContext('2d');
canvas.height = 150;
canvas.width = 400;
var xPos = 25;
var yPos = 25;
var width = 150;
var height = 75;
var radius = 30;
context.strokeStyle = "blue";
context.lineWidth = 20;
context.lineCap = "square";
context.shadowOffsetX = 3;
context.shadowOffsetY = 3;
context.shadowBlur = 5;
context.shadowColor = "gray";
context.beginPath();
context.moveTo(xPos, yPos);
context.lineTo(xPos + width - radius, yPos);
context.arcTo(xPos + width, yPos, xPos + width, yPos + radius, radius);
context.lineTo(xPos + width, yPos + height);
context.stroke();
</script>
Имеются две функции, для построения кубической и квадратичной кривой Безье:
quadraticCurveTo(Px, Py, x, y)
bezierCurveTo(P1x, P1y, P2x, P2y, x, y)
x и y - это точки в которые необходимо перейти, а координаты P(Px, Py) в квадратичной кривой это дополнительные точки, которые используются для построения кривой. В кубической кривой соответственно две дополнительные точки.
<canvas id='bezier_demo'>Кривая Безье</canvas>
<script>
var canvas = document.getElementById("bezier_demo");
var context = canvas.getContext('2d');
canvas.height = 200;
canvas.width = 260;
context.beginPath();
context.moveTo(10, 15);
context.bezierCurveTo(75, 55, 175, 20, 250, 15);
context.moveTo(10, 15);
context.quadraticCurveTo(100, 100, 250, 15);
context.stroke();
</script>
<canvas id='color_bezier'>Раскрашиваем кривые Безье</canvas>
<script>
var canvas = document.getElementById("color_bezier");
var context = canvas.getContext('2d');
canvas.height = 100;
canvas.width = 260;
context.strokeStyle = '#f00';
context.beginPath();
context.moveTo(10, 15);
context.bezierCurveTo(75, 55, 175, 20, 250, 15);
context.stroke();
context.strokeStyle = '#0f0';
context.beginPath();
context.moveTo(10, 15);
context.quadraticCurveTo(100, 100, 250, 15);
context.stroke();
</script>
Функция isPointInPath(float x, float y) вернёт значение true, если точка с переданными координатами находится внутри пути. Создадим путь в виде прямоугольника и проверим:
Данный скрипт должен вывести в отладочную консоль сначала true, а затем false.
<p><canvas id='example8'>Пример 8</canvas></p>
<script type="text/javascript">
var example = document.getElementById("example8");
var ctx = example.getContext('2d');
example.height = 400;
example.width = 400;
ctx.beginPath();
ctx.rect(200, 200, 100, 200);
ctx.stroke();
console.log(ctx.isPointInPath(250, 250));
console.log(ctx.isPointInPath(100, 100));
</script>
Функция clip() ничего не рисует. После её вызова любой объект будет рисоваться только в том случае, когда он находится в области на которой определён путь. Нарисуем круг и ограничим область рисования этим кругом. Затем нарисуем две линии, которые будут видны только внутри круга:
Если закомментировать вызов функции clip(), то увидим, как на самом деле рисуются линии.
<canvas id='clip_demo'>Clip</canvas>
<script>
var canvas = document.getElementById("clip_demo");
var context = canvas.getContext('2d');
canvas.height = 400;
canvas.width = 600;
context.beginPath();
context.arc(200, 200, 150, 0, Math.PI * 2, true);
context.stroke(); //Нарисуем круг по которому определим область пути
context.clip(); //Ограничим область для рисования областью пути
context.beginPath();
context.moveTo(100, 320);
context.lineTo(500, 120);
context.lineTo(50, 250);
context.stroke() //Нарисуем линии, которые будут видны только внутри круга
</script>
Тени canvas отбрасываются всегда, просто они отбрасываются с нулевым смещением и нулевым размытием. Есть четыре свойства управляющие тенями (через знак равно указаны стандартные значения):
Возьмем предыдущий пример и посмотрим на тени
<canvas id='clip_shadow'>Shadow</canvas>
<script>
var canvas = document.getElementById("clip_shadow");
var context = canvas.getContext('2d');
canvas.height = 400;
canvas.width = 600;
context.beginPath();
context.arc(200, 200, 150, 0, Math.PI * 2, true);
context.stroke(); //Нарисуем круг по которому определим область пути
context.clip(); //Ограничим область для рисования областью пути
context.shadowOffsetX = -10;
context.shadowOffsetY = -10;
context.shadowBlur = 2;
context.shadowColor = 'black';
context.beginPath();
context.moveTo(100, 320);
context.lineTo(500, 120);
context.lineTo(50, 250);
context.stroke() //Нарисуем линии, которые будут видны только внутри круга
</script>
Пример с прямоугольниками.
<canvas id='rect_shadow'>Shadow</canvas>
<script>
var canvas = document.getElementById("rect_shadow");
var context = canvas.getContext('2d');
canvas.height = 100;
canvas.width = 600;
var x1Pos = 25;
var x2Pos = 200;
var yPos = 10;
var length = 150; var height = 50;
// первый прямоугольник с тенью
context.shadowOffsetX = 4;
context.shadowOffsetY = 4;
context.shadowBlur = 3;
context.fillStyle = "deeppink";
context.shadowColor = "gray";
context.fillRect (x1Pos, yPos, length, height);
// второй прямоугольник с тенью
context.shadowOffsetX = 12;
context.shadowOffsetY = 12;
context.shadowBlur = 4;
context.strokeStyle = "aqua";
context.shadowColor = "lightgreen";
context.lineWidth = 8;
context.strokeRect (x2Pos, yPos, length, height);
</script>
Сначала создаётся объект градиента при помощи функции createLinearGradient(float x1, float y1, float x2, float y2) из точки (x1; y1) в точку (x2; y2). Затем добавляются цвета при помощи функции addColorStop(float offset, string color), где offset - отступ со значениями от 0 до 1, а color - нужный цвет. Далее созданный градиент применяется как стиль заливки в свойстве fillStyle.
<canvas id="lineargradient" width="160" height="160"></canvas>
<script>
var canvas = document.getElementById("lineargradient");
var context = canvas.getContext("2d");
var gradient = context.createLinearGradient(0, 0, 150, 150);
gradient.addColorStop(0.0, 'blue');
gradient.addColorStop(0.5, 'red');
gradient.addColorStop(1.0, 'green');
context.fillStyle = gradient;
// рисуем залитый прямоугольник
context.fillRect(0, 0, 150, 150);
</script>
Радиальный градиент создаётся с помощью функции createRadialGradient(float x1, float y1, float r1, float x2, float y2, float r2) - плавный переход цвета из окружности с центром в точке (x1; y1) и радиусом r1 в окружность с центром точке (x2; y2) и радиусом r2.
Нарисуем шар с псевдо-освещением
<canvas id="radialgradient" width="500" height="170"></canvas>
<script>
var canvas = document.getElementById("radialgradient");
var context = canvas.getContext("2d");
context.shadowOffsetX = 10;
context.shadowOffsetY = 15;
context.shadowBlur = 10;
context.shadowColor = '#0F0';
var gradient = context.createRadialGradient(60, 60, 15, 75, 75, 75);
gradient.addColorStop(0.0, '#0F0');
gradient.addColorStop(1.0, '#0DA805');
context.fillStyle = gradient;
context.beginPath();
context.arc(75, 75, 75, 0, Math.PI * 2, false);
context.fill();
</script>
Прозрачность задаётся через атрибут globalAlpha. Значения находятся в диапазоне от 0 до 1, где 0 - полная прозрачность, 1 - сплошной цвет.
<canvas id="transparent_demo" width="500" height="100"></canvas>
<script>
var canvas = document.getElementById("transparent_demo");
var context = canvas.getContext("2d");
// первый объект
var xPos = 20;
var yPos = 20;
var gap = -20;
var width = 80; var height = 80;
// тень
context.shadowOffsetX = 4;
context.shadowOffsetY = 4;
context.shadowBlur = 3;
context.shadowColor = "gray";
// прозрачность
context.globalAlpha = 1;
context.fillStyle = "orange";
context.fillRect (xPos + (0 * width) + (0 * gap), yPos, width, height);
context.globalAlpha = .5;
context.fillStyle = "blue";
context.fillRect (xPos + (1 * width) + (1 * gap), yPos, width, height);
context.globalAlpha = .25;
context.fillStyle = "red";
context.fillRect (xPos + (2 * width) + (2 * gap), yPos, width, height);
context.globalAlpha = .25;
context.fillStyle = "limegreen";
context.fillRect (xPos + (3 * width) + (3 * gap), yPos, width, height);
context.globalAlpha = .4;
context.fillStyle = "magenta";
context.fillRect (xPos + (4 * width)+(4 * gap), yPos, width, height);
context.globalAlpha = .25;
context.fillStyle = "gold";
context.fillRect (xPos + (5 * width) + (5 * gap), yPos, width, height);
context.globalAlpha = .4;
context.fillStyle = "turquoise";
context.fillRect (xPos + (6 * width) + (6 * gap), yPos, width, height);
Также прозрачность можно задать в атрибутах цвета:
context.fillStyle = "rgb(0, 0, 255, .5)";
Кроме цветов и градиентов fillStyle и strokeStyle в качестве значения могут принимать и так называемые шаблоны. Шаблоны можно создать из того же самого canvas элемента, изображения или видео. Для примера будем использовать изображение. Шаблон создается методом createPattern(object any, string repeat), где repeat может принимать следующие значения:«repeat» (по умолчанию),«repeat-x»,«repeat-y»,«no-repeat».
<canvas id="pascalCanvas" width="800" height="800"></canvas>
<script>
function drawPixel(x, y, context) {
context.fillRect(x, y, 1, 1);
}
var canvas = document.getElementById("pascalCanvas");
var context = canvas.getContext("2d");
// gradient style
var gradient = context.createLinearGradient(0, 0, 0, canvas.height);
gradient.addColorStop(0, "#00f");
gradient.addColorStop(1, "#f30");
context.fillStyle = gradient;
//context.fillStyle = "#000";
//Pascal's triangle
var tr = new Array(canvas.height);
for (i = 0; i < canvas.height; i++) {
tr[i] = new Array(canvas.width);
for (k = 0; k < canvas.width; k++) {
if (k == 0)
tr[i][k] = 1;
else
tr[i][k] = 0;
}
}
for (i = 1; i < canvas.height; i++) {
for (k = 1; k < canvas.width; k++) {
tr[i][k] = (tr[i-1][k-1] + tr[i-1][k]) % 2;
}
}
//draw
for (i = 0; i < canvas.height; i++) {
for (k = 0; k < canvas.width; k++) {
if (tr[i][k] != 0)
drawPixel(k, i, context);
}
}
</script>
Чтобы нарисовать изображение, нужно создать его объект с помощью конструктора Image, затем установить путь к изображению через свойство src полученного объекта.
Прежде чем рисовать изображение, его стоит загрузить. Для этого добавим обработчик события load для объекта img, добавим его после создания объекта.
Далее можно нарисовать изображение исходного размера с помощью функции drawImage(object img, float x, float y), где указывается его верхний левый угол в точке (x;y).
Для масштабирования используется другая версия функции - drawImage(object img, float x, float y, float w, float h) - в последних двух параметрах указывается ширина и высота.
Также можно обрезать картинку через ещё одну версию функции drawImage(object img, float sx, float sy, float sw, float sh, float cx, float cy, float cw, float ch) - нарисует часть изображения шириной sw и высотой sh расположенную в точке (sx,sy) в исходном изображении на canvas с шириной cw и высотой ch в точке (cx,cy).
var img = new Image()
img.onload = function(){
//Тут ваш код для работы с контекстом
}
img.src = 'path.png'
Выведем изображения с разными размерами.
<canvas id="images_demo" width="500" height="150" style = "border:2px solid black"></canvas>
<script>
var canvas = document.getElementById("images_demo");
var context = canvas.getContext("2d");
var smallImageXPos = 40;
var smallImageYPos = 55;
var smallImageWidth = 75;
var smallImageHeight = 75;
var largeImageXPos = 225;
var largeImageYPos = 10;
var sourceCropX = 25;
var sourceCropY = 25;
var sourceCropWidthX = 50;
var sourceCropWidthY = 50;
var imageWidth = 80;
var imageHeight = 80;
var smallImage = new Image();
var largeImage = new Image();
smallImage.onload = function()
{
context.drawImage(smallImage, smallImageXPos, smallImageYPos);
context.drawImage(smallImage, smallImageXPos + 80, smallImageYPos - 25,
smallImageWidth, smallImageHeight);
}
largeImage.onload = function()
{
context.drawImage(largeImage, largeImageXPos, largeImageYPos);
context.drawImage (largeImage, sourceCropX, sourceCropY,
sourceCropWidthX, sourceCropWidthY,
largeImageXPos + 140, largeImageYPos + 10,
imageWidth, imageHeight);
}
smallImage.src = "../images/star.jpg";
largeImage.src = "../images/star.jpg";
context.shadowOffsetX = -3;
context.shadowOffsetY = 3;
context.shadowBlur = 8;
context.shadowColor = "gray";
</script>
Нельзя вызывать метод drawImage(), если картинка не загружена в браузер. В примере я заранее вывел картинку при помощи тега img. Обычно, в подобных случаях используют вызов window.onload() или document.getElementById("imageID").onload.
<canvas id="otherImage" width="250" height="300" style="border:1px solid #d3d3d3;">
Ваш браузер не поддерживает canvas
</canvas>
<script>
window.onload = function() {
var canvas = document.getElementById('otherImage');
var context = canvas.getContext('2d');
var image = new Image();
image.onload = function() {
context.drawImage(image, 30, 30);
};
image.src = 'http://developer.alexanderklimov.ru/android/images/android_cat.jpg';
}
</script>
Для сохранения изображений существует три метода (getAsFile,getBlob,toDataURL), самый удобный - toDataURL поскольку именно он наиболее хорошо поддерживается браузерами. Стоит заметить что метод применяется не к контексту, а к canvas элементу, впрочем его можно получить как свойство 'canvas' контекста, также этот метод принимает как аргумент тип изображения (по умолчанию 'png'). Этот метод вернет изображение в формате base64.
Существуют функции рисование текста. Залитый текст рисуется через функцию context.fillText(string text, float x, float y) в точке (x;y)
Функция fillText() имеет необязательный аргумент maxWidth, который не совсем корректно работает в некоторых браузерах.
Свойство контекста font управляет стилем текста и имеет синтаксис схожий с css:
// формат
// context.font = "style weight size face";
Не все атрибуты свойства font обязательно указывать. Если какой-то атрибут пропущен, то будет использоваться значение по умолчанию.
Для стилей используются следующие значения
Для веса используются значения:
Для размеров:
Выбор шрифта зависит от поддержки браузерами, поэтому лучше использовать стандартные.
context.font = "bold italic 30px sans-serif";
context.fillText("Hello Kitty", 300, 300);
Управлять цветом мы можем через свойства fillStyle и strokeStyle.
Для рисования контуров текста применяется функции strokeText() вместо fillText().
Для выравнивания текста существует свойство textAlign, оно может принимать пять возможных значений:
<canvas id="textalign_demo" width="500" height="170" style = "border:2px solid black"></canvas>
<script>
var canvas = document.getElementById("textalign_demo");
var context = canvas.getContext("2d");
var xPos = canvas.width/2;
var yPos = 30;
context.font = "15pt Arial";
context.fillStyle = "blue";
context.strokeStyle = "hotpink";
context.lineWidth = 1;
context.beginPath();
context.moveTo(xPos, 0);
context.lineTo(xPos, canvas.height);
context.stroke();
context.textAlign = "right";
context.fillText("right", xPos, yPos * 1);
context.textAlign = "end";
context.fillText("end", xPos, yPos * 2);
context.textAlign = "center";
context.fillText("center", xPos, yPos * 3);
context.textAlign = "left";
context.fillText("left", xPos, yPos * 4);
context.textAlign = "start";
context.fillText("start", xPos, yPos * 5);
</script>
Для управления линией основания текста существует свойство textBaseline, оно может принимать следующие значения:
Измерить ширину текста можно через measureText(string text). Она вернет специальный объект TextMetrics, который обладает свойством width — ширина текста в пикселях.
<canvas id="drawtext_demo" width="500" height="170"></canvas>
<script>
var canvas = document.getElementById("drawtext_demo");
var context = canvas.getContext("2d");
// центрируем текст
var mText = "Hello Kitty!";
var xPos = canvas.width/2;
var yPos = canvas.height/2;
context.font = "60pt Comic Sans MS";
context.fillStyle = "lime";
context.textAlign = "center";
context.textBaseline = "middle";
context.fillText(mText, xPos, yPos);
</script>
Наложение двух фигур можно осуществить при помощи свойства globalCompositeOperation, которое может принимать одно из значений.
Выведем все способы в таблице.
|
|
|
|
|
|
|
|
|
|
|
<table border="1" align="center">
<tr>
<td>
<canvas id="source-over" width="120" height="110"></canvas><br/><l>source-over</l>
</td>
<td>
<canvas id="source-in" width="120" height="110"></canvas><br/><l>source-in</l>
</td>
<td>
<canvas id="source-out" width="120" height="110"></canvas><br/><l>source-out</l>
</td>
<td>
<canvas id="source-atop" width="120" height="110"></canvas><br/><l>source-atop</l>
</td>
</tr>
<tr>
<td>
<canvas id="destination-over" width="120" height="110"></canvas><br/><l>destination-over</l>
</td>
<td>
<canvas id="destination-in" width="120" height="110"></canvas><br/><l>destination-in</l>
</td>
<td>
<canvas id="destination-out" width="120" height="110"></canvas><br/><l>destination-out</l>
</td>
<td>
<canvas id="destination-atop" width="120" height="110"></canvas><br/><l>destination-atop</l>
</td>
</tr>
<tr>
<td>
<canvas id="lighter" width="120" height="110"></canvas><br/><l>lighter</l>
</td>
<td>
<canvas id="copy" width="120" height="110"></canvas><br/><l>copy</l>
</td>
<td>
<canvas id="xor" width="120" height="110"></canvas><br/><l>xor</l>
</td>
</tr>
</table>
<script>
function drawShapes(type)
{
canvas = document.getElementById(type);
context = canvas.getContext("2d");
var squareOffset = 15;
var squareSide = 70;
var circleOffset = 73;
var circleRadius = 35;
context.fillStyle = "blue";
context.fillRect(squareOffset, squareOffset, squareSide, squareSide);
context.globalCompositeOperation = type;
context.fillStyle = "red";
context.beginPath();
context.arc(circleOffset, circleOffset, circleRadius, 0, Math.PI * 2, true);
context.fill();
}
drawShapes("source-over");
drawShapes("source-in");
drawShapes("source-out");
drawShapes("source-atop");
drawShapes("destination-over");
drawShapes("destination-in");
drawShapes("destination-out");
drawShapes("destination-atop");
drawShapes("lighter");
drawShapes("copy");
drawShapes("xor");
</script>