Why I can't clear a canvas with another empty canvas in HTML5?











up vote
3
down vote

favorite












const buffer = document.createElement('canvas');
const context = buffer.getContext('2d');
const canvas = document.getElementById('canvas');
const screen = canvas.getContext('2d');
// buffer canvas and screen canvas have same width and height

// draw a circle on buffer canvas
context.beginPath();
context.arc(50, 50, 10, 0, Math.PI * 2);
context.fillStyle = 'rgba(156, 39, 176,1)';
context.fill();

// render to screen canvas (working)
screen.drawImage(buffer, 0, 0);

// clear canvas when click
canvas.addEventListener('click', () => {
context.clearRect(0, 0, buffer.width, buffer.height);
screen.drawImage(buffer, 0, 0); // not working
// only working with `screen.clearRect(0, 0, canvas.width, canvas.height);`
})


Like the code above, when using an empty canvas to clear another canvas, it's not working. (HTML only with <canvas id="canvas"></canvas> tag). Live Demo on https://jsfiddle.net/wjvtzng7/










share|improve this question






















  • In javaScript you only get a reference of your objects. if you have 2 of them, you have 2 exact the same object, if you change the one, then you changed the other too. That is the reason why your function not work like you think.
    – episch
    yesterday










  • HTML5 only allow one canvas instance?
    – sabertazimi
    yesterday












  • buffer and canvas refer to different <canvas> instances in above code
    – sabertazimi
    yesterday












  • No that was not what I meant. I mean in your JavaScript this is const buffer = document.createElement ('canvas'); const canvas = document.getElementById ('canvas'); takes care of the buffer and canvas are both references from the same canvas, all changes to buffer or canvas, directly affect both variables, which is just a reference of the objects in there.
    – episch
    yesterday






  • 2




    fillRect doesn't truly clear buffer and canvas (It works in line 14 too).
    – sabertazimi
    yesterday















up vote
3
down vote

favorite












const buffer = document.createElement('canvas');
const context = buffer.getContext('2d');
const canvas = document.getElementById('canvas');
const screen = canvas.getContext('2d');
// buffer canvas and screen canvas have same width and height

// draw a circle on buffer canvas
context.beginPath();
context.arc(50, 50, 10, 0, Math.PI * 2);
context.fillStyle = 'rgba(156, 39, 176,1)';
context.fill();

// render to screen canvas (working)
screen.drawImage(buffer, 0, 0);

// clear canvas when click
canvas.addEventListener('click', () => {
context.clearRect(0, 0, buffer.width, buffer.height);
screen.drawImage(buffer, 0, 0); // not working
// only working with `screen.clearRect(0, 0, canvas.width, canvas.height);`
})


Like the code above, when using an empty canvas to clear another canvas, it's not working. (HTML only with <canvas id="canvas"></canvas> tag). Live Demo on https://jsfiddle.net/wjvtzng7/










share|improve this question






















  • In javaScript you only get a reference of your objects. if you have 2 of them, you have 2 exact the same object, if you change the one, then you changed the other too. That is the reason why your function not work like you think.
    – episch
    yesterday










  • HTML5 only allow one canvas instance?
    – sabertazimi
    yesterday












  • buffer and canvas refer to different <canvas> instances in above code
    – sabertazimi
    yesterday












  • No that was not what I meant. I mean in your JavaScript this is const buffer = document.createElement ('canvas'); const canvas = document.getElementById ('canvas'); takes care of the buffer and canvas are both references from the same canvas, all changes to buffer or canvas, directly affect both variables, which is just a reference of the objects in there.
    – episch
    yesterday






  • 2




    fillRect doesn't truly clear buffer and canvas (It works in line 14 too).
    – sabertazimi
    yesterday













up vote
3
down vote

favorite









up vote
3
down vote

favorite











const buffer = document.createElement('canvas');
const context = buffer.getContext('2d');
const canvas = document.getElementById('canvas');
const screen = canvas.getContext('2d');
// buffer canvas and screen canvas have same width and height

// draw a circle on buffer canvas
context.beginPath();
context.arc(50, 50, 10, 0, Math.PI * 2);
context.fillStyle = 'rgba(156, 39, 176,1)';
context.fill();

// render to screen canvas (working)
screen.drawImage(buffer, 0, 0);

// clear canvas when click
canvas.addEventListener('click', () => {
context.clearRect(0, 0, buffer.width, buffer.height);
screen.drawImage(buffer, 0, 0); // not working
// only working with `screen.clearRect(0, 0, canvas.width, canvas.height);`
})


