i'm working on a spinner i am stuck on how to set specific percentage to the spinner.
Here is my demo => https://jsfiddle.net/fmvucqno/
inside options variable i have 10% and 90% i want to achieve 10% fill and 90% fill on the usernames.
<input type="button" value="spin" style="float:left;" id='spin'/>
<canvas id="canvas" width="500" height="500"></canvas>
<body style="background-color: white">
<script>
var options = [
[
'#david',
'10%',
],
[
'#burn',
'90%'
]
];
var startAngle = 0;
var arc = Math.PI / (options.length / 2);
var spinTimeout = null;
var spinArcStart = 10;
var spinTime = 0;
var spinTimeTotal = 0;
var ctx;
document.getElementById("spin").addEventListener("click", spin);
function byte2Hex(n)
{
var nybHexString = "0123456789ABCDEF";
return String(nybHexString.substr((n >> 4) & 0x0F, 1)) + nybHexString.substr(n & 0x0F, 1);
}
function RGB2Color(r, g, b)
{
return '#' + byte2Hex(r) + byte2Hex(g) + byte2Hex(b);
}
function getColor(item, maxitem)
{
var phase = 0;
var center = 128;
var width = 127;
var frequency = Math.PI * 2 / maxitem;
red = Math.sin(frequency * item + 2 + phase) * width + center;
green = Math.sin(frequency * item + 0 + phase) * width + center;
blue = Math.sin(frequency * item + 4 + phase) * width + center;
return RGB2Color(red, green, blue);
}
function drawRouletteWheel()
{
var canvas = document.getElementById("canvas");
if (canvas.getContext)
{
var outsideRadius = 200;
var textRadius = 160;
var insideRadius = 125;
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, 500, 500);
ctx.strokeStyle = "black";
ctx.lineWidth = 2;
ctx.font = 'bold 12px Helvetica, Arial';
for (var i = 0; i < options.length; i++)
{
var angle = startAngle + i * arc;
ctx.fillStyle = getColor(i, options.length);
ctx.beginPath();
ctx.arc(250, 250, outsideRadius, angle, angle + arc, false);
ctx.arc(250, 250, insideRadius, angle + arc, angle, true);
ctx.stroke();
ctx.fill();
ctx.save();
ctx.shadowOffsetX = -1;
ctx.shadowOffsetY = -1;
ctx.shadowBlur = 0;
ctx.shadowColor = "rgb(220,220,220)";
ctx.fillStyle = "black";
ctx.translate(250 + Math.cos(angle + arc / 2) * textRadius,
250 + Math.sin(angle + arc / 2) * textRadius);
ctx.rotate(angle + arc / 2 + Math.PI / 2);
var text = options[i];
ctx.fillText(text, -ctx.measureText(text).width / 2, 0);
ctx.restore();
}
//Arrow
ctx.fillStyle = "black";
ctx.beginPath();
ctx.moveTo(250 - 4, 250 - (outsideRadius + 5));
ctx.lineTo(250 + 4, 250 - (outsideRadius + 5));
ctx.lineTo(250 + 4, 250 - (outsideRadius - 5));
ctx.lineTo(250 + 9, 250 - (outsideRadius - 5));
ctx.lineTo(250 + 0, 250 - (outsideRadius - 13));
ctx.lineTo(250 - 9, 250 - (outsideRadius - 5));
ctx.lineTo(250 - 4, 250 - (outsideRadius - 5));
ctx.lineTo(250 - 4, 250 - (outsideRadius + 5));
ctx.fill();
}
}
function spin()
{
spinAngleStart = Math.random() * 10 + 10;
spinTime = 0;
spinTimeTotal = Math.random() * 3 + 4 * 1000;
rotateWheel();
}
function rotateWheel()
{
spinTime += 30;
if (spinTime >= spinTimeTotal)
{
stopRotateWheel();
return;
}
var spinAngle = spinAngleStart - easeOut(spinTime, 0, spinAngleStart, spinTimeTotal);
startAngle += (spinAngle * Math.PI / 180);
drawRouletteWheel();
spinTimeout = setTimeout('rotateWheel()', 30);
}
function stopRotateWheel()
{
clearTimeout(spinTimeout);
var degrees = startAngle * 180 / Math.PI + 90;
var arcd = arc * 180 / Math.PI;
var index = Math.floor((360 - degrees % 360) / arcd);
ctx.save();
ctx.font = 'bold 30px Helvetica, Arial';
var text = options[index]
ctx.fillText(text, 250 - ctx.measureText(text).width / 2, 250 + 10);
ctx.restore();
}
function easeOut(t, b, c, d)
{
var ts = (t /= d) * t;
var tc = ts * t;
return b + c * (tc + -3 * ts + 3 * t);
}
drawRouletteWheel();
</script>
Although some options are set up for the different people, which include the percentage they should occupy, these are not actually used.
The arc is calculated to be equal for all users - Math.PI / (options.length / 2)
Instead we need to use the value given in the option for that user, and we have to gradually add to the start angle to know where to start the next arc.
Here's the snippet with the changes:
var options = [
[
'#david',
'10%',
],
[
'#burn',
'90%'
]
];
var startAngle = 0;
var arc = Math.PI / (options.length / 2);
var spinTimeout = null;
var spinArcStart = 10;
var spinTime = 0;
var spinTimeTotal = 0;
var ctx;
document.getElementById("spin").addEventListener("click", spin);
function byte2Hex(n)
{
var nybHexString = "0123456789ABCDEF";
return String(nybHexString.substr((n >> 4) & 0x0F, 1)) + nybHexString.substr(n & 0x0F, 1);
}
function RGB2Color(r, g, b)
{
return '#' + byte2Hex(r) + byte2Hex(g) + byte2Hex(b);
}
function getColor(item, maxitem)
{
var phase = 0;
var center = 128;
var width = 127;
var frequency = Math.PI * 2 / maxitem;
red = Math.sin(frequency * item + 2 + phase) * width + center;
green = Math.sin(frequency * item + 0 + phase) * width + center;
blue = Math.sin(frequency * item + 4 + phase) * width + center;
return RGB2Color(red, green, blue);
}
function drawRouletteWheel()
{
var canvas = document.getElementById("canvas");
if (canvas.getContext)
{
var outsideRadius = 200;
var textRadius = 160;
var insideRadius = 125;
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, 500, 500);
ctx.strokeStyle = "black";
ctx.lineWidth = 2;
ctx.font = 'bold 12px Helvetica, Arial';
var angle = startAngle;
for (var i = 0; i < options.length; i++)
{ arc = Math.PI * Number(options[i][1].replace('%','')) / 50;
ctx.fillStyle = getColor(i, options.length);
ctx.beginPath();
ctx.arc(250, 250, outsideRadius, angle, angle + arc, false);
ctx.arc(250, 250, insideRadius, angle + arc, angle, true);
ctx.stroke();
ctx.fill();
ctx.save();
ctx.shadowOffsetX = -1;
ctx.shadowOffsetY = -1;
ctx.shadowBlur = 0;
ctx.shadowColor = "rgb(220,220,220)";
ctx.fillStyle = "black";
ctx.translate(250 + Math.cos(angle + arc / 2) * textRadius,
250 + Math.sin(angle + arc / 2) * textRadius);
ctx.rotate(angle + arc / 2 + Math.PI / 2);
var text = options[i];
ctx.fillText(text, -ctx.measureText(text).width / 2, 0);
ctx.restore();
angle += (i+1) * arc;
}
//Arrow
ctx.fillStyle = "black";
ctx.beginPath();
ctx.moveTo(250 - 4, 250 - (outsideRadius + 5));
ctx.lineTo(250 + 4, 250 - (outsideRadius + 5));
ctx.lineTo(250 + 4, 250 - (outsideRadius - 5));
ctx.lineTo(250 + 9, 250 - (outsideRadius - 5));
ctx.lineTo(250 + 0, 250 - (outsideRadius - 13));
ctx.lineTo(250 - 9, 250 - (outsideRadius - 5));
ctx.lineTo(250 - 4, 250 - (outsideRadius - 5));
ctx.lineTo(250 - 4, 250 - (outsideRadius + 5));
ctx.fill();
}
}
function spin()
{
spinAngleStart = Math.random() * 10 + 10;
spinTime = 0;
spinTimeTotal = Math.random() * 3 + 4 * 1000;
rotateWheel();
}
function rotateWheel()
{
spinTime += 30;
if (spinTime >= spinTimeTotal)
{
stopRotateWheel();
return;
}
var spinAngle = spinAngleStart - easeOut(spinTime, 0, spinAngleStart, spinTimeTotal);
startAngle += (spinAngle * Math.PI / 180);
drawRouletteWheel();
spinTimeout = setTimeout('rotateWheel()', 30);
}
function stopRotateWheel()
{
clearTimeout(spinTimeout);
var degrees = startAngle * 180 / Math.PI + 90;
var arcd = arc * 180 / Math.PI;
var index = Math.floor((360 - degrees % 360) / arcd);
ctx.save();
ctx.font = 'bold 30px Helvetica, Arial';
var text = options[index]
ctx.fillText(text, 250 - ctx.measureText(text).width / 2, 250 + 10);
ctx.restore();
}
function easeOut(t, b, c, d)
{
var ts = (t /= d) * t;
var tc = ts * t;
return b + c * (tc + -3 * ts + 3 * t);
}
drawRouletteWheel();
<input type="button" value="spin" style="float:left;" id='spin'/>
<canvas id="canvas" width="500" height="500"></canvas>
Related
I am working on the canvas showing levels according to users below is my code the issue is after clip the image on the first level the next drawing and animations stops working.
The canvas holds a json array which is used to draw the levels Class levels
holds the method to deay static shapes and functions starting with animate uses animation frames to animate line or circles.
HTML:
<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
</head>
<body>
<canvas id="levelchart" data-levels="[{"text":"Mark","dotcolor":"#28912e","linecolor":"#28912e","current":"0","completed":"1","image":"http:\/\/nessgoods.com\/timthumb.php?src=http:\/\/www.nessgoods.com\/upload\/users\/3\/pills_311869.jpg&q=100"},{"text":5,"dotcolor":"#28912e","linecolor":"#28912e","current":"0","pending":"0","completed":"1"},{"text":25,"dotcolor":"#28912e","linecolor":"#28912e","current":"0","pending":"0","completed":"1"},{"text":125,"dotcolor":"#28912e","linecolor":"#28912e","current":"0","pending":"0","completed":"1"},{"text":625,"dotcolor":"#28912e","linecolor":"#28912e","current":"0","pending":"0","completed":"1"},{"text":3125,"dotcolor":"#28912e","linecolor":"#28912e","current":"0","pending":"0","completed":"1"},{"text":15625,"dotcolor":"#3498db","linecolor":"#3498db","current":"1","completed":"1","pending":"3125"},{"text":78125,"dotcolor":"#3498db","linecolor":"#3498db","current":0,"pending":"0","completed":0},{"text":390625,"dotcolor":"#3498db","linecolor":"#3498db","current":0,"pending":"0","completed":0}]" width="1360" height="380"></canvas>
</body>
JS:
<script
src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous"></script>
<script type="text/javascript">
class levels{
constructor(){
var x = 0;
var y = 0;
var height = 0;
var width = 0;
var canvas = 0;
var fill = 0;
var start = 0;
var end = 0;
var lineWidth = 0;
var color = 0;
var gradient = 0;
var lineCap = "square";
var to = 0;
var data = 0;
var counter = 0;
var circleanimate = 0;
var percent=0;
var completed = 0;
var imagee = "";
}
config(){
}
line(){
// console.log(this.end);
this.canvas.beginPath();
this.canvas.moveTo(this.start, this.y);
this.canvas.lineTo(this.end, this.y);
this.canvas.lineWidth = this.lineWidth;
this.canvas.strokeStyle = this.color;
this.canvas.lineCap = this.lineCap
this.canvas.stroke();
};
circle(){
this.canvas.beginPath();
this.canvas.moveTo(this.end, this.y);
this.canvas.arc(this.end, this.y, this.radius, 0, 2 * Math.PI);
this.canvas.fillStyle = this.color;
this.canvas.fill();
this.canvas.closePath();
}
baloon(){
var bheight = (10 - lv.counter + lv.counter * 8 / 100 * canvas.height);
var totheight = canvas.height - (60 + bheight);
var height = totheight + 80 / 100 * bheight;
this.canvas.beginPath();
//console.log("check "+bheight+" "+totheight+" "+height);
var last = (lv.end-30) + (15 / 100 * bheight);
var y = lv.y-50;
this.canvas.moveTo(last + (12 / 100 * bheight), height - (13 / 100 * bheight));
this.canvas.bezierCurveTo(last - (16 / 100 * bheight), y, last - (16 / 100 * bheight), y, last - (16 / 100 * bheight), y);
this.canvas.bezierCurveTo(last - (36 / 100 * bheight), height, last - (36 / 100 * bheight), height, last - (36 / 100 * bheight), height);
this.canvas.arc(last - (18 / 100 * bheight), totheight + (38 / 100 * bheight), (last + (14 / 100 * bheight)) - (last - (28 / 100 * bheight)), 0.75 * Math.PI, 0.25 * Math.PI);
this.canvas.strokeStyle = lv.color;
this.canvas.lineWidth=3;
this.canvas.stroke();
// count++;
console.log(lv.imagee+" as");
if (this.imagee != "") {
var img = new Image();
img.src = this.imagee;
var newcanvas = this.canvas;
img.onload = function (e)
{
newcanvas.beginPath();
newcanvas.moveTo(last - (18 / 100 * bheight), totheight + (38 / 100 * bheight));
newcanvas.arc(last - (18 / 100 * bheight), totheight + (38 / 100 * bheight), (last + (14 / 100 * bheight)) - (last - (28 / 100 * bheight)) - 1, 0, 2 * Math.PI);
newcanvas.strokeStyle = "#fff";
newcanvas.stroke();
newcanvas.clip();
newcanvas.drawImage(img,last - (18 / 100 * bheight)-(1.5/100*canvas.width),totheight + (38 / 100 * bheight)-(1.5/100*canvas.width));
lv.canvas.beginPath();
// lv.image="";
}
}
}
}
function animateCircle() {
if(lv.circleanimate<2.1){
requestAnimationFrame(animateCircle);
lv.canvas.beginPath();
lv.canvas.moveTo(lv.end, lv.y);
lv.canvas.arc(lv.end, lv.y, lv.radius, (lv.circleanimate-0.1) * Math.PI, lv.circleanimate * Math.PI);
lv.canvas.fillStyle = lv.color;
lv.strokeStyle = "none";
lv.canvas.fill();
lv.canvas.closePath();
lv.circleanimate=lv.circleanimate+0.1;
}else{
lv.circleanimate=0;
if (lv.end == 0) {
lv.start = 0;
lv.end = 0;
lv.to = 30;
lv.color = lv.data[0].linecolor;
lv.style = "normal";
if(lv.data[0].hasOwnProperty("image")){
lv.imagee = lv.data[0].image;
}
} else {
lv.style = "bold";
lv.start = lv.end + 10;
var index = lv.counter-1;
if(lv.counter>=8){
index = 8;
}
console.log(index+" c ");
lv.imagee = "";
if(lv.data[index].hasOwnProperty("image")){
var w = 3/100*canvas.width;
lv.imagee = lv.data[index].image+"&w="+w+"&h="+w;
}
lv.color = lv.data[index].linecolor;
lv.percent = (Number(lv.data[index].pending) / Number(lv.data[index].text) * 100);
lv.completed = lv.data[index].completed;
lv.end = lv.start;
var p = (lv.counter * 2)+2;
lv.to = lv.to + ((p / 100) * workarea);
}
animateElipse();
animateLineFill();
}
}
function animateElipse(){
if(lv.circleanimate<2.1){
requestAnimationFrame(animateElipse);
var bheight = (10 - lv.counter + lv.counter * 8 / 100 * canvas.height);
var totheight = canvas.height - (60 + bheight);
var height = totheight + 80 / 100 * bheight;
var last = lv.end-25;
var y = lv.y-48;
lv.canvas.beginPath();
lv.canvas.moveTo(last, y);
lv.canvas.ellipse(last, y, 8, 2, 0,0, lv.circleanimate * Math.PI);
lv.canvas.fillStyle = "#e4e5e7";
lv.canvas.fill();
lv.circleanimate=lv.circleanimate+0.1;
}else{
lv.baloon();
}
}
function animateLineFill(){
if(lv.end<lv.to){
requestAnimationFrame(animateLineFill);
}else if(lv.counter<lv.count){
lv.circleanimate=0;
if (lv.end == 0) {
lv.start = 0;
lv.end = 0;
lv.to = 30;
lv.color = lv.data[0].linecolor;
lv.style = "normal";
} else {
lv.style = "bold";
lv.start = lv.end + 8;
var index = lv.counter;
if(lv.counter>=8){
index = 8;
}
lv.imagee = "";
if(lv.data[index].hasOwnProperty("image")){
var w = 3/100*canvas.width;
lv.imagee = lv.data[index].image+"&w="+w+"&h="+w;
}
lv.color = lv.data[index].linecolor;
lv.end = lv.start;
// var p = (lv.counter+1.9 * 5);
// lv.to = lv.to + ((p / 100) * workarea);
}
animateCircle();
lv.counter++;
}
lv.line();
lv.end++;
}
var lv = new levels();
var canvas = document.querySelector("canvas#levelchart");
/*canvas.width = (98 / 100) * $("div.team_link").width();
canvas.height = (28 / 100) * canvas.width;*/
canvas.width = (98 / 100) * $(window).width();
canvas.height = (28 / 100) * canvas.width;
var c = canvas.getContext('2d');
var workarea = (canvas.width);
var points = workarea / 10;
var start = canvas.width - 10;
var last = 0;
var y = canvas.height - 10;
var cheight = canvas.height;
var data = document.getElementById("levelchart").getAttribute("data-levels");
data = JSON.parse(data);
var i = 0;
var style = "normal";
lv.start = start;
lv.end = last;
lv.canvas = c;
lv.color="#000000";
lv.y = y;
lv.start = 50;
lv.end = workarea-50;
lv.lineWidth = 4;
lv.color = "#eee";
lv.lineCap = "round";
lv.line();
lv.end = 0;
lv.radius = 5;
lv.count = data.length;
lv.data = data;
lv.counter = 0;
if (lv.end == 0) {
lv.start = 0;
lv.end = 0;
lv.to = 30;
lv.color = lv.data[0].linecolor;
lv.style = "normal";
}
animateLineFill();
</script>
In image.load function we have to call .save() on canvas and after clip() we have call the .restore() function as defined in below code.
img.onload = function (e)
{
newcanvas.save();
newcanvas.beginPath();
newcanvas.moveTo(last - (18 / 100 * bheight), totheight + (38 / 100 * bheight));
newcanvas.arc(last - (18 / 100 * bheight), totheight + (38 / 100 * bheight), (last + (14 / 100 * bheight)) - (last - (28 / 100 * bheight)) - 1, 0, 2 * Math.PI);
newcanvas.strokeStyle = "#fff";
newcanvas.stroke();
newcanvas.clip();
newcanvas.drawImage(img,last - (18 / 100 * bheight)-(1.5/100*canvas.width),totheight + (38 / 100 * bheight)-(1.5/100*canvas.width));
newcanvas.restore();
// lv.image="";
}
For some strange and sudden reason, my canvas seems to make lines thicker and darker on the right ~1/4-ish. I have tried multiple browsers and different computers and they all have the same rendering issue EXCEPT for Chrome for Android. Here is a screenshot of the test lines that I drew:
And here is the code in case anyone was wondering:
var canvas = document.getElementById("foreground");
var context = canvas.getContext("2d");
var height = 450;
var width = 600;
canvas.width = width;
canvas.height = height;
function draw() {
context.clearRect(0, 0, canvas.height, canvas.width);
for (var i = 1; i < (800 - (0 * 2)) / 35; i++) {
context.beginPath();
context.moveTo(200 + (i * 35) + 0 | 0, 50 + 0 | 0);
context.lineWidth = 1;
context.lineTo(200 + (i * 35) + 0 | 0, 50 + 800 - 0 | 0);
context.strokeStyle = "black";
context.stroke();
context.closePath();
}
for (var i = 1; i < (800 - (0 * 2)) / 35; i++) {
context.beginPath();
context.moveTo(200 + 0 | 0, 50 + (i * 35) + 0 | 0);
context.lineWidth = 0.5;
context.lineTo(200 + 800 - 0 | 0, 50 + (i * 35) + 0 | 0);
context.strokeStyle = "black";
context.stroke();
context.closePath();
}
requestAnimationFrame(draw);
}
draw();
<div id="container">
<canvas id="foreground"></canvas>
</div>
You're not clearing the canvas properly: you swapped width and height. The requestAnimationFrame then draws everything again, and since only part of the image is cleared, the part that's not, gets 'thicker'.
The fix:
context.clearRect(0, 0, canvas.width, canvas.height);
var canvas = document.getElementById("foreground");
var context = canvas.getContext("2d");
var height = 450;
var width = 600;
canvas.width = width;
canvas.height = height;
function draw() {
context.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 1; i < (800 - (0 * 2)) / 35; i++) {
context.beginPath();
context.moveTo(200 + (i * 35) + 0 | 0, 50 + 0 | 0);
context.lineWidth = 1;
context.lineTo(200 + (i * 35) + 0 | 0, 50 + 800 - 0 | 0);
context.strokeStyle = "black";
context.stroke();
context.closePath();
}
for (var i = 1; i < (800 - (0 * 2)) / 35; i++) {
context.beginPath();
context.moveTo(200 + 0 | 0, 50 + (i * 35) + 0 | 0);
context.lineWidth = 0.5;
context.lineTo(200 + 800 - 0 | 0, 50 + (i * 35) + 0 | 0);
context.strokeStyle = "black";
context.stroke();
context.closePath();
}
requestAnimationFrame(draw);
}
draw();
<div id="container">
<canvas id="foreground"></canvas>
</div>
Simply remove draw from requestAnimationFrame.
var canvas = document.getElementById("foreground");
var context = canvas.getContext("2d");
var height = 450;
var width = 600;
canvas.width = width;
canvas.height = height;
function draw() {
context.clearRect(0, 0, canvas.height, canvas.width);
for (var i = 1; i < (800 - (0 * 2)) / 35; i++) {
context.beginPath();
context.moveTo(200 + (i * 35) + 0 | 0, 50 + 0 | 0);
context.lineWidth = 1;
context.lineTo(200 + (i * 35) + 0 | 0, 50 + 800 - 0 | 0);
context.strokeStyle = "black";
context.stroke();
context.closePath();
}
for (var i = 1; i < (800 - (0 * 2)) / 35; i++) {
context.beginPath();
context.lineTo(200 + 0 | 0, 50 + (i * 35) + 0 | 0);
context.lineWidth = 0.5;
context.lineTo(200 + 800 - 0 | 0, 50 + (i * 35) + 0 | 0);
context.strokeStyle = "black";
context.stroke();
context.closePath();
}
requestAnimationFrame();
}
draw();
<div id="container">
<canvas id="foreground"></canvas>
</div>
I have spheres bouncing off each other and the canvas walls, however im struggling on the speed. How would I control the speed? so maybe connected to the beginpath function? so they kind of explode and then bounce everywhere
<script type="text/javascript">
$(function () {
var canvas = $("#target");
var context = canvas.get(0).getContext("2d");
var canvasWidth = canvas.width();
var canvasHeight = canvas.height();
$(window).resize(resizeCanvas);
function resizeCanvas() {
canvas.attr("width", $(window).get(0).innerWidth);
canvas.attr("height", $(window).get(0).innerHeight);
canvasWidth = canvas.width();
canvasHeight = canvas.height();
};
var Sphere = function (x, y, radius, mass, vX, vY) {
this.x = x;
this.y = y;
this.radius = radius;
this.mass = mass;
this.vX = vX;
this.vY = vY;
this.updatePosition = function () {
this.x += this.vX;
this.y += this.vY;
};
this.checkBoundaryCollision = function () {
if (this.x - this.radius < 0) {
this.x = this.radius;
this.vX *= -1;
} else if (this.x + this.radius > canvasWidth) {
this.x = canvasWidth - this.radius;
this.vX *= -1;
}
if (this.y - this.radius < 0) {
this.y = this.radius;
this.vY *= -1;
} else if (this.y + this.radius > canvasHeight) {
this.y = canvasHeight - this.radius;
this.vY *= -1;
}
}
}
resizeCanvas();
var spheresLength = 20;
var spheres = new Array();
function loadContent() {
for (var i = 0; i < spheresLength; i++) {
var x = 20 + (Math.random() * (canvasWidth - 40));
var y = 20 + (Math.random() * (canvasHeight - 40));
var radius = 5 + Math.random() * 10;
var mass = radius / 2;
var vX = Math.random() * 4 - 2;
var vY = Math.random() * 4 - 2;
spheres.push(new Sphere(x, y, radius, mass, vX, vY));
};
animate();
}
loadContent();
function animate() {
update();
draw();
setTimeout(animate, 33);
}
function update() {
for (var i = 0; i < spheresLength; i++) {
var sphere1 = spheres[i];
for (var j = i + 1; j < spheresLength; j++) {
var sphere2 = spheres[j];
var dX = sphere2.x - sphere1.x;
var dY = sphere2.y - sphere1.y;
var distance = Math.sqrt((dX * dX) + (dY * dY));
if (distance < sphere1.radius + sphere2.radius) {
var angle = Math.atan2(dY, dX);
var sine = Math.sin(angle);
var cosine = Math.cos(angle);
var x = 0;
var y = 0;
var xB = dX * cosine + dY * sine;
var yB = dY * cosine - dX * sine;
var vX = sphere1.vX * cosine + sphere1.vY * sine;
var vY = sphere1.vY * cosine - sphere1.vX * sine;
var vXb = sphere2.vX * cosine + sphere2.vY * sine;
var vYb = sphere2.vY * cosine - sphere2.vX * sine;
var vTotal = vX - vXb;
vX = (
(sphere1.mass - sphere2.mass) * vX + 2 * sphere2.mass * vXb
)
/ (sphere1.mass + sphere2.mass);
vXb = vTotal + vX;
xB = x + (sphere1.radius + sphere2.radius);
sphere1.x = sphere1.x + (x * cosine - y * sine);
sphere1.y = sphere1.y + (y * cosine + x * sine);
sphere2.x = sphere1.x + (xB * cosine - yB * sine);
sphere2.y = sphere1.y + (yB * cosine + xB * sine);
sphere1.vX = vX * cosine - vY * sine;
sphere1.vY = vY * cosine + vX * sine;
sphere2.vX = vXb * cosine - vYb * sine;
sphere2.vY = vYb * cosine + vXb * sine;
}
}
sphere1.updatePosition();
sphere1.checkBoundaryCollision();
}
}
function draw() {
context.clearRect(0, 0, canvasWidth, canvasHeight);
context.fillStyle = "rgb(255, 255, 255)";
for (var i = 0; i < spheresLength; i++) {
var sphere = spheres[i];
context.beginPath();
context.arc(sphere.x, sphere.y, sphere.radius, 0, Math.PI * 2);
context.closePath();
context.fill();
}
}
});
</script>
The "speed" of the balls is a function of the distance they travel per frame. This code runs about 3 frames per second, and it looks like the distance is a function of the "mass." You can increase the speed by increasing the factor that determines the distance traveled in each frame (in the update() function.)
Incidentally, I wasn't able to get this code to work. In future, try prototyping on jsFiddle.net or Codepen.io.
UPDATE:
Here's the line that controls the velocity of the balls:
vX = ((sphere1.mass - sphere2.mass) * vX + 2 * sphere2.mass * vXb)
/ (sphere1.mass + sphere2.mass);
That value, 2, is the overall velocity modifier. Small increases to that value correlate to large increases in velocity. Kick it up to 2.25 and watch them fly.
I want to draw a cylinder on canvas with control box to re size the cylinder.
Here's some javascript code I created to answer my own question:
function drawCylinder ( x, y, w, h ) {
context.beginPath(); //to draw the top circle
for (var i = 0 * Math.PI; i < 2 * Math.PI; i += 0.001) {
xPos = (this.x + this.w / 2) - (this.w / 2 * Math.sin(i)) *
Math.sin(0 * Math.PI) + (this.w / 2 * Math.cos(i)) *
Math.cos(0 * Math.PI);
yPos = (this.y + this.h / 8) + (this.h / 8 * Math.cos(i)) *
Math.sin(0 * Math.PI) + (this.h / 8 *
Math.sin(i)) * Math.cos(0 * Math.PI);
if (i == 0) {
context.moveTo(xPos, yPos);
}
else
{
context.lineTo(xPos, yPos);
}
}
context.moveTo(this.x, this.y + this.h / 8);
context.lineTo(this.x, this.y + this.h - this.h / 8);
for (var i = 0 * Math.PI; i < Math.PI; i += 0.001) {
xPos = (this.x + this.w / 2) - (this.w / 2 * Math.sin(i)) * Math.sin(0 * Math.PI) + (this.w / 2 * Math.cos(i)) * Math.cos(0 * Math.PI);
yPos = (this.y + this.h - this.h / 8) + (this.h / 8 * Math.cos(i)) * Math.sin(0 * Math.PI) + (this.h / 8 * Math.sin(i)) * Math.cos(0 * Math.PI);
if (i == 0) {
context.moveTo(xPos, yPos);
}
else
{
context.lineTo(xPos, yPos);
}
}
context.moveTo(this.x + this.w, this.y + this.h / 8);
context.lineTo(this.x + this.w, this.y + this.h - this.h / 8);
context.stroke();
}
Thank you! This is just what I was looking for. While implementing your function in my own code I made some changes like passing in the canvas context as an argument, simplifying the math and getting the code to pass JSLint.
function drawCylinder(ctx, x, y, w, h) {
'use strict';
var i, xPos, yPos, pi = Math.PI, twoPi = 2 * pi;
ctx.beginPath();
for (i = 0; i < twoPi; i += 0.001) {
xPos = (x + w / 2) - (w / 2 * Math.cos(i));
yPos = (y + h / 8) + (h / 8 * Math.sin(i));
if (i === 0) {
ctx.moveTo(xPos, yPos);
} else {
ctx.lineTo(xPos, yPos);
}
}
ctx.moveTo(x, y + h / 8);
ctx.lineTo(x, y + h - h / 8);
for (i = 0; i < pi; i += 0.001) {
xPos = (x + w / 2) - (w / 2 * Math.cos(i));
yPos = (y + h - h / 8) + (h / 8 * Math.sin(i));
if (i === 0) {
ctx.moveTo(xPos, yPos);
} else {
ctx.lineTo(xPos, yPos);
}
}
ctx.moveTo(x + w, y + h / 8);
ctx.lineTo(x + w, y + h - h / 8);
ctx.stroke();
}
If you want to draw a 3D cylinder, the easiest way is to use a library like tQuery (http://jeromeetienne.github.com/tquery/) :
var world = tQuery.createWorld().boilerplate().start();
var object = tQuery. createCylinder().addTo(world);
If you want to draw a '2d' cylinder, you can do so using canvas 2d API to draw a rectangle then a elipse in top of it. It will appear as a cylinder.
var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d');
var pos={};
const angleToRadian = function (angle) {
return Math.PI / 180 * angle;
}
var Arc = function (x, y, r, d,s) {
this.r = r;
this.x = x;
this.y = y;
// this.d=d;
ctx.beginPath();
ctx.arc(x, y, r, angleToRadian(0), angleToRadian(180));
ctx.moveTo((Number(x) + Number(r)), y);
// ctx.lineTo((Number(x) + Number(r)), d);
ctx.arc(x, y - d, r, angleToRadian(0), angleToRadian(360));
ctx.moveTo((Number(x)+Number(r)),y);
ctx.lineTo((Number(x)+Number(lX())), ((Number(y)-Number(d))+Number(r)-Number(lY())));
// ctx.moveTo((Number(x)+Number(lX())), ((Number(y)-Number(d))-Number(lY())+Number(r)));
ctx.lineTo((Number(x)+Number(lX())),(Number(y)+Number(r)-Number(lY())));
// ctx.moveTo((Number(x)+Number(lX())),(Number(y)+Number(r)-Number(lY())));
ctx.lineTo(Number(x), ((Number(y)+Number(r))-Number(d)));
// ctx.moveTo(Number(x), ((Number(y)+Number(r))-Number(d)));
ctx.lineTo(Number(x),(Number(y)+Number(r)));
// ctx.moveTo(Number(x),(Number(y)+Number(r)));
ctx.lineTo((Number(x)-Number(lX())), (Number(y)-Number(d)+Number(r)-Number(lY())));
// ctx.moveTo((Number(x)-Number(lX())), (Number(y)-Number(d)+Number(r)-Number(lY())));
ctx.lineTo((Number(x)-Number(lX())), (Number(y)+Number(r)-Number(lY())));
// ctx.moveTo((Number(x)-Number(lX())), (Number(y)+Number(r)-Number(lY())));
ctx.lineTo((Number(x)-Number(r)), (Number(y)-Number(d)));
// ctx.moveTo((Number(x)-Number(r)), (Number(y)-Number(d)));
ctx.lineTo((Number(x)-Number(r)), y);
ctx.strokeStyle = "#9c3028";
ctx.closePath();
// ctx.stroke();
ctx.fillStyle="#9b3028"
ctx.fill();
}
var lY = function () {
return Math.sqrt((Math.pow(((Math.cos(67.5 * Math.PI / 180) * this.r) * 2), 2) -
Math.pow((Math.cos(22.5 * Math.PI / 180) * (Math.cos(67.5 * Math.PI / 180) * this.r) * 2), 2)));
}
var lX = function () {
return Math.sqrt((Math.pow(((Math.cos(67.5 * Math.PI / 180) * this.r) * 2), 2) - (Math.pow(((Math.cos(67.5 * Math.PI / 180) * this.r) * 2), 2) -
Math.pow((Math.cos(22.5 * Math.PI / 180) * (Math.cos(67.5 * Math.PI / 180) * this.r) * 2), 2))));
}
document.addEventListener('mouseup',mouseUp);
document.addEventListener('mousedown',mouseDown);
document.addEventListener('mousemove',draw);
function mouseDown(e){
pos.x=e.clientX;
pos.y=e.clientY;
}
function mouseUp(e){
pos.pozX=e.clientX;
pos.pozY=e.clientY;
}
function draw(e){
if(e.buttons!==1) return;
ctx.clearRect(0,0,500,500);
Arc(pos.x, pos.y, e.clientY, e.clientX);
}
using action script how to draw a semi circle...i need to add tha semicircle in another circle the circle looks like this
![alt text][1]
how to draw a semi circle inside that circle
Use the following function to draw the required arc.
function drawArc(centerX, centerY, radius, startAngle, arcAngle, steps){
startAngle -= .25;
var twoPI = 2 * Math.PI;
var angleStep = arcAngle/steps;
var xx = centerX + Math.cos(startAngle * twoPI) * radius;
var yy = centerY + Math.sin(startAngle * twoPI) * radius;
moveTo(xx, yy);
for(var i=1; i<=steps; i++){
var angle = startAngle + i * angleStep;
xx = centerX + Math.cos(angle * twoPI) * radius;
yy = centerY + Math.sin(angle * twoPI) * radius;
lineTo(xx, yy);
}
}
lineStyle(0, 0xFF0000);
drawArc(250, 250, 200, 45/360, -90/360, 20);
Semicircle? Well its joining the end points isn't it. Use lineto.
Thank you so much loxxy.. I have made a few alteration and got dashed line too.
function drawArc(centerX, centerY, radius, startAngle, arcAngle, steps){
centerY=centerY+radius
startAngle -= .25;
var twoPI = 2 * Math.PI;
var angleStep = arcAngle/steps;
trace(angleStep)
var xx = centerX + Math.cos(startAngle * twoPI) * radius;
var yy = centerY + Math.sin(startAngle * twoPI) * radius;
mc.graphics.moveTo(xx, yy);
for(var i=1; i<=steps; i++){
var angle = startAngle + i * angleStep;
xx = centerX + Math.cos(angle * twoPI) * radius;
yy = centerY + Math.sin(angle * twoPI) * radius;
if(i%2==0){
mc.graphics.moveTo(xx, yy);
}else{
mc.graphics.lineTo(xx, yy);
}
}
}