JavaScript ctx.fill() and ctx.stroke very slow - javascript

I know I am now supposed to just ask you "why is my code so slow" and give you a big amount of code, but I have this problem for a week now, and it really frustrates me.
function drawFront() {
ctx.beginPath();
var tempPosition = scene.box.func.calcPos(scene.box.names[i], 0, 0, 0);
ctx.moveTo(tempPosition.x, tempPosition.y);
var tempPosition = scene.box.func.calcPos(scene.box.names[i], 1, 0, 0);
ctx.lineTo(tempPosition.x, tempPosition.y);
var tempPosition = scene.box.func.calcPos(scene.box.names[i], 1, 1, 0);
ctx.lineTo(tempPosition.x, tempPosition.y);
var tempPosition = scene.box.func.calcPos(scene.box.names[i], 0, 1, 0);
ctx.lineTo(tempPosition.x, tempPosition.y);
ctx.closePath();
if (scene.box[scene.box.names[i]].material.useFaces == true){ //this is true
ctx.fillStyle = scene.box[scene.box.names[i]].material.faces[0].c;
ctx.fill();
}
if (scene.box[scene.box.names[i]].material.grid == true) // this is true
ctx.stroke();
}
This code is supposed to draw a shape with 4 corners, all of these corner positions are calculated using the scene.box.func.calcPos() function. All of this works perfectly fine, but the drawing gets slower and slower and slower as times moves by.
My CPU temperature gradually goes up from 40°C to 80°C and above.
What could be the cause of this?
EDIT:
here is a jsfiddle of it: https://jsfiddle.net/fswxtxyz/
here is the github page to the project: https://github.com/Quoteme/Fluchtpunkt3D
Thank you very very much for your help

Related

Making an If-Else Statement to Choose Color of a Shape in a Canvas

I am currently tasked with creating shapes on a canvas of different colors using a DOM. This is my first experience with the DOM. All the HTML and JS works fine if there was 1 color for all shapes, but I am trying to edit the function in question (drawShape(canvasID)) to have an if-else statement that determines the name of the canvasID and have a color associated with it.
Below is my first attempt at differentiating between two canvasId's to display either a red or blue rectangle.
function getElement(elementName) {
var element = document.getElementById(elementName);
return element;
}
function drawShape(canvasID){
var canvas = getElement(canvasID);
alert("Canvas is" + canvas);
var ctx= canvas.getContext('2d');
//ctx.rect(25, 25, 100, 100);
//ctx.fillStyle = "red";
//ctx.fill();
if (canvas == "CANVAS1"){
ctx.rect(25, 25, 100, 100);
ctx.fillStyle = "red";
ctx.fill();
}else if (canvas == "CANVAS2"){
ctx.rect(25, 25, 100, 100);
ctx.fillStyle = "blue";
ctx.fill();
}
}
As I said the rest of the program runs fine, and if I delete the if/else statements and use the lines that are currently comments, then the program will display all the rectangles as red. I just wanted advice on differentiating the colors. Any help is appreciated!
If editing to show all the JS and HTML is necessary just let me know!
Recently had almost the same problem.
Be sure to use "ctx.beginPath();" objects separator;
You can always replace a rect with a line.
See my code for changing color lines:
function lines(color1,color2) {
for (i = 0, j = 0; i <= 8 * 20; i += 20, j++) {
ct3.beginPath();
ct3.moveTo(300, 30 + i);
ct3.lineTo(900, 30 + i);
ct3.lineWidth = 20;
ct3.strokeStyle = (j%2 != 0) ? color1 : color2;
ct3.stroke();
}
}

clearRect produces white box (not removes set colors)

