Ответ 1
По соображениям производительности не рисуйте круг, если вы можете его избежать. Просто нарисуйте прямоугольник шириной и высотой:
ctx.fillRect(10,10,1,1); // fill in the pixel at (10,10)
Рисование строки на холсте HTML5 довольно просто, используя функции context.moveTo()
и context.lineTo()
.
Я не совсем уверен, можно ли нарисовать точку, то есть цвет одного пикселя. Функция lineTo не будет рисовать одну пиксельную линию (очевидно).
Есть ли способ сделать это?
По соображениям производительности не рисуйте круг, если вы можете его избежать. Просто нарисуйте прямоугольник шириной и высотой:
ctx.fillRect(10,10,1,1); // fill in the pixel at (10,10)
Если вы планируете рисовать много пикселей, гораздо эффективнее использовать данные изображения на холсте для рисования пикселей.
var canvas = document.getElementById("myCanvas");
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
var ctx = canvas.getContext("2d");
var canvasData = ctx.getImageData(0, 0, canvasWidth, canvasHeight);
// That how you define the value of a pixel //
function drawPixel (x, y, r, g, b, a) {
var index = (x + y * canvasWidth) * 4;
canvasData.data[index + 0] = r;
canvasData.data[index + 1] = g;
canvasData.data[index + 2] = b;
canvasData.data[index + 3] = a;
}
// That how you update the canvas, so that your //
// modification are taken in consideration //
function updateCanvas() {
ctx.putImageData(canvasData, 0, 0);
}
Чем вы можете использовать его таким образом:
drawPixel(1, 1, 255, 0, 0, 255);
drawPixel(1, 2, 255, 0, 0, 255);
drawPixel(1, 3, 255, 0, 0, 255);
updateCanvas();
Для получения дополнительной информации вы можете взглянуть на это сообщение в блоге Mozilla: http://hacks.mozilla.org/2009/06/pushing-pixels-with-canvas/
Кажется странным, но тем не менее HTML5 поддерживает рисование линий, кругов, прямоугольников и многих других основных фигур, у него нет ничего подходящего для рисования основной точки. Единственный способ сделать это - имитировать точку с тем, что у вас есть.
Итак, в основном есть 3 возможных решения:
У каждого из них есть свои недостатки.
Линия
function point(x, y, canvas){
canvas.beginPath();
canvas.moveTo(x, y);
canvas.lineTo(x+1, y+1);
canvas.stroke();
}
Имейте в виду, что мы тянемся к юго-восточному направлению, и если это край, может возникнуть проблема. Но вы также можете рисовать в любом другом направлении.
Прямоугольник
function point(x, y, canvas){
canvas.strokeRect(x,y,1,1);
}
или быстрее, используя fillRect, потому что движок визуализации просто заполнит один пиксель.
function point(x, y, canvas){
canvas.fillRect(x,y,1,1);
}
круг
Одна из проблем с кругами заключается в том, что двигателю сложнее отображать их
function point(x, y, canvas){
canvas.beginPath();
canvas.arc(x, y, 1, 0, 2 * Math.PI, true);
canvas.stroke();
}
та же идея, что и прямоугольник, который вы можете достичь с помощью заливки.
function point(x, y, canvas){
canvas.beginPath();
canvas.arc(x, y, 1, 0, 2 * Math.PI, true);
canvas.fill();
}
Проблемы со всеми этими решениями:
Если вам интересно, что лучший способ нарисовать точку, я бы пошел с заполненным прямоугольником. Вы можете увидеть здесь jsperf с сравнительными тестами
В моем Firefox этот трюк работает:
function SetPixel(canvas, x, y)
{
canvas.beginPath();
canvas.moveTo(x, y);
canvas.lineTo(x+0.4, y+0.4);
canvas.stroke();
}
Небольшое смещение не отображается на экране, но заставляет механизм рендеринга фактически нарисовать точку.
Вышеупомянутое утверждение: "Если вы планируете рисовать много пикселей, гораздо эффективнее использовать данные изображения на холсте для рисования пикселов", кажется, совершенно неверно - по крайней мере, с Chrome 31.0.1650.57 м или в зависимости от вашего определения "много пикселей". Я бы предпочел прокомментировать прямо на соответствующую запись, но, к сожалению, у меня еще не хватает точек stackoverflow:
Я думаю, что я рисую "много пикселей", и поэтому я сначала внимательно следил за соответствующими советами. Позже я изменил свою реализацию на простой ctx.fillRect(..) для каждой нарисованной точки, см. http://www.wothke.ch/webgl_orbittrap/Orbittrap.htm
Интересно, что глупая реализация ctx.fillRect() в моем примере фактически по крайней мере в два раза быстрее, чем метод двойной буферизации на основе ImageData.
По крайней мере, для моего сценария кажется, что встроенная ctx.getImageData/ctx.putImageData на самом деле невероятно медленная. (Было бы интересно узнать процент пикселей, которые нужно коснуться до того, как подход на основе ImageData может взять на себя инициативу.)
Заключение: если вам нужно оптимизировать производительность, вам нужно профилировать свой код и действовать на ВАШИХ результатах.
Это должно выполнить задание
//get a reference to the canvas
var ctx = $('#canvas')[0].getContext("2d");
//draw a dot
ctx.beginPath();
ctx.arc(20, 20, 10, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();