How to move an object in some defined angle? - javascript

"I am making a game in which I need to move an object to a target position. I am half the way but the ball has many defects like:1) If you keep tx=ty then it works fine but when you change it, the object is displaced, but why?2) If you keep the target behind the object, the object does not move, why?"
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var cx = 100;
var cy = 100;
var r1 = 25;
var r2 = 50;
var a = 10;
var tx = 500;
var ty = 400;
function draw() {
var vx = Math.cos(Math.atan2(ty, tx));
var vy = Math.sin(Math.atan2(ty, tx));
if(cx < tx && cy < ty){
cx += vx + a;
cy += vy + a;
}
ctx.clearRect(0, 0, c.width, c.height);
// target
ctx.fillStyle = "blue";
ctx.strokeStyle = "rgb(0, 0, 179)";
ctx.lineWidth = 20;
ctx.beginPath();
ctx.arc(tx, ty, r2, 0, 2 * Math.PI);
ctx.stroke();
ctx.fill();
// ball
ctx.fillStyle = "red";
ctx.strokeStyle = "rgb(179, 0, 0)";
ctx.lineWidth = 20;
ctx.beginPath();
ctx.arc(cx, cy, r1, 0, 2 * Math.PI);
ctx.stroke();
ctx.fill();
requestAnimationFrame(draw);
}
requestAnimationFrame(draw);

1 => Can you give an example in an edit to your question?
2 => This is probably because you check in your if statement this: cx < tx && cy < ty.
That means when cx and cy are both smaller then tx and ty.
Working snippet:
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var cx = 100;
var cy = 100;
var r1 = 25;
var r2 = 50;
var a = 0.5; // Made edit to 0.5 to move it slower
var tx = 500; // Made edit from t_x to tx
var ty = 400; // Made edit from t_y to ty
function draw() {
var vx = Math.cos(Math.atan2(ty, tx));
var vy = Math.sin(Math.atan2(ty, tx));
if(cx < tx && cy < ty){
cx += vx + a;
cy += vy + a;
}
ctx.clearRect(0, 0, c.width, c.height);
// target
ctx.fillStyle = "blue";
ctx.strokeStyle = "rgb(0, 0, 179)";
ctx.lineWidth = 20;
ctx.beginPath();
ctx.arc(tx, ty, r2, 0, 2 * Math.PI); // Edit t_x and t_y to tx and ty
ctx.stroke();
ctx.fill();
// ball
ctx.fillStyle = "red";
ctx.strokeStyle = "rgb(179, 0, 0)";
ctx.lineWidth = 20;
ctx.beginPath();
ctx.arc(cx, cy, r1, 0, 2 * Math.PI);
ctx.stroke();
ctx.fill();
requestAnimationFrame(draw);
}
requestAnimationFrame(draw);
<canvas id="canvas"></canvas>

Related

Circle is not connecting through lines properly using Canvas

