다시 그리기 위해 캔버스를 지우는 방법


1012

합성 작업을 실험하고 캔버스에 이미지를 그린 후 이미지를 제거하고 합성하려고합니다. 어떻게해야합니까?

다른 이미지를 다시 그리려면 캔버스를 지워야합니다. 이것은 한동안 계속 될 수 있으므로 매번 새로운 사각형을 그리는 것이 가장 효율적인 옵션이라고 생각하지 않습니다.

답변:


1292
const context = canvas.getContext('2d');

context.clearRect(0, 0, canvas.width, canvas.height);

42
에 대한주의 clearRect는 필요 어느 쪽 변형되지 않은 상황을, 또는 실제의 경계를 추적.
— Phrogz

7
캔버스 너비를 설정하면 a) 다른 값으로 설정 한 다음 다시 웹킷 호환성을 위해 다시 설정해야 하며 b) 컨텍스트 변환 이 재설정 됩니다 .
— Phrogz

45
폭 트릭을 사용하지 마십시오. 더러운 해킹입니다. JavaScript와 같은 고급 언어에서 원하는 것은 의도를 가장 잘 표현한 다음 하위 수준의 코드가이를 달성하도록하는 것입니다. 너비를 자체로 설정해도 캔버스를 지우는 진정한 의도 는 아닙니다 .
— andrewrk

22
완전히 사소한 제안이지만 제안 context.clearRect(0, 0, context.canvas.width, context.canvas.height)합니다. 그것은 사실상 같은 것이지만 하나의 의존성이 적습니다 (2 대신 1 변수)
— gman

6
이 답변의 최근 독자 : 이 답변이 수정되었으며 위의 설명 중 일부가 더 이상 적용되지 않는다는 점에 유의하십시오 .
— daveslab

719

사용하다: context.clearRect(0, 0, canvas.width, canvas.height);

전체 캔버스를 지우는 가장 빠르고 설명적인 방법입니다.

사용하지 마세요: canvas.width = canvas.width;

재설정 canvas.width하면 모든 캔버스 상태 (예 : 변환, lineWidth, strokeStyle 등)가 재설정 되며 매우 느리고 (clearRect와 비교하여) 모든 브라우저에서 작동하지 않으며 실제로 수행하려는 작업을 설명하지 않습니다.

변환 된 좌표 다루기

당신은 변환 행렬을 수정 한 경우 (예를 들어, 사용 scale, rotate또는 translate다음) context.clearRect(0,0,canvas.width,canvas.height)가능성이 캔버스의 전체 보이는 부분을 취소하지 않습니다.

해결책? 캔버스를 지우기 전에 변환 매트릭스를 재설정하십시오.

// Store the current transformation matrix
context.save();

// Use the identity matrix while clearing the canvas
context.setTransform(1, 0, 0, 1, 0, 0);
context.clearRect(0, 0, canvas.width, canvas.height);

// Restore the transform
context.restore();

편집 : 방금 프로파일을 작성했으며 (Chrome에서는) 변환을 재설정하지 않고 300x150 (기본 크기) 캔버스를 지우는 것이 약 10 % 빠릅니다. 캔버스 크기가 커질수록이 차이는 줄어 듭니다.

그것은 이미 상대적으로 중요하지 않지만 대부분의 경우 당신이 지우는 것보다 훨씬 더 많은 그림을 그릴 것입니다.이 성능 차이는 관련이 없다고 생각합니다.

100000 iterations averaged 10 times:
1885ms to clear
2112ms to reset and clear

4
@YumYumYum : clear ()가 표준 함수입니까? 아닌 것 같습니다.
— nobar

7
대신 canvas사용하여 지역 변수 의 필요성을 제거 할 수 있습니다 ctx.canvas.
— Drew Noakes

1
@DrewNoakes, 좋은 지적이지만, 거의 항상 속도 목적을 위해 별도의 변수를 선택합니다. 극도로 작지만 자주 사용하는 속성 (특히 애니메이션 루프 내부)의 별칭을 지정하여 역 참조 시간을 피하려고합니다.
— Prestaul


