Issue
It's really strange that it works when globalCompositeOperation is 'source-atop',but it fails when globalCompositeOperation is ''destination-atop'.It seems that different types of words can not be showed together.Here is code snippet.
window.requestAnimationFrame(draw);
let FirstTime=Date.now();
function draw(){
var canvas = document.getElementById("myCanvas");
const width_mid=canvas.width/2;
const height_mid=canvas.height/2;
var timeStamp=Date.now();
var num=Math.floor((timeStamp-FirstTime)/300);
if(num>15)
return;
var ctx = canvas.getContext("2d");
ctx.font = "200px 华文行楷";
ctx.textAlign="center";
ctx.fillText("CHH算法网",width_mid,height_mid+40);
// ctx.globalCompositeOperation='source-atop';
ctx.globalCompositeOperation='destination-atop';
ctx.beginPath();
ctx.moveTo(0,300);
ctx.quadraticCurveTo(70,100,200,70);
var end_x=200;
var bezier_x;
for(var i=0;i<num;i++){
if(i%2==0){
end_x+=10;
bezier_x=end_x+100;
}
else{
end_x+=200;
bezier_x=end_x-130;
}
ctx.quadraticCurveTo(bezier_x,i%2?100:100,end_x,i%2?70:280);
}
ctx.strokeStyle="white";
ctx.lineWidth=200;
ctx.stroke();
window.requestAnimationFrame(draw);
}
body{
background-color: rgb(255, 213, 0);
}
#btn{
text-align: center;
position: relative;
left:40%;
top:70px;
width: 200px;
height: 100px;
border-radius: 200px;
color:white;
background-color: rgb(25, 99, 145);
font-size: 30px;
font-family:"Lucida Sans Typewriter";
border:none;
}
#btn:hover{
color:rgb(25, 99, 145);
background-color: white;
}
<canvas id="myCanvas" width="1300px" height="300px"></canvas>
I changed the globalCompositeOperation,finding that only one type of words could be showed if globalCompositeOperation is 'destination-atop'.What I was hoping to do is to use the brush as an eraser to erase the yellow color and the title below it would emerge gradually.
Solution
I am not sure why your issue is limited to Firefox, but the solution here is to simply make sure your context is reset correctly every time you start drawing. I found adding ctx.save()
before doing anything and ctx.restore()
after completing your loop fixes your issue, though I am unsure why it only applies to the CH letters and not the other characters. Either way, it's safe to do so and every browser supports it. It's also good practice to do that anyway to ensure you never wind up in a context where you unsure of the state it is in.
Another issue with this persistent composite operation is that, since you aren't resetting it and you aren't clearing the canvas, the operation is technically applied to the pixels that already exist. It's therefor best to do both: clear your context and clear your canvas. In the snippet below I have done both:
const canvas = document.getElementById( "myCanvas" );
const ctx = canvas.getContext( "2d" );
const width_mid = canvas.width / 2;
const height_mid = canvas.height / 2;
let time = null;
let useSourceAtop = false;
function draw( timeStamp ){
if( time === null ) time = timeStamp;
const num = Math.floor((timeStamp-time)/300);
if( num > 15 ) return;
ctx.save(); // <- save the current state of your context - and since we have made no changes to it, this means save the current, reset context
ctx.clearRect( 0, 0, canvas.width, canvas.height ); // <-- Clear the canvas so you don't draw over the same pixel (this could mess with things such as anti-aliasing as a 50% alpha pixel would continuously get printed, making it more opaque etc)
ctx.font = "200px 华文行楷";
ctx.textAlign = "center";
ctx.fillText( "CHH算法网", width_mid, height_mid+40 );
if( useSourceAtop ) ctx.globalCompositeOperation = 'source-atop';
else ctx.globalCompositeOperation = 'destination-atop';
ctx.beginPath();
ctx.moveTo( 0, 300 );
ctx.quadraticCurveTo( 70, 100, 200, 70 );
let end_x = 200;
let bezier_x;
for( let i = 0; i < num; i++ ){
if( i%2 == 0 ){
end_x += 10;
bezier_x = end_x + 100;
} else {
end_x += 200;
bezier_x = end_x - 130;
}
ctx.quadraticCurveTo(
bezier_x,
i%2 ? 100 : 100,
end_x,
i%2 ? 70 : 280
);
}
ctx.strokeStyle = "white";
ctx.lineWidth = 200;
ctx.stroke();
ctx.restore(); // <-- reset any changes made to your context, like globalCompositeOperation, transforms, lineWidths, colors, etc... to the last time you saved them.
window.requestAnimationFrame( draw );
}
window.requestAnimationFrame( draw );
document.addEventListener( 'dblclick', event => {
event.preventDefault();
useSourceAtop = !useSourceAtop;
time = null;
window.requestAnimationFrame( draw );
});
body {
background-color: rgb(255, 213, 0);
}
canvas {
width: 100%;
}
<canvas id="myCanvas" width="1300px" height="300px"></canvas>
I also took the liberty to add some whitespace to your code, I know, it's a preference first and foremost, but I think legible code with breathing space makes it easier to parse and communicate about it. My eyes don't have to try to recognise the difference between characters smashed together.
Answered By - somethinghere
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.