I am trying to create 11 circles which connected through lines with a middle circle. I am trying to draw the circles. Here I have doing some r&d but I could not able to make lines. Please help me to complete this.
var canvas, ctx;
var circlePoints = [];
function createCanvasPainting() {
canvas = document.getElementById('myCanvas');
if (!canvas || !canvas.getContext) {
return false;
}
canvas.width = 600;
canvas.height = 600;
ctx = canvas.getContext('2d');
ctx.strokeStyle = '#B8D9FE';
ctx.fillStyle = '#B8D9FE';
ctx.translate(300, 250);
ctx.arc(0, 0, 50, 0, Math.PI * 2); //center circle
ctx.stroke();
ctx.fill();
var angleRotate = 0;
for (var i=0; i<11; i++) {
if (i > 0) {
angleRotate += 32.72;
}
lineToAngle(ctx, 0, 0, 200, angleRotate);
}
}
function lineToAngle(ctx, x1, y1, length, angle) {
angle *= Math.PI / 180;
var x2 = x1 + length * Math.cos(angle),
y2 = y1 + length * Math.sin(angle);
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.lineWidth = 1;
ctx.arc(x2, y2, 40, 0, Math.PI * 2);
ctx.fill();
ctx.stroke();
circlePoints.push({x: x2, y: y2});
// console.log(circlePoints);
}
createCanvasPainting();
<canvas id="myCanvas"></canvas>
Here is my JSFiddle Link
See below I removed all the "noise" from your code.
Just circles with lines connecting with a middle circle.
canvas = document.getElementById('myCanvas');
canvas.width = canvas.height = 200;
ctx = canvas.getContext('2d');
ctx.lineWidth = 1;
ctx.translate(99, 99);
angle = 0;
function draw() {
ctx.clearRect(-99, -99, 200, 200);
ctx.beginPath();
ctx.arc(0, 0, 35 + Math.cos(angle / 3000), 0, Math.PI * 2);
ctx.stroke();
ctx.fill();
for (var i = 0; i < 11; i++) {
a = angle * Math.PI / 180;
x = 80 * Math.cos(a)
y = 80 * Math.sin(a)
ctx.beginPath();
ctx.arc(x, y, 18, 0, Math.PI * 2);
ctx.moveTo(x, y);
ctx.lineTo(0, 0);
ctx.fill();
ctx.stroke();
angle += 32.7;
}
}
setInterval(draw, 10);
<canvas id="myCanvas"></canvas>

How to get coordinates of every circle from this Canvas

I need to create a pattern where 5 circles connected by lines to a middle main circle.
So I have created dynamically by rotating in some certain angle. Now I need each and every circle's x and y axis coordinates for capturing the click events on every circle.
Please help me how to find out of coordinates of every circle?
var canvas, ctx;
function createCanvasPainting() {
canvas = document.getElementById('myCanvas');
if (!canvas || !canvas.getContext) {
return false;
}
canvas.width = 600;
canvas.height = 600;
ctx = canvas.getContext('2d');
ctx.strokeStyle = '#B8D9FE';
ctx.fillStyle = '#B8D9FE';
ctx.translate(300, 250);
ctx.arc(0, 0, 50, 0, Math.PI * 2); //center circle
ctx.stroke();
ctx.fill();
drawChildCircles(5);
fillTextMultiLine('Test Data', 0, 0);
drawTextInsideCircles(5);
}
function drawTextInsideCircles(n) {
let ang_unit = Math.PI * 2 / n;
ctx.save();
for (var i = 0; i < n; i++) {
ctx.rotate(ang_unit);
//ctx.moveTo(0,0);
fillTextMultiLine('Test Data', 200, 0);
ctx.strokeStyle = '#B8D9FE';
ctx.fillStyle = '#B8D9FE';
}
ctx.restore();
}
function drawChildCircles(n) {
let ang_unit = Math.PI * 2 / n;
ctx.save();
for (var i = 0; i < n; ++i) {
ctx.rotate(ang_unit);
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(100,0);
ctx.arc(200, 0, 40, 0, Math.PI * 2);
let newW = ctx.fill();
ctx.stroke();
}
ctx.restore();
}
function fillTextMultiLine(text, x, y) {
ctx.font = 'bold 13pt Calibri';
ctx.textAlign = 'center';
ctx.fillStyle = "#FFFFFF";
// Defining the `textBaseline`…
ctx.textBaseline = "middle";
var lineHeight = ctx.measureText("M").width * 1.2;
var lines = text.split("\n");
for (var i = 0; i < lines.length; ++i) {
// console.log(lines);
if (lines.length > 1) {
if (i == 0) {
y -= lineHeight;
} else {
y += lineHeight;
}
}
ctx.fillText(lines[i], x, y);
}
}
createCanvasPainting();
<canvas id="myCanvas"></canvas>
The problem here is that you are rotating the canvas matrix and your circles are not aware of their absolute positions.
Why don't you use some simple trigonometry to determine the center of your circle and the ending of the connecting lines ?
function lineToAngle(ctx, x1, y1, length, angle) {
angle *= Math.PI / 180;
var x2 = x1 + length * Math.cos(angle),
y2 = y1 + length * Math.sin(angle);
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
return {x: x2, y: y2};
}
Ref: Finding coordinates after canvas Rotation
After that, given the xy center of your circles, calculating if a coord is inside a circle, you can apply the following formula:
Math.sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)) < r
Ref: Detect if user clicks inside a circle