Like the code above, when using an empty canvas to clear another canvas, it's not working. (HTML only with <canvas id="canvas"></canvas> tag). Live Demo on https://jsfiddle.net/wjvtzng7/










share|improve this question













const buffer = document.createElement('canvas');
const context = buffer.getContext('2d');
const canvas = document.getElementById('canvas');
const screen = canvas.getContext('2d');
// buffer canvas and screen canvas have same width and height

// draw a circle on buffer canvas
context.beginPath();
context.arc(50, 50, 10, 0, Math.PI * 2);
context.fillStyle = 'rgba(156, 39, 176,1)';
context.fill();

// render to screen canvas (working)
screen.drawImage(buffer, 0, 0);

// clear canvas when click
canvas.addEventListener('click', () => {
context.clearRect(0, 0, buffer.width, buffer.height);
screen.drawImage(buffer, 0, 0); // not working
// only working with `screen.clearRect(0, 0, canvas.width, canvas.height);`
})


Like the code above, when using an empty canvas to clear another canvas, it's not working. (HTML only with <canvas id="canvas"></canvas> tag). Live Demo on https://jsfiddle.net/wjvtzng7/







javascript html html5 canvas html5-canvas






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked yesterday









sabertazimi

274




274












  • In javaScript you only get a reference of your objects. if you have 2 of them, you have 2 exact the same object, if you change the one, then you changed the other too. That is the reason why your function not work like you think.
    – episch
    yesterday










  • HTML5 only allow one canvas instance?
    – sabertazimi
    yesterday












  • buffer and canvas refer to different <canvas> instances in above code
    – sabertazimi
    yesterday












  • No that was not what I meant. I mean in your JavaScript this is const buffer = document.createElement ('canvas'); const canvas = document.getElementById ('canvas'); takes care of the buffer and canvas are both references from the same canvas, all changes to buffer or canvas, directly affect both variables, which is just a reference of the objects in there.
    – episch
    yesterday






  • 2




    fillRect doesn't truly clear buffer and canvas (It works in line 14 too).
    – sabertazimi
    yesterday


















  • In javaScript you only get a reference of your objects. if you have 2 of them, you have 2 exact the same object, if you change the one, then you changed the other too. That is the reason why your function not work like you think.
    – episch
    yesterday










  • HTML5 only allow one canvas instance?
    – sabertazimi
    yesterday












  • buffer and canvas refer to different <canvas> instances in above code
    – sabertazimi
    yesterday












  • No that was not what I meant. I mean in your JavaScript this is const buffer = document.createElement ('canvas'); const canvas = document.getElementById ('canvas'); takes care of the buffer and canvas are both references from the same canvas, all changes to buffer or canvas, directly affect both variables, which is just a reference of the objects in there.
    – episch
    yesterday






  • 2




    fillRect doesn't truly clear buffer and canvas (It works in line 14 too).
    – sabertazimi
    yesterday
















In javaScript you only get a reference of your objects. if you have 2 of them, you have 2 exact the same object, if you change the one, then you changed the other too. That is the reason why your function not work like you think.
– episch
yesterday




In javaScript you only get a reference of your objects. if you have 2 of them, you have 2 exact the same object, if you change the one, then you changed the other too. That is the reason why your function not work like you think.
– episch
yesterday












HTML5 only allow one canvas instance?
– sabertazimi
yesterday






HTML5 only allow one canvas instance?
– sabertazimi
yesterday














buffer and canvas refer to different <canvas> instances in above code
– sabertazimi
yesterday






buffer and canvas refer to different <canvas> instances in above code
– sabertazimi
yesterday














No that was not what I meant. I mean in your JavaScript this is const buffer = document.createElement ('canvas'); const canvas = document.getElementById ('canvas'); takes care of the buffer and canvas are both references from the same canvas, all changes to buffer or canvas, directly affect both variables, which is just a reference of the objects in there.
– episch
yesterday




No that was not what I meant. I mean in your JavaScript this is const buffer = document.createElement ('canvas'); const canvas = document.getElementById ('canvas'); takes care of the buffer and canvas are both references from the same canvas, all changes to buffer or canvas, directly affect both variables, which is just a reference of the objects in there.
– episch
yesterday




2




2




fillRect doesn't truly clear buffer and canvas (It works in line 14 too).
– sabertazimi
yesterday




fillRect doesn't truly clear buffer and canvas (It works in line 14 too).
– sabertazimi
yesterday












1 Answer
1






active

oldest

