HTML5 Canvas에는 단일 픽셀을 명시 적으로 설정하는 방법이 없습니다.
매우 짧은 선을 사용하여 픽셀을 설정할 수는 있지만 앤티 앨리어싱 및 선 캡이 방해 될 수 있습니다.
또 다른 방법은 작은 ImageData
객체 를 만들고 다음을 사용하는 것입니다 .
context.putImageData(data, x, y)
그것을 제자리에 두십시오.
누구나 효율적이고 신뢰할 수있는 방법을 설명 할 수 있습니까?
답변
두 가지 최고의 경쟁자가 있습니다.
-
1 × 1 이미지 데이터를 생성하고 색상을 설정
putImageData
하고 위치를 지정하십시오.var id = myContext.createImageData(1,1); // only do this once per page var d = id.data; // only do this once per page d[0] = r; d[1] = g; d[2] = b; d[3] = a; myContext.putImageData( id, x, y );
-
fillRect()
픽셀을 그리는 데 사용 합니다 (별칭 문제가 없어야 함).ctx.fillStyle = "rgba("+r+","+g+","+b+","+(a/255)+")"; ctx.fillRect( x, y, 1, 1 );
http://jsperf.com/setting-canvas-pixel/9 또는 https://www.measurethat.net/Benchmarks/Show/1664/1 에서 속도를 테스트 할 수 있습니다.
최대 속도를 원하는 브라우저에 대해 테스트하는 것이 좋습니다. 2017 년 7 월 현재 fillRect()
Firefox v54 및 Chrome v59 (Win7x64)에서 5-6 배 더 빠릅니다.
다른 대안은 다음과 같습니다.
-
사용하여
getImageData()/putImageData()
전체 캔버스에; 다른 옵션보다 약 100 배 느립니다. -
데이터 URL을 사용하여 사용자 지정 이미지를 만들고
drawImage()
이를 사용 하여 표시 :var img = new Image; img.src = "data:image/png;base64," + myPNGEncoder(r,g,b,a); // Writing the PNGEncoder is left as an exercise for the reader
-
원하는 모든 픽셀로 채워진 다른 이미지 나 캔버스를 만들고 원하는 픽셀
drawImage()
만 블리 팅 하는 데 사용 합니다. 아마도 매우 빠를 것이지만 필요한 픽셀을 미리 계산해야하는 한계가 있습니다.
내 테스트는 캔버스 컨텍스트를 저장 및 복원하지 않습니다 fillStyle
. fillRect()
성능 이 저하 될 수 있습니다. 또한 깨끗한 슬레이트로 시작하거나 각 테스트에 대해 정확히 동일한 픽셀 세트를 테스트하지 않습니다.
답변
언급되지 않은 한 가지 방법은 getImageData를 사용한 다음 putImageData를 사용하는 것입니다.
이 방법은 한 번에 많이 그리기를 원할 때 유용합니다.
http://next.plnkr.co/edit/mfNyalsAR2MWkccr
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
var id = ctx.getImageData(0, 0, canvasWidth, canvasHeight);
var pixels = id.data;
var x = Math.floor(Math.random() * canvasWidth);
var y = Math.floor(Math.random() * canvasHeight);
var r = Math.floor(Math.random() * 256);
var g = Math.floor(Math.random() * 256);
var b = Math.floor(Math.random() * 256);
var off = (y * id.width + x) * 4;
pixels[off] = r;
pixels[off + 1] = g;
pixels[off + 2] = b;
pixels[off + 3] = 255;
ctx.putImageData(id, 0, 0);
답변
나는 고려하지 fillRect()
않았지만, 대답은 그것을 벤치마킹하도록 자극했다 putImage()
.
맥북 프로 (구)에 크롬 9.0.597.84으로, 임의의 위치에서 10 만 개 무작위 색깔의 픽셀을 퍼팅과 100ms의 채 걸리지 putImage()
만, 거의 사용 900ms fillRect()
. ( http://pastebin.com/4ijVKJcC의 벤치 마크 코드 ).
대신 루프 외부에서 단일 색상을 선택하고 임의의 위치에 해당 색상을 플롯하면에 putImage()
대해 59ms 대 102ms가 걸립니다 fillRect()
.
구문에서 CSS 색상 사양을 생성하고 구문 분석하는 오버 헤드가 rgb(...)
대부분의 차이를 담당 하는 것으로 보입니다 .
ImageData
반면에 원시 RGB 값을 블록에 똑바로 넣으면 문자열 처리 또는 구문 분석이 필요하지 않습니다.
답변
function setPixel(imageData, x, y, r, g, b, a) {
var index = 4 * (x + y * imageData.width);
imageData.data[index+0] = r;
imageData.data[index+1] = g;
imageData.data[index+2] = b;
imageData.data[index+3] = a;
}
답변
브라우저마다 다른 방법을 선호하는 것 같으므로 로딩 프로세스의 일부로 세 가지 방법 모두로 더 작은 테스트를 수행하여 어느 것이 가장 적합한 지 알아 낸 다음 응용 프로그램 전체에서 사용하는 것이 합리적 일 수 있습니다.
답변
이상하게 보이지만 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 를 볼 수 있습니다 .
답변
사각형은 어떻습니까? 그것은 ImageData
객체를 만드는 것보다 더 효율적이어야 합니다.