canvas js fill an arc with image

I am trying to fill a circle (arc) with an image.
Here is my code :
draw() {
ctx.save();
let boulePat = new Image();
switch(this.couleur) {
case "red":
boulePat.src = "images/red.png";
break;
case "green":
boulePat.src = "images/green.png";
break;
case "orange":
boulePat.src = "images/orange.png";
break;
case "yellow":
boulePat.src = "images/yellow.png";
break;
case "purple":
boulePat.src = "images/purple.png";
break;
}
var pattern = ctx.createPattern(boulePat, "repeat");
ctx.beginPath();
ctx.arc(this.x, this.y, 15, 0, 2 * Math.PI);
ctx.fillStyle = pattern;
ctx.fill();
ctx.restore();
}
With this, I have empty or black circles ...
Could you help me, please ?
Thank you very much.
You have to wait for the image to load before you can use it in createPattern, like so:
See this stack answer
Keep in mind, the image will start from 0,0 coordinates in relation to the canvas. You will need to factor this into any offsets (using ctx.transform(xOffset, yOffset)) if necessary.
var canvas = document.getElementById("myCanvasNoTranslate");
var canvas2 = document.getElementById("myCanvasWithTranslate");
function drawCanvas(_canvas) {
var context = _canvas.getContext("2d");
draw(context);
}
function draw(ctx) {
ctx.save();
ctx.strokeSyle = "rgb(0, 0, 0)";
ctx.lineWidth = 3;
ctx.strokeRect(0, 0, 400, 200);
let boulePat = new Image();
boulePat.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e9/16777216colors.png/100px-16777216colors.png";
boulePat.onload = function () {
var pattern = ctx.createPattern(boulePat, "repeat");
ctx.fillStyle = pattern;
ctx.beginPath();
ctx.arc(100, 100, 50, 0, 2 * Math.PI);
// translate canvas to offset where the image coordinates are for .fill()
if (ctx.canvas === canvas2) {
ctx.translate(50, 50);
}
ctx.fill();
// restore ctx back to before the translate()
ctx.restore();
}
}
drawCanvas(canvas);
drawCanvas(canvas2);
With ctx.translate() for background fill<br/>
<canvas id="myCanvasWithTranslate" height="200px" width="400px"></canvas>
<br/><br/>
Without ctx.translate() for background fill<br/>
<canvas id="myCanvasNoTranslate" height="200px" width="400px"></canvas>
The code below takes an image URL, the radius of the arc, and the angle/size of the arc, and returns a canvas that has that image clipped to the given arc, and "contained" within the arc such that the image fills the arc without changing the image's aspect ratio:
async function getArcClippedCanvas(imageUrl, radius, arcSizeDeg) {
let arcSizeRad = (arcSizeDeg/360)*2*Math.PI;
// derive required width and height of canvas from radius and arc size
let width;
if(arcSizeDeg >= 180) {
width = radius*2;
} else {
width = radius*Math.sin(arcSizeRad/2)*2;
}
let height;
if(arcSizeDeg <= 180) {
height = radius;
} else {
height = radius + radius*Math.sin( (arcSizeRad-Math.PI)/2 );
}
let arcCenterX = width/2;
let arcCenterY = radius; // remember, y axis starts from top of canvas
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
let img = new Image();
await new Promise(resolve => {
img.onload = resolve;
img.src = imageUrl;
});
let centerAngle = -Math.PI/2;
ctx.beginPath();
ctx.moveTo(arcCenterX, arcCenterY);
ctx.arc(arcCenterX, arcCenterY, radius, centerAngle - (arcSizeDeg/2)*2*Math.PI/360, centerAngle + (arcSizeDeg/2)*2*Math.PI/360);
ctx.clip();
// we want to "cover" the canvas with the image without changing the image's aspect ratio
drawImageToCanvasContained(ctx, img, 0, 0, canvas.width, canvas.height);
return canvas;
}
function drawImageToCanvasContained(ctx, img, x, y, w, h, offsetX, offsetY) {
// By Ken Fyrstenberg Nilsen: https://stackoverflow.com/a/21961894/11950764
if(arguments.length === 2) {
x = y = 0;
w = ctx.canvas.width;
h = ctx.canvas.height;
}
// default offset is center
offsetX = typeof offsetX === "number" ? offsetX : 0.5;
offsetY = typeof offsetY === "number" ? offsetY : 0.5;
// keep bounds [0.0, 1.0]
if(offsetX < 0) offsetX = 0;
if(offsetY < 0) offsetY = 0;
if(offsetX > 1) offsetX = 1;
if(offsetY > 1) offsetY = 1;
let iw = img.width;
let ih = img.height;
let r = Math.min(w / iw, h / ih);
let nw = iw * r; // new prop. width
let nh = ih * r; // new prop. height
let cx, cy, cw, ch, ar = 1;
// decide which gap to fill
if(nw < w) ar = w / nw;
if(Math.abs(ar - 1) < 1e-14 && nh < h) ar = h / nh; // updated
nw *= ar;
nh *= ar;
// calc source rectangle
cw = iw / (nw / w);
ch = ih / (nh / h);
cx = (iw - cw) * offsetX;
cy = (ih - ch) * offsetY;
// make sure source rectangle is valid
if(cx < 0) cx = 0;
if(cy < 0) cy = 0;
if(cw > iw) cw = iw;
if(ch > ih) ch = ih;
// fill image in dest. rectangle
ctx.drawImage(img, cx, cy, cw, ch, x, y, w, h);
}