변환 행렬 수정의 경우에 전체 캔버스를 취소하는 또 다른 방법은 단순히 변환을 추적하고 그들에게 자신을 적용하는 것입니다 canvas.width및 canvas.height청소 때. 변환 재설정과 비교하여 런타임 차이에 대한 수치 분석을 수행하지 않았지만 약간 더 나은 성능을 낼 것으로 생각됩니다.
— NanoWizard

226

선을 그리는 경우 다음을 잊지 마십시오.

context.beginPath();

그렇지 않으면 줄이 지워지지 않습니다.


10
나는 이것이 한동안 여기에 있었음을 알고 있으며,이 모든 시간 후에 주석을 달리는 것은 아마도 어리석은 일이지만, 이것은 1 년 동안 나를 괴롭 혔습니다 ... 당신이 새로운 길을 시작할 때 전화beginPath 하십시오. 기존 경로를 지우려는 캔버스를 지우고 있습니다! 이것은 끔찍한 관행이며 그림을 거꾸로 보는 방법입니다.
— Prestaul

캔버스의 모든 것을 지우려면 어떻게해야합니까? 게임을 만들고 있으며 수백 분의 1 초마다 화면을 다시 그려야한다고 가정 해 보겠습니다.

1
@JoseQuinones beginPath는 캔버스에서 아무것도 지우지 않고 경로를 재설정하여 이전 경로 항목을 그리기 전에 제거합니다. 아마도 필요할 수도 있지만 그리기 작업으로, 지우기 작업이 아닙니다. clear, beginPath 및 draw, clear 및 beginPath, draw하지 마십시오. 차이가 의미가 있습니까? 예를 보려면 여기를보십시오 : w3schools.com/tags/canvas_beginpath.asp
— Prestaul

1
이것은 시간이 지남에 따라 경험 한 애니메이션의 속도 저하를 해결했습니다. 모든 단계에서 그리드 선을 다시 그렸지만 이전 단계에서 선을 지우지 않았습니다.
— Georg Patscheider

118

다른 사람들은 이미 질문에 대답하는 훌륭한 일을했지만 clear()컨텍스트 객체에 대한 간단한 방법이 당신에게 유용 하다면 (나에게) 이것이 여기에 대한 답변을 기반으로 사용하는 구현입니다.

CanvasRenderingContext2D.prototype.clear = 
  CanvasRenderingContext2D.prototype.clear || function (preserveTransform) {
    if (preserveTransform) {
      this.save();
      this.setTransform(1, 0, 0, 1, 0, 0);
    }

    this.clearRect(0, 0, this.canvas.width, this.canvas.height);

    if (preserveTransform) {
      this.restore();
    }           
};

용법:

window.onload = function () {
  var canvas = document.getElementById('canvasId');
  var context = canvas.getContext('2d');

  // do some drawing
  context.clear();

  // do some more drawing
  context.setTransform(-1, 0, 0, 1, 200, 200);
  // do some drawing with the new transform
  context.clear(true);
  // draw more, still using the preserved transform
};

6
이것은 훌륭한 구현입니다. 네이티브 프로토 타입 향상을 완벽하게 지원하지만, 할당하기 전에 "클리어"가 정의되지 않았는지 확인하고 싶을 수도 있습니다. 언젠가 네이티브 구현을 기대하고 있습니다. :) 브라우저가 CanvasRenderingContext2D를 얼마나 광범위하게 지원하고 "쓰기 가능"상태로 두는지 알고 있습니까?
— Prestaul

피드백 @Prestaul에 감사드립니다-또한 브라우저 가이 방식으로 자바 스크립트 객체를 확장하지 못하게해서는 안됩니다.
— JonathanK

@JonathanK, 나는 변환을 재설정하지 않고 지우는 것 사이의 성능 차이에 대한 프로파일 링을보고 싶습니다. 나는 당신이 작은 그림을하고 있다면 차이가 분명 할 것이라고 생각하지만 당신이 그리는 것이 사소한 것이 아니라면 명확한 단계는 무시할 수 있습니다 ... 나중에 더 많은 시간이있을 때 테스트해야 할 수도 있습니다 :)
— Prestaul