votes

















up vote
1
down vote



accepted










If we write down what you are doing, we get:



One offscreen canvas "buffer", and one visible canvas "screen".



Step by step,





  • draw a circle on "buffer"

    At this stage


    • "buffer" represents a circle,

    • "screen" represents an empty image (transparent pixels).




  • draw "buffer" on "screen" canvas


    • "buffer" represents a circle,

    • "screen" represents a circle




  • clear "buffer"


    • "buffer" represents an empty image (transparent pixels)

    • "screen" represents a circle




  • draw "buffer" on "screen" canvas


    • "buffer" represents an empty image (transparent pixels)

    • "screen" represents a circle




It seems your confusion comes from the last bullet. But this operation could be rewritten as




  • draw an empty image (transparent pixels) to an image that represents a circle.


This indeed does nothing... at least in normal compositing mode source-over where drawing a fully transparent pixel does nothing. See alpha-compositing for more reads about it.



So if you wish to clear your "screen" canvas, you indeed need to clear it using the clearRect() method of the screen context. There are other ways, but don't use them.







Now, I felt I should also point out that there are other compositing modes than source-over available, and that what you expected can actually be done with one of these: copy.






const buffer = document.createElement('canvas');
const context = buffer.getContext('2d');
const canvas = document.getElementById('canvas');
const screen = canvas.getContext('2d');

// initialize
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
buffer.width = window.innerWidth;
buffer.height = window.innerHeight;
// draw a circle
context.beginPath();
context.arc(50, 50, 10, 0, Math.PI * 2);
context.fillStyle = 'rgba(156, 39, 176,1)';
context.fill();

// render to screen canvas
screen.drawImage(buffer, 0, 0);

// clear canvas when click
canvas.addEventListener('click', () => {
context.clearRect(0, 0, buffer.width, buffer.height);
// only the next drawing operation on screen will be visible
// everything else will get cleared out
screen.globalCompositeOperation = "copy";
screen.drawImage(buffer, 0, 0);
// set back to default mode
screen.globalCompositeOperation = "sourc-over";
})

<canvas id="canvas"></canvas>








share|improve this answer





















  • Awesome! Have learned compositing modes
    – sabertazimi
    19 hours ago











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53265265%2fwhy-i-cant-clear-a-canvas-with-another-empty-canvas-in-html5%23new-answer', 'question_page');
}
);

Post as a guest
































1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote



accepted










If we write down what you are doing, we get:



One offscreen canvas "buffer", and one visible canvas "screen".



Step by step,





  • draw a circle on "buffer"

    At this stage


    • "buffer" represents a circle,

    • "screen" represents an empty image (transparent pixels).




  • draw "buffer" on "screen" canvas


    • "buffer" represents a circle,

    • "screen" represents a circle




  • clear "buffer"


    • "buffer" represents an empty image (transparent pixels)

    • "screen" represents a circle




  • draw "buffer" on "screen" canvas


    • "buffer" represents an empty image (transparent pixels)

    • "screen" represents a circle




It seems your confusion comes from the last bullet. But this operation could be rewritten as




  • draw an empty image (transparent pixels) to an image that represents a circle.


This indeed does nothing... at least in normal compositing mode source-over where drawing a fully transparent pixel does nothing. See alpha-compositing for more reads about it.



So if you wish to clear your "screen" canvas, you indeed need to clear it using the clearRect() method of the screen context. There are other ways, but don't use them.







Now, I felt I should also point out that there are other compositing modes than source-over available, and that what you expected can actually be done with one of these: copy.






const buffer = document.createElement('canvas');
const context = buffer.getContext('2d');
const canvas = document.getElementById('canvas');
const screen = canvas.getContext('2d');

// initialize
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
buffer.width = window.innerWidth;
buffer.height = window.innerHeight;
// draw a circle
context.beginPath();
context.arc(50, 50, 10, 0, Math.PI * 2);
context.fillStyle = 'rgba(156, 39, 176,1)';
context.fill();

// render to screen canvas
screen.drawImage(buffer, 0, 0);

// clear canvas when click
canvas.addEventListener('click', () => {
context.clearRect(0, 0, buffer.width, buffer.height);
// only the next drawing operation on screen will be visible
// everything else will get cleared out
screen.globalCompositeOperation = "copy";
screen.drawImage(buffer, 0, 0);
// set back to default mode
screen.globalCompositeOperation = "sourc-over";
})

<canvas id="canvas"></canvas>








share|improve this answer





















  • Awesome! Have learned compositing modes
    – sabertazimi
    19 hours ago