java script canvas clock rotate number in correct position

clock digit display incorrect position how to rotate correct position .
I think does not colculate correct angle of each digit.
these lines of code have error and here is calculate angle of each digit
any one finde the error and how to solve this
and how to calculate analog clock wise digit
for (var n = 1; n <=12; n++) {
var theta = (n - 12) * (Math.PI * 2) / 12;
var x = clockRadius * 0.7 * Math.cos(theta);
var y = clockRadius * 0.7 * Math.sin(theta);
ctx.fillText(n, x, y);
ctx.rotate(theta);
}
clock image here
clock clocke
<canvas id="canvas" width="150" height="150"></canvas>
<script>
function init(){
clock();
setInterval(clock, 1000);
}
function toRad(degrees) {
return degrees * (Math.PI / 180);
}
function clock(){
var ctx = document.getElementById('canvas').getContext('2d');
var clockRadius = 110;
ctx.save();
ctx.clearRect(0,0,150,150);
ctx.translate(75,75);
ctx.scale(0.4,0.4);
ctx.rotate(-Math.PI/2);
ctx.fillStyle = "white";
ctx.lineWidth = 8;
ctx.lineCap = "round";
ctx.font = '22px Helvetica,Arial,sans-serif';
ctx.fillStyle = '#fff';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
var now = new Date($("#datetime").val());
//alert(now);
var sec = now.getSeconds();
var min = now.getMinutes();
var hr = now.getHours();
hr = hr>=12 ? hr-12 : hr;
for (var n = 1; n <=12; n++) {
var theta = (n - 12) * (Math.PI * 2) / 12;
var x = clockRadius * 0.7 * Math.cos(theta);
var y = clockRadius * 0.7 * Math.sin(theta);
ctx.fillText(n, x, y);
ctx.rotate(theta );
}
ctx.strokeStyle = "white";
ctx.save();
for (var i=0; i < 12; i++){
ctx.beginPath();
ctx.rotate(Math.PI/6);
ctx.moveTo(100,0);
ctx.lineTo(120,0);
ctx.stroke();
}
ctx.restore();
// Minute marks
ctx.save();
ctx.lineWidth = 5;
for (i=0;i<60;i++){
if (i%5!=0) {
ctx.beginPath();
ctx.moveTo(117,0);
ctx.lineTo(120,0);
ctx.stroke();
}
ctx.rotate(Math.PI/30);
}
ctx.restore();
ctx.fillStyle = "black";
// write Hours
ctx.strokeStyle = "#4D514E";
ctx.save();
ctx.rotate( hr*(Math.PI/6) + (Math.PI/360)*min + (Math.PI/21600)*sec )
ctx.lineWidth = 14;
ctx.beginPath();
ctx.moveTo(-20,0);
ctx.lineTo(80,0);
ctx.stroke();
ctx.restore();
// write Minutes
ctx.save();
ctx.rotate( (Math.PI/30)*min + (Math.PI/1800)*sec )
ctx.lineWidth = 10;
ctx.beginPath();
ctx.moveTo(-28,0);
ctx.lineTo(110,0);
ctx.stroke();
ctx.restore();
// Write seconds
ctx.save();
ctx.rotate(sec * Math.PI/30);
ctx.strokeStyle = "#D40000";
ctx.fillStyle = "#D40000";
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(-30,0);
ctx.lineTo(110,0);
ctx.stroke();
ctx.beginPath();
ctx.arc(0,0,10,0,Math.PI*2,true);
ctx.fill();
ctx.beginPath();
ctx.arc(0,0,10,0,Math.PI*2,true);
ctx.stroke();
ctx.fillStyle = "rgba(0,0,0,0)";
ctx.arc(0,0,3,0,Math.PI*2,true);
ctx.fill();
ctx.restore();
ctx.beginPath();
ctx.lineWidth = 14;
ctx.strokeStyle = '#494545';
ctx.arc(0,0,142,0,Math.PI*2,true);
ctx.stroke();
ctx.restore();
} init();
</script>
You rotate the whole context in the line 7 of the clock function.
function clock(){
var ctx = document.getElementById('canvas').getContext('2d');
var clockRadius = 110;
ctx.save();
ctx.clearRect(0,0,150,150);
ctx.translate(75,75);
ctx.scale(0.4,0.4);
ctx.rotate(-Math.PI/2); // <-- remove this
ctx.fillStyle = "white";
...
You need to remove that. Instead of doing that you can just rotate when drawing the arms.
// write Hours
ctx.rotate( -Math.PI/2 + hr*(Math.PI/6) + (Math.PI/360)*min + (Math.PI/21600)*sec )
// write Minutes
ctx.rotate( -Math.PI/2 + (Math.PI/30)*min + (Math.PI/1800)*sec )
// Write seconds
ctx.rotate( -Math.PI/2 + sec * Math.PI/30);
(and the codes for drawing digits will need a minor fix)
var theta = (n - 3) * (Math.PI * 2) / 12;
function init(){
clock();
setInterval(clock, 1000);
}
function toRad(degrees) {
return degrees * (Math.PI / 180);
}
function clock(){
var ctx = document.getElementById('canvas').getContext('2d');
var clockRadius = 110;
ctx.save();
ctx.clearRect(0,0,150,150);
ctx.translate(75,75);
ctx.scale(0.4,0.4);
ctx.fillStyle = "white";
ctx.lineWidth = 8;
ctx.lineCap = "round";
ctx.font = '22px Helvetica,Arial,sans-serif';
ctx.fillStyle = '#fff';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
var now = new Date('2000/1/1 ' + $("#datetime").val());
//alert(now);
var sec = now.getSeconds();
var min = now.getMinutes();
var hr = now.getHours();
hr = hr>=12 ? hr-12 : hr;
for (var n = 1; n <=12; n++) {
var theta = (n - 3) * (Math.PI * 2) / 12;
var x = clockRadius * 0.7 * Math.cos(theta);
var y = clockRadius * 0.7 * Math.sin(theta);
ctx.fillText(n, x, y);
}
ctx.strokeStyle = "white";
ctx.save();
for (var i=0; i < 12; i++){
ctx.beginPath();
ctx.rotate(Math.PI/6);
ctx.moveTo(100,0);
ctx.lineTo(120,0);
ctx.stroke();
}
ctx.restore();
// Minute marks
ctx.save();
ctx.lineWidth = 5;
for (i=0;i<60;i++){
if (i%5!=0) {
ctx.beginPath();
ctx.moveTo(117,0);
ctx.lineTo(120,0);
ctx.stroke();
}
ctx.rotate(Math.PI/30);
}
ctx.restore();
ctx.fillStyle = "black";
// write Hours
ctx.strokeStyle = "#4D514E";
ctx.save();
ctx.rotate( -Math.PI/2 + hr*(Math.PI/6) + (Math.PI/360)*min + (Math.PI/21600)*sec )
ctx.lineWidth = 14;
ctx.beginPath();
ctx.moveTo(-20,0);
ctx.lineTo(80,0);
ctx.stroke();
ctx.restore();
// write Minutes
ctx.save();
ctx.rotate( -Math.PI/2 +(Math.PI/30)*min + (Math.PI/1800)*sec )
ctx.lineWidth = 10;
ctx.beginPath();
ctx.moveTo(-28,0);
ctx.lineTo(110,0);
ctx.stroke();
ctx.restore();
// Write seconds
ctx.save();
ctx.rotate(-Math.PI/2 +sec * Math.PI/30);
ctx.strokeStyle = "#D40000";
ctx.fillStyle = "#D40000";
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(-30,0);
ctx.lineTo(110,0);
ctx.stroke();
ctx.beginPath();
ctx.arc(0,0,10,0,Math.PI*2,true);
ctx.fill();
ctx.beginPath();
ctx.arc(0,0,10,0,Math.PI*2,true);
ctx.stroke();
ctx.fillStyle = "rgba(0,0,0,0)";
ctx.arc(0,0,3,0,Math.PI*2,true);
ctx.fill();
ctx.restore();
ctx.beginPath();
ctx.lineWidth = 14;
ctx.strokeStyle = '#494545';
ctx.arc(0,0,142,0,Math.PI*2,true);
ctx.stroke();
ctx.restore();
} init();
canvas {
background: blue;
}
<input type="time" id="datetime" value="03:45:01">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas" width="150" height="150"></canvas>
<script>
</script>
Since you call ctx.rotate(-Math.PI/2) at the beginning of your clock function, you need to rotate the digits back. To do this you'd need to translate context to a digit coordinates first, and then rotate the context by Math.PI/2.
Replace this part of code in your for loop:
ctx.fillText(n, x, y);
ctx.rotate(theta );
with this:
ctx.save();
ctx.translate(x, y);
ctx.rotate(Math.PI/2);
ctx.fillText(n, 0, 0);
ctx.restore();

Animate a Canvas Diamond Shape to Draw when scrolled to

I'm attempting to draw this shape on screen with canvas.
I have referenced this example which draws a circle: http://jsfiddle.net/loktar/uhVj6/4/ ,but cannot figure it out. Any help would be greatly appreciated. I'm new to canvas.
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var endPercent = 85;
var curPerc = 0;
var counterClockwise = false;
var circ = Math.PI * 2;
var quart = Math.PI / 2;
context.lineWidth = 10;
context.strokeStyle = '#ad2323';
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.shadowBlur = 10;
context.shadowColor = '#656565';
function animate(current) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.arc(x, y, radius, -(quart), ((circ) * current) - quart, false);
context.stroke();
curPerc++;
if (curPerc < endPercent) {
requestAnimationFrame(function () {
animate(curPerc / 100)
});
}
}
animate();
I plan on having a bullet point on each angle that would pop up and slightly pause whenever the line gets to that point.

Categories

Resources