How do I make something Rotate towards mouse? - javascript

I am trying to solve a question which has been bugging me for a while, can someone explain to me how to make the *red rectangle face/aim towards my mouse and explain to me how it works it would be awesome!!!
Here is the Fiddle
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var player = {
x: 200,
y: 200,
}
drawPlayer = function(something) {
context.beginPath();
context.fillStyle = "blue";
context.arc(something.x, something.y, 30, 0, 2 * Math.PI);
context.fill();
context.fillStyle = "red";
context.fillRect(something.x, something.y - 10, 50, 20);
context.restore();
}
update = function() {
context.clearRect(0, 0, 500, 500)
drawPlayer(player);
}
setInterval(update, 20);
<canvas id="canvas" style="outline: 1px solid #ccc" width="500" height="500"></canvas>

Use context.translate to translate coordinates to the center of your player and then context.rotate to rotate the rectangle.
To find the angle between the mouse position and the center of the player you can use Math.atan2 function.
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var player = {
x: 200,
y: 200,
}
drawPlayer = function(something, angle) {
context.clearRect(0, 0, 500, 500);
context.beginPath();
context.fillStyle = "blue";
context.arc(something.x, something.y, 30, 0, 2 * Math.PI);
context.fill();
// save the untranslated context
context.save();
context.beginPath();
// move the rotation point to the center of the player
context.translate(something.x, something.y);
context.rotate(angle);
context.fillStyle = "red";
// note that coordinates are translated,
// so 0 is player.x and -10 is player.y - 10
context.fillRect(0, - 10, 50, 20);
// restore the context to its untranslated state
context.restore();
}
drawPlayer(player, 0);
document.onmousemove = function(e) {
var angle = Math.atan2(e.pageY - player.y, e.pageX - player.x)
drawPlayer(player, angle);
}
<canvas id="canvas" style="outline: 1px solid #ccc" width="500" height="500"></canvas>

Related

html5 canvas drawing partially

