I'm trying to make a simple animation for a wheel, and I'm not sure how to define the animation function of it.
index.html, can be found below, trying to keep the body clean... (no real reson).
<!DOCTYPE html>
<html>
<head>
</head>
<body>
</body>
</html>
javascript, can be found below or using the jsfiddle link.
I have compose the wheel from 2 main canvas, one is the outterWheel and the other one is the innerWheel which is filled to cover the lines of outterWheel, give the impression of a mechanical wheel.
let buttonDOM = document.createElement('canvas');
buttonDOM.id = 'outterWheel';
buttonDOM.width = 80;
buttonDOM.height = 60;
document.body.appendChild(buttonDOM);
ctx = document.getElementById('outterWheel').getContext('2d');
ctx.lineWidth = 2;
ctx.beginPath();
const smallLines = [ 0, 22.5, 45, 67.5, 90, 112.5, 135, 157.5, 180, 202.5, 225, 247.5, 270, 292.5, 315, 337.5 ];
ctx.fillStyle = "#76D7C4";
ctx.fillRect(0, 0, 80, 60);
ctx.arc(40, 30, 15, 0, 2 * Math.PI);
for (var angle of smallLines){
ctx.moveTo(40, 30);
ctx.lineTo(40 + 17 * Math.cos(angle * Math.PI * 2 / 360), 30 + 17 * Math.sin(angle * Math.PI * 2 / 360));
}
ctx.stroke();
buttonDOM = document.createElement('canvas');
buttonDOM.id = 'innerWheel';
buttonDOM.width = 80;
buttonDOM.height = 60;
document.body.appendChild(buttonDOM);
ctx = document.getElementById('innerWheel').getContext('2d');
ctx.lineWidth = 2;
ctx.beginPath();
ctx.fillStyle = "#76D7C4";
ctx.clearRect(0, 0, 80, 60);
ctx.arc(40, 30, 15, 0, 2 * Math.PI);
ctx.fillStyle = "#76D7C4";
ctx.fill();
for (var angle of smallLines){
ctx.moveTo(40, 30);
ctx.lineTo(40 + 18 * Math.cos((angle + 11.25) * Math.PI * 2 / 360), 30 + 18 * Math.sin((angle + 11.25) * Math.PI * 2 / 360));
}
ctx.stroke();
https://jsfiddle.net/nh63c28w/2/
At the moment you're using two <canvas> elements to draw your wheels. I'd recommend using a single instance for creating each wheel initially. With the help of the canvas.toDataURL() you can store a snapshot of your canvas' content to a element and re-use the two images to compose your final animation on the canvas.
To actually draw the animation we can utilize a combination of the translate(), rotate() and drawImage() methods. translate will move the context to a specific x & y position, rotate will rotate the canvas by a certain amount given in radians and drawImage will finally draw the given image at the context's current position.
To change the animation over time - like rotating the wheels - we need to re-trigger the animation function. This is done by the requestAnimationFrame() function which calls a given callBack function at the refreshrate of your monitor e.g. 60 times per second on a 60hz display.
For example:
let buttonDOM = document.createElement('canvas');
buttonDOM.id = 'outerWheel';
buttonDOM.width = 80;
buttonDOM.height = 60;
document.body.appendChild(buttonDOM);
ctx = document.getElementById('outerWheel').getContext('2d');
ctx.lineWidth = 2;
ctx.beginPath();
const smallLines = [0, 22.5, 45, 67.5, 90, 112.5, 135, 157.5, 180, 202.5, 225, 247.5, 270, 292.5, 315, 337.5];
ctx.fillStyle = "#76D7C4";
ctx.fillRect(0, 0, 80, 60);
ctx.arc(40, 30, 15, 0, 2 * Math.PI);
for (var angle of smallLines) {
ctx.moveTo(40, 30);
ctx.lineTo(40 + 17 * Math.cos(angle * Math.PI * 2 / 360), 30 + 17 * Math.sin(angle * Math.PI * 2 / 360));
}
ctx.stroke();
ctx.closePath();
let outerWheel = new Image();
outerWheel.src = buttonDOM.toDataURL();
ctx.lineWidth = 2;
ctx.beginPath();
ctx.clearRect(0, 0, 80, 60);
ctx.arc(40, 30, 15, 0, 2 * Math.PI);
ctx.fill();
for (var angle of smallLines) {
ctx.moveTo(40, 30);
ctx.lineTo(40 + 18 * Math.cos((angle + 11.25) * Math.PI * 2 / 360), 30 + 18 * Math.sin((angle + 11.25) * Math.PI * 2 / 360));
}
ctx.stroke();
ctx.closePath();
let innerWheel = new Image();
innerWheel.src = buttonDOM.toDataURL();
let innerWheelProperties = {
x: 75,
y: 100,
rotation: 0
};
let outerWheelProperties = {
x: 250,
y: 100,
rotation: 0
};
buttonDOM.width = 300;
buttonDOM.height = 200;
function animation() {
ctx.clearRect(0, 0, buttonDOM.width, buttonDOM.height);
ctx.save();
ctx.translate(innerWheelProperties.x, innerWheelProperties.y);
ctx.rotate(innerWheelProperties.rotation * Math.PI / 180);
ctx.drawImage(innerWheel, 0 - innerWheel.width / 2, 0 - innerWheel.height / 2);
ctx.restore();
ctx.save();
ctx.translate(outerWheelProperties.x, outerWheelProperties.y);
ctx.rotate(outerWheelProperties.rotation * Math.PI / 180);
ctx.drawImage(outerWheel, 0 - outerWheel.width / 2, 0 - outerWheel.height / 2);
ctx.restore();
outerWheelProperties.rotation++;
innerWheelProperties.rotation -= 0.5;
requestAnimationFrame(animation);
}
requestAnimationFrame(animation);
Related
So I looked at the answer here: Draw arrow head in canvas using Angle
But it didn't seem to do it the way I wanted. I definitely do not want to use rotate, what I would like, is based on an Angle in degrees (0 being up on the screen, 180 being down, etc) is draw an arrow pointing in that direction.
Now I slept through trig in highschool so the correct usage of Rads, Sin and Cos are... well, they elude me :(.
Anyways, I have the angle already computed, and based on that I want to draw like the following:
The top one is at 0 degrees in my computation, the lower one 90 degrees.
I'm using a 2d canvas as my draw surface.
Inspired by the trigonometry of this answer I made a line + two smaller lines for the arrow part.
const size = 200;
var canvas = document.querySelector("canvas")
canvas.width = size;
canvas.height = size;
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, size, size);
ctx.strokeStyle = "red"
function lineToAngle(ctx, x1, y1, length, angle) {
angle = (angle - 90) * 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.stroke();
ctx.fill();
return {
x: x2,
y: y2
};
}
function draw_arrow(ctx, x1, y1, length, angle) {
var pos = lineToAngle(ctx, x1, y1, length, angle);
lineToAngle(ctx, pos.x, pos.y, 10, angle - 135);
lineToAngle(ctx, pos.x, pos.y, 10, angle + 135);
}
var pos = draw_arrow(ctx, 50, 50, 50, 30);
ctx.strokeStyle = "blue"
for (var angle = 0; angle <= 360; angle += 30) {
draw_arrow(ctx, 100, 100, 60, angle);
}
<canvas></canvas>
Overkill maybe?
This may help or may not.
Rather than create the arrow (shape) with a set of draw calls you can create a
Path2D to hold the shape with the helper function Path (in demo code below) that converts a set of arrays (each array a sub path) to a Path2D object. For example. const arrow = Path([[0, 0, 180, 0], [160, -10, 180, 0, 160, 10]]); a simple line arrow. To draw the path call ctx.stroke(arrow) or ctx.fill(arrow);
Define a style using Style eg const red = Style(...["#F00", , 2, "round"])
Position, rotate, and scale
Then the function drawPath(ctx, path, style, centerX, centerY, deg, scale) where...
ctx context to draw on.
path path to draw
style style to use,
centerX, centerY point to rotate around
deg angle in degrees from 0 deg pointing up, and positive values moving clockwize
scale lets you set the scale and defaults to 1.
Example use
// draw red arrow pointing up
const arrow = Path([[0, 0, 180, 0], [160, -10, 180, 0, 160, 10]]);
const red = Style(...["#F00", , 2, "round"]);
drawPath(ctx, arrow, red, 200, 200, 0);
Demo
Working example draw 6 arrows using 3 styles rotating around center of canvas.
const Path = (paths) => {
var j = 0, xx, yy, path = new Path2D();;
for (const subPath of paths) {
j = 0;
while (j < subPath.length) {
const [x, y] = [subPath[j++], subPath[j++]];
j === 2 ?
path.moveTo(...([xx, yy] = [x, y])) :
xx === x && yy === y ? path.closePath() : path.lineTo(x, y);
}
}
return path;
}
const Style = (strokeStyle, fillStyle, lineWidth, lineJoin = "bevel") => ({strokeStyle, fillStyle, lineWidth, lineJoin});
const styles = {
redLine: Style(...["#F00", , 6, "round"]),
greenFill: Style(...[ , "#0A0"]),
fillAndLine: Style(...["#000", "#0AF", 2, "round"]),
};
const paths = {
lineArrow: Path([ [10, 0, 180, 0], [160, -10, 180, 0, 160, 10] ]),
fatArrow: Path([ [10, -5, 180, -5, 170, -15, 200, 0, 170, 15, 180, 5, 10, 5, 10, -5] ]),
diamondArrow: Path([ [60, 0, 100, -15, 150, 0, 100, 15, 60, 0] ]),
};
requestAnimationFrame(mainLoop);
const [W, H, ctx] = [can.width, can.height, can.getContext("2d")];
const DEG2RAD = Math.PI / 180, DEG_0_OFFSET = -90;
function drawPath(ctx, path, style, centerX, centerY, deg, scale = 1) {
const rad = (deg + DEG_0_OFFSET) * DEG2RAD;
const [ax, ay] = [Math.cos(rad) * scale, Math.sin(rad) * scale];
ctx.setTransform(ax, ay, -ay, ax, centerX, centerY);
Object.assign(ctx, style);
style.fillStyle && ctx.fill(path);
style.strokeStyle && ctx.stroke(path);
ctx.setTransform(1, 0, 0, 1, 0, 0);
}
function mainLoop(time) {
ctx.clearRect(0, 0, W, H);
drawPath(ctx, paths.fatArrow, styles.fillAndLine, W * 0.5, H * 0.5, (time / 15000) * 360, 0.5);
drawPath(ctx, paths.fatArrow, styles.greenFill, W * 0.5, H * 0.5, (time / 20000) * 360);
drawPath(ctx, paths.diamondArrow, styles.fillAndLine, W * 0.5, H * 0.5, (time / 30000) * 360, 0.5);
drawPath(ctx, paths.diamondArrow, styles.greenFill, W * 0.5, H * 0.5, (time / 60000) * 360);
drawPath(ctx, paths.lineArrow, styles.redLine, W * 0.5, H * 0.5, (time / 5000) * 360, 0.9);
drawPath(ctx, paths.lineArrow, styles.redLine, W * 0.5, H * 0.5, (time / 10000) * 360);
requestAnimationFrame(mainLoop);
}
<canvas id="can" width="400" height="400"></canvas>
I have drawn the curved line using below lines of code, I need to draw an arrowhead.For this I need to draw 2 lines wth some angle and rotate it some some angle. It is very confusing to draw. I am following the post present in the link provided for arrowhead.
.html
<canvas id = "canvas" width = "100px" height = "120px"></canvas>
.ts
arrow({ x: 10, y: 10 }, { x: 100, y: 140 }, 15); //function called on reload.
function arrow(p1, p2, size) {
var angle = Math.atan2((p2.y - p1.y), (p2.x - p1.x));
//curve line
ctx.strokeStyle = 'white';
ctx.beginPath();
ctx.lineWidth=3;
ctx.moveTo(40,0);
ctx.bezierCurveTo(30, 0, -70, 75, 100, 150);
ctx.lineTo(100,120)
ctx.stroke();
//to draw a triangle ??
}
I tried look a like
arrow({ x: 10, y: 10 }, { x: 100, y: 140 }, 15); //function called on reload.
function arrow(p1, p2, size) {
var angle = Math.atan2((p2.y - p1.y), (p2.x - p1.x));
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
//curve line
ctx.fillStyle = "";
ctx.fillRect(0,0,200,200);
ctx.strokeStyle = 'white';
ctx.beginPath();
ctx.lineWidth=3;
ctx.moveTo(40,20);
ctx.bezierCurveTo(30,40, -0,110, 100, 149.5);
ctx.moveTo(100,150.6);
ctx.lineTo(82,133);
ctx.stroke();
ctx.moveTo(100,149.7);
ctx.lineTo(76,146);
ctx.stroke();
//to draw a triangle ??
}
<canvas id = "canvas" width = "150px" height = "300px"></canvas>
You need some mathematics for this. This javascript method will draw a simple arrow head at the end of a line using canvas. It doesn't matter from which angle you come into the "arrow head".
//..come to the end of the line at some point
ctx.lineTo(tox, toy);
//draw the arrow head
ctx.lineTo(tox - headlen * Math.cos(angle + Math.PI / 5), toy - headlen * Math.sin(angle + Math.PI / 5));
ctx.moveTo(tox, toy);
ctx.lineTo(tox - headlen * Math.cos(angle - Math.PI / 5), toy - headlen * Math.sin(angle - Math.PI / 5));
So i have this basic script which makes 4 circles move around a centre, and I have put in two circles which are the route which the circles follow.. The problem is that there's odd unwanted lines joining the circles to the stationary one's. I think it may be because the line for the circles ctx.arc(cx, cy, 200, 200, 0, 2 * Math.PI); is within the draw function. Does anyone know how to solve this? (Placing the stationary circles outside the draw function causes them to disappear when the canvas is cleared.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var w = canvas.width;
var h = canvas.height;
var dd = 3;
var dd2 = 3;
var dd3 = 3;
var dd4 = 3;
var angle = 0;
var angle2 = 0;
var angle3 = 0;
var angle4 = 0;
var cx = 1000;
var cy = 1000;
var radius = 200;
var radius2 = 300;
var radius3 = 400;
var radius4 = 500;
var fps = 100;
ctx.fillStyle = "yellow";
ctx.strokeStyle = "skyblue";
(function () {
"use strict";
function draw(x, y) {
ctx.save();
ctx.clearRect(0, 0, w, h);
ctx.beginPath();
ctx.arc(cx, cy, 75, 75, 0, 2 * Math.PI);
ctx.fillStyle = "lightgray";
ctx.arc((x - 50 / 2) + 25, (y - 30 / 2) + 15, 25, 25, 0, 2 * Math.PI);
ctx.arc(cx, cy, 200, 200, 0, 2 * Math.PI);
ctx.stroke();
ctx.closePath();
ctx.restore();
}
function draw1(x1, y1) {
ctx.save();
ctx.beginPath();
ctx.fillStyle = "orange";
ctx.arc((x1 - 50 / 2) + 25, (y1 - 30 / 2) + 15, 25, 25, 0, 2 * Math.PI);
ctx.arc(cx, cy, 300, 300, 0, 2 * Math.PI);
ctx.stroke();
ctx.closePath();
ctx.restore();
}
function draw2(x2, y2) {
ctx.save();
ctx.beginPath();
ctx.fillStyle = "blue";
ctx.arc((x2 - 50 / 2) + 25, (y2 - 30 / 2) + 15, 25, 25, 0, 2 * Math.PI);
ctx.arc(cx, cy, 400, 400, 0, 2 * Math.PI);
ctx.stroke();
ctx.closePath();
ctx.restore();
}
function draw3(x3, y3) {
ctx.save();
ctx.beginPath();
ctx.fillStyle = "red";
ctx.arc((x3 - 50 / 2) + 25, (y3 - 30 / 2) + 15, 25, 25, 0, 2 * Math.PI);
ctx.arc(cx, cy, 500, 500, 0, 2 * Math.PI);
ctx.stroke();
ctx.closePath();
ctx.restore();
}
window.requestAnimFrame = (function (callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
window.setTimeout(callback, 1000 / fps);
};
}());
function animate() {
setTimeout(function () {
requestAnimFrame(animate);
ctx.beginPath();
angle += Math.acos(1 - Math.pow(dd / radius, 2) / 2);
var newX = cx + radius * Math.cos(angle),
newY = cy + radius * Math.sin(angle),
newX1 = cx + radius2 * Math.cos(angle2),
newY1 = cy + radius2 * Math.sin(angle2),
newX2 = cx + radius3 * Math.cos(angle3),
newY2 = cy + radius3 * Math.sin(angle3),
newX3 = cx + radius4 * Math.cos(angle4),
newY3 = cy + radius4 * Math.sin(angle4);
draw(newX, newY);
ctx.arc(cx, cy, radius, 0, Math.PI * 2);
ctx.closePath();
ctx.beginPath();
angle2 += Math.acos(1 - Math.pow(dd2 / radius2, 2) / 2);
draw1(newX1, newY1);
ctx.arc(cx, cy, radius2, 0, 2 * Math.PI);
ctx.closePath();
ctx.beginPath();
angle3 += Math.acos(1 - Math.pow(dd3 / radius3, 2) / 2);
draw2(newX2, newY2);
ctx.arc(cx, cy, radius3, 0, 2 * Math.PI);
ctx.closePath();
ctx.beginPath();
angle4 += Math.acos(1 - Math.pow(dd4 / radius4, 2) / 2);
draw3(newX3, newY3);
ctx.arc(cx, cy, radius4, 0, 2 * Math.PI);
ctx.closePath();
}, 1000 / fps);
}
animate();
}());
You have to use ctx.beginPath(), ctx.closePath() and ctx.stroke() for EVERY arc you create, else it will connect them with lines (as you yourself also would have to, if you were drawing and were not allowed to take the pencil off the paper):
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var w = canvas.width;
var h = canvas.height;
var dd = 3;
var dd2 = 3;
var dd3 = 3;
var dd4 = 3;
var angle = 0;
var angle2 = 0;
var angle3 = 0;
var angle4 = 0;
var cx = 1000;
var cy = 1000;
var radius = 200;
var radius2 = 300;
var radius3 = 400;
var radius4 = 500;
var fps = 100;
ctx.fillStyle = "yellow";
ctx.strokeStyle = "skyblue";
(function () {
"use strict";
function draw(x, y) {
ctx.save();
ctx.clearRect(0, 0, w, h);
ctx.beginPath();
ctx.arc(cx, cy, 75, 75, 0, 2 * Math.PI);
ctx.closePath();
ctx.stroke();
ctx.fillStyle = "lightgray";
ctx.beginPath();
ctx.arc((x - 50 / 2) + 25, (y - 30 / 2) + 15, 25, 25, 0, 2 * Math.PI);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.arc(cx, cy, 200, 200, 0, 2 * Math.PI);
ctx.closePath();
ctx.stroke();
ctx.restore();
}
function draw1(x1, y1) {
ctx.save();
ctx.fillStyle = "orange";
ctx.beginPath();
ctx.arc((x1 - 50 / 2) + 25, (y1 - 30 / 2) + 15, 25, 25, 0, 2 * Math.PI);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.arc(cx, cy, 300, 300, 0, 2 * Math.PI);
ctx.closePath();
ctx.stroke();
ctx.restore();
}
function draw2(x2, y2) {
ctx.save();
ctx.fillStyle = "blue";
ctx.beginPath();
ctx.arc((x2 - 50 / 2) + 25, (y2 - 30 / 2) + 15, 25, 25, 0, 2 * Math.PI);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.arc(cx, cy, 400, 400, 0, 2 * Math.PI);
ctx.closePath();
ctx.stroke();
ctx.restore();
}
function draw3(x3, y3) {
ctx.save();
ctx.fillStyle = "red";
ctx.beginPath();
ctx.arc((x3 - 50 / 2) + 25, (y3 - 30 / 2) + 15, 25, 25, 0, 2 * Math.PI);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.arc(cx, cy, 500, 500, 0, 2 * Math.PI);
ctx.closePath();
ctx.stroke();
ctx.restore();
}
window.requestAnimFrame = (function (callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
window.setTimeout(callback, 1000 / fps);
};
}());
function animate() {
setTimeout(function () {
requestAnimFrame(animate);
angle += Math.acos(1 - Math.pow(dd / radius, 2) / 2);
var newX = cx + radius * Math.cos(angle),
newY = cy + radius * Math.sin(angle),
newX1 = cx + radius2 * Math.cos(angle2),
newY1 = cy + radius2 * Math.sin(angle2),
newX2 = cx + radius3 * Math.cos(angle3),
newY2 = cy + radius3 * Math.sin(angle3),
newX3 = cx + radius4 * Math.cos(angle4),
newY3 = cy + radius4 * Math.sin(angle4);
draw(newX, newY);
ctx.arc(cx, cy, radius, 0, Math.PI * 2);
angle2 += Math.acos(1 - Math.pow(dd2 / radius2, 2) / 2);
draw1(newX1, newY1);
ctx.arc(cx, cy, radius2, 0, 2 * Math.PI);
angle3 += Math.acos(1 - Math.pow(dd3 / radius3, 2) / 2);
draw2(newX2, newY2);
ctx.arc(cx, cy, radius3, 0, 2 * Math.PI);
angle4 += Math.acos(1 - Math.pow(dd4 / radius4, 2) / 2);
draw3(newX3, newY3);
ctx.arc(cx, cy, radius4, 0, 2 * Math.PI);
}, 1000 / fps);
}
animate();
}());
<canvas id="canvas" width="2000" height="2000"></canvas>
E.g. I changed the following:
ctx.beginPath();
ctx.arc(cx, cy, 75, 75, 0, 2 * Math.PI);
ctx.fillStyle = "lightgray";
ctx.arc((x - 50 / 2) + 25, (y - 30 / 2) + 15, 25, 25, 0, 2 * Math.PI);
ctx.arc(cx, cy, 200, 200, 0, 2 * Math.PI);
ctx.stroke();
ctx.closePath();
Into this:
ctx.beginPath();
ctx.arc(cx, cy, 75, 75, 0, 2 * Math.PI);
ctx.closePath(); //Added
ctx.stroke(); //Added
ctx.fillStyle = "lightgray";
ctx.beginPath(); //Added
ctx.arc((x - 50 / 2) + 25, (y - 30 / 2) + 15, 25, 25, 0, 2 * Math.PI);
ctx.closePath(); //Added
ctx.stroke(); //Added
ctx.beginPath(); //Added
ctx.arc(cx, cy, 200, 200, 0, 2 * Math.PI);
ctx.closePath(); //Reversed order (doesn't really matter, but looks better IMO)
ctx.stroke(); //Reversed order (doesn't really matter, but looks better IMO)
I have two arcs with strokes and i want to have a line animate between them. The line should animate perpendicular to the points of the inner circle.
Here's something that I hacked together that is almost what I want.
things that are wrong with it are:
the length of the line is not the length between the 2 circle as it revolves around the inner circle.
sometimes the line is not perpendicular to the points of the inner circle. for example when it goes to the corner of the circle it tilts at an angle a little.
I had problem understanding how to use the trig function for lineTo. maybe because that changes the length of the line and I didn't know how to get the x and y coordinates of the outer circle to get the end point of the line. I'm used to doing math.cos * length and this gives me a line at an angle. I don't what a line I just wanted the coords of the outer circle.
window.onload = function(){
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
function lineAtAngle(startX, startY, angleDeg, length, startX2, startY2, angleDeg2, length2){
var angle = angleDeg * (Math.PI / 180);
var angle2 = angleDeg2 * (Math.PI / 180);
// context.moveTo(startX, startY);
context.beginPath();
context.moveTo(
Math.cos(angle) * length + startX,
Math.sin(angle) * length + startY
)
context.lineTo(
Math.cos(angle2) *(length2 )+ startX2,
Math.sin(angle2) *(length2) + startY2
)
// context.lineTo(canvas.width / 2 + 60, canvas.height / 2, angle2, length2)
context.lineWidth = 10;
context.stroke();
context.closePath();
console.log("startX2: " + startX2 + " startY2: " + startY2 )
console.log(Math.sin(angle2) + startY2)
console.log(length)
}
function myLineTo(startX, startY, angleDeg, length){
}
var length1 = canvas.width / 2 + 60 - canvas.width / 2 -30
var length2 = canvas.width / 2 ;
// var length2 = 1;
console.log(length2)
var angle1 = 0;
var angle2 = 0;
(function animate(){
context.clearRect(0,0, canvas.width, canvas.height);
window.requestAnimationFrame(animate);
context.beginPath()
context.arc(canvas.width / 2, canvas.height / 2, 30, 0, 2 * Math.PI, true)
context.lineWidth = 1;
context.stroke()
context.beginPath();
context.arc(canvas.width / 2, canvas.height / 2, 60, 0, 2 * Math.PI, true);
context.stroke();
context.closePath()
context.beginPath();
context.arc(canvas.width / 2, canvas.height / 2, 3, 0, 2 * Math.PI, true)
context.fill()
context.closePath();
angle1++
angle2++
// lineAtAngle(canvas.width / 2 , canvas.height / 2 , angle1, length1, canvas.width / 2 + 60, canvas.height / 2, angle2, length2 )
lineAtAngle(canvas.width / 2 , canvas.height / 2 , angle1, length1, canvas.width / 2 + 60, canvas.height / 2, angle2, length2 )
}())
}
canvas{
background: #aaa;
}
<canvas id="canvas" width="400" height="400"></canvas>
I believe the below is what you're trying to achieve.
I've simplified the code somewhat by using the Canvas's built-in methods to translate the coordinate space to the center and by removing the extra function which had way too many parameters passed when all it needed was one angle and two radii.
window.onload = function(){
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var radius1 = 30;
var radius2 = 60;
var angle = 0;
(function animate(){
context.clearRect(0, 0, canvas.width, canvas.height);
// save state and adjust coordinate space
context.save();
context.translate(canvas.width / 2, canvas.height / 2);
context.lineWidth = 1;
context.beginPath()
context.arc(0, 0, radius1, 0, 2 * Math.PI, true)
context.stroke()
context.beginPath();
context.arc(0, 0, radius2, 0, 2 * Math.PI, true);
context.stroke();
context.beginPath();
context.arc(0, 0, 3, 0, 2 * Math.PI, true);
context.fill()
++angle;
var rads = angle * Math.PI / 180;
var x = Math.cos(rads);
var y = Math.sin(rads);
context.lineWidth = 10;
context.beginPath();
context.moveTo(radius1 * x, radius1 * y);
context.lineTo(radius2 * x, radius2 * y);
context.stroke();
// restore transformations for next pass
context.restore();
window.requestAnimationFrame(animate)
}())
}
canvas { background: #aaa; }
<canvas id="canvas" width="400" height="200"></canvas>
The idea for drawing a line is that you need to supply a start point (moveTo), and an end point (lineTo). Your current code is complicating the whole thing with multiple angles and lengths. What you want to imagine you are doing is starting at the center of your circle, then adding an offset which places the start point at the edge of the inner circle. Using trig is perfectly fine here. The length of your line will simply be outer radius minus inner radius, in the same direction as your offset (only one angle was needed).
Without fundamentally changing your approach, the code below shows the changes you could use to try this. Have your line function take a starting point (x, y) and an offset, as well as the angle and length. The starting point is your circle center, and the offset is the radius of the inner circle. The length (again) is simply the outer radius minus the inner radius.
window.onload = function(){
var innerCircleRadius = 30;
var outerCircleRadius = 60;
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var angle1 = 0;
function lineAtAngle(startX, startY, angleDeg, offset, length) {
var angle = angleDeg * (Math.PI / 180); // Convert to radians.
var cosAngle = Math.cos(angle); // Only need cos(angle) once.
var sinAngle = Math.sin(angle); // Only need sin(angle) once.
var startXPos = cosAngle * offset + startX;
var startYPos = sinAngle * offset + startY;
var endXPos = cosAngle * length + startXPos;
var endYPos = sinAngle * length + startYPos;
context.beginPath();
context.moveTo(startXPos, startYPos);
context.lineTo(endXPos, endYPos);
context.lineWidth = 10;
context.stroke();
context.closePath();
}
(function animate() {
context.clearRect(0,0, canvas.width, canvas.height);
window.requestAnimationFrame(animate);
context.beginPath()
context.arc(canvas.width / 2, canvas.height / 2, innerCircleRadius, 0, 2 * Math.PI, true)
context.lineWidth = 1;
context.stroke()
context.beginPath();
context.arc(canvas.width / 2, canvas.height / 2, outerCircleRadius, 0, 2 * Math.PI, true);
context.stroke();
context.closePath()
context.beginPath();
context.arc(canvas.width / 2, canvas.height / 2, 3, 0, 2 * Math.PI, true)
context.fill()
context.closePath();
angle1++
lineAtAngle(canvas.width / 2 , canvas.height / 2 , angle1, innerCircleRadius, outerCircleRadius - innerCircleRadius);
}())
}
canvas {
background: #aaa;
}
<canvas id="canvas" width="400" height="400"></canvas>
I have created the following draw function:
function draw(ctx, scale, angle) {
// DRAW SHAPE:
var rotation = (Math.PI / 180) * angle;
var h = scale * (Math.sqrt(3) / 2);
var radius = h / 4;
ctx.fillStyle = '#BE1942';
ctx.strokeStyle = "#FF2159";
ctx.lineJoin = "round";
ctx.lineWidth = radius;
ctx.save();
ctx.translate(getCX(), getCY());
ctx.rotate(rotation);
ctx.beginPath();
ctx.moveTo(0, -h / 2);
ctx.lineTo(-scale / 2, h / 2);
ctx.lineTo(scale / 2, h / 2);
ctx.lineTo(0, -h / 2);
ctx.closePath();
ctx.stroke();
ctx.fill();
// RESET:
ctx.restore();
// FINALIZE:
ctx.save();
}
I have noticed that when I rotate this triangle, it does not rotate around the true centre, but much rather at an offset. Is there a simple way to make it rotate around the true centre? I assumed it should already do that since I am drawing it from the centre coordinates.
Your x,y do not add up to 0,0, but to (0, h/2)
ctx.moveTo(0, -h / 2);
ctx.lineTo(-scale / 2, h / 2);
ctx.lineTo(scale / 2, h / 2);
So modify your translation, or say
ctx.moveTo(0, -2*h / 3);
ctx.lineTo(-scale / 2, h / 3);
ctx.lineTo(scale / 2, h / 3);
ctx.lineTo(0, -2*h / 3);