I am making a solar system with pre-made planets and want to know how to get more than one to rotate around the sun. I ran into the issue of not being able to rotate 2 at once. Any solutions?Here is current code:
Orbiting page:
var canvasP = document.getElementById("planetsOrbit");
var ctx2 = canvasP.getContext("2d");
var angle = 6 * Math.PI / 180;
var cx = window.innerWidth / 2;
var cy = window.innerHeight / 2.12;
var radiusNew = (window.innerHeight + window.innerWidth) * 0.15;
function resizeCanvasPOrbit() {
ctx2.clearRect(0, 0, canvasP.width, canvasP.height);
if (canvasP.width < window.innerWidth) {
canvasP.width = window.innerWidth * 0.99;
}'
if (canvasP.height < window.innerHeight)
{
canvasP.height = window.innerHeight * 0.98;
}
w = canvasP.width
h = canvasP.height
}
function draw(x, y) {
ctx2.clearRect(0, 0, w, h);
ctx2.save();
ctx2.beginPath();
ctx2.beginPath();
roa(x, y, window.innerHeight * window.innerWidth * 0.00008);
ctx2.stroke();
ctx2.restore();
};
function keepDrawing() {
ctx2.clearRect(0, 0, w, h);
draw(newX, newY);
setTimeout(keepDrawing, 250);
}
window.requestAnimFrame = (function (callback) {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 5000 / 60);
};
})();
var fps = 60;
function animate() {
setTimeout(function () {
requestAnimationFrame(animate);
// increase the angle of rotation A.K.A SPEED!
angle += 1 * Math.PI / 3600;
//calculate the new ball.x / ball.y
var newX = cx - radiusNew * Math.cos(angle);
var newY = cy + radiusNew * Math.sin(angle);
//draw
ctx2.clearRect(0, 0, w, h);
draw(newX, newY);
//draw the centerpoint
ctx2.beginPath();
ctx2.arc(cx, cy, radiusNew, 0, Math.PI * 2, false);
ctx2.closePath();
}, 1000 / fps);
}
animate();
and the Premade Planets:
//sun
solus = function(xAxis, yAxis, radius) {
ctx.shadowBlur=400
ctx.shadowColor="red"
ctx.fillStyle ="#ff9900";
ctx.beginPath();
ctx.arc(xAxis, yAxis, radius, 0, Math.PI * 2, false)
ctx.fill();
ctx.shadowBlur = 0;
}
//Fighting Pits
pits = function(xAxis, yAxis, radius) {
ctx.beginPath();
ctx.fillStyle ="#990000"
ctx.arc(xAxis, yAxis, radius, 0, Math.PI , false)
ctx.moveTo(xSpot1,ySpot1)
ctx.lineTo(xSpot1,ySpot2)
ctx.lineTo(xSpot2,ySpot2)
ctx.lineTo(xSpot2,ySpot3)
ctx.lineTo(xSpot3,ySpot4)
ctx.lineTo(xSpot4,ySpot3)
ctx.lineTo(xSpot4,ySpot2)
ctx.lineTo(xSpot5,ySpot2)
ctx.lineTo(xSpot5,ySpot1)
ctx.lineTo(xSpot1,ySpot1)
ctx.fill();
}
//Water Planet
roa = function(xAxis, yAxis, radius) {
ctx2.shadowBlur = 0;
ctx2.beginPath();
ctx2.fillStyle ="#00ffff"
ctx2.arc(xAxis, yAxis, radius, 0, Math.PI * 2, false)
ctx2.fill();
}
//Forest planet atmoshpere
eldridA = function(xAxis, yAxis, radius) {
ctx.beginPath();
ctx.fillStyle ="rgba(230, 230, 230, 0.3)";
ctx.arc(xAxis, yAxis, radius, 0, Math.PI * 2, false)
ctx.fill();
}
//forest core
eldrid = function(xAxis, yAxis, radius) {
ctx.shadowColor = "rgba(230, 230, 230, 0.2)";
ctx.shadowBlur = 200;
ctx.beginPath();
ctx.fillStyle ="#ff9900"
ctx.arc(xAxis, yAxis, radius / 2, 0, Math.PI * 2, false)
ctx.fill();
xAxis2 = xAxis - window.innerWidth * 0.009
yAxis2 = yAxis + window.innerHeight * 0.007
ctx.arc(xAxis2, yAxis2, radius / 4, 0, Math.PI * 2, false)
ctx.fill();
ctx.beginPath();
xAxis3 = xAxis + window.innerWidth * 0.011
ctx.arc(xAxis3 , yAxis2, radius / 3, 0, Math.PI * 2, false)
ctx.fill();
ctx.beginPath();
yAxis3 = yAxis - window.innerHeight * 0.03
ctx.arc(xAxis, yAxis3, radius / 3, 0, Math.PI * 2, false)
ctx.fill();
ctx.shadowBlur = 0;
ctx.shadowColor = null;
}
So how can I get more than one planet to orbit the Sun? any Help is appreciated.
I did a simple demo of a solar system with multiple planets using canvas: http://codepen.io/giladaya/pen/PWWKLP
I believe that you can easily adapt it to your needs and I'll explain the main parts of the code:
Each planet has it's own properties like radius, distance from center, radial velocity and a reference to a draw function.
var planets = [
{
name: 'sun', // for reference
rad: 30, // Planet radius
distance: 0, // Planet distance from center
rv: 0, // radial velocity (deg/sec)
drawFunc: drawSun // draw function
},
{
name: 'foo',
rad: 10,
distance: 70,
rv: 1,
drawFunc: drawBlue
},
{
name: 'bar',
rad: 15,
distance: 100,
rv: 2,
drawFunc: drawRed
}
];
The main loop iterates over all the planets, updates their current angle according to the radial velocity and draws each one in it's new, updated location.
function draw() {
ctx.fillRect(-cW/2, -cH/2, cW, cH);
var now = Date.now(),
dts = (now - lastFrameTime) / 1000;
planets.forEach(function(planet, idx){
var theta = 0;
planetsAngle[idx] += planet.rv/Math.PI * dts;
theta = planetsAngle[idx];
var x = planet.distance * Math.cos(theta);
var y = planet.distance * Math.sin(theta);
planet.drawFunc(ctx, x, y, planet.rad);
});
lastFrameTime = now;
requestAnimationFrame(draw);
}
Note that if using requestAnimationFrame, you don't need to set timers.
The draw function for each planet can be as complicated as you want in order to have more elements on the planet. For example:
function drawRed(ctx, x, y, rad) {
ctx.save();
ctx.fillStyle = 'red';
ctx.translate(x, y);
ctx.beginPath();
ctx.arc(0, 0, rad, 0, 2*Math.PI , false);
ctx.fill();
ctx.fillStyle = '#A00';
ctx.fillRect(-4, -4, 8, 8);
ctx.restore();
}
Related
I would like to be able to simulate the movement of the body on a "carousel" with respect to physics. (centripetal, centrifugal force, angular speed). Below is some sample code.
<!DOCTYPE html>
<html>
<head>
<script>
var rotate = Math.PI / 180;
var ballRotation = 1;
function drawthis() {
var friction = 0.5;
context.setTransform(1, 0, 0, 1, 0, 0);
context.clearRect(0, 0, cvs.width, cvs.height);
context.translate(350, 350);
context.rotate(rotate);
context.beginPath();
context.arc(1, 1, 12, 0, 2 * Math.PI, false);
context.fill();
context.beginPath();
context.arc(0, 0, 150, 0, Math.PI * 2, false);
context.lineWidth = 6;
context.stroke();
motion = ballRotation - friction;
rotate += motion;
requestAnimationFrame(drawthis);
}
function init() {
cvs = document.getElementById("canvas");
context = cvs.getContext("2d");
context.clearRect(0, 0, context.width, context.height);
context.fillStyle = "#ff0000";
requestAnimationFrame(drawthis);
}
</script>
</head>
<body onload="init()">
<canvas id="canvas" width="800" height="800"></canvas>
</body>
</html>
I mean something like this
Ball on a turn table
Below you will find a simple simulation of a point sliding on a turning wheel. The point represents the contact point of a ball.
The simulation ignores the fact that the ball can roll, or has mass.
The ball slides via a simple friction model, where friction is a scalar value applied to the difference between the balls speed vector, and the speed of the wheel at the point under the ball.
There is only 1 force involved. It is the force tangential to the vector from the ball to the wheel center, subtracted by the ball movement vector and then multiplied by the friction coefficient.
For details on how this is calculated see comments in the function ball.update()
Notes
That if the ball starts at the dead center of the wheel nothing will happen.
I could not workout if it was the path of the ball you wanted or just the simulation of the ball, so I added both.
The ball resets after it leaves the wheel.
The wheel is marked with text and center cross so its rotation can be seen.
const ROTATE = Math.PI / 50;
const WHEEL_SIZE = 0.6;
Math.rand = (min, max) => Math.random() * (max - min) + min;
Math.randPow = (min, max, p) => Math.random() ** p * (max - min) + min;
var friction = 0.35;
const ctx = canvas.getContext("2d");
requestAnimationFrame(mainLoop);
ctx.font = "30px arial";
ctx.textAlign = "center";
scrollBy(0, canvas.height / 2 - canvas.height / 2 * WHEEL_SIZE);
function mainLoop() {
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
wheel.update();
ball.update(wheel, arrow);
wheel.draw();
path.draw();
ball.draw();
arrow.draw(ball);
requestAnimationFrame(mainLoop);
}
const path = Object.assign([],{
draw() {
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.strokeStyle = "#F00";
ctx.lineWidth = 1;
ctx.beginPath();
for (const p of this) { ctx.lineTo(p.x, p.y) }
ctx.stroke();
},
reset() { this.length = 0 },
add(point) {
this.push({x: point.x, y: point.y});
if (this.length > 1000) { // prevent long lines from slowing render
this.shift()
}
}
});
const arrow = {
dx: 0,dy: 0,
draw(ball) {
if (this.dx || this.dy) {
const dir = Math.atan2(this.dy, this.dx);
// len is converted from frame 1/60th second to seconds
const len = Math.hypot(this.dy, this.dx) * 60;
const aXx = Math.cos(dir);
const aXy = Math.sin(dir);
ctx.setTransform(aXx, aXy, -aXy, aXx, ball.x, ball.y);
ctx.beginPath();
ctx.lineTo(0,0);
ctx.lineTo(len, 0);
ctx.moveTo(len - 4, -2);
ctx.lineTo(len, 0);
ctx.lineTo(len - 4, 2);
ctx.strokeStyle = "#FFF";
ctx.lineWidth = 2;
ctx.stroke();
}
}
};
const ball = {
x: canvas.width / 2 + 4,
y: canvas.height / 2,
dx: 0, // delta pos Movement vector
dy: 0,
update(wheel, arrow) {
// get distance from center
const dist = Math.hypot(wheel.x - this.x, wheel.y - this.y);
// zero force arrow
arrow.dx = 0;
arrow.dy = 0;
// check if on wheel
if (dist < wheel.radius) {
// get tangent vector direction
const tangent = Math.atan2(this.y - wheel.y, this.x - wheel.x) + Math.PI * 0.5 * Math.sign(wheel.dr);
// get tangent as vector
// which is distance times wheel rotation in radians.
const tx = Math.cos(tangent) * dist * wheel.dr;
const ty = Math.sin(tangent) * dist * wheel.dr;
// get difference between ball vector and tangent vector scaling by friction
const fx = arrow.dx = (tx - this.dx) * friction;
const fy = arrow.dy = (ty - this.dy) * friction;
// Add the force vector
this.dx += fx;
this.dy += fy;
} else if (dist > wheel.radius * 1.7) { // reset ball
// to ensure ball is off center use random polar coord
const dir = Math.rand(0, Math.PI * 2);
const dist = Math.randPow(1, 20, 2); // add bias to be close to center
this.x = canvas.width / 2 + Math.cos(dir) * dist;
this.y = canvas.height / 2 + Math.sin(dir) * dist;
this.dx = 0;
this.dy = 0;
path.reset();
}
// move the ball
this.x += this.dx;
this.y += this.dy;
path.add(ball);
},
draw() {
ctx.fillStyle = "#0004";
ctx.setTransform(1, 0, 0, 1, this.x + 5, this.y + 5);
ctx.beginPath();
ctx.arc(0, 0, 10, 0, 2 * Math.PI);
ctx.fill();
ctx.fillStyle = "#f00";
ctx.setTransform(1, 0, 0, 1, this.x, this.y);
ctx.beginPath();
ctx.arc(0, 0, 12, 0, 2 * Math.PI);
ctx.fill();
ctx.fillStyle = "#FFF8";
ctx.setTransform(1, 0, 0, 1, this.x - 5, this.y - 5);
ctx.beginPath();
ctx.ellipse(0, 0, 2, 3, -Math.PI * 0.75, 0, 2 * Math.PI);
ctx.fill();
},
}
const wheel = {
x: canvas.width / 2, y: canvas.height / 2, r: 0,
dr: ROTATE, // delta rotate
radius: Math.min(canvas.height, canvas.width) / 2 * WHEEL_SIZE,
text: "wheel",
update() { this.r += this.dr },
draw() {
const aXx = Math.cos(this.r);
const aXy = Math.sin(this.r);
ctx.setTransform(aXx, aXy, -aXy, aXx, this.x, this.y);
ctx.fillStyle = "#CCC";
ctx.strokeStyle = "#000";
ctx.lineWidth = 6;
ctx.beginPath();
ctx.arc(0, 0, this.radius, 0, 2 * Math.PI);
ctx.stroke();
ctx.fill();
ctx.strokeStyle = ctx.fillStyle = "#aaa";
ctx.lineWidth = 2;
ctx.beginPath();
ctx.lineTo(-20,0);
ctx.lineTo(20,0);
ctx.moveTo(0,-20);
ctx.lineTo(0,20);
ctx.stroke();
ctx.fillText(this.text, 0, this.radius - 16);
},
}
<canvas id="canvas" width="300" height="300"></canvas>
Centripetal force
Centripetal is the force towards the center of the turning wheel. However because the ball is sliding the force calculated is not a centripetal force.
You can calculate the centripetal force by scaling the vector from the ball to the center by the dot product of the "vector to center" dot "force vector"
The force vector on the ball is shown as a white arrow. The arrows size is the force as acceleration in pixels per second.
The vector is towards the center but will never point directly at the center of the wheel.
Approximation
This simulation is an approximation. You will need an understanding of calculus and differential equations to get closer to reality.
Using a more complex simulation would only be noticeable if the friction was very close or at 1 and it is easier then to just fix the ball to the wheel, scaling the position from center by an inverse power of the friction coefficient.
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>
I want to rotate a triangle in the center of itself.
I have this script:
var ctx = canvas.getContext('2d');
var angle = 30;
setInterval(rotate, 50);
function rotate() {
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.translate(150, 150); // x, y
ctx.rotate(angle * Math.PI / 180)
ctx.fillStyle = "yellow";
var path=new Path2D();
path.moveTo(-50+50,-25);
path.lineTo(-50,-50-25);
path.lineTo(-50-50,-25);
ctx.fill(path);
ctx.restore();
angle++;
}
<canvas id="canvas" width="1800" height="700"></canvas>
It rotates it, but not in the center. I want it to look like this:
var ctx = canvas.getContext('2d');
setInterval(rotate, 50);
var angle = 30;
function rotate() {
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.translate(50, 50);
ctx.rotate(angle * Math.PI / 180)
ctx.fillStyle = "green";
ctx.fillRect(-25, -25, 50, 50);
ctx.restore();
angle++;
}
<canvas id="canvas" width="1800" height="700"></canvas>
I think, I just have to get the width and hight of the triangle and devive it by 2, but I don't know, how to do that.
Thx for every answer!
What you want is the centroid of your shape.
var ctx = canvas.getContext('2d');
var angle = 30;
var points = [
{x:0, y:-25},
{x:-50, y:-75},
{x:-100, y:-25}
];
// first sum it all
var sums = points.reduce( (sum, point) => {
sum.x += point.x;
sum.y += point.y;
return sum;
}, {x:0, y:0});
// we want the mean
var centroid = {
x: sums.x / points.length,
y: sums.y / points.length
};
rotate();
function rotate() {
ctx.setTransform(1,0,0,1,0,0);
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// general position in canvas
ctx.translate(100, 100);
// move to centroid of our triangle
ctx.translate(centroid.x, centroid.y); // x, y
// rotate
ctx.rotate(angle * Math.PI / 180)
// go back to our initial position
ctx.translate(-centroid.x, -centroid.y); // x, y
ctx.fillStyle = "yellow";
var path=new Path2D();
path.moveTo(points[0].x, points[0].y);
path.lineTo(points[1].x, points[1].y);
path.lineTo(points[2].x, points[2].y);
ctx.fill(path);
// demo only
ctx.beginPath();
ctx.arc(centroid.x, centroid.y, 50, 0, Math.PI*2)
ctx.stroke();
angle++;
requestAnimationFrame( rotate );
}
<canvas id="canvas" width="1800" height="700"></canvas>
Create the Path once
You are using a Path2D object which is reusable.
If you create the triangle already centered on its origin (or any path for that matter) it is then trivial to rotate it.
Reusing the path object is also a lot quicker if you have a lot to render.
The function to creates a path from a set of points. It automatically centers the path to its own origin (defined by the mean of its points)
const point = (x, y) => ({x, y});
function createPath(...points) {
var cx = 0; cy = 0;
for (const p of points) {
cx += p.x;
cy += p.y;
}
cx /= points.length;
cy /= points.length;
const path = new Path2d;
for (const p of points) { path.lineTo(p.x - cx, p.y - cy); }
path.closePath();
return path;
}
To create the triangle
const triangle = createPath(point(0,-25), point(-50,-75), point(-100,-25));
Then you can render it rotated about its own origin with
function drawPath(path, x, y, angle) {
ctx.setTransform(1, 0, 0, 1, x, y);
ctx.rotate(angle);
ctx.stroke(path);
}
Example
Shows how to create various shapes centered on their means. Each shape is a path created once and then rendered as needed.
const point = (x, y) => ({x, y});
const triangle = createPath(point(0,-25), point(-50,-75), point(-100,-25));
const rectangle = createPath(point(0,-25), point(-50,-25), point(-50,-125), point(0,-125));
const thing = createPath(point(0,-12), point(-25,-12), point(-25,-62), point(0,-62), point(22,-35));
function drawPath(path, x, y, angle) {
ctx.setTransform(1, 0, 0, 1, x, y);
ctx.rotate(angle);
ctx.stroke(path);
}
function drawPath_V2(path, x, y, scale, angle, strokeStyle, fillStyle) {
ctx.setTransform(scale, 0, 0, scale, x, y);
ctx.rotate(angle);
fillStyle && (ctx.fillStyle = fillStyle, ctx.fill(path));
strokeStyle && (ctx.strokeStyle = strokeStyle, ctx.stroke(path));
}
function renderLoop(time) {
ctx.clearRect(0, 0, can.width, can.height);
const scale = Math.sin(time / 500) * 0.2 + 1.0;
const scale2 = Math.cos(time / 1000) * 0.4 + 1.0;
drawPath(triangle, 75, 74, time / 1000 * Math.PI); //360 every 2 second
// scale path
drawPath_V2(rectangle, 125, 125, scale, time / 2000 * Math.PI, "black"); //360 every 4 second
// fill scale path
drawPath_V2(thing, 125, 100, scale2, time / 3000 * Math.PI, "", "black");
ctx.setTransform(1, 0, 0, 1, 0, 0);
requestAnimationFrame(renderLoop);
}
requestAnimationFrame(renderLoop);
const can = Object.assign(document.createElement("canvas"), {width: 200, height: 200});
document.body.appendChild(can);
const ctx = can.getContext("2d");
function createPath(...points) {
var cx = 0; cy = 0;
for (const p of points) {
cx += p.x;
cy += p.y;
}
cx /= points.length;
cy /= points.length;
const path = new Path2D;
for (const p of points) {
path.lineTo(p.x - cx , p.y - cy);
}
path.closePath();
return path;
}
I am experiencing trouble in rotating a circle with HTML5 canvas.
the function is about control a circle,
but the scale is out of control...
anyone know how to adjust(or set rotate) the scale to fit the canvas circle?
The starting angle(0.7 pi) and endAngle(0.3 pi).
Do I need to reset the rotate?
--> ctx.rotate(Math.PI * 3 / 16);
-->(math.pi*15/10*1/8)
var degrees = 0;
var color = "lightblue";
var bgcolor = "#222";
var canvas, ctx, W, Htext;
function init_rpm(name, val) {
canvas = document.getElementById(name);
ctx = canvas.getContext("2d");
//dimensions
W = canvas.width;
H = canvas.height;
//Clear the canvas everytime a chart is drawn
ctx.clearRect(0, 0, W, H);
//Background 360 degree arc
ctx.beginPath();
ctx.lineWidth = 25;
ctx.strokeStyle = bgcolor;
ctx.arc(W / 2, H / 2, Math.floor(W / 3), 0.7 * Math.PI, 0.3 * Math.PI, false); //you can see thr src now
ctx.stroke();
//center circle
ctx.save();
ctx.beginPath();
ctx.strokeStyle = 'rgba(255, 255, 255, .2)';
ctx.lineWidth = 10;
ctx.arc(W / 2, H / 2, Math.floor(W / 3) - 40, 0.7 * Math.PI, 0.3 * Math.PI, false);
ctx.stroke();
ctx.restore();
// scale
ctx.save();
ctx.translate(300, 300);
for (var i = 0; i < 9; i++) {
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = 'rgba(255, 255, 255, .3)';
ctx.moveTo(130, 0);
ctx.lineTo(140, 0);
ctx.stroke();
ctx.rotate(Math.PI * 3 / 16);
}
ctx.restore();
//angle in radians =angle in drgrees*pi/180 make color
var percent = val / 8000 * 100;
ctx.beginPath();
ctx.lineWidth = 30;
// ctx.strokeStyle= color;
var my_gradient = ctx.createLinearGradient(0, 150, 250, 300);
my_gradient.addColorStop(0, "#B31918");
my_gradient.addColorStop(1, "#FFA000");
ctx.strokeStyle = my_gradient;
//the arc start from the rightmost end. if we deduct 90 degrees from the angles
//the arc will start from the top most end
ctx.arc(W / 2, H / 2, Math.floor(W / 3), 0.7 * Math.PI, 0.7 * Math.PI + 1.6 * Math.PI / 100 * percent, false); //you can see thr src now
ctx.stroke();
//add text
ctx.fillStyle = color;
ctx.font = "7vh play";
// text=Math.floor(degrees/360*8)+' RPM';
text = degrees / 360 * 8;
text_width = ctx.measureText(text).width;
ctx.fillText(text, W / 2 - text_width / 2, H / 2 + 15);
ctx.font = "3vh play";
text2 = 'RPM';
ctx.fillText(text2, W / 2 - text_width / 2, H / 2 + 70);
}
function draw(val, name, type) {
// console.log(val);
if (name != "" || name != null) {
if (type == "rpm") {
if (val != "" || val != null) {
degrees = val / 1000 / 8 * 360;
} else {
degrees = 180;
}
init_rpm(name, val);
} else if (type == "kmh") {
if (val != "" || val != null) {
degrees = val;
} else {
degrees = 180;
}
init_kmh(name);
}
} else {
console.log('can not find canvas id');
}
}
$(document).ready(function () {
//canvas init
draw(0, "canvas3", "rpm");
var rpmControl2 = document.querySelector('input[id=get_rpm]');
rpmControl2.addEventListener('input', function () {
draw(this.value, "canvas3", "rpm");
});
});
#canvas2{
display:inline;
}
body{
background:#333;
font-family: 'Play', sans-serif;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<div class="container-fluid">
<input id="get_rpm" type="number" value="0" min="0" max="8000" step="100" />
<span style="color:white">RPM</span>
<canvas id="canvas3" width="600" height="600"></canvas>
Your scale is drawn by drawing its lines in a single direction and then controlling the context's rotation to make all these lines point at a different angle.
Just like if you held a ruler always in the same direction and simply rotated the leaf of paper underneath.
So to control the rotation of your scale, you have to set the context's rotation (or leaf of paper) before you draw the first line.
var ctx = c.getContext('2d');
angle.oninput = function(e) {
ctx.clearRect(0, 0, c.width, c.height);
var rad = angle.value * (Math.PI / 180);
// move the context so its center be at 0,0
ctx.setTransform(1, 0, 0, 1, c.width/2, c.height/2);
// rotate it so we face the required angle
ctx.rotate(rad);
var stepAngle = Math.PI*2 / 14,
innerRad = c.width / 2.8,
outerRad = c.width / 2.5;
ctx.beginPath();
for(var i = 0; i < 12; i++) {
ctx.moveTo(0, innerRad); // move vertically
ctx.lineTo(0, outerRad); // draw line vertically
ctx.rotate(stepAngle); // rotate by fixed increment
}
ctx.stroke(); // all drawn, we can stroke
ctx.setTransform(1, 0, 0, 1, 0, 0); // reset context's position
};
angle.oninput();
<input type="range" min="0" max="360" id="angle"><br>
<canvas id="c" width="200" height="200"></canvas>
And with your code:
var degrees = 0;
var color = "lightblue";
var bgcolor = "#222";
var canvas, ctx, W, Htext;
function init_rpm(name, val) {
canvas = document.getElementById(name);
ctx = canvas.getContext("2d");
//dimensions
W = canvas.width;
H = canvas.height;
//Clear the canvas everytime a chart is drawn
ctx.clearRect(0, 0, W, H);
//Background 360 degree arc
ctx.beginPath();
ctx.lineWidth = 25;
ctx.strokeStyle = bgcolor;
ctx.arc(W / 2, H / 2, Math.floor(W / 3), 0.7 * Math.PI, 0.3 * Math.PI, false); //you can see thr src now
ctx.stroke();
//center circle
ctx.beginPath();
ctx.strokeStyle = 'rgba(255, 255, 255, .2)';
ctx.lineWidth = 10;
ctx.arc(W / 2, H / 2, Math.floor(W / 3) - 40, 0.7 * Math.PI, 0.3 * Math.PI, false);
ctx.stroke();
//EDITS BEGIN HERE
// scale
ctx.setTransform(1, 0, 0, 1, 300, 300);
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = 'rgba(255, 255, 255, .3)';
// there should be 10 lines
var stepAngle = (Math.PI * 2) / 10;
// begin angle
ctx.rotate(0.7 * Math.PI);
// draw only 9 of the 10 lines
for (var i = 0; i < 9; i++) {
ctx.moveTo(130, 0);
ctx.lineTo(140, 0);
ctx.rotate(stepAngle);
}
ctx.stroke();
ctx.setTransform(1, 0, 0, 1, 0, 0);
//EDITS END HERE
var percent = val / 8000 * 100;
ctx.beginPath();
ctx.lineWidth = 30;
var my_gradient = ctx.createLinearGradient(0, 150, 250, 300);
my_gradient.addColorStop(0, "#B31918");
my_gradient.addColorStop(1, "#FFA000");
ctx.strokeStyle = my_gradient;
//the arc start from the rightmost end. if we deduct 90 degrees from the angles
//the arc will start from the top most end
ctx.arc(W / 2, H / 2, Math.floor(W / 3), 0.7 * Math.PI, 0.7 * Math.PI + 1.6 * Math.PI / 100 * percent, false); //you can see thr src now
ctx.stroke();
//add text
ctx.fillStyle = color;
ctx.font = "7vh play";
// text=Math.floor(degrees/360*8)+' RPM';
text = degrees / 360 * 8;
text_width = ctx.measureText(text).width;
ctx.fillText(text, W / 2 - text_width / 2, H / 2 + 15);
ctx.font = "3vh play";
text2 = 'RPM';
ctx.fillText(text2, W / 2 - text_width / 2, H / 2 + 70);
}
function draw(val, name, type) {
// console.log(val);
if (name != "" || name != null) {
if (type == "rpm") {
if (val != "" || val != null) {
degrees = val / 1000 / 8 * 360;
} else {
degrees = 180;
}
init_rpm(name, val);
} else if (type == "kmh") {
if (val != "" || val != null) {
degrees = val;
} else {
degrees = 180;
}
init_kmh(name);
}
} else {
console.log('can not find canvas id');
}
}
$(document).ready(function () {
//canvas init
draw(0, "canvas3", "rpm");
var rpmControl2 = document.querySelector('input[id=get_rpm]');
rpmControl2.addEventListener('input', function () {
draw(this.value, "canvas3", "rpm");
});
});
#canvas2{
display:inline;
}
body{
background:#333;
font-family: 'Play', sans-serif;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<div class="container-fluid">
<input id="get_rpm" type="number" value="0" min="0" max="8000" step="100" />
<span style="color:white">RPM</span>
<canvas id="canvas3" width="600" height="600"></canvas>
Hi I try to make an animation. A circle should run from right to left. Now the problem is that no circle become drawed in the canvas. I check in chromes developer tool the console log but there was no error. Have anyone a idea what the mistake is?
window.onload = window.onresize = function() {
var C = 1; // canvas width to viewport width ratio
var el = document.getElementById("myCanvas");
var viewportWidth = window.innerWidth;
var viewportHeight = window.innerHeight;
var canvasWidth = viewportWidth * C;
var canvasHeight = viewportHeight;
el.style.position = "fixed";
el.setAttribute("width", canvasWidth);
el.setAttribute("height", canvasHeight);
var x = canvasWidth / 100;
var y = canvasHeight / 100;
var ballx = canvasWidth / 100;
var n;
window.ctx = el.getContext("2d");
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
// draw triangles
function init() {
ballx;
return setInterval(main_loop, 1000);
}
function drawcircles() {
function getRandomElement(array) {
if (array.length == 0) {
return undefined;
}
return array[Math.floor(Math.random() * array.length)];
}
var circles = [
'#FFFF00',
'#FF0000',
'#0000FF'
];
ctx.beginPath();
ctx.arc(ballx * 108, canvasHeight / 2, x * 5, 0, 2 * Math.PI, false);
ctx.fillStyle = JSON.stringify(getRandomElement(circles));
ctx.fill();
ctx.closePath;
}
function draw() {
var counterClockwise = false;
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
//first halfarc
ctx.beginPath();
ctx.arc(x * 80, y * 80, y * 10, 0 * Math.PI, 1 * Math.PI, counterClockwise);
ctx.lineWidth = y * 1;
ctx.strokeStyle = 'black';
ctx.stroke();
ctx.closePath;
//second halfarc
ctx.beginPath();
ctx.arc(x * 50, y * 80, y * 10, 0 * Math.PI, 1 * Math.PI, counterClockwise);
ctx.lineWidth = y * 1;
ctx.strokeStyle = 'black';
ctx.stroke();
ctx.closePath;
//third halfarc
ctx.beginPath();
ctx.arc(x * 20, y * 80, y * 10, 0 * Math.PI, 1 * Math.PI, counterClockwise);
ctx.lineWidth = y * 1;
ctx.strokeStyle = 'black';
ctx.stroke();
ctx.closePath;
// draw stop button
ctx.beginPath();
ctx.moveTo(x * 87, y * 2);
ctx.lineTo(x * 87, y * 10);
ctx.lineWidth = x;
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x * 95, y * 2);
ctx.lineTo(x * 95, y * 10);
ctx.lineWidth = x;
ctx.stroke();
ctx.closePath;
//circle
}
function update() {
ballx -= 0.1;
if (ballx < 0) {
ballx = -radius;
}
}
function main_loop() {
drawcircles();
draw();
update();
}
init();
function initi() {
console.log('init');
// Get a reference to our touch-sensitive element
var touchzone = document.getElementById("myCanvas");
// Add an event handler for the touchstart event
touchzone.addEventListener("mousedown", touchHandler, false);
}
function touchHandler(event) {
// Get a reference to our coordinates div
var can = document.getElementById("myCanvas");
// Write the coordinates of the touch to the div
if (event.pageX < x * 50 && event.pageY > y * 10) {
ballx += 1;
} else if (event.pageX > x * 50 && event.pageY > y * 10) {
ballx -= 1;
}
console.log(event, x, ballx);
draw();
}
initi();
draw();
}
<div id="gameArea">
<canvas id="myCanvas"></canvas>
</div>
Your call to draw() after calling drawcircles() has a ctx.clearRect - this clears the canvas (including the just drawn circles).
Moving drawcircles(); to after draw(); in main_loop will make the circle appear. Note that you have to wait for a bit for the circle to be drawn within the visible area.