canvas doesn't work when other div are added - javascript

I got this problem: I found a very cool pen on codepen, I take it, modified, but when I put this in my html page doesn't work with other divs.
Here the pen https://jsfiddle.net/jtz21sz3/
<canvas id="stage" width="400" height="400">
<p>Your browser doesn't support canvas.</p>
</canvas>
everything work, but when i try to insert a sticky menu in the top the canvas draws the circle, but I can't drag them.
https://jsfiddle.net/Lp9w34sd/1/
<div class="sticky-menu-wrapper">
<nav class="main-menu clear">
<div class="menu-menu-1-container"><ul id="menu-menu-1" class="menu" style="text-align:center">
<li id="menu-item-135" class="menu-item menu-item-type-custom menu-item-object-custom" style=" text-align:left; float: left; padding-top:16px;"><a>RELEASE</a></li>
</ul></div>
</nav>
</div>
<canvas id="stage" width="400" height="400">
<p>Your browser doesn't support canvas.</p>
</canvas>
Any idea how to fix it?

Change function getMouseXY(e) { to this
function getMouseXY(e) {
mouseX = e.offsetX;
mouseY = e.offsetY;
if (mouseX < 0) mouseX = 0;
if (mouseY < 0) mouseY = 0;
}

Just add position:absolute (or fixed) to the nav.
var stage = document.getElementById('stage');
var browserX = window.screenX;
var browserY = window.screenY;
var balls = [];
var total = 6;
var currentDrag = null;
var mouseX = 0;
var mouseY = 0;
var stageWidth = $(document).width();
var stageHeight = $(document).height();
stage.width = stageWidth;
stage.height = stageHeight;
var IE = document.all ? true : false;
if (!IE) document.addEventListener(Event.MOUSEMOVE, getMouseXY, false);
document.onmousemove = getMouseXY;
window.onresize = function(event) {
stage.width = 10;
stage.height = 10;
stageWidth = $(document).width();
stageHeight = $(document).height();
stage.width = stageWidth;
stage.height = stageHeight;
}
generate();
var drawingCanvas = document.getElementById('stage');
if (drawingCanvas.getContext) {
var context = drawingCanvas.getContext('2d');
setInterval(render, 20);
}
jQuery(document).ready(function() {
$(document).mousedown(function(e) {
onMouseDown();
});
$(document).mouseup(function(e) {
onMouseUp();
});
})
function onMouseDown() {
var j = balls.length;
while (--j > -1) {
var dx = mouseX - balls[j].x;
var dy = mouseY - balls[j].y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < balls[j].size / 2) {
currentDrag = balls[j];
currentDrag.dragging = true;
return;
}
}
}
function onMouseUp() {
if (currentDrag != null) currentDrag.dragging = false;
}
function generate() {
for (var i = 0; i < total; i++) {
var ball = {};
ball.color = "#" + genHex();
ball.bounce = .5 + (Math.random() * .5);
ball.vx = Math.random() * 50 - 25;
ball.vy = Math.random() * 50 - 25;
ball.size = 75 - (ball.bounce * 25);
ball.x = Math.random() * stageWidth;
ball.y = Math.random() * stageHeight;
balls[balls.length] = ball;
}
}
function genHex() {
colors = new Array(14)
colors[0] = "0"
colors[1] = "1"
colors[2] = "2"
colors[3] = "3"
colors[4] = "4"
colors[5] = "5"
colors[5] = "6"
colors[6] = "7"
colors[7] = "8"
colors[8] = "9"
colors[9] = "a"
colors[10] = "b"
colors[11] = "c"
colors[12] = "d"
colors[13] = "e"
colors[14] = "f"
digit = new Array(5)
color = ""
for (i = 0; i < 6; i++) {
digit[i] = colors[Math.round(Math.random() * 14)]
color = color + digit[i]
}
return color;
}
function render() {
var isChange = (browserX != window.screenX || browserY != window.screenY);
if (isChange) {
var diffX = browserX - window.screenX;
browserX = window.screenX;
var diffY = browserY - window.screenY;
browserY = window.screenY;
}
var j = balls.length;
while (--j > -1) {
update(balls[j]);
if (isChange) {
balls[j].vx += (diffX * .05);
balls[j].vy += (diffY * .1);
}
}
draw();
}
function draw() {
context.clearRect(0, 0, stageWidth, stageHeight);
var i = balls.length;
while (--i > -1) {
context.fillStyle = balls[i].color;
context.beginPath();
context.arc(balls[i].x, balls[i].y, balls[i].size, 0, Math.PI * 2, true);
context.closePath();
context.fill();
}
}
function update(ball) {
collisionCheck();
var gravity = 0;
var drag = .98;
if (ball.dragging) {
ball.vx = ball.x - ball.ox;
ball.vy = ball.y - ball.oy;
ball.ox = ball.x;
ball.oy = ball.y;
ball.x = mouseX;
ball.y = mouseY;
if ((ball.x + ball.size) > stageWidth) {
ball.x = stageWidth - ball.size;
} else if ((ball.x - ball.size) < 0) {
ball.x = 0 + ball.size;
}
if ((ball.y + ball.size) > stageHeight) {
ball.y = stageHeight - ball.size;
} else if ((ball.y - ball.size) < 0) {
ball.y = 0 + ball.size;
}
} else {
ball.x += ball.vx;
ball.y += ball.vy;
if ((ball.x + ball.size) > stageWidth) {
ball.x = stageWidth - ball.size;
ball.vx = -ball.vx * ball.bounce;
} else if ((ball.x - ball.size) < 0) {
ball.x = 0 + ball.size;
ball.vx = -ball.vx * ball.bounce;
}
if ((ball.y + ball.size) > stageHeight) {
ball.y = stageHeight - ball.size;
ball.vy = -ball.vy * ball.bounce;
} else if ((ball.y - ball.size) < 0) {
ball.y = 0 + ball.size;
ball.vy = -ball.vy * ball.bounce;
}
ball.vx = ball.vx * drag;
ball.vy = ball.vy * drag + gravity;
}
}
function collisionCheck() {
var spring = .5;
for (var i = 0; i < (total - 1); ++i) {
var ball0 = balls[i];
for (var j = i + 1; j < total; ++j) {
var ball1 = balls[j];
var dx = ball1.x - ball0.x;
var dy = ball1.y - ball0.y;
var dist = Math.sqrt(dx * dx + dy * dy);
var minDist = ball0.size + ball1.size;
if (dist < minDist) {
var angle = Math.atan2(dy, dx);
var tx = ball0.x + dx / dist * minDist;
var ty = ball0.y + dy / dist * minDist;
var ax = (tx - ball1.x);
var ay = (ty - ball1.y);
ball0.x -= ax;
ball0.y -= ay;
ball1.x += ax;
ball1.y += ay;
ball0.vx -= (ax * spring);
ball0.vy -= (ay * spring);
ball1.vx += (ax * spring);
ball1.vy += (ay * spring);
}
}
}
}
function getMouseXY(e) {
if (IE) {
mouseX = event.clientX + document.body.scrollLeft
mouseY = event.clientY + document.body.scrollTop
} else {
mouseX = e.pageX
mouseY = e.pageY
}
if (mouseX < 0) {
mouseX = 0;
}
if (mouseY < 0) {
mouseY = 0;
}
return true;
}
#stage { margin:0; padding:0; background-color:#DDD; }
.sticky-menu-wrapper {
position:absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sticky-menu-wrapper">
<nav class="main-menu clear">
<div class="menu-menu-1-container"><ul id="menu-menu-1" class="menu" style="text-align:center">
<li id="menu-item-135" class="menu-item menu-item-type-custom menu-item-object-custom" style=" text-align:left; float: left; padding-top:16px;"><a>RELEASE</a></li>
</ul></div>
</nav>
</div>
<div>
<canvas id="stage" width="400" height="400">
<p>Your browser doesn't support canvas.</p>
</canvas>
</div>

Related

MouseDown Event is not working on other computers

I have a problem with a mousedown event that is so weird for me. I'm at intermediate level but I have a beginner problem.
I'm making a game in which a player can control a ball and there are some bricks with texts on them. The player must first shoot a word e.g (Ethiopia) and there is another brick with the same word. Then after shooting Ethiopia the player must shoot the other Ethiopia.
Code :
function dummyHttpRequest() {
return `Iran
Denmark
Sweden
Iraq
Brazil
Ethiopia
England
Finland
Canada`;
}
var isindrag = false;
const canvas = document.getElementById("mycanvas");
const ctx = canvas.getContext("2d");
ctx.font = "12pt Arial";
ctx.fillStyle = "blue";
ctx.fillText("Mouse Speed : ", 0, 20);
var x = canvas.width / 2;
var y = canvas.height / 2;
var posbricks = [];
var times = 0;
var dx = 0;
var dy = 0;
var radius = 15;
var oldx = 0;
var oldy = 0;
var speed = 0;
var friction = 0.005;
//const XHRnames = new XMLHttpRequest();
//XHRnames.open("GET", "data.txt", false);
//XHRnames.send();
//var names = XHRnames.responseText.split("\n");
var names = dummyHttpRequest().split("\n");
var namesResults = [];
var numberOfSelected = [];
for (i in names) {
numberOfSelected[i] = 0;
}
for (var i = 0; i < names.length * 2; i++) {
randnumf();
}
function randnumf() {
var randnum = Math.round(Math.random() * (names.length - 1));
if (numberOfSelected[randnum] < 2) {
namesResults[i + 3] = names[randnum];
numberOfSelected[randnum]++;
}
else {
randnumf();
}
}
var whatitemshooted;
var isshooted = false;
var interval = setInterval(function () {
times++;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.closePath();
if (dx > 0) {
dx -= friction;
}
else if (dx < 0) {
dx += friction;
}
if (dy > 0) {
dy -= friction;
}
else if (dy < 0) {
dy += friction;
}
x += dx;
y += dy;
if (isindrag) {
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(oldx, oldy);
ctx.stroke();
ctx.closePath();
}
for (var i = 1; i <= 6; i++) {
if (times == 1) {
posbricks[i - 1] = [];
}
for (var j = 1; j <= 3; j++) {
if (times == 1) {
posbricks[i - 1][j - 1] = { x: (i - 1) * 100, y: (j - 1) * 70, text: namesResults[(i * 3) + j - 1] };
//console.log(posbricks[i - 1][j - 1].text);
}
var fontsize = 20 - posbricks[i - 1][j - 1].text.length;
ctx.font = fontsize + "pt Arial";
ctx.fillStyle = "blue";
ctx.fillRect(posbricks[i - 1][j - 1].x, posbricks[i - 1][j - 1].y, 70, 30);
ctx.fillStyle = "yellow";
ctx.fillText(posbricks[i - 1][j - 1].text, posbricks[i - 1][j - 1].x + 5, posbricks[i - 1][j - 1].y + 20);
if (y - radius <= posbricks[i - 1][j - 1].y + 20 && y + radius >= posbricks[i - 1][j - 1].y && x + radius >= posbricks[i - 1][j - 1].x && x - radius <= posbricks[i - 1][j - 1].x + 40) {
dx = -dx;
dy = -dy;
if (isshooted) {
var condition = whatitemshooted.x != posbricks[i - 1][j - 1].x || whatitemshooted.y != posbricks[i - 1][j - 1].y;
}
if (!isshooted) {
isshooted = true;
whatitemshooted = posbricks[i - 1][j - 1];
}
else {
if (posbricks[i - 1][j - 1].text == whatitemshooted.text && condition) {
ctx.clearRect(posbricks[i - 1][j - 1].x, posbricks[i - 1][j - 1].y, 110, 20);
posbricks[i - 1][j - 1].x = NaN;
posbricks[i - 1][j - 1].y = NaN;
ctx.clearRect(whatitemshooted.x, whatitemshooted.y, 110, 20);
whatitemshooted.x = NaN;
whatitemshooted.y = NaN;
isshooted = false;
}
whatitemshooted = null;
}
}
}
}
ctx.fillStyle = "red";
ctx.beginPath();
ctx.arc(x, y, radius, 0, 2 * Math.PI);
ctx.fill();
checkCollision();
}, 10);
/*
oldx = x;
x = event.clientX;
y = event.clientY;
speed = Math.abs(x - oldx);
*/
function checkCollision() {
if (x >= canvas.width - radius || x <= radius) {
dx = -dx;
}
if (y >= canvas.height - radius || y <= radius) {
dy = -dy;
}
}
canvas.addEventListener("mousedown", function (event) {
if (event.clientX >= x && event.clientX <= x + (radius * 2) && event.clientY >= y && event.clientY <= y + (radius * 2)) {
dx = 0;
dy = 0;
isindrag = true;
oldx = x;
oldy = y;
}
});
canvas.addEventListener("mousemove", function (event) {
if (isindrag) {
x = event.clientX;
y = event.clientY;
}
});
canvas.addEventListener("mouseup", function (event) {
if (isindrag && event.clientX < canvas.width && event.clientY < canvas.height && event.clientX > 0 && event.clientY > 0) {
isindrag = false;
dx = -(x - oldx) / 30;
dy = -(y - oldy) / 30;
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<canvas id="mycanvas" width="600" height="600"></canvas>
<script src="index.js"></script>
</body>
</html>
In Data.txt :
Iran
Denmark
Sweden
Iraq
Brazil
Ethiopia
England
Finland
Canada
On my computer (with web server for chrome) it runs completely fine but on my other computer (in a website) the ball doesn't move when I drag it.
What should I do?

Delayed transformations in JavaScript?

I'm working on a simple DHTML application, nothing strange: I have around 500 balls colliding with each other with different speeds and by clicking a button they stack based on their velocities creating a Maxwell-Boltzmann distribution(but that's another talk).
Well, for switching from the first to the second case I'm changing every single x and y coordinate for every single ball, to move them and pile them in that way.
Now, my question is: is it possible to have a sort of an animation in which balls from the first chaotic case, instead of jumping into the chart-configuration in one frame(as soon as the button gets clicked), gradually stack on top of each other in a much fancier and "graphical" animation? For example with transitions or transformations, but I couldn't manage to find a way to do that... I'm quite new to programming.
By the way, here's the full code:
FULL CODE:
class Ball {
constructor(x, y, dx, dy, radius, color){
this.radius = radius;
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
// mass is that of a sphere as opposed to circle
// it *does* make a difference in how realistic it looks
this.mass = this.radius * this.radius * this.radius;
this.color = color;
};
draw() {
ctx.beginPath();
ctx.arc(Math.round(this.x), Math.round(this.y), this.radius, 0, 2 * Math.PI);
ctx.fillStyle = this.color;
ctx.fill();
// ctx.strokeStyle = this.color;
ctx.stroke();
ctx.closePath();
};
speed() {
// magnitude of velocity vector
return Math.sqrt(this.dx * this.dx + this.dy * this.dy);
};
angle() {
// velocity's angle with the x axis
return Math.atan2(this.dy, this.dx);
};
onGround() {
return (this.y + this.radius >= canvas.height)
};
};
//FUNCTIONS
//will remove
function randomColor() {
let red = Math.floor(Math.random() * 3) * 127;
let green = Math.floor(Math.random() * 3) * 127;
let blue = Math.floor(Math.random() * 3) * 127;
// dim down the small balls
if (!bigBalls){
red *= 0.65
green *= 0.65
blue *= 0.65
}
let rc = "rgb(" + red + ", " + green + ", " + blue + ")";
return rc;
}
function randomX() {
let x = Math.floor(Math.random() * canvas.width);
if (x < 30) {
x = 30;
} else if (x + 30 > canvas.width) {
x = canvas.width - 30;
}
return x;
}
function randomY() {
let y = Math.floor(Math.random() * canvas.height);
if (y < 30) {
y = 30;
} else if (y + 30 > canvas.height) {
y = canvas.height - 30;
}
return y;
}
//will remove
function randomRadius() {
if (bigBalls) {
let r = Math.ceil(Math.random() * 10 + 20);
return r;
} else {
let r = Math.ceil(Math.random() * 2 + 2);
//let r = 5;
return r;
}
}
//will remove
function randomDx() {
let r = Math.floor(Math.random() * 10 - 4);
return r;
}
//will remove
function randomDy() {
let r = Math.floor(Math.random() * 10 - 3);
return r;
}
function distanceNextFrame(a, b) {
return Math.sqrt((a.x + a.dx - b.x - b.dx)**2 + (a.y + a.dy - b.y - b.dy)**2) - a.radius - b.radius;
}
function distance(a, b) {
return Math.sqrt((a.x - b.x)**2 + (a.y - b.y)**2);
}
let canvas = document.getElementById("myCanvas");
let ctx = canvas.getContext("2d");
let objArray = [];
let probArray = [];
let paused = false;
let bumped = false;
let leftHeld = false;
let upHeld = false;
let rightHeld = false;
let downHeld = false;
let arrowControlSpeed = .25;
let gravityOn = false;
let clearCanv = true;
let bigBalls = false;
let lastTime = (new Date()).getTime();
let currentTime = 0;
let dt = 0;
let numStartingSmallBalls = 500;
let numStartingBigBalls = 0;
document.addEventListener("keydown", keyDownHandler);
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function keyDownHandler(event) {
if (event.keyCode == 80) { // p
paused = !paused;
} else if (event.keyCode == 82) { // r
objArray = [];
} else if (event.keyCode == 75) { // k
clearCanv = !clearCanv;
} else if (event.keyCode == 88) { // x
bigBalls = !bigBalls;
}
}
function canvasBackground() {
canvas.style.backgroundColor = "rgb(215, 235, 240)";
}
function wallCollision(ball) {
if (ball.x - ball.radius + ball.dx < 0 ||
ball.x + ball.radius + ball.dx > canvas.width) {
ball.dx *= -1;
}
if (ball.y - ball.radius + ball.dy < 0 ||
ball.y + ball.radius + ball.dy > canvas.height) {
ball.dy *= -1;
}
if (ball.y + ball.radius > canvas.height) {
ball.y = canvas.height - ball.radius;
}
if (ball.y - ball.radius < 0) {
ball.y = ball.radius;
}
if (ball.x + ball.radius > canvas.width) {
ball.x = canvas.width - ball.radius;
}
if (ball.x - ball.radius < 0) {
ball.x = ball.radius;
}
}
function ballCollision() {
for (let i=0; i<objArray.length-1; i++) {
for (let j=i+1; j<objArray.length; j++) {
let ob1 = objArray[i]
let ob2 = objArray[j]
let dist = distance(ob1, ob2)
if (dist < ob1.radius + ob2.radius) {
let theta1 = ob1.angle();
let theta2 = ob2.angle();
let phi = Math.atan2(ob2.y - ob1.y, ob2.x - ob1.x);
let m1 = ob1.mass;
let m2 = ob2.mass;
let v1 = ob1.speed();
let v2 = ob2.speed();
let dx1F = (v1 * Math.cos(theta1 - phi) * (m1-m2) + 2*m2*v2*Math.cos(theta2 - phi)) / (m1+m2) * Math.cos(phi) + v1*Math.sin(theta1-phi) * Math.cos(phi+Math.PI/2);
let dy1F = (v1 * Math.cos(theta1 - phi) * (m1-m2) + 2*m2*v2*Math.cos(theta2 - phi)) / (m1+m2) * Math.sin(phi) + v1*Math.sin(theta1-phi) * Math.sin(phi+Math.PI/2);
let dx2F = (v2 * Math.cos(theta2 - phi) * (m2-m1) + 2*m1*v1*Math.cos(theta1 - phi)) / (m1+m2) * Math.cos(phi) + v2*Math.sin(theta2-phi) * Math.cos(phi+Math.PI/2);
let dy2F = (v2 * Math.cos(theta2 - phi) * (m2-m1) + 2*m1*v1*Math.cos(theta1 - phi)) / (m1+m2) * Math.sin(phi) + v2*Math.sin(theta2-phi) * Math.sin(phi+Math.PI/2);
ob1.dx = dx1F;
ob1.dy = dy1F;
ob2.dx = dx2F;
ob2.dy = dy2F;
/* if(ob1.speed() * 160 < 400)
ob1.color = 'lightblue';
else if(ob1.speed() * 160 > 800)
ob1.color = 'red';
else
ob1.color = 'orange';
if(ob2.speed() * 160 < 400)
ob2.color = 'lightblue';
else if(ob2.speed() * 160 > 800)
ob2.color = 'red';
else
ob2.color = 'orange';*/
staticCollision(ob1, ob2);
}
}
wallCollision(objArray[i]);
}
if (objArray.length > 0)
wallCollision(objArray[objArray.length - 1])
}
function staticCollision(ob1, ob2, emergency = false)
{
let overlap = ob1.radius + ob2.radius - distance(ob1, ob2);
let smallerObject = ob1.radius < ob2.radius ? ob1 : ob2;
let biggerObject = ob1.radius > ob2.radius ? ob1 : ob2;
// When things go normally, this line does not execute.
// "Emergency" is when staticCollision has run, but the collision
// still hasn't been resolved. Which implies that one of the objects
// is likely being jammed against a corner, so we must now move the OTHER one instead.
// in other words: this line basically swaps the "little guy" role, because
// the actual little guy can't be moved away due to being blocked by the wall.
if (emergency) [smallerObject, biggerObject] = [biggerObject, smallerObject]
let theta = Math.atan2((biggerObject.y - smallerObject.y), (biggerObject.x - smallerObject.x));
smallerObject.x -= overlap * Math.cos(theta);
smallerObject.y -= overlap * Math.sin(theta);
if (distance(ob1, ob2) < ob1.radius + ob2.radius) {
// we don't want to be stuck in an infinite emergency.
// so if we have already run one emergency round; just ignore the problem.
if (!emergency) staticCollision(ob1, ob2, true)
}
}
function moveObjects() {
for (let i=0; i<objArray.length; i++) {
let ob = objArray[i];
ob.x += ob.dx * 1;
ob.y += ob.dy * 1;
}
}
function drawObjects() {
for (let obj in objArray) {
objArray[obj].draw();
}
}
let begin = true;
let temperature;
document.getElementById("temp").oninput = function()
{
temperature = parseInt(document.getElementById("temp").value);
generateBalls(temperature);
}
function drawChart()
{
let index = 0
let cx = 10 , cy;
for(let i = 0; i < 59; i++) {
cy = canvas.height - 6;
if(probArray[i] != 0) {
n = 0;
while(n < probArray[i]) {
objArray[index + n].x = cx;
objArray[index + n].y = cy;
cy -= 12;
n++;
}
index += n;
}
cx += 20;
}
chart = !chart;
}
function draw() {
/*currentTime = (new Date()).getTime();
dt = (currentTime - lastTime) / 1000; // delta time in seconds
// dirty and lazy solution
// instead of scaling down every velocity vector
// we decrease the speed of time
dt *= 20;*/
if(begin) {
generateBalls(300);
begin = false;
}
//work in progress
if(chart) {
drawChart();
}
if (clearCanv) clearCanvas();
canvasBackground();
if (!paused) {
moveObjects();
ballCollision();
}
drawObjects();
lastTime = currentTime;
window.requestAnimationFrame(draw);
}
//work in progress
function setColor(vel)
{
let red = 255, green = 255, blue = 255;
let rc;
green /= (vel * 0.001);
blue /= (vel * 0.01);
return rc = "rgb(" + red + ", " + green + ", " + blue + ")";
}
let N = 550;
let m = 2.66e-26;
let T = 5;
let dV = 50;
let k = 1.38e-23;
let v = 50;
let balls;
let angolox;
let vel;
let color;
function generateBalls(T)
{
paused = false;
v = 50;
objArray = [];
for(let i = 0; i < 59; i++)
{ //each 50m/s, with dv = 50, until 2000m/s
//molecules number between v and v+50
probArray[i] = Math.floor(4 * Math.PI * N * (((m) / (2 * Math.PI * k * T))**1.5) * (v**2) * Math.exp((-m) / (2 * k * T) * (v**2)) * dV);
v += 50;
}
v = 50;
let l;
for(let i = 0; i < 59; i++)
{
let n = 0;
balls = 0;
while(n < probArray[i])
{
angolox = ((Math.random() * 360) * Math.PI) / 180; //converted in radians;
vel = Math.round((Math.random() * 50) + v) / 160;
if(vel * 160 < 400)
color = 'lightblue';
else if(vel * 160 > 800)
color = 'red';
else
color = 'orange';
l = objArray.length;
objArray[objArray.length] = new Ball(randomX(), randomY(), Math.cos(angolox) * vel, Math.sin(angolox) * vel, 5, color);
balls++;
n++;
}
v += 50;
}
}
let chart = false
function drawChart_bool() {
chart = !chart;
paused = !paused;
}
draw();
body {
background-color: khaki;
text-align: center;
font-family: Ubuntu Mono;
}
#title {
color: black;
font-size: 200%;
font-style: normal;
margin: 1px;
border: 1px;
}
#balls {
margin-top: 5px;
}
#myCanvas {
margin-top: -20px;
}
section.footer {
color: black;
font-family: Ubuntu Mono;
font-style: normal;
font-size: small;
}
#disclaimer {
font-size: 74%;
color: gray;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>2d collision</title>
<link rel="stylesheet" type="text/css" href="gas.css">
</head>
<body style="text-align: center">
<canvas onload="generateBalls()" id="myCanvas" width="1225%" height="500" style="border:1px solid black; margin-top: 10px;"></canvas>
<p>
<input type="range" min="50" max="2050" value="300" step="100" id="temp">
<input type="button" onclick="drawChart_bool()">
<strong>[K]</strong> to toggle clearCanvas(); <br>
<strong>[P]</strong>: pause/unpause || <strong>[R]</strong>: [RESET]
</p>
<div id="disclaimer" align="center" style="word-break: break-word; width: 350px; display:inline-block;">
<p>
Make sure to press a few buttons and play around.<br>Made with pure javascript.
</p>
</div>
</section>
</body>
<script src="gas.js"></script>
</html>
FUNCTION I USE TO DRAW CHART(objArray is an ascending ordered one, based on speeds)
function drawChart()
{
let index = 0
let cx = 10 , cy;
for(let i = 0; i < 59; i++) {
cy = canvas.height - 6;
if(probArray[i] != 0) {
n = 0;
while(n < probArray[i]) {
objArray[index + n].x = cx;
objArray[index + n].y = cy;
cy -= 12;
n++;
}
index += n;
}
cx += 20;
}
chart = !chart;
}
FUNCTION I USE TO GENERATE BALLS:
function generateBalls(T)
{
paused = false;
v = 50;
objArray = [];
for(let i = 0; i < 59; i++)
{ //each 50m/s, with dv = 50, until 2000m/s
//molecules number between v and v+50
probArray[i] = Math.floor(4 * Math.PI * N * (((m) / (2 * Math.PI * k * T))**1.5) * (v**2) * Math.exp((-m) / (2 * k * T) * (v**2)) * dV);
v += 50;
}
v = 50;
let l;
for(let i = 0; i < 59; i++)
{
let n = 0;
balls = 0;
while(n < probArray[i])
{
angolox = ((Math.random() * 360) * Math.PI) / 180; //converted in radians;
vel = Math.round((Math.random() * 50) + v) / 160;
if(vel * 160 < 400)
color = 'lightblue';
else if(vel * 160 > 800)
color = 'red';
else
color = 'orange';
l = objArray.length;
objArray[objArray.length] = new Ball(randomX(), randomY(), Math.cos(angolox) * vel, Math.sin(angolox) * vel, 5, color);
balls++;
n++;
}
v += 50;
}
}
Heartfelt thanks in advance for any answer,
Greg.🙏