좋아, 나는 프로파일 링을했고 내 게시물에 세부 사항을 추가 할 것입니다.
— Prestaul

35
  • Chrome은 context.clearRect ( x , y , w , h );@ Pentium10에서 제안한대로 잘 응답 하지만 IE9는이 지침을 완전히 무시하는 것 같습니다.
  • IE9는 다음과 같이 응답하는 것 같습니다. canvas.width = canvas.width;하지만 먼저 너비를 변경하는 @John Allsopp의 솔루션을 사용하지 않으면 선, 모양, 그림 및 기타 개체가 명확하지 않습니다.

따라서 캔버스와 컨텍스트가 다음과 같이 생성 된 경우 :

var canvas = document.getElementById('my-canvas');
var context = canvas.getContext('2d');

다음과 같은 방법을 사용할 수 있습니다.

function clearCanvas(context, canvas) {
  context.clearRect(0, 0, canvas.width, canvas.height);
  var w = canvas.width;
  canvas.width = 1;
  canvas.width = w;
}

13
컨텍스트 만 전달하고을 사용하여 메소드를 단순화 할 수 있습니다 context.clearRect(0,0,context.canvas.width,context.canvas.height).
— Phrogz

5
IE 9는 clearRect 호출에 절대적으로 응답해야합니다 ... ( msdn.microsoft.com/en-us/library/ff975407(v=vs.85).aspx 참조 ) canvas.width를 변경하는 속도가 느린 유일한 방법 두 번 변경하고 clearRect를 호출하면 속도가 느려질 수 있습니다.
— Prestaul

1
죄송합니다. 더 명확 해져야합니다 ...이 방법은 (변환을 적용하지 않는 한) 작동하지만 필요하지 않은 [느린] 무차별 대입 기술입니다. clearRect를 사용하는 것이 가장 빠르며 캔버스를 구현하는 모든 브라우저에서 작동해야합니다.
— Prestaul

1
나는 IE가 여전히 경로 버퍼에 있기 때문에 라인을 다시 그리는 것으로 생각합니다. 나는이 형식을 사용하고 완벽하게 작동합니다. function clearCanvas(ctx) { ctx.beginPath(); ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); }
— DarrenMB

나는이 전에 각각의 모든 방법을 시도했지만 ...이 유일한 방법이었습니다. 선, 사각형 및 텍스트와 함께 Chrome을 사용하고 있습니다 ... 내장해야 할 일을 너무 어렵게 생각하지 않았을 것입니다! 감사!
— Anthony Griggs

26

이것은 2018이지만 여전히 다시 그리기 위해 캔버스를 완전히 지우는 기본 방법은 없습니다. 캔버스를 완전히 지우지 clearRect() 않습니다 . 비 채우기 형식의 도면은 밖으로 삭제되지 않습니다 (예. rect())

1. 그리는 방법에 관계없이 캔버스를 완전히 지우려면 :

context.clearRect(0, 0, context.canvas.width, context.canvas.height);
context.beginPath();

장점 : strokeStyle, fillStyle 등을 유지합니다. 지연이 없습니다.

단점 : 무언가를 그리기 전에 이미 beginPath를 사용하는 경우 불필요

2. 너비 / 높이 핵 사용 :

context.canvas.width = context.canvas.width;

또는

context.canvas.height = context.canvas.height;

장점 : IE와 함께 작동 단점 : strokeStyle, fillStyle을 검은 색으로 재설정합니다. 게으른;

네이티브 솔루션이 존재하지 않는 이유가 궁금합니다. 실제로 clearRect()대부분의 사용자는 beginPath()새로운 경로를 그리기 전에 수행 하기 때문에 단일 회선 솔루션으로 간주됩니다 . beginPath는 선을 그릴 때만 사용되며 닫힌 경로는 아닙니다.rect().

이것이 받아 들여진 대답이 내 문제를 해결하지 못한 이유이며 다른 해킹을 시도하는 데 몇 시간을 낭비했습니다. 모질라 저주