I want to create the logo above using the html5 canvas but at the end of the day, it displayed only a triangle.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Coa</title>
</head>
<body>
<canvas id="logo" width="900" height="80">
<h1>COA</h1>
</canvas>
<script>
//function that draw the logo. I create a JavaScript function for drawing the
var drawLogo = function(){
var canvas = document.getElementById('logo');
var context = canvas.getContext("2d");
//applying gradient
var gradient = context.createLinearGradient(0, 0, 0, 40);
gradient.addColorStop(0, "#aa0000");
gradient.addColorStop(1, "#ff0000");
// use the strokepath,beginPath() and closePath() methods to start drawing a line, stroke and close when finish
context.fillStyle = gradient;
context.strokeStyle = gradient;
context.lineWidth = 2;
context.beginPath();
context.moveTo(0, 40);
context.lineTo(30, 0);
context.lineTo(60, 40);
context.lineTo(285, 40);
context.fill();
context.closePath();
//adding text
context.font = "italic 40px 'Arial'";
context.fillText("Coa", 60,36);
//Moving the Origin so as to fit the square under the triangle
context.save();
context.translate(20, 20);
context.fillRect(0, 0, 20, 20);
//use a path to draw the inner triangle
context.fillStyle("#ffffff");
context.strokeStyle("#ffffff");
context.lineWidth = 2;
context.beginPath();
context.moveTo();
context.lineTo(0, 20);
context.lineTo(10, 0);
context.lineTo(20, 20);
context.lineTo(0, 20);
context.fill();
context.closePath();
context.restore();
};
//Then invoke this method after first checking for the existence of the <canvas> element
var canvas = document.getElementById("logo");
if(canvas.getContext){
drawLogo();
}
</script>
</body>
</html>
I don't know what am doing wrong that makes the the code not working properly.
I have searched the internet and couldn't find anything tangible that solve the problem. Any help will be appreciated.
UPDATE: Try this:
if (document.getElementById('logo')) {
var canvas = document.getElementById("logo");
var context = canvas.getContext("2d");
//applying gradient
var gradient = context.createLinearGradient(0, 0, 0, 40);
gradient.addColorStop(0, "#aa0000");
gradient.addColorStop(1, "#ff0000");
context.strokeStyle = gradient;
context.fillStyle = gradient;
context.lineWidth = 2;
context.beginPath();
context.moveTo(0, 40);
context.lineTo(30, 0);
context.lineTo(60, 40);
context.lineTo(285, 40);
context.stroke();
context.fillRect(20, 20, 20, 20);
context.beginPath();
context.moveTo(30, 20);
context.lineTo(37, 28);
context.lineTo(35, 40);
context.lineTo(25, 40);
context.lineTo(23, 28);
context.lineTo(30, 20);
context.fillStyle="#ffffff";
context.fill();
context.fillStyle="#000000";
context.font = "italic 40px Arial";
context.fillText("coa", 60,36);
}
I moved around some of your code and it works now for me on Firefox. It looks like you haven't put the pentagon in the canvas yet. Here is a JSFillde:
https://jsfiddle.net/o289buyk/
if (document.getElementById('logo')) {
var canvas = document.getElementById("logo");
var context = canvas.getContext("2d");
//applying gradient
var gradient = context.createLinearGradient(0, 0, 0, 40);
gradient.addColorStop(0, "#aa0000");
gradient.addColorStop(1, "#ff0000");
// use the strokepath,beginPath() and closePath() methods to start drawing a line, stroke and close when finish
context.fillStyle = gradient;
context.strokeStyle = gradient;
context.lineWidth = 2;
context.beginPath();
context.moveTo(0, 40);
context.lineTo(30, 0);
context.lineTo(60, 40);
context.lineTo(285, 40);
context.fill();
context.closePath();
//adding text
context.font = "italic 40px 'Arial'";
context.fillText("Coa", 60,36);
//Moving the Origin so as to fit the square under the triangle
context.save();
context.translate(20, 20);
context.fillRect(0, 0, 20, 20);
//use a path to draw the inner triangle
context.fillStyle("#ffffff");
context.strokeStyle("#ffffff");
context.lineWidth = 2;
context.beginPath();
context.moveTo();
context.lineTo(0, 20);
context.lineTo(10, 0);
context.lineTo(20, 20);
context.lineTo(0, 20);
context.fill();
context.closePath();
context.restore();
}

How to rotate a canvas by following mouse if the canvas already has something drawn on it