How to resize text added with fillText() in canvas?

I have three canvas-elements that lay over the another. the first is a picture the second a filter and the third should be a text. I made the filter resizeable und draggable with the mouse events, but somehow this does not work with the text the same way. and i want to resize the text with four corner buttons and want to make it draggable. The text is added via a self-programmed simple texteditor.
click me please
click me please
The red square is where the rectangles are drawn now, but htey should be around the text, and the blue square is the hitbox to drag the text.
Now my Js-Code for the text.
var colorButton = document.getElementById("primary_color");
var textArea = document.getElementById("text");
var editor = document.getElementById("text");
var overlay = document.getElementById("overlay");
var textFontFamily = document.getElementById("selectForFonts");
var textColor;
var fontStyleFamily = 'Arial';
var boldness = 'normal';
var italicness = 'normal';
var data;
/**Function to get the color and color the text*/
colorButton.onchange = function() {
textColor = colorButton.value;
textArea.style.color = textColor;
}
function showOverlay() {
overlay.style.display = "block";
}
function writeText() {
$(function() {
var canvasText = document.getElementById("canvasText");
var ctxText = canvasText.getContext("2d");
var $canvasText = $("#canvasText");
var canvasOffset;
var offsetX;
var offsetY;
var isDown;
var dx;
var dy;
var lastX = 0;
var lastY = 0;
var iW;
var iH;
var iLeft = 0;
var iTop = 0;
var iRight, iBottom, iOrientation;
canvasText.height = renderableHeight;
canvasText.width = renderableWidth;
overlay.style.display = "none";
data = textArea.value;
canvasText.style.display = "block";
canvasOffset = $canvasText.offset();
offsetX = canvasOffset.left;
offsetY = canvasOffset.top;
isDown = false;
var textWidthtemp = ctxText.measureText(data);
var textWidth = textWidthtemp.width;
var textHeight = parseInt("50");
var font = italicness + " " + boldness + " " + textHeight + "px " + fontStyleFamily;
iW = textWidth;
iH = textHeight;
facW = 1; // canvasText.width / canvasText.offsetWidth;
facH = 1; //canvasText.height / canvasText.offsetHeight;
console.log(facW + " " + facH);
iRight = iLeft + iW;
iBottom = iTop + iH;
console.log(iTop);
console.log(iBottom);
console.log(iRight);
console.log(iBottom);
iOrientation = "Wide"; //(iW >= iH) ? "Wide" : "Tall";
draw(true);
var border = 10;
var isLeft = false;
var isRight = false;
var isTop = false;
var isBottom = false;
var iAnchor;
canvasText.onmousedown = handleMousedown;
canvasText.onmousemove = handleMousemove;
canvasText.onmouseup = handleMouseup;
canvasText.onmouseout = handleMouseup;
function hitResizeAnchor(x, y) {
// which borders are under the mouse
isLeft = (x * facW > iLeft && x * facW < iLeft + border);
isRight = (x * facW < iRight && x * facW > iRight - border);
isTop = (y * facH > iTop && y * facH < iTop + border);
isBottom = (y * facH < iBottom && y * facH > iBottom - border);
isDragged = (x * facW > iLeft && x * facW < iRight && y * facH > iTop && y * facH < iBottom);
// return the appropriate anchor
if (isTop && isLeft) {
return (iOrientation + "TL");
}
if (isTop && isRight) {
return (iOrientation + "TR");
}
if (isBottom && isLeft) {
return (iOrientation + "BL");
}
if (isBottom && isRight) {
return (iOrientation + "BR");
}
if (isDragged) {
return "DR"
}
return (null);
}
var resizeFunctions = {
WideTR: function(x, y) {
iRight = x * facW;
iTop = iBottom - (iH * (iRight - iLeft) / iW);
},
TallTR: function(x, y) {
iTop = y * facH;
iRight = iLeft + (iW * (iBottom - iTop) / iH);
},
WideBR: function(x, y) {
iRight = x * facW;
iBottom = iTop + (iH * (iRight - iLeft) / iW);
},
TallBR: function(x, y) {
iBottom = y * facH;
iRight = iLeft + (iW * (iBottom - iTop) / iH);
},
WideBL: function(x, y) {
iLeft = x * facW;
iBottom = iTop + (iH * (iRight - iLeft) / iW);
},
TallBL: function(x, y) {
iBottom = y * facH;
iLeft = iRight - (iW * (iBottom - iTop) / iH);
},
WideTL: function(x, y) {
iLeft = x * facW;
iTop = iBottom - (iH * (iRight - iLeft) / iW);
},
TallTL: function(x, y) {
iBottom = y * facH;
iLeft = iRight - (iW * (iBottom - iTop) / iH);
},
DR: function(x, y) {
console.log("DX: " + dx + "DY: " + dy);
iLeft += dx;
iRight += dx;
iTop += dy;
iBottom += dy;
}
};
function handleMousedown(e) {
// tell the browser we'll handle this mousedown
e.preventDefault();
e.stopPropagation();
var mouseX = e.clientX - offsetX;
var mouseY = e.clientY - offsetY;
iAnchor = hitResizeAnchor(mouseX, mouseY);
if (iAnchor == "DR") {
lastX = mouseX;
lastY = mouseY;
isDown = (true);
} else {
isDown = (iAnchor);
}
}
function handleMouseup(e) {
// tell the browser we'll handle this mouseup
e.preventDefault();
e.stopPropagation();
if (iAnchor == "DR") {
isDown = false;
} else {
isDown = false;
draw(true);
}
}
function handleMousemove(e) {
// tell the browser we'll handle this mousemove
e.preventDefault();
e.stopPropagation();
// return if we're not dragging
if (!isDown) {
return;
}
// get MouseX/Y
var mouseX = e.clientX - offsetX;
var mouseY = e.clientY - offsetY;
//if Picture is dragged
if (iAnchor == "DR") {
dx = mouseX - lastX;
dy = mouseY - lastY;
// set the lastXY for next time we're here
lastX = mouseX;
lastY = mouseY;
resizeFunctions[iAnchor](mouseX, mouseY);
draw(true);
} else {
// reset iLeft,iRight,iTop,iBottom based on drag
resizeFunctions[iAnchor](mouseX, mouseY);
// redraw the resized image
draw(false);
}
}
function draw(withAnchors) {
ctxText.clearRect(0, 0, canvasText.width, canvasText.height);
ctxText.font = font;
ctxText.fillStyle = textColor;
ctxText.fillText(data, iLeft, iTop - textHeight);
if (withAnchors) {
ctxText.fillRect(iLeft, iTop - textHeight, border, border);
ctxText.fillRect(iRight - border, iTop - textHeight, border, border);
ctxText.fillRect(iRight - border, iBottom - border - textHeight, border, border);
ctxText.fillRect(iLeft, iBottom - border - textHeight, border, border);
}
}
});
}
function bold() {
var temp = textArea.style.fontWeight;
if (temp == 'normal') {
textArea.style.fontWeight = 'bold';
boldness = 'bold';
} else {
textArea.style.fontWeight = 'normal';
boldness = 'normal';
}
}
function italic() {
var temp = textArea.style.fontStyle;
if (temp == 'normal') {
textArea.style.fontStyle = 'italic';
italicness = 'italic';
} else {
textArea.style.fontStyle = 'normal';
italicness = 'normal';
}
}
function changeFont() {
var temp = textFontFamily.options[textFontFamily.selectedIndex].value;
console.log(temp);
textArea.style.fontFamily = temp;
fontStyleFamily = temp;
}
<div id="display" class="flex-workspace-item-big z-depth-2">
<canvas id=canvas style="width:inherit ;height:inherit; position: absolute; z-index: 0;"></canvas>
<canvas id=canvasFilter style="width:inherit ;height:inherit; position: absolute; display: none; z-index: 1"></canvas>
<canvas id=canvasText style="width:inherit ;height:inherit; position: absolute; display: none; z-index: 2"></canvas>
</div>