I have multiple stacked contexts in a canvas (each will be displaying circles, then deleting cirles, creating new circle in new location on the context). I was testing the feasibility with this code:
var radius = 10;
cx2 = document.getElementById("myCanvasID").getContext('2d');
cx2.beginPath();
cx2.arc(150, 150, 10, 0, Math.PI*2, true);
cx2.closePath();
cx2.fillStyle = '#6495ED';
cx2.fill();
cx2.lineWidth = 2;
cx2.strokeStyle = '#003300';
cx2.stroke();
//ctx2.fillColor = "rgba(0-255, 0-255, 0-255, 0-1)"
cx2.clearRect(0,0,300,300);
//cx2.globalCompositeOperation = "destination-out"
//cx2.fillStyle = 'rgba(0, 255, 0, 0)';
// cx2.fillRect(0, 0, 300, 300);
// cx2.globalCompositeOperation = "destination-in"
cx2.beginPath();
cx2.arc(180, 180, 10, 0, Math.PI*2, true);
cx2.closePath();
cx2.fillStyle = '#6495ED';
cx2.fill();
cx2.lineWidth = 2;
cx2.strokeStyle = '#003300';
cx2.stroke();
The issue with clearRect is that it leaves a white rectangle and I want to have it transparent, as the layer below has a background.
Other layers will be stacked on top and all needs to be transparent, the deleting of the circle and redrawing should not affect this.
I have tried a few other commands, but none have worked so far. clearRect gives me this white rectangle:
https://jsfiddle.net/dorien/tghgsw5g/
You have one context: .getContext('2d') returns the CanvasRenderingContext2D for the canvas. It does not create new contexts. So, when you cx2.clearRect(0,0,300,300); you're also clearing cx1 because, well, it's the same context.
If you want separate "layers" you need to create separate <canvas>'s and position them on top of each other.

How to change color of circle temporarily in HTML5 Canvas

I am trying to build simon game using html5 canvas and pure javascript. I have managed to get the simon game UI using html5 canvas. My next step is to make the four components light up randomly. I am not sure if this is even possible with html5 canvas or probably my approach is wrong. Any hints in the right direction will be of great help. My code is as follows
codepen link: http://codepen.io/anon/pen/QEdPRN?editors=1010
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
//bigger circle
ctx.beginPath();
ctx.arc(235,230,140,0,2*Math.PI);
ctx.fillStyle = '#000';
ctx.fill();
ctx.stroke();
//smaller circle
ctx.beginPath();
ctx.arc(235,230,60,0,2*Math.PI);
ctx.fillStyle = '#fff';
ctx.fill();
ctx.stroke();
//draw the four arcs
var x = [240,240,230,230];
var y = [240,225,225,240];
var start = [0,1.5*Math.PI,1*Math.PI,0.5*Math.PI];
var end = [0.5*Math.PI,0,1.5*Math.PI,1*Math.PI];
var color = ["blue","red","green","yellow"];
var draw = function (a,b,c,d,e) {
ctx.beginPath();
ctx.arc(a,b,90,c,d);
ctx.lineWidth = 50;
ctx.strokeStyle = e;
ctx.stroke();
}
function drawSimon() {
for(var i=0;i<4;i++){
draw(x[i],y[i],start[i],end[i],color[i]);
}
}
drawSimon();
Your first problem: This is just a static image.
You only call drawSimon() once, thus it only gets drawn once. To fix this, you need to use requestAnimationFrame or setInterval (preferably the first).
requestAnimationFrame is like a simple method call, but delays the method, so it lines up with the screen's framerate. You need to call drawSimon from inside drawSimon with this.
function drawSimon() {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); //Clear the screen
//Draw the simon here
requestAnimationFrame(drawSimon);
}
drawSimon();
Next you want to choose a random color and make it lighter. There's a problem with this. Your colors are all already pure colors, you can't make them brighter. You need to use darker colors (example: rgb(150, 0, 0) instead of red). Then you need to choose a random index between 0 and 3 (inclusively), and make the color in that place brighter.
var index = Math.floor(Math.random() * 4);
switch (index) {
case 0:
color[0] = "blue";
break;
case 1:
color[0] = "red";
break;
case 2:
color[0] = "green";
break;
case 3:
color[0] = "yellow";
break;
}
Third step: make the colors change back.
You could achieve this with a time counter. Each time you set a color to brighter save the time this was done. Each frame, check the time between the current time and the last time you changed to colors, and if it's over a specific limit, set them back the same way you did with the brighter colors.
//global scope:
var lastChange = 0;
//Change a color to lighter here
lastChange = Date.now();
//Later in the code
if (Date.now() - lastChange > maxTime) {
//Change colors back here
}

