javascript - interactive clipping does not refresh screen - javascript

I need to have a program that allows the user to clip an image with a rectangle:
https://jsfiddle.net/w3qfLr10/58/
I expected that when I clicked on different locations on the canvas, the program will clip the background image at that location. However, as you can see from the link, each time the mouse is clicked, the screen does not get refreshed. I expected the background is only clipped by one rectangle at the latest mouse location; instead, it seems like the background is clipped by all the mouse clicks.Thanks
Here is my code:
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<canvas id='myCanvas' width="480" height="320"> </canvas>
<script >
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var imageObj = new Image();
var rectX = 75;
var rectY = 60;
function draw() {
context.clearRect(0,0, canvas.width, canvas.height);
context.beginPath();
context.rect(rectX, rectY, 250, 180);
context.clip();
context.drawImage(imageObj, 69, 50);
};
imageObj.onload = function() {
draw();
canvas.onmouseup = function(e) {
rectX = e.x;
rectY = e.y;
draw();
};
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
</script>
</body>
</html>

I figured out what was wrong. To make the program behaves the way I intended it to behave, I just need to add context.save() before the path and context.restore() after the drawing. So, the new code would look like this:
....
context.clearRect(0,0, canvas.width, canvas.height);
context.save(); //new code
context.beginPath();
context.rect(rectX, rectY, 250, 180);
context.clip();
context.drawImage(imageObj, 69, 50);
context.restore();//new code

Related

Javascript Canvas one item flickering

I am trying to make to objects move towards each other in Canvas, when they meet and overlap one should then disappear and the other should fall down. Now I got the animation to do that, but one of the items is flickering.
<!DOCTYPE html>
<html>
<head>
<style>
canvas{border:#666 3px solid;}
</style>
</head>
<body onload="draw(530,15); draw1(1,15);">
<canvas id="canvas" width="600" height="400"></canvas>
<script>
function draw(x,y){
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.save();
ctx.clearRect(x, y, 600, 400);
ctx.fillStyle = "rgba(0,200,0,1)";
ctx.fillRect (x, y, 70, 50);
ctx.restore();
x -= 0.5;
if(x==300)
{
return;
};
var loopTimer = setTimeout('draw('+x+','+y+')',5);
};
function draw1(w,e){
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.save();
ctx.clearRect(w-1,e-2,600,400);
ctx.fillStyle = "rgba(0,200,0,1)";
ctx.fillRect (w, e, 70, 50);
ctx.restore();
w += 1;
if(w==265)
{
w -= 1;
e +=2;
};
var loopTimer = setTimeout('draw1('+w+','+e+')',10);
};
</script>
</body>
</html>
Been trying for two days, but can't seem to fix it properly. Thanks in advance.
You are rendering too many frames per second forcing the browser to present frames. Each time a draw function returns the browser presumes you want to present the frame to the page.
Animations need to be synced to the display refresh rate which for most devices is 60FPS. To do this you have one render loop that handles all the animation. You call this function via requestAnimationFrame (RAF) which ensures that the animation stays in sync with the display hardware and browser rendering.
<!DOCTYPE html>
<html>
<head>
<style>
canvas{border:#666 3px solid;}
</style>
</head>
<!-- dont need this <body onload="draw(530,15); draw1(1,15);">-->
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
var canvas,ctx,x,y,w,e;
var canvas,ctx,x,y,w,e;
function draw() {
ctx.fillStyle = "rgba(0,200,0,1)";
ctx.fillRect(x, y, 70, 50);
};
function draw1(w, e) {
ctx.fillStyle = "rgba(0,200,0,1)";
ctx.fillRect(w, e, 70, 50);
};
function update(time){ // high precision time passed by RAF when it calls this function
ctx.clearRect(0,0,canvas.width,canvas.height); // clear all of the canvas
if(w + 70 >= x){
e += 2;
}else{
x -= 0.75;
w += 1;
};
draw(x,y);
draw1(w,e);
requestAnimationFrame(update)
// at this point the function exits and the browser presents
// the canvas bitmap for display
}
function start(){ // set up
x = 530;
y = 15;
w = 1;
e = 15;
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
requestAnimationFrame(update)
}
window.addEventListener("load",start);
</script>
</body>
</html>
You're method of animation is very outdated (ie, the use of setTimeout). Instead you should be using requestAnimationFrame as demonstrated below. This will give smooth, flicker free animation.
<!DOCTYPE html>
<html>
<head>
<style>
canvas{border:#666 3px solid;}
</style>
</head>
<body onload="requestAnimationFrame(animate);">
<canvas id="canvas" width="600" height="400"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var x = 530, y = 15;
function animate(){
requestID = requestAnimationFrame(animate);
ctx.clearRect(x, y, 600, 400);
ctx.fillStyle = "rgba(0,200,0,1)";
ctx.fillRect (x, y, 70, 50);
x -= 0.5;
if(x==300)
{
cancelAnimationFrame(requestID)
};
}
</script>
</body>
</html>
the first 2 parameters of ctx.clearReact in both draw functions should be 0:
ctx.clearRect(0, 0, 600, 400);
This means you clear all canvas.

Paint circle method JavaScript

I am trying to find a way to draw a circle using JavaScript and redraw it while erasing the old circle.
i got this code:
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 15;
drawCircle(centerX,centerY,radius);
drawCircle(150,150,25);
function drawCircle(centerX,centerY,radius)
{
var canvas = document.getElementById('myCanvas');
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'black';
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
};
</script>
The problem is that this two methods draw two circles instead of drawing one instead of the other.
I am beginner in JS would appreciate help on making better way of drawing and erasing the circle
Thanks
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 15;
function drawCircle(centerX,centerY,radius)
{
// Erase context
context.clearRect(0,0,canvas.width,canvas.height);
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'black';
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
};
drawCircle(centerX,centerY,radius);
drawCircle(150,150,25);
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="578" height="200"></canvas>
If you want to remove a circle from the canvas you will have to draw a circle (same position; same size) but this time with the color of the canvas background.
drawCircle(150,150,25,'black');
// ...
drawCircle(150,150,25,'white'); // removes previous circle if the canvas was white colored
If you want to erase everything from the canvas before drawing something new you can just execute this
context.clearRect(0, 0, canvas.width, canvas.height);

html5 - drawing multiple circles - each filled with different images

Alright so ive looked around and found a code that will successfulyl enable me to draw a circle on canvas and use that circle as a mask for my image.
The code looks like this: (codus to the real creater that i dont know)
var ctx = document.getElementById('your_canvas').getContext("2d");
ctx.arc(100,100, 50, 0, Math.PI*2,true); // you can use any shape
ctx.clip();
var img = new Image();
img.addEventListener('load', function(e) {
ctx.drawImage(this, 0, 0, 200, 300);
}, true);
img.src="/path/to/image.jpg";
Lets assume I want to have 5 different circles all with different images and all and each positioned differently.
Anyone got an idea on how id go about that?
To keep the code short, create a function with parameters for the settings that will change from image to image.
Reusable function:
function drawImageCircle(ctx, circleX, circleY, radius,
imageX, imageY, imageWidth, imageHeight, imageUrl) {
var img = new Image();
img.onload = function(){
ctx.save();
ctx.beginPath();
ctx.arc(circleX, circleY, radius, 0, Math.PI*2, true);
ctx.clip();
ctx.drawImage(this, imageX, imageY, imageWidth, imageHeight);
ctx.restore();
};
img.src = imageUrl;
}
var ctx = document.getElementById('your_canvas').getContext("2d");
drawImageCircle(ctx, 100,100, 50, 0,0, 200,300, 'image1.jpg');
drawImageCircle(ctx, 400,400, 50, 300,300, 200,300, 'image2.jpg');
The use of save() and restore() is important when doing this more than once.
Yep, pretty much what Matt said...
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/Vu2Fm/
You can improve this code by using an image preloader to load all 5 of your images prior to drawing on the canvas.
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var img1=new Image();
img1.onload=function(){
var img2=new Image();
img2.onload=function(){
// draw a clipping circle and then an image to clip
ctx.save();
ctx.beginPath();
ctx.strokeStyle="blue";
ctx.arc(100, 100, 50, 0 , 2 * Math.PI, false);
ctx.stroke();
ctx.clip();
ctx.beginPath();
ctx.arc(100, 100, 50, 0 , 2 * Math.PI, false);
ctx.drawImage(img1,10,0);
ctx.restore();
// draw a second clipping circle and then an image to clip
ctx.save();
ctx.beginPath();
ctx.strokeStyle="green";
ctx.arc(275, 100, 75, 0 , 2 * Math.PI, false);
ctx.stroke();
ctx.clip();
ctx.beginPath();
ctx.drawImage(img2,150,0);
ctx.restore();
}
img2.src="http://dl.dropbox.com/u/139992952/coffee.png";
}
img1.src="http://dl.dropbox.com/u/139992952/house%20vector.png";
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=400 height=250></canvas>
</body>
</html>

How to rotate the existing content of HTML5 canvas?

Is there a way to rotate the existing content of HTML5 canvas by Javascript? I know it's possible to rotate an image that will be drawn on to canvas, but I want to rotate the content that has been drawn on to canvas, for example, a 200x200 corner of a 400x400 canvas, or any specific region of an existing canvas.
Same question to scale the existing canvas content...
I know getImageData/putImageData provide a potential to transform the pixel array, but it's just too slow and inefficient.
It's pretty easy to do with a temp canvas.
Live Demo
Live Demo Animated (just for the heck of it)
The above example draws 2 boxes, then rotates and scales from 0,0 to 200,200
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
canvas.width = canvas.height = 400;
// fill the canvas black, and draw 2 boxes
ctx.fillStyle = "#000";
ctx.fillRect(0,0,400,400);
ctx.fillStyle = "rgb(255,0,0)";
ctx.fillRect(10,10,190,190);
ctx.fillStyle = "rgb(255,255,0)";
ctx.fillRect(250,250,90,90);
// Create a temp canvas to store our data (because we need to clear the other box after rotation.
var tempCanvas = document.createElement("canvas"),
tempCtx = tempCanvas.getContext("2d");
tempCanvas.width = canvas.width;
tempCanvas.height = canvas.height;
// put our data onto the temp canvas
tempCtx.drawImage(canvas,0,0,canvas.width,canvas.height);
// Append for debugging purposes, just to show what the canvas did look like before the transforms.
document.body.appendChild(tempCanvas);
// Now clear the portion to rotate.
ctx.fillStyle = "#000";
ctx.fillRect(0,0,200,200);
ctx.save();
// Translate (190/2 is half of the box we drew)
ctx.translate(190/2, 0);
// Scale
ctx.scale(0.5,0.5);
// Rotate it
ctx.rotate(45*Math.PI/180);
// Finally draw the image data from the temp canvas.
ctx.drawImage(tempCanvas,0,0,200,200,10,10,190,190);
ctx.restore();
If you first want to draw on a canvas and then rotate it for use on e.g. corners, you can to that when you "clone" the canvas or by using CSS.
Examples
Get the first canvas element:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
draw on it:
ctx.fillStyle = 'blue';
ctx.fillRect(0,0, 25, 5);
ctx.fill();
ctx.fillStyle = 'red';
ctx.fillRect(25, 0, 25, 5);
ctx.fill();
clone it to another canvas (that is rotated by CSS):
var ctx2 = document.getElementById("canvas2").getContext("2d");
ctx2.drawImage(canvas, 0,0);
or rotate the canvas while you "clone" it:
var ctx3 = document.getElementById("canvas3").getContext("2d");
ctx3.rotate(Math.PI/2);
ctx3.translate(0,-50);
ctx3.drawImage(canvas, 0,0);
here is the CSS for rotating it:
#canvas2 {
-webkit-transform:rotate(90deg);
-moz-transform:rotate(90deg);
-o-transform:rotate(90deg);
-ms-transform:rotate(90deg);
}
Here is the full example:
<!DOCTYPE html>
<html>
<head>
<script>
window.onload = function() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = 'blue';
ctx.fillRect(0,0, 25, 5);
ctx.fill();
ctx.fillStyle = 'red';
ctx.fillRect(25, 0, 25, 5);
ctx.fill();
var ctx2 = document.getElementById("canvas2").getContext("2d");
ctx2.drawImage(canvas, 0,0);
var ctx3 = document.getElementById("canvas3").getContext("2d");
ctx3.rotate(Math.PI/2);
ctx3.translate(0,-50);
ctx3.drawImage(canvas, 0,0);
}
</script>
<style>
#canvas2 {
-webkit-transform:rotate(90deg);
-moz-transform:rotate(90deg);
-o-transform:rotate(90deg);
-ms-transform:rotate(90deg);
}
</style>
</head>
<body>
<canvas id="canvas" width="50" height="50"></canvas>
<canvas id="canvas2" width="50" height="50"></canvas>
<canvas id="canvas3" width="50" height="50"></canvas>
</body>
</html>

Moving Objects on html5 Canvas

I placed an text on html5 canvas object using fillText option, question is I need to move the text position or change the color of the text that is already rendered.
Shortly I need to know how to Manipulate particular child of canvas element
This will move a small circle over your canvas
var can = document.getElementById('canvas');
can.height = 1000; can.width = 1300;
var ctx = can.getContext('2d');
var x = 10, y = 100;
ctx.fillStyle = "black";
ctx.fillRect(700, 100, 100, 100);
function draw() {
ctx.beginPath();
ctx.arc(x, y, 20, 0, 2 * Math.PI);
ctx.fillStyle = 'rgba(250,0,0,0.4)';
ctx.fill();
x += 2;
ctx.fillStyle = "rgba(34,45,23,0.4)";
ctx.fillRect(0, 0, can.width, can.height);
requestAnimationFrame(draw);
//ctx.clearRect(0,0,can.width,can.height);
}
draw();
<canvas id="canvas" style="background:rgba(34,45,23,0.4)"></canvas>
I think there is no object model behind the canvas, so you cannot access a "child object" like a "text object" and change it.
What you can do is that you draw the text again with a different color that overwrites the "pixels" of the canvas.
If you want to move the text, first you have to either clear the canvas or re-draw the text with a background/transparent color to get rid of the text in the previous position. Then you can draw the text in the new position.
I've never tried it but I think this would be the way to do it.
var canvas = document.getElementById("canvas"); //get the canvas dom object
var ctx = canvas.getContext("2d"); //get the context
var c = { //create an object to draw
x:0, //x value
y:0, //y value
r:5; //radius
}
var redraw = function(){ // this function redraws the c object every frame (FPS)
ctx.clearRect(0, 0, canvas.width, canvas.height); // clear the canvas
ctx.beginPath(); //start the path
ctx.arc(c.x, c.y, c.r, 0, Math.PI*2); //draw the circle
ctx.closePath(); //close the circle path
ctx.fill(); //fill the circle
requestAnimationFrame(redraw);//schedule this function to be run on the next frame
}
function move(){ // this function modifies the object
var decimal = Math.random() // this returns a float between 0.0 and 1.0
c.x = decimal * canvas.width; // mulitple the random decimal by the canvas width and height to get a random pixel in the canvas;
c.y = decimal * canvas.height;
}
redraw(); //start the animation
setInterval(move, 1000); // run the move function every second (1000 milliseconds)
Here is a fiddle for it.
http://jsfiddle.net/r4JPG/2/
If you want easing and translations, change the move method accordingly.
Hope it is allowed to advertise somebody's project.
Take a look at http://ocanvas.org/ you can get inspiration there.
It is object like canvas library. Allows you to handle events, make animations etc.
<html>
<head>
<title>Canvas Exam</title>
</head>
<body>
<canvas id="my_canvas" height="500" width="500" style="border:1px solid black">
</canvas>
<script>
var dom=document.getElementById("my_canvas");
var ctx=dom.getContext("2d");
var x1=setInterval(handler,1);
var x=50;
var y=50;
r=40;
function handler()
{
ctx.clearRect(0,0,500,500);
r1=(Math.PI/180)*0;
r2=(Math.PI/180)*360;
ctx.beginPath();
//x=x*Math.random();
x=x+2;
r=r+10*Math.random();
ctx.arc(x,y,r,r1,r2);
ctx.closePath();
ctx.fillStyle="blue";
ctx.fill();
ctx.stroke();
if(x>400)
{
x=50;
y=y+10;
}
r=40;
}
</script>
</body>
</html>

Categories

Resources