HTML infinite pan-able canvas

How can I create an 'infinite' canvas with text boxes dotted around? Like this one at the Desmos site.
I have not managed to implement it myself.
The simplest approach to a pan-able canvas is to draw everything relative to an offset, in this example I have called this panX & panY. Imagine it as a coordinate you use to move the viewport (the area of the infinite board that is currently visible in the canvas).
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: black;
}
canvas {
position: absolute;
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
border: solid 1px white;
border-radius: 10px;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="application/javascript">
var imageWidth = 180;
var imageHeight = 160;
var canvas = null;
var ctx = null;
var bounds = null;
var selectedBox = null;
var panX = 0;
var panY = 0;
var mouseX = 0;
var mouseY = 0;
var oldMouseX = 0;
var oldMouseY = 0;
var mouseHeld = false;
var boxArray = [];
function DraggableBox(x,y,width,height,text) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.text = text;
this.isSelected = false;
}
DraggableBox.prototype.isCollidingWidthPoint = function(x,y) {
return (x > this.x && x < this.x + this.width)
&& (y > this.y && y < this.y + this.height);
}
DraggableBox.prototype.drag = function(newX,newY) {
this.x = newX - this.width * 0.5;
this.y = newY - this.height * 0.5;
}
DraggableBox.prototype.draw = function() {
if (this.isSelected) {
ctx.fillStyle = "darkcyan";
ctx.fillRect(
this.x - panX,
this.y - panY,
this.width,
this.height
);
ctx.fillStyle = "black";
} else {
ctx.fillRect(
this.x - panX,
this.y - panY,
this.width,
this.height
);
}
ctx.fillStyle = "white";
ctx.fillText(
this.text,
this.x + this.width * 0.5 - panX,
this.y + this.height * 0.5 - panY,
this.width
);
ctx.fillStyle = "black";
}
window.onmousedown = function(e) {
mouseHeld = true;
if (!selectedBox) {
for (var i = boxArray.length - 1; i > -1; --i) {
if (boxArray[i].isCollidingWidthPoint(mouseX + panX,mouseY + panY)) {
selectedBox = boxArray[i];
selectedBox.isSelected = true;
requestAnimationFrame(draw);
return;
}
}
}
}
window.onmousemove = function(e) {
mouseX = e.clientX - bounds.left;
mouseY = e.clientY - bounds.top;
if (mouseHeld) {
if (!selectedBox) {
panX += oldMouseX - mouseX;
panY += oldMouseY - mouseY;
} else {
selectedBox.x = mouseX - selectedBox.width * 0.5 + panX;
selectedBox.y = mouseY - selectedBox.height * 0.5 + panY;
}
}
oldMouseX = mouseX;
oldMouseY = mouseY;
requestAnimationFrame(draw);
}
window.onmouseup = function(e) {
mouseHeld = false;
if (selectedBox) {
selectedBox.isSelected = false;
selectedBox = null;
requestAnimationFrame(draw);
}
}
function draw() {
ctx.fillStyle = "gray";
ctx.fillRect(0,0,imageWidth,imageHeight);
var box = null;
var xMin = 0;
var xMax = 0;
var yMin = 0;
var yMax = 0;
ctx.fillStyle = "black";
for (var i = 0; i < boxArray.length; ++i) {
box = boxArray[i];
xMin = box.x - panX;
xMax = box.x + box.width - panX;
yMin = box.y - panY;
yMax = box.y + box.height - panY;
if (xMax > 0 && xMin < imageWidth && yMax > 0 && yMin < imageHeight) {
box.draw();
}
}
}
window.onload = function() {
canvas = document.getElementById("canvas");
canvas.width = imageWidth;
canvas.height = imageHeight;
bounds = canvas.getBoundingClientRect();
ctx = canvas.getContext("2d");
ctx.textAlign = "center";
ctx.font = "15px Arial"
boxArray.push(new DraggableBox(Math.random() * 320,Math.random() * 240,100,25,"This is a draggable text box"));
boxArray.push(new DraggableBox(Math.random() * 320,Math.random() * 240,100,50,"Another text box"));
boxArray.push(new DraggableBox(Math.random() * 320,Math.random() * 240,100,50,"Text in a box"));
boxArray.push(new DraggableBox(Math.random() * 320,Math.random() * 240,100,50,"I find this box quite texing"));
boxArray.push(new DraggableBox(Math.random() * 320,Math.random() * 240,150,50,"You weren't supposed to find this box"));
requestAnimationFrame(draw);
}
window.onunload = function() {
canvas = null;
ctx = null;
bounds = null;
selectedBox = null;
boxArray = null;
}
</script>
</body>
</html>