up vote
1
down vote



accepted










If we write down what you are doing, we get:



One offscreen canvas "buffer", and one visible canvas "screen".



Step by step,





  • draw a circle on "buffer"

    At this stage


    • "buffer" represents a circle,

    • "screen" represents an empty image (transparent pixels).




  • draw "buffer" on "screen" canvas


    • "buffer" represents a circle,

    • "screen" represents a circle




  • clear "buffer"


    • "buffer" represents an empty image (transparent pixels)

    • "screen" represents a circle




  • draw "buffer" on "screen" canvas


    • "buffer" represents an empty image (transparent pixels)

    • "screen" represents a circle




It seems your confusion comes from the last bullet. But this operation could be rewritten as




  • draw an empty image (transparent pixels) to an image that represents a circle.


This indeed does nothing... at least in normal compositing mode source-over where drawing a fully transparent pixel does nothing. See alpha-compositing for more reads about it.



So if you wish to clear your "screen" canvas, you indeed need to clear it using the clearRect() method of the screen context. There are other ways, but don't use them.







Now, I felt I should also point out that there are other compositing modes than source-over available, and that what you expected can actually be done with one of these: copy.






const buffer = document.createElement('canvas');
const context = buffer.getContext('2d');
const canvas = document.getElementById('canvas');
const screen = canvas.getContext('2d');

// initialize
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
buffer.width = window.innerWidth;
buffer.height = window.innerHeight;
// draw a circle
context.beginPath();
context.arc(50, 50, 10, 0, Math.PI * 2);
context.fillStyle = 'rgba(156, 39, 176,1)';
context.fill();

// render to screen canvas
screen.drawImage(buffer, 0, 0);

// clear canvas when click
canvas.addEventListener('click', () => {
context.clearRect(0, 0, buffer.width, buffer.height);
// only the next drawing operation on screen will be visible
// everything else will get cleared out
screen.globalCompositeOperation = "copy";
screen.drawImage(buffer, 0, 0);
// set back to default mode
screen.globalCompositeOperation = "sourc-over";
})

<canvas id="canvas"></canvas>








share|improve this answer





















  • Awesome! Have learned compositing modes
    – sabertazimi
    19 hours ago













up vote
1
down vote



accepted







up vote
1
down vote



accepted






If we write down what you are doing, we get:



One offscreen canvas "buffer", and one visible canvas "screen".



Step by step,





  • draw a circle on "buffer"

    At this stage


    • "buffer" represents a circle,

    • "screen" represents an empty image (transparent pixels).




  • draw "buffer" on "screen" canvas


    • "buffer" represents a circle,

    • "screen" represents a circle




  • clear "buffer"


    • "buffer" represents an empty image (transparent pixels)

    • "screen" represents a circle




  • draw "buffer" on "screen" canvas


    • "buffer" represents an empty image (transparent pixels)

    • "screen" represents a circle




It seems your confusion comes from the last bullet. But this operation could be rewritten as




  • draw an empty image (transparent pixels) to an image that represents a circle.


This indeed does nothing... at least in normal compositing mode source-over where drawing a fully transparent pixel does nothing. See alpha-compositing for more reads about it.



So if you wish to clear your "screen" canvas, you indeed need to clear it using the clearRect() method of the screen context. There are other ways, but don't use them.







Now, I felt I should also point out that there are other compositing modes than source-over available, and that what you expected can actually be done with one of these: copy.






const buffer = document.createElement('canvas');
const context = buffer.getContext('2d');
const canvas = document.getElementById('canvas');
const screen = canvas.getContext('2d');

// initialize
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
buffer.width = window.innerWidth;
buffer.height = window.innerHeight;
// draw a circle
context.beginPath();
context.arc(50, 50, 10, 0, Math.PI * 2);
context.fillStyle = 'rgba(156, 39, 176,1)';
context.fill();

// render to screen canvas
screen.drawImage(buffer, 0, 0);

// clear canvas when click
canvas.addEventListener('click', () => {
context.clearRect(0, 0, buffer.width, buffer.height);
// only the next drawing operation on screen will be visible
// everything else will get cleared out
screen.globalCompositeOperation = "copy";
screen.drawImage(buffer, 0, 0);
// set back to default mode
screen.globalCompositeOperation = "sourc-over";
})

<canvas id="canvas"></canvas>








share|improve this answer












If we write down what you are doing, we get:



One offscreen canvas "buffer", and one visible canvas "screen".