나는 이것이 캔버스 그리기에 대한 정답이라고 생각합니다. beginPath가 도움이되는 동안 clearRect를 호출하는 방법에 관계없이 context.stroke가 남아 있습니다.
— Shao-Kui

20

x, y 좌표와 캔버스의 높이와 너비를 전달하여 clearRect 메소드를 사용하십시오. ClearRect는 전체 캔버스를 다음과 같이 지 웁니다.

canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);

이것을 메소드에 넣고 화면을 새로 고칠 때마다 호출하면됩니다.

에 @ XXX.xxx PLZ 캔버스의 ID를 확인하여 HTML과 첫 번째 줄에 동일한 사용 (ID로 요소를 얻을 수 있습니다)
— VISHWAS

14

여기에 좋은 대답이 많이 있습니다. 또 다른 참고 사항은 때때로 캔버스를 부분적으로 만 지우는 것이 재미 있다는 것입니다. 즉, 이전 이미지를 완전히 지우는 대신 "페이드 아웃"합니다. 이것은 좋은 트레일 효과를 줄 수 있습니다.

그것은 간단합니다. 배경색이 흰색이라고 가정합니다.

// assuming background color = white and "eraseAlpha" is a value from 0 to 1.
myContext.fillStyle = "rgba(255, 255, 255, " + eraseAlpha + ")";
myContext.fillRect(0, 0, w, h);

나는 그것이 가능하다는 것을 알고 당신의 대답에 아무런 문제가 없습니다. 움직이는 것, 당신이 움직이는 2 개의 물체가 있고 그중 하나만 트레일하고 싶다면 어떻게 할 것입니까?
— super

그것은 훨씬 더 복잡한 거래입니다. 이 경우 오프 스크린 캔버스를 작성해야하며 각 프레임은 여기에 설명 된 부분 지우기 방법을 사용하여 해당 캔버스에 추적 할 오브젝트를 그리고 각 프레임은 기본 캔버스를 100 % 지우고 비트 레일 드를 그립니다. 그런 다음 drawImage ()를 사용하여 오프 스크린 캔버스를 기본 캔버스에 합성합니다. 또한 globalCompositeOperation을 이미지에 적합한 것으로 설정해야합니다. 예를 들어 "곱하기"는 밝은 배경의 어두운 물체에 적합합니다.
— 오리온 엘렌 질

12

빠른 방법은

canvas.width = canvas.width

작동 방식은 Idk이지만 작동합니다!


와. 이것은 실제로 작동합니다. 어떻게 이것을 찾았습니까?
— zipzit

@zipit 일반적인 비운 후에도 medium.com에서 찾은 빠른 트릭은 렌더링되지 않았습니다 :)
— Jacob Morris

1
왜 이것이 효과가 있는지 알아 내려고 머리를 당기고 있습니다! 공유해 주셔서 감사합니다!
— aabbccsmith

누구나 왜 그것이 작동하는지, 심지어 canvas.width + = 0도 그 일을하는지 설명 할 수 있습니까?이 뒤에 숨겨진 과학은 무엇입니까?
— PYK

8

이것은 경계 및 행렬 변환에 관계없이 내가 사용하는 것입니다.

function clearCanvas(canvas) {
  const ctx = canvas.getContext('2d');
  ctx.save();
  ctx.globalCompositeOperation = 'copy';
  ctx.strokeStyle = 'transparent';
  ctx.beginPath();
  ctx.lineTo(0, 0);
  ctx.stroke();
  ctx.restore();
}

기본적으로 컨텍스트의 현재 상태를 저장하고 copyas로 투명 픽셀을 그립니다 globalCompositeOperation. 그런 다음 이전 컨텍스트 상태를 복원합니다.


그것은 나를 위해 작동합니다 ...! 감사.
— NomanJaved

6

이것은 chart.js의 pieChart에서 작동했습니다.

<div class="pie_nut" id="pieChartContainer">
    <canvas id="pieChart" height="5" width="6"></canvas> 
</div>

$('#pieChartContainer').html(''); //remove canvas from container
$('#pieChartContainer').html('<canvas id="pieChart" height="5" width="6"></canvas>'); //add it back to the container