Error reading 'Cannot read property 'x' of undefined' in HTML5 Canvas code

I am having a problem with my JavaScript code. Since I made it so that you could delete shapes from the canvas an error is appearing when I try adding additional shapes to the canvas. The error reads: 'Cannot read property 'x' of undefined'. When the error appears, it quotes line 116 of the code, which reads: 'var dx = tmpRingB.x - tmpRing.x;'. I need to make it so this error does not appear. The code is as below.
var shapeObj = function (counter, context, canvas, settingsBox) {
//Where sound info goes (freq, vol, amp, adsr etc)
this.id = "shape"+counter;
this.ctx = context;
this.canvas = canvas;
this.sBox = settingsBox;
this.audioProperties = {
duration: Math.random()*1-0.1,
frequency: Math.random()*44000-220
}
this.x = Math.random()*this.ctx.canvas.width;
this.y = Math.random()*this.ctx.canvas.height;
this.radius = 40;
this.vx = Math.random()*6-3;
this.vy = Math.random()*6-3;
this.draw = function () {
this.ctx.beginPath();
this.ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
this.ctx.closePath();
this.ctx.stroke();
}
this.clickTest = function (e) {
var canvasOffset = this.canvas.offset();
var canvasX = Math.floor(e.pageX-canvasOffset.left);
var canvasY = Math.floor(e.pageY-canvasOffset.top);
var dX = this.x-canvasX;
var dY = this.y-canvasY;
var distance = Math.sqrt((dX*dX)+(dY*dY));
if (distance <= this.radius) {
this.manageClick();
}
};
this.manageClick = function(){
alert('this is ' + this.id);
this.sBox.populate(this.audioProperties, this);
this.radius -= 10;
}
this.update = function(newProps){
// repopulate the shapes with new settings
}
}
var settingsBox = function (){
this.populate = function(props, obj){
for (a in props){
alert(props[a]);
}
}
}
$(document).ready(function() {
var canvas = $('#myCanvas');
var ctx = 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 - 2);
canvas.attr("height", $(window).get(0).innerHeight - 124);
canvasWidth = canvas.width();
canvasHeight = canvas.height();
};
resizeCanvas();
canvas.onselectstart = function () { return false; }
ctx.strokeStyle = "rgb(255, 255, 255)";
ctx.lineWidth = 5;
var playAnimation = true;
$(canvas).click(function(e) {
for (i = 0; i < objects.length; i++) {
objects[i].clickTest(e);
}
});
objects = [];
sBox = new settingsBox();
for (var i = 0; i < 4; i++) {
var ring = new shapeObj(i, ctx, canvas, sBox);
objects[i] = ring;
objects[i].draw();
}
$("#button4").click(function() {
var ring = new shapeObj(i, ctx, canvas, sBox);
objects[i] = ring;
objects[i++].draw();
playSoundA();
});
function animate() {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
deadObjects = [];
for (var i = 0; i < objects.length; i++) {
var tmpRing = objects[i];
for (var j = i+1; j < objects.length; j++) {
var tmpRingB = objects[j];
var dx = tmpRingB.x - tmpRing.x;
var dy = tmpRingB.y - tmpRing.y;
var dist = Math.sqrt((dx * dx) + (dy * dy));
if(dist < tmpRing.radius + tmpRingB.radius) {
playSound();
//Put collision animations here!!!
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 = tmpRing.vx * cosine + tmpRing.vy * sine;
var vy = tmpRing.vy * cosine - tmpRing.vx * sine;
var vxb = tmpRingB.vx * cosine + tmpRingB.vy * sine;
var vyb = tmpRingB.vy * cosine - tmpRingB.vx * sine;
vx *= -1;
vxb *= -1;
xb = x + (tmpRing.radius + tmpRingB.radius);
tmpRing.x = tmpRing.x + (x * cosine - y * sine);
tmpRing.y = tmpRing.y + (y * cosine + x * sine);
tmpRingB.x = tmpRing.x + (xb * cosine - yb * sine);
tmpRingB.y = tmpRing.y + (yb * cosine + xb * sine);
tmpRing.vx = vx * cosine - vy * sine;
tmpRing.vy = vy * cosine + vx * sine;
tmpRingB.vx = vxb * cosine - vyb * sine;
tmpRingB.vy = vyb * cosine + vxb * sine;
tmpRing.loop = true;
};
};
tmpRing.x += tmpRing.vx;
tmpRing.y += tmpRing.vy;
if (tmpRing.x - tmpRing.radius < 0) {
playSound();
tmpRing.x = tmpRing.radius;
tmpRing.vx *= -1;
} else if (tmpRing.x + tmpRing.radius > ctx.canvas.width) {
playSound();
tmpRing.x = ctx.canvas.width - tmpRing.radius;
tmpRing.vx *= -1;
};
if (tmpRing.y - tmpRing.radius < 0) {
playSound();
tmpRing.y = tmpRing.radius;
tmpRing.vy *= -1;
} else if (tmpRing.y + tmpRing.radius > ctx.canvas.height) {
playSound();
tmpRing.y = ctx.canvas.height - tmpRing.radius;
tmpRing.vy *= -1;
};
if(tmpRing.radius <= 0) {
deadObjects.push(tmpRing);
}
objects[i].draw();
};
if (deadObjects.length > 0) {
for (var d = 0; d < deadObjects.length; d++) {
var tmpDeadObject = deadObjects[d];
objects.splice(objects.indexOf(tmpDeadObject), 1);
}
}
if(playAnimation) {
setTimeout(animate, 33);
};
};
animate();
});
Any ideas?
Thanks for the help.
Your object is undefined because you've deleted it. A simple solution is to check to see if the object is still defined.
insert the following line just before the line with the error.
if(!(tmpRingB && tmpRing)) continue;
a better solution is to clean house on your array when you delete it.

Categories