I am getting error about clearRect (canvas in html) - javascript

I want an image to fall from the top and clear the entire canvas when the condition is true. everything is fine until ctx.clearRect(0, 0, c.width, c.height);
inactive. please help me. Thank you in advance. Here is my code
let c = document.getElementById("myCanvas"),
ctx = c.getContext("2d"),
img = new Image;
img.src = "./img/l1.png";
c.width = 300;
c.height = 600;
let s = setInterval(() => {
if (yBlock + Math.max(y1, y2, y3, y4) * 30 > 570) {
clearInterval(s);
yBlock -= 1;
ctx.clearRect(0, 0, c.width, c.height);
}
ctx.clearRect(0, 0, 300, 600);
ctx.beginPath();
ctx.drawImage(img, xBlock * 30, yBlock, xSize, ySize);
ctx.closePath();
yBlock += 1;
},
1);

Related

Is it possible to add shadowblur with clip in canvas?

I am drawing a canvas.
I simplified my code.
There is a transparent circle.
The background is rgba 0,0,0,0.5.
I'd like to add "shadowblur" for the transparent circle. However, it's fail.
Is it possible?
I have another logic:
Create one circle with linear-gradient (rgba 0,0,0,0.5, transparent)
However, it seems no good.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="Preloader">
<canvas id="myCanvas"></canvas>
</div>
<style>
.Preloader {
background-color: #7bf;
}
</style>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
c.width = window.innerWidth;
c.height = window.innerHeight;
class ball {
constructor(x, y) {
this.position = {
x: x,
y: y
}
this.r = 100
}
draw() {
ctx.beginPath();
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, 0, c.width, c.height);
ctx.fill();
ctx.closePath();
ctx.save();
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.r, 0, 2 * Math.PI, false);
ctx.clip();
ctx.clearRect(0, 0, c.width, c.height);
ctx.shadowBlur = 0;
ctx.closePath();
ctx.restore();
}
update() {
this.draw()
this.position.x++
this.position.y++
}
}
var Ball = new ball(c.width / 2, c.height / 2)
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, c.width, c.height);
Ball.update();
};
animate();
</script>
</body>
</html>
If you mean that you want the edges of the clipping-area to be smoother, then you can use compositing to use any bitmap as a mask:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
c.width = window.innerWidth;
c.height = window.innerHeight;
class ball {
constructor(x, y) {
this.position = {
x: x,
y: y
}
this.r = 100
}
draw() {
// fillRect doesn't need beginPath(), and it does fill()
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, 0, c.width, c.height);
// closePath encloses the current subpath
// it doesn't "end" the path declaration
// beginPath does that
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.r, 0, 2 * Math.PI, false);
// we use compositing to create our hole, with shadow:
ctx.globalCompositeOperation = "destination-out";
ctx.shadowBlur = 30;
ctx.shadowColor = "black";
ctx.fillStyle = 'black';
ctx.fill();
// restore
ctx.shadowBlur = 0;
ctx.globalCompositeOperation = "source-over";
}
update() {
this.draw()
this.position.x++
this.position.y++
}
}
var Ball = new ball(c.width / 2, c.height / 2)
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, c.width, c.height);
Ball.update();
};
animate();
.Preloader {
background-color: #7bf;
}
<div class="Preloader">
<canvas id="myCanvas"></canvas>
</div>
This would also work with CanvasGradient instead of shadowBlur:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
c.width = window.innerWidth;
c.height = window.innerHeight;
class ball {
constructor(x, y) {
this.position = {
x: x,
y: y
}
this.r = 100
}
draw() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, 0, c.width, c.height);
ctx.globalCompositeOperation = "destination-out";
ctx.fillStyle = ctx.createRadialGradient(this.position.x, this.position.y, this.r, this.position.x, this.position.y, 0);
ctx.fillStyle.addColorStop(0, "transparent");
ctx.fillStyle.addColorStop(.25, "black");
ctx.fillRect(0, 0, c.width, c.height);
// restore
ctx.globalCompositeOperation = "source-over";
}
update() {
this.draw()
this.position.x++
this.position.y++
}
}
var Ball = new ball(c.width / 2, c.height / 2)
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, c.width, c.height);
Ball.update();
};
animate();
.Preloader {
background-color: #7bf;
}
<div class="Preloader">
<canvas id="myCanvas"></canvas>
</div>
Or even in Chrome and Firefox by using CSS blur filters:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
c.width = window.innerWidth;
c.height = window.innerHeight;
class ball {
constructor(x, y) {
this.position = {
x: x,
y: y
}
this.r = 100
}
draw() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, 0, c.width, c.height);
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.r, 0, 2 * Math.PI, false);
// we use compositing to create our hole, with shadow:
ctx.globalCompositeOperation = "destination-out";
ctx.filter = "blur(15px)";
ctx.fill();
// restore
ctx.filter = "none";
ctx.globalCompositeOperation = "source-over";
}
update() {
this.draw()
this.position.x++
this.position.y++
}
}
var Ball = new ball(c.width / 2, c.height / 2)
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, c.width, c.height);
Ball.update();
};
animate();
.Preloader {
background-color: #7bf;
}
<div class="Preloader">
<canvas id="myCanvas"></canvas>
</div>