5

테스트 한 모든 브라우저에서 가장 빠른 방법은 실제로 흰색 또는 원하는 색상으로 채우는 것입니다. 나는 매우 큰 모니터를 가지고 있으며 전체 화면 모드에서 clearRect는 느리게 느리지 만 fillRect는 합리적입니다.

context.fillStyle = "#ffffff";
context.fillRect(0,0,canvas.width, canvas.height);

단점은 캔버스가 더 이상 투명하지 않다는 것입니다.


4

웹킷에서 너비를 다른 값으로 설정 한 다음 다시 초기 값으로 설정할 수 있습니다


4
function clear(context, color)
{
    var tmp = context.fillStyle;
    context.fillStyle = color;
    context.fillRect(0, 0, context.canvas.width, context.canvas.height);
    context.fillStyle = tmp;
}

이것은 clearRect (0,0, canvas.width, canvas.height)보다 느립니다
— sEver

4

간단하지만 읽기 쉽지 않은 방법은 다음과 같습니다.

var canvas = document.getElementId('canvas');

// after doing some rendering

canvas.width = canvas.width;  // clear the whole canvas

2

나는 항상 사용

cxt.fillStyle = "rgb(255, 255, 255)";
cxt.fillRect(0, 0, canvas.width, canvas.height);

이것이 가장 쉬운 방법입니다! 글쎄, 적어도 나를 위해.
— Jacques Olivier

1
context.clearRect(0,0,w,h)   

주어진 사각형을 RGBA 값으로 채 웁니다 : 000
0 : Chrome으로
0 255 255 : FF & Safari로

그러나

context.clearRect(0,0,w,h);    
context.fillStyle = 'rgba(0,0,0,1)';  
context.fillRect(0,0,w,h);  

브라우저에 관계없이 사각형을
0 0 0 255로
채 웁니다!


1
Context.clearRect(starting width, starting height, ending width, ending height);

예: context.clearRect(0, 0, canvas.width, canvas.height);



0

가장 빠른 방법 :

canvas = document.getElementById("canvas");
c = canvas.getContext("2d");

//... some drawing here

i = c.createImageData(canvas.width, canvas.height);
c.putImageData(i, 0, 0); // clear context by putting empty image data

12
와우 ... 어떤 브라우저에서? 내 경우 (OS X의 Chrome 22 및 Firefox 14) 귀하의 방법은 훨씬 느린 옵션입니다. jsperf.com/canvas-clear-speed/9
— Prestaul

1
> 5 년이 지난 후에도이 방법은 ~ 700 배 더 느린 매우 큰 방법으로 여전히 가장 느린 방법 clearRect입니다.
— mgthomas99

0

clearRect 만 사용하는 경우 도면을 제출하기위한 양식이있는 경우 지우기 대신 제출을 받거나 먼저 지운 후 빈 도면을 업로드 할 수 있으므로 추가해야합니다. 함수 시작시 preventDefault :

   function clearCanvas(canvas,ctx) {
        event.preventDefault();
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    }


<input type="button" value="Clear Sketchpad" id="clearbutton" onclick="clearCanvas(canvas,ctx);">

그것이 누군가를 돕기를 바랍니다.


0

나는 항상 이것을 사용한다

ctx.clearRect(0, 0, canvas.width, canvas.height)
window.requestAnimationFrame(functionToBeCalled)

노트

clearRect와 requestAnimationFrame을 결합하면 원하는 애니메이션을보다 유동적으로 만들 수 있습니다.


-2

다음은 표준 캔버스를 지우는 방법에 대한 훌륭한 예이지만 paperjs를 사용하는 경우 작동합니다.

JavaScript에서 전역 변수를 정의하십시오.

var clearCanvas = false;

PaperScript에서 다음을 정의하십시오.

function onFrame(event){
    if(clearCanvas && project.activeLayer.hasChildren()){
        project.activeLayer.removeChildren();
        clearCanvas = false;
    }
}

이제 clearCanvas를 true로 설정하면 화면에서 모든 항목이 지워집니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.