I currently have a canvas that has an element drawn on it that I draw using a custom function and the onload function I would like to know how to be able to rotate this canvas around by following the mouse 360 degrees like turning a wheel. The code is as follows
<!DOCTYPE html>
<html>
<head>
<title>Help</title>
</head>
<body>
<canvas id="MyCanvas" width="500" height="500"></canvas>
<script>
var ctx = document.getElementById("MyCanvas").getContext("2d");
ctx.translate(250,250);
function draw(){
ctx.arc(0,0,100,0,Math.PI*2,false); // x, y, radius, start angle, end angle, false/true
ctx.stroke();
ctx.beginPath();
ctx.moveTo(-100,0);
ctx.lineTo(100,0);
ctx.moveTo(100,0);
ctx.lineTo(60,-80);
ctx.moveTo(60,-80);
ctx.lineTo(-100,0);
ctx.stroke();
}
window.onload=draw;
</script>
</body>
</html>
Does anyone know how this would be possible I have tried multiple different functions. however, they do not seem to be able to do anything.
help will be very appreciated.
Edited but with slight issue
<!DOCTYPE html>
<html>
<head>
<title>Help</title>
</head>
<style>
canvas{
border: 2px solid black;
}
</style>
<body>
<canvas id="Canvas" height="300"></canvas>
<script>
const ctx = canvas.getContext("2d");
const mouse = { x: 0, y: 0 };
function mouseEvents(e) {
const bounds = canvas.getBoundingClientRect();
mouse.x = e.pageX - bounds.left - scrollX;
mouse.y = e.pageY - bounds.top - scrollY;
}
document.addEventListener("mousemove", mouseEvents);
function drawRotated(x, y, angle) {
ctx.setTransform(1, 0, 0, 1, x, y);
ctx.rotate(angle);
ctx.beginPath();
ctx.arc(0, 0, 100, 0, Math.PI * 2);
ctx.moveTo(-100, 0);
ctx.lineTo(100, 0);
ctx.lineTo(60, -80);
ctx.closePath();
ctx.stroke();
}
function update(timer) {
ctx.setTransform(1, 0, 0, 1, 0, 0); // reset transform
ctx.clearRect(0, 0, 300, 300);
var angle = Math.atan2(mouse.y - 150, mouse.x - 150);
drawRotated(150, 150, angle);
requestAnimationFrame(update);
}
requestAnimationFrame(update);
</script>
</body>
</html>
You need to create a mouse move listener, and an animation loop.
In the animation loop get the mouse position and use Math.atan2( to get the direction from the center canvas to the mouse.
Then set the transform with ctx.setTransform to scale and position the designs rotation center, and then use ctx.rotate to rotate the transform to point along the angle computed.
See snippet for more details
const ctx = canvas.getContext("2d");
// create mouse event listener
const mouse = { x: 0, y: 0 };
function mouseEvents(e) {
const bounds = canvas.getBoundingClientRect();
mouse.x = e.pageX - bounds.left - scrollX;
mouse.y = e.pageY - bounds.top - scrollY;
}
document.addEventListener("mousemove", mouseEvents);
// draw design at x,y and rotated by angle
function drawRotated(x, y, angle) {
ctx.setTransform(1, 0, 0, 1, x, y);
ctx.rotate(angle);
ctx.beginPath();
ctx.arc(0, 0, 100, 0, Math.PI * 2);
ctx.moveTo(-100, 0);
ctx.lineTo(100, 0);
ctx.lineTo(60, -80);
ctx.closePath();
ctx.stroke();
}
// render loop called 60 times a second
function update(timer) {
ctx.setTransform(1, 0, 0, 1, 0, 0); // reset transform
ctx.clearRect(0, 0, 300, 300);
// get angle from center to mouse
var angle = Math.atan2(mouse.y - 150, mouse.x - 150);
// draw rotated design
drawRotated(150, 150, angle);
requestAnimationFrame(update);
}
requestAnimationFrame(update);
canvas {
border: 2px solid black;
}
<canvas id="canvas" height=300></canvas>

Drawing lights on a canvas

Hi i'm trying to draw lights in a canvas like this:
<canvas id="myCanvas" width="600" height="300"></canvas>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "rgba(0,0,0,0.75)";
ctx.fillRect(0,0,300,300);
ctx.clearRect(0,0,300,300);
var grd = ctx.createRadialGradient(150,150,0,150,150,150);
grd.addColorStop(0, "rgba(255,255,0,0)");
grd.addColorStop(1, "rgba(0,0,0,0.75)");
ctx.fillStyle = grd;
ctx.fillRect(0,0,300,300);
ctx.clearRect(300,0,600,300);
var grd = ctx.createRadialGradient(450,150,0,450,150,150);
grd.addColorStop(0, "rgba(255,255,0,0)");
grd.addColorStop(1, "rgba(0,0,0,0.75)");
ctx.fillStyle = grd;
ctx.fillRect(300,0,600,300);
</script>
The problem is when the lights overlap
<canvas id="myCanvas" width="500" height="300"></canvas>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "rgba(0,0,0,0.75)";
ctx.fillRect(0,0,300,300);
ctx.clearRect(0,0,300,300);
var grd = ctx.createRadialGradient(150,150,0,150,150,150);
grd.addColorStop(0, "rgba(255,255,0,0)");
grd.addColorStop(1, "rgba(0,0,0,0.75)");
ctx.fillStyle = grd;
ctx.fillRect(0,0,300,300);
ctx.clearRect(200,0,500,300);
var grd = ctx.createRadialGradient(350,150,0,350,150,150);
grd.addColorStop(0, "rgba(255,255,0,0)");
grd.addColorStop(1, "rgba(0,0,0,0.75)");
ctx.fillStyle = grd;
ctx.fillRect(200,0,500,300);
</script>
I need the lights come together and not overlap
also i need to see an image below the canvas
how can i Solve ?
that's the effect i'm looking for
I've used 2 canvas, 1 for scenery and 1 above for lights
This is almost what i'm looking for , but it remains a bit 'darker where the lights overlap, there is too little light in the center of each light, and it looks like a white light instead of a yellow light
http://jsfiddle.net/vgmc4m87/
Thanks
If you really want to overlap those two gradients, I would suggest a few things,
Get rid of the clearRect()
Change
grd.addColorStop(0, "rgba(255,255,0,0)"); grd.addColorStop(1, "rgba(0,0,0,0.75)");
Such that the second color stop has 0 alpha component, this way the gradient will actually fade out as it goes towards the edge of the circle. And you can actually overlap circles only if they're fading towards the end.
Don't use fillRect(), use arcs instead.
See, https://jsfiddle.net/fL4xffnq/3/. I've not preserved colours, but it should give you a good idea on how to proceed.
jsFiddle : https://jsfiddle.net/CanvasCode/p3k7cwqs/
javascript
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext("2d");
var image = new Image();
image.src = "http://images4.fanpop.com/image/photos/16000000/Beautiful-Cat-cats-16096437-1280-800.jpg";
image.onload = function () {
ctx.drawImage(image, 0, 0, 500, 400);
var grd = ctx.createRadialGradient(150, 150, 0, 0, 150, 200);
grd.addColorStop(0, "rgba(255,255,0,1)");
grd.addColorStop(1, "rgba(0,0,0,0)");
ctx.beginPath();
ctx.fillStyle = grd;
ctx.arc(150, 150, 200, 0, Math.PI * 2, false)
ctx.fill();
var grd = ctx.createRadialGradient(350, 150, 0, 350, 150, 200);
grd.addColorStop(0, "rgba(255,255,0,1)");
grd.addColorStop(1, "rgba(0,0,0,0)");
ctx.beginPath();
ctx.fillStyle = grd;
ctx.arc(350, 150, 200, 0, Math.PI * 2, false)
ctx.fill();
};
Adding to #nisargjhaveri's answer setting ctx.globalCompositeOperation = "lighter" creates a nice effect.
function drawBackground() {
var can = document.getElementById('background');
var ctx = can.getContext('2d');
var grd = ctx.createLinearGradient(0, 0, 0, 150);
grd.addColorStop(0, "rgba(0,255,255,1)");
grd.addColorStop(1, "rgba(30,100,200,1)");
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 500, 150);
var grd = ctx.createLinearGradient(0, 150, 0, 300);
grd.addColorStop(0, "rgba(15,75,25,1)");
grd.addColorStop(1, "rgba(30,150,50,1)");
ctx.fillStyle = grd;
ctx.fillRect(0, 150, 500, 300);
}
drawBackground();
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var bg = document.getElementById("background");
var x1 = 150;
var y1 = 150;
var x2 = 350;
var y2 = 150;
var step1 = {
x: 1,
y: 1
};
var step2 = {
x: -1,
y: 1
};
function loop() {
ctx.save();
ctx.fillStyle = "rgba(0,0,0,1)";
ctx.clearRect(0, 0, 500, 300);
// Create a white to transparent gradient for the circles
// Circle one
var grd = ctx.createRadialGradient(x1, y1, 0, x1, y1, 150);
grd.addColorStop(.75, "rgba(255,255,0,1)");
grd.addColorStop(1, "rgba(255,255,0,0)");
ctx.beginPath();
ctx.fillStyle = grd;
ctx.arc(x1, y1, 150, 0, Math.PI * 2, false)
ctx.fill();
// Circle two
var grd = ctx.createRadialGradient(x2, y2, 0, x2, y2, 150);
grd.addColorStop(.75, "rgba(255,255,255,1)");
grd.addColorStop(1, "rgba(255,255,255,0)");
ctx.beginPath();
ctx.fillStyle = grd;
ctx.arc(x2, y2, 150, 0, Math.PI * 2, false)
ctx.fill();
// Fill the white part with the background image.
ctx.globalCompositeOperation = "source-atop";
ctx.drawImage(bg, 0, 0, bg.width, bg.height);
// Fill the transparent part with gray.
ctx.globalCompositeOperation = "destination-atop"
ctx.fillStyle = "rgba(63,63,63,1)";
ctx.fillRect(0, 0, c.width, c.height);
// clear the globalCompositeOperation
ctx.restore();
step1.x = x1 > c.width ? -1 : x1 < 0 ? 1 : step1.x;
step1.y = y1 > c.height ? -1 : y1 < 0 ? 1 : step1.y;
step2.x = x2 > c.width ? -1 : x2 < 0 ? 1 : step2.x;
step2.y = y2 > c.height ? -1 : y2 < 0 ? 1 : step2.y;
x1 += step1.x;
y1 += step1.y;
x2 += step2.x;
y2 += step2.y;
setTimeout(loop, 1000 / 60);
}
loop()
<canvas id="background" width="500" height="300" style='display:none'></canvas>
<canvas id="myCanvas" width="500" height="300"></canvas>