How can I change canvas globalAlpha as ctx moves along the X-axis

I have made an audio-player and it has a canvas for its seeklider.
The ctx is the pointer that tracks audio.currentTime.
I am trying to achieve an effect so that when the ctx is moving along the X axis, the canvas before that point should have globalAlpha set to 0.4, and canvas after the ctx set to globalAlpha = 0.6.
<div class="slider-container ">
<canvas id ="canvas" height ="90" width ="300"></canvas>
</div>
//Javascript
//Load canvasbackground image.
function drawbg(){
canvasbackground_index = playlist_index;
canvasbg.src = cdir+canvasbackground[canvasbackground_index]+png;
ctx.drawImage(canvasbg,0,0,canvas.width, canvas.height);
}
//calculate canvas.ctx position on X-axis relative to audio.currentTime
function ctxupdate() {
ct = audio.currentTime * (100 / audio.duration);
ctx.x = (ct/100) * canvas.width;
seekto = ctx.x;
}
//draw a thin vertical rectangle relative to audio.currentTime
function draw() {
ctx.fillStyle = "rgb(250,250,250)";
ctx.fillRect(ctx.x, 0, 1, 90);
ctx.x = ct;
}
//animate canvas
function canvasAnimate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
requestAnimationFrame(canvasAnimate);
drawbg();
ctxupdate();
draw();
}
canvasAnimate();
Would using js instead of css be ok. Something similar to this?
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
canvas.width = 300;
canvas.height= 100;
let pic = new Image();
pic.src="https://static.toiimg.com/photo/72975551.cms"
class Cursor {
constructor(x) {
this.x = x;
}
draw() {
ctx.strokeStyle = "white";
ctx.strokeRect(this.x ,0, 2, 100);
ctx.stroke();
}
update() {
this.x == canvas.width ? this.x = 0 : this.x++
this.draw();
}
}
let cursor = new Cursor(0);
function changeBG() {
ctx.drawImage(pic,0,0,canvas.width,canvas.height);
ctx.fillStyle = "rgba(255, 255, 255, 0.4)"
ctx.fillRect(0, 0, 0 + cursor.x, canvas.height);
ctx.fillStyle = "rgba(255, 255, 255, 0.6)";
ctx.fillRect(0, 0, cursor.x + canvas.width, canvas.height);
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
cursor.update();
changeBG();
requestAnimationFrame(animate);
}
animate();
<canvas id ="canvas" height ="90" width ="300"></canvas>
UPDATE: I took your ctxupdate() function and moved the contents of that to drawbg(). Then I added the fillRect and fillStyle code from above to drawbg(). The stopCanvasbg() is not used but I left it because you had it in there.
So from your sizeCanvas() to your canvasAnimate() here;s what it looks like
function sizecanvas() {
if(window.innerWidth >= 1469) {
canvas.width = 1469
canvas.clientWidth = canvas.width;
} else {
canvas.width = canvas.clientWidth;
}
}
function drawbg(){
ct = audio.currentTime * (100 / audio.duration);
//if (isNaN(ctx.x)) return;
ctx.x = (ct/100) * canvas.width;
seekto = ctx.x;
canvasbackground_index = playlist_index;
canvasbg.src = cdir+canvasbackground[canvasbackground_index]+png;
ctx.drawImage(canvasbg,0,0,canvas.width, canvas.height);
ctx.fillStyle = "rgba(255, 255, 255, 0.6)"
ctx.fillRect(0, 0, 0 + seekto, canvas.height);
ctx.fillStyle = "rgba(255, 255, 255, 0.2)";
ctx.fillRect(0, 0, seekto + canvas.width, canvas.height);
}
function stopCanvasbg(){
canvasbackground_index = (canvasbackground.length -1);
console.log(canvasbackground_index);
canvasbg.src = canvasbackground_index;
ctx.drawImage(canvasbg,0,0,canvas.width, canvas.height);
}
function canvasAnimate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawbg();
requestAnimationFrame(canvasAnimate);
}
canvasAnimate();
See if that works on your end.

