Show the drawing process using JavaScript and HTML5 canvas

I am currently trying to create a small pythagoras tree using JavaScript / JQuery and HTML5 canvas.

The algorithm works fine, but, unfortunately, I do not see the drawing process. The user interface just freezes and shows the whole picture after completion.

Current behavior: http://www.kappelcation.com/index.php?contentid=4 This is the behavior I would like: http://www.jjam.de/Java/Applets/Fraktale/Pythagoras_Baum.html (you need enable Java applet and click several times to see drawing progress).

$(document).ready(function(){ //just some listeners and initialization initCanvas(); $(autOrManSelect).change(function(){ if(($(this).val()==1)) //changed from manual to automatic { $(pythagorasCanvas).click(); } }); $(startButton).click(function(event){ $(this).unbind(event); $(this).html('Add Leaves'); $(restartButton).css("visibility", "visible"); startTree(); $(this).click(function(){ var next = parseInt($(depthInput).val())+1; $(depthInput).val(next); $(pythagorasCanvas).click(); }); }); $(restartButton).click(function(){ startTree(); }); }); function initCanvas() //adjust size, clear the canvas and draw a boarder { var canvas = document.getElementById("pythagorasCanvas"); canvas.height=600; canvas.width=$(mainDiv).width()-40; $(pythagorasCanvas).unbind("click"); if (canvas.getContext) { var context = canvas.getContext("2d"); //clear canvas drawRectangle(context, new Point(0,canvas.height), new Point(canvas.width,canvas.height), new Point(canvas.width,0), new Point(0,0), "#FFFFFF"); //draw border for canvas drawRectangle(context,new Point(0,canvas.height),new Point(canvas.width,canvas.height), new Point(canvas.width, 0),new Point(0,0), '#000000', true); } } function startTree() //start drawing process { initCanvas(); var canvas = document.getElementById("pythagorasCanvas"); if (canvas.getContext) { var context = canvas.getContext("2d"); var rectLength = parseInt($(firstSquareInput).val()); var startWidth = canvas.width/2-rectLength/2; var startHeight = canvas.height-canvas.height/4; var startA = new Point(startWidth, startHeight); var startB = new Point(startWidth+rectLength, startHeight); drawBranch(context, startA, startB, 0); } } function Point(x, y) { this.x = x; this.y = y; } function drawBranch(context, a, b, depth) //gets called recursively { var maxDepth = $(depthInput).val(); if(depth<maxDepth) { depth++; //calculate positions of current rectangle var dx = bx - ax; var dy = ay - by; var c = new Point(bx-dy, by-dx); var d = new Point(ax-dy, ay-dx); //draw current rectangle drawRectangle(context, a, b, c, d); //calculate new position var offSetX; if($(triangleOffsetInput).val().toLowerCase()=="random") { offSetX = Math.random(); } else { offSetX = parseFloat($(triangleOffsetInput).val())/100; //first offset in x-direction (in relation to a square length of 1) } var offSetY = -Math.sqrt(Math.pow(0.5,2)-Math.pow((0.5-offSetX),2)); //Pythagoras to get the offset in y (negative sign necessary because the y-values get smaller upwards) var e = new Point( dx + offSetX*(cx-dx) + offSetY*(ay-by), dy + offSetX*(cy-dy) + offSetY*(bx-ax)); if($(fillTriangleBox).prop("checked")) { drawTriangle(context, c, d, e); } var autOrMan = $(autOrManSelect).val(); if(autOrMan==1) { //draw new positions drawBranch(context, d, e, depth); drawBranch(context, e ,c, depth); } else { $(pythagorasCanvas).click(function(event) { $(this).unbind(event); drawBranch(context, d, e, depth); drawBranch(context, e ,c, depth); }); } } else { $(pythagorasCanvas).click(function(event) { $(this).unbind(event); drawBranch(context, a, b, depth); }); } } function drawTriangle(context, c, d, e, color) { if(typeof(color)==='undefined') { color='#'+$(triangleColorInput).val(); } context.strokeStyle = color; context.beginPath(); context.moveTo(cx, cy); context.lineTo(dx, dy); context.lineTo(ex, ey); context.closePath(); context.fillStyle = color; context.fill(); context.stroke(); } function drawRectangle(context, a, b, c, d, color, ignoreFill) { if(typeof(color)==='undefined') { color='#'+$(rectColorInput).val(); } if(typeof(ignoreFill)==='undefined') { ignoreFill=false; } context.strokeStyle = color; context.beginPath(); context.moveTo(ax, ay); context.lineTo(bx, by) context.lineTo(cx, cy); context.lineTo(dx, dy); context.closePath(); if($(fillRectBox).prop("checked") && !ignoreFill) { context.fillStyle = color; context.fill(); } context.stroke(); } 

I tried to use the setTimeout () function to make the drawing process asynchronous to achieve the desired behavior, but I either could not execute it, or setTimeout () does not help in this situation.

Hope you can give me a hint. Thank you in advance!

+4
source share
2 answers

I think the following (unverified) modification of your drawBranch function using setTimeout should work

 if(autOrMan==1) { //draw new positions setTimeout(function() { drawBranch(context, d, e, depth); drawBranch(context, e ,c, depth); }, 0); } else { $(pythagorasCanvas).click(function(event) { $(this).unbind(event); drawBranch(context, d, e, depth); drawBranch(context, e ,c, depth); }); } 
+1
source

This freezes because JavaScript is single-threaded . Instead of calling drawBranch recursively, schedule it recursively through setTimeout , and then drop out of the function. This will give the browser time to redraw the canvas.

+1
source

Source: https://habr.com/ru/post/1482043/


All Articles