how can use a loop to draw it multiple times in random places in my canvas?

I've drawn a leaf in canvas, but now i want to draw it multiple times on my canvas and in random places. I've mostly used bezier curves to draw my leaf, is and i do not know how to use a loop to create more of them in random places, because of the coordinates.
My code:
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="800" height="800" style="border:1px solid #c3c3c3;">
</canvas>
<script>
var c = document.getElementById("myCanvas");
var context = c.getContext("2d");
context.lineWidth = 5;
context.beginPath();
context.moveTo(100, 150);
context.strokeStyle="#009900";
context.bezierCurveTo(170, 110, 400, 10, 500, 150);
context.stroke();
context.moveTo(100, 150);
context.strokeStyle="#009900";
context.bezierCurveTo(170, 130, 430, 310, 500, 150);
context.stroke();
context.fillStyle = '#99FF66';
context.fill();
context.strokeStyle="#009900";
context.moveTo(250, 150);
context.bezierCurveTo(400, 100, 400, 180, 500, 150);
context.stroke();
context.closePath();
context.beginPath();
context.strokeStyle="#996633";
context.moveTo(500, 150);
context.lineTo(580,150);
context.stroke();
context.closePath();
</script>
</body>
</html>
The simplest solution that I can come up with is to use the context.translate function to move to where you want to draw the leaf before drawing it:
//Generate x y coords, offset by the x,y of the leaf:
var x = (Math.random()*500) - 250;
var y = (Math.random()*500) - 150;
//Translate
context.translate(x, y);
//Draw leaf
//Translate back
context.translate(-x,-y)
Code to draw two leaves at random positions:
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="800" height="800" style="border:1px solid #c3c3c3;">
</canvas>
<script>
var c = document.getElementById("myCanvas");
var context = c.getContext("2d");
context.lineWidth = 5;
for(var i = 0; i < 2; i++) {
//Generate x y coords, offset by the top x,y of the leaf:
var x = (Math.random()*500) - 250;
var y = (Math.random()*500) - 150;
//Translate
context.translate(x, y);
//Draw
context.beginPath();
context.moveTo(100, 150);
context.strokeStyle="#009900";
context.bezierCurveTo(170, 110, 400, 10, 500, 150);
context.stroke();
context.moveTo(100, 150);
context.strokeStyle="#009900";
context.bezierCurveTo(170, 130, 430, 310, 500, 150);
context.stroke();
context.fillStyle = '#99FF66';
context.fill();
context.strokeStyle="#009900";
context.moveTo(250, 150);
context.bezierCurveTo(400, 100, 400, 180, 500, 150);
context.stroke();
context.closePath();
context.beginPath();
context.strokeStyle="#996633";
context.moveTo(500, 150);
context.lineTo(580,150);
context.stroke();
context.closePath();
//Translate Back
context.translate(-x, -y);
}
</script>
</body>
Since you want to re-use some of your code -> isolate the parameters and build a function out of it.
Then any pattern will be easy to build.
http://jsbin.com/mimisuziyi/1/
function drawLeaf(x,y, size, rotation) {
context.lineWidth = 5;
context.save();
context.translate(x,y);
context.scale(size/400, size/400);
context.rotate(rotation);
context.beginPath();
context.moveTo(0, 0);
context.strokeStyle="#009900";
context.bezierCurveTo(70, -40, 300, 10-150, 400, 0);
context.stroke();
context.moveTo(0, 0);
context.strokeStyle="#009900";
context.bezierCurveTo(70, -20, 330, 160, 400, 0);
context.stroke();
context.fillStyle = '#99FF66';
context.fill();
context.strokeStyle="#009900";
context.moveTo(150, 0);
context.bezierCurveTo(300, -50, 300, 30, 400, 0);
context.stroke();
context.closePath();
context.beginPath();
context.strokeStyle="#996633";
context.moveTo(400, 0);
context.lineTo(480,0);
context.closePath();
context.stroke();
context.restore();
}
used with :
drawLeaf(100, 150, 400, 0);
or :
var leafCount = 5;
for (var i=0; i<leafCount; i++) {
drawLeaf(150, 300, 100, 2*i*Math.PI/leafCount)
}