why isnt the background clearing the circle?

I want a ball falling, with gravity. But the background won't clear the previous circle. (the falling part isnt implemented yet) why doesnt it erase the last drawn object?
let c, ctx;
let met;
let colorArray = ["green", "yellow", "orange", "red"];
window.onload = function(){
c = document.getElementById("boom");
ctx = c.getContext("2d");
c.width = window.innerWidth - 165;
c.height = window.innerHeight;
setup();
draw();
}
function setup(){
met = new Meteor(200, 400, 10, 0, 5);
}
function draw(){
window.requestAnimationFrame(draw);
ctx.fillStyle = colorArray[Math.floor(Math.random() * colorArray.length)];
ctx.fillRect(0, 0, c.width, c.height);
met.draw();
met.fall();
};
class Meteor {
constructor(x, y, r, xSpeed, ySpeed){
this.xPos = x;
this.yPos = y;
this.radius = r;
this.xSpeed = xSpeed;
this.ySpeed = ySpeed;
this.color = "blue";
this.acceleration = 0.5;
}
draw(){
ctx.fillStyle = this.color;
ctx.arc(this.xPos, this.yPos, this.radius, 0, 2 * Math.PI);
//ctx.fill();
ctx.stroke();
}
fall(){
this.yPos += (this.ySpeed);
}
}
Also, if you have any tips on how to make it have gravity, please don't hesitate to tell me. Ive been struggling with it for a while now.
In draw() add this before the call to met.draw():
ctx.clearRect(0, 0, window.innerWidth, window.innterHeight)
This will clear the screen every frame.
For gravity, add a dt parameter to your draw function, then pass it to met.draw() like this:
function draw(dt){
window.requestAnimationFrame(draw);
ctx.fillStyle = colorArray[Math.floor(Math.random() * colorArray.length)];
ctx.fillRect(0, 0, c.width, c.height);
ctx.clearRect(0, 0, window.innerWidth, window.innterHeight) // Clear screen here
met.draw(dt);
met.fall();
};
Then in the Meteor class, use the dt in the draw() function to calculate your y position based on velocity. Here dt will be your delta time for the calculation.

How to fade out an item in canvas

I have a full screen canvas in my page. There are also some dive elements over this canvas. there is an circle element in the canvas that moves with the cursor everywhere in the page. However when the cursor arrives to the div element over the canvas, the circle shape stays in the last place it was on the canvas before arriving to the div.
DEMO: JSFIDDLE
Is ther any way that I can fade-out the circle shape when the cursor is over the div element and fade it in when it backs to the canvas?
Also is there any other effect rather than fading out? like making it small and then fade-out...
Here is the bit of code related to the circle:
function writeMessage(canvas, message, x, y) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var pattern = context.createPattern(imageResized, 'no-repeat');//Use imageResized, not imageObj.
context.fillStyle = pattern;
context.fill();
context.fillStyle = 'black';
context.beginPath();
context.arc(x, y, 60, 0, 2 * Math.PI);
}
Well, you can always create your own fade function that gets called on mouseout (or mouseleave) event. Here's one I quickly built for you:
function fadeOut(canvas, message, x, y, amount) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var pattern = context.createPattern(imageResized, 'no-repeat');
context.fillStyle = pattern;
context.fill();
context.font = '28pt Calibri';
context.fillStyle = 'black';
context.beginPath();
context.arc(x, y, amount, 0, 2 * Math.PI);
if (amount > 0) {
setTimeout(function(){
fadeOut(canvas, message, x, y, --amount);
}, 2);
}
else {
context.clearRect(0, 0, canvas.width, canvas.height);
}
}
See it in action here: http://jsfiddle.net/2p9dn8ed/42/
Or in the snippet:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = 0;
var y = 0;
var width = window.innerWidth;
var height = window.innerHeight;
var imageObj = new Image();
console.log(window.innerWidth + "----" + window.innerHeight);
//Create another canvas to darw a resized image to.
var imageResized = document.createElement('canvas');
imageResized.width = width;
imageResized.height = height;
//Wait for the original image to low to draw the resize.
imageObj.onload = function() {
//Find hoe mauch to scale the image up to cover.
var scaleX = width / imageObj.width;
var scaleY = height / imageObj.height;
var scaleMax = Math.max(scaleX, scaleY);
var ctx = imageResized.getContext('2d');
ctx.scale(scaleMax, scaleMax);
ctx.drawImage(imageObj, 0, 0);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
function writeMessage(canvas, message, x, y) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var pattern = context.createPattern(imageResized, 'no-repeat');//Use imageResized, not imageObj.
context.fillStyle = pattern;
context.fill();
context.font = '28pt Calibri';
context.fillStyle = 'black';
//context.fillText(message, x, y);
context.beginPath();
context.arc(x, y, 60, 0, 2 * Math.PI);
//context.stroke();
//
}
function fadeOut(canvas, message, x, y, amount) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var pattern = context.createPattern(imageResized, 'no-repeat');//Use imageResized, not imageObj.
context.fillStyle = pattern;
context.fill();
context.font = '28pt Calibri';
context.fillStyle = 'black';
//context.fillText(message, x, y);
context.beginPath();
context.arc(x, y, amount, 0, 2 * Math.PI);
//context.stroke();
//
if (amount > 0) {
setTimeout(function(){
fadeOut(canvas, message, x, y, --amount);
}, 2);
}
else {
context.clearRect(0, 0, canvas.width, canvas.height);
}
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function (evt) {
var mousePos = getMousePos(canvas, evt);
var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
writeMessage(canvas, message, mousePos.x, mousePos.y);
}, false);
canvas.addEventListener('mouseout', function(evt){
var mousePos = getMousePos(canvas, evt);
var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
console.log(1);
fadeOut(canvas, message, mousePos.x, mousePos.y, 60);
});
// Get the canvas element form the page
var canvas = document.getElementById("myCanvas");
/* Rresize the canvas to occupy the full page,
by getting the widow width and height and setting it to canvas*/
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
anvas, img {
display:block;
margin:1em auto;
border:1px solid black;
}
canvas {
background:url('../img/spiral_galaxy-1920x1080.jpg');
background-size: cover;
position: absolute;
left: 0; top: 0;
width: 100%; height: 100%;
z-index:-1;
}
div{
width:200px;
height:200px;
background:rgba(0,0,0,0.5);
position: fixed;
top: 20%;
left: 20%;
}
<canvas id="myCanvas" width="578" height="400"></canvas>
<div><h1>TEXT</h1></div>