html5 canvas drawing position not correct

I am currently writing a simple snake game.
http://jsfiddle.net/jhGq4/3/
I started with drawing the grid for the background
function fill_grid() {
ctx.beginPath();
var row_no = w/cw;
var col_no = h/cw;
for (var i=0;i<row_no;i++)
{
for (var j=0;j<col_no;j++)
{
ctx.rect(i*cw, j*cw, (i+1)*cw, (j+1)*cw);
ctx.fillStyle = 'black';
ctx.fill();
ctx.lineWidth = 1;
ctx.strokeStyle = '#135d80';
ctx.stroke();
}
}
}
It works great but when i paint the snake, the position gets wrong and the length is doubled. I tried to console.log the x position of my snake but they are correct.
function paint_cell(x, y)
{
console.log(x*cw);
console.log((x+1)*cw);
ctx.fillStyle = '#fff799';
ctx.fillRect(x*cw, y*cw, (x+1)*cw, (y+1)*cw);
ctx.lineWidth = 1;
ctx.strokeStyle = '#135d80';
ctx.strokeRect(x*cw, y*cw, (x+1)*cw, (y+1)*cw);
}
***Because someone wants to learn how to make a snake game,
this is my final solution for this game.
http://jsfiddle.net/wd9z9/
You can also visit my site to play:
use WSAD to play.
http://www.catoyeung.com/snake2/single.php
:D
I tested this alternative init function:
function init()
{
fill_grid();
// create_snake1();
// paint_snake1();
paint_cell(5, 5)
}
Which paints a square starting at coords (5,5), but of size 6x6.
I believe you are misusing the fillRect() method. Use
ctx.fillRect(x*cw, y*cw, cw, cw);
Instead of
ctx.fillRect(x*cw, y*cw, (x+1)*cw, (y+1)*cw);
the same probably applies to strokeRect.
Incidentally, I was looking at your grid-fill function. You fill i*j adjacent squares, which works, but you really only need i vertical lines and j horizontal ones - which is a lot less processing. Run a quicker loop with fewer calculations:
function fill_grid() {
ctx.beginPath();
ctx.fillStyle = 'black';
ctx.fillRect(0,0,w,h);
for (var i=0;i<=h;i+=cw)
{
ctx.moveTo(0,i);
ctx.lineTo(w,i);
ctx.moveTo(i,0);
ctx.lineTo(i,h);
}
ctx.stroke();
}
I would also only define line width and stroke colour once, as you initialise the canvas. You may not need to worry about this of course. But this kind of care can make a difference if you refresh the grid often to animate your snakes.

HTML5 Canvas Basic Line Animation

So, I'm trying to get into HTML5 Canvas with a small project animating an existing header consisting of red laser-like lines bursting from a single point. I'm able to draw these lines as I want them, and animate them as a group at a nice speed, but the next hurdle is above my head, I think: I'd like each line to move independently!
I've got an object defining the starting point for my lines such as:
var myLines = {
a: 1500,
b: 700,
c: 400,
d: 310,
e: 140,
f: 60
}
And I then draw with a loop kinda like:
for (var i in myLines)
{
var cur = myLines[i];
context.beginPath();
context.moveTo(0, canvas.height);
context.lineTo(canvas.width, myLine.y-cur);
context.stroke();
}
Using an awkward method of incrementation:
var step = 1;
if (myLine.y+step > canvas.height) {set = false;}
if (myLine.y-step < 0) {set = true;}
if (set) {
myLine.y = myLine.y+step;
} else {
myLine.y = myLine.y-step;
}
I'm aware the above code is poorly written, I'm out of my league here, I work during the day as a chef in a small kitchen, but I'd like some advice, please!
Here's a fiddle to see it all in action.
Thanks in advance!
If I were you I would change the script so that each line was a separate object, rather than just an offset. Something like:
var line = { x: 0, y: 0, speed: 1 };
That way each line can have its own speed, and inside your loop, you can do something like the following to add on the speed and flip it when you reach the edge of the screen:
line.x += line.speed;
if(/* edge of screen */) {
line.speed = -line.speed;
}

Categories