Step by step,





  • draw a circle on "buffer"

    At this stage


    • "buffer" represents a circle,

    • "screen" represents an empty image (transparent pixels).




  • draw "buffer" on "screen" canvas


    • "buffer" represents a circle,

    • "screen" represents a circle




  • clear "buffer"


    • "buffer" represents an empty image (transparent pixels)

    • "screen" represents a circle




  • draw "buffer" on "screen" canvas


    • "buffer" represents an empty image (transparent pixels)

    • "screen" represents a circle




It seems your confusion comes from the last bullet. But this operation could be rewritten as




  • draw an empty image (transparent pixels) to an image that represents a circle.


This indeed does nothing... at least in normal compositing mode source-over where drawing a fully transparent pixel does nothing. See alpha-compositing for more reads about it.



So if you wish to clear your "screen" canvas, you indeed need to clear it using the clearRect() method of the screen context. There are other ways, but don't use them.







Now, I felt I should also point out that there are other compositing modes than source-over available, and that what you expected can actually be done with one of these: copy.






const buffer = document.createElement('canvas');
const context = buffer.getContext('2d');
const canvas = document.getElementById('canvas');
const screen = canvas.getContext('2d');

// initialize
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
buffer.width = window.innerWidth;
buffer.height = window.innerHeight;
// draw a circle
context.beginPath();
context.arc(50, 50, 10, 0, Math.PI * 2);
context.fillStyle = 'rgba(156, 39, 176,1)';
context.fill();

// render to screen canvas
screen.drawImage(buffer, 0, 0);

// clear canvas when click
canvas.addEventListener('click', () => {
context.clearRect(0, 0, buffer.width, buffer.height);
// only the next drawing operation on screen will be visible
// everything else will get cleared out
screen.globalCompositeOperation = "copy";
screen.drawImage(buffer, 0, 0);
// set back to default mode
screen.globalCompositeOperation = "sourc-over";
})

<canvas id="canvas"></canvas>








const buffer = document.createElement('canvas');
const context = buffer.getContext('2d');
const canvas = document.getElementById('canvas');
const screen = canvas.getContext('2d');

// initialize
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
buffer.width = window.innerWidth;
buffer.height = window.innerHeight;
// draw a circle
context.beginPath();
context.arc(50, 50, 10, 0, Math.PI * 2);
context.fillStyle = 'rgba(156, 39, 176,1)';
context.fill();

// render to screen canvas
screen.drawImage(buffer, 0, 0);

// clear canvas when click
canvas.addEventListener('click', () => {
context.clearRect(0, 0, buffer.width, buffer.height);
// only the next drawing operation on screen will be visible
// everything else will get cleared out
screen.globalCompositeOperation = "copy";
screen.drawImage(buffer, 0, 0);
// set back to default mode
screen.globalCompositeOperation = "sourc-over";
})

<canvas id="canvas"></canvas>





const buffer = document.createElement('canvas');
const context = buffer.getContext('2d');
const canvas = document.getElementById('canvas');
const screen = canvas.getContext('2d');

// initialize
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
buffer.width = window.innerWidth;
buffer.height = window.innerHeight;
// draw a circle
context.beginPath();
context.arc(50, 50, 10, 0, Math.PI * 2);
context.fillStyle = 'rgba(156, 39, 176,1)';
context.fill();

// render to screen canvas
screen.drawImage(buffer, 0, 0);

// clear canvas when click
canvas.addEventListener('click', () => {
context.clearRect(0, 0, buffer.width, buffer.height);
// only the next drawing operation on screen will be visible
// everything else will get cleared out
screen.globalCompositeOperation = "copy";
screen.drawImage(buffer, 0, 0);
// set back to default mode
screen.globalCompositeOperation = "sourc-over";
})

<canvas id="canvas"></canvas>






share|improve this answer












share|improve this answer



share|improve this answer










answered yesterday









Kaiido

37.2k45295




37.2k45295












  • Awesome! Have learned compositing modes
    – sabertazimi
    19 hours ago


















  • Awesome! Have learned compositing modes
    – sabertazimi
    19 hours ago
















Awesome! Have learned compositing modes
– sabertazimi
19 hours ago




Awesome! Have learned compositing modes
– sabertazimi
19 hours ago


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53265265%2fwhy-i-cant-clear-a-canvas-with-another-empty-canvas-in-html5%23new-answer', 'question_page');
}
);

Post as a guest




















































































Popular posts from this blog

Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

ComboBox Display Member on multiple fields

Is it possible to collect Nectar points via Trainline?