Whole canvas is being rotated?

I am just trying my hands at HTML5's most talked feature i.e canvas. There are 2 rectangles and I only want to rotate 1st and keep the 2nd one as it is. Problem is when the below code runs my whole canvas is rotated and both rectangles are rotated. I can't even find any API where I can get reference to the object that I have drawn and rotate only that specific object instead of the whole context.
Code:
<script type="text/javascript">
var context;
var radian = 0.01;
var w, h;
$(document).ready(function () {
w = document.width;
h = document.height;
var canvas = $('#canvas');
context = canvas[0].getContext('2d');
canvas[0].width = w;
canvas[0].height = h;
setInterval(startAnim, 200);
});
function startAnim() {
context.clearRect(0, 0, w, h);
context.strokeStyle = 'rgb(0,0,0)';
context.fillStyle = 'rgb(0,0,0)';
context.fillRect(0, 0, w, h);
context.strokeStyle = 'rgb(0,0,0)';
context.fillStyle = 'rgb(255,255,0)';
context.rotate(radian);
context.strokeRect(400, 300, 200, 200);
context.fillRect(400, 300, 200, 200);
context.fillStyle = 'rgb(0,255,255)';
context.fillRect(500, 400, 200, 200);
radian += 0.01;
}
</script>
How can I prevent this from happening?
Finally, I have resolved the issue on my own by trial and error. This is the code:
<script type="text/javascript">
var context;
var radian = 0.01;
var w, h;
$(document).ready(function () {
w = document.width;
h = document.height;
var canvas = $('#canvas');
context = canvas[0].getContext('2d');
canvas[0].width = w;
canvas[0].height = h;
setInterval(startAnim, 100);
});
function startAnim() {
context.save();
context.strokeStyle = 'rgb(0,0,0)';
context.fillStyle = 'rgb(0,0,0)';
context.fillRect(0, 0, w, h);
context.rotate(radian);
context.strokeStyle = 'rgb(0,0,0)';
context.fillStyle = 'rgb(255,255,0)';
context.strokeRect(400, 300, 200, 200);
context.fillRect(400, 300, 200, 200);
context.restore();
context.fillStyle = 'rgb(0,255,255)';
context.fillRect(500, 400, 200, 200);
radian += 0.1;
}
</script>
As I understand you have to clear the whole canvas and redraw everything, between each frame. Keep the data for the rectangles in memory. Do the context.clearRect(0, 0, w, h); between each frame, then draw the rectangles again with there new altered properties.

Categories