HTML5 Canvas: Bezier curve to draw on load

I have draw the Bezier Curve. But I Want Animate the Bezier Curve in onload for 1 time.
Please help me..
Here the below code:
window.onload = function() {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var x=10, y=25;
function curve() {
context.beginPath();
context.moveTo(214, 0);
context.bezierCurveTo(328, 80, 153, 82, 216, 162);
context.lineWidth = 10;
context.strokeStyle = 'gray';
context.stroke();
}
curve();
};
<body>
<canvas id="canvas" width="300" height="300" style="text-align: left; border: 1px solid black; position: absolute; left: 100px;"></canvas>
</body>
Curve draw on 0 to (328, 80, 153, 82, 216, 162)
You can cheat to get the effect, although the animation does not bend according to the line
(you have to stop the timer and this might not work if there are other drawn object near it)
http://jsfiddle.net/o9k83k0g/
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var x=10, y=25;
var show=0;
function curve() {
context.beginPath();
context.moveTo(214, 0);
context.bezierCurveTo(328, 80, 153, 82, 216, 162);
context.lineWidth = 10;
context.strokeStyle = 'gray';
context.stroke();
context.beginPath();
context.fillStyle = 'white';
context.fillRect(160,0+show,100,175-show);
context.stroke();
show=show+1;
}
setInterval(function(){curve();}, 30);
If you want to animate the curve, you can structurate your code like that :
var snake = {
points:[ {x:100,y:100},{x:100,y:150},{x:100,y:200},{x:100,y:250} ]
}
function loop(){
physic( snake )
display( snake )
}
setInterval( loop, 20 )
In the physic function, you update points in the snake structure according to what you want.
In the display function you do something like that :
function display( snake ){
var point = snake.points[0];
ctx.beginPath();
ctx.lineWidth = 10;
ctx.moveTo( point.x, point.y );
for( i=0; i< snake.points.length-1; i++ ){
point = snake.points[i];
var xc = (point.x + snake.points[i + 1].x) / 2;
var yc = (point.y + snake.points[i + 1].y) / 2;
ctx.quadraticCurveTo( point.x, point.y, xc, yc );
}
ctx.stroke();
}
The difficult part is the physic function.
function physic( snake ){
snake.points[2].x++ // An example
}

Categories

Resources