javascript setTimeout() не работает должным образом

#javascript #html #html5-canvas

#javascript #HTML #html5-холст

Вопрос:

Я пытаюсь создать веб-сайт, чтобы визуально показать работу алгоритма средней линии. Я хочу отобразить точки через определенный интервал времени, но функция setTimeout() работает неправильно. Он просто показывает конечный результат после ожидания в течение 3 секунд.

 <canvas id="ltpcanvas" style="border: 1px solid #000000;">
</canvas>
<script>
    window.onload = function(){
        var ltpc = document.getElementById('ltpcanvas');
        ltpc.width = window.innerWidth;
        ltpc.height = window.innerHeight;
        var context = ltpc.getContext('2d');
        var cx1,cx2,cy1,cy2;
        var count=0;
        ltpc.addEventListener('mousedown',onDown,false);
        function onDown(event){
            count  ;
            cx = event.pageX;
            cy = event.pageY;
            cy-=9;
            cx-=9;
            if(count == 1){
                cx1=cx;
                cy1=cy;
            }
            else{
                cx2=cx;
                cy2=cy;
            }
            var ltpc = document.getElementById('ltpcanvas');
            var context = ltpc.getContext('2d');
            context.fillStyle = 'black';
            context.beginPath();
            context.arc(cx,cy,2,0*Math.PI,2*Math.PI,true);
            context.closePath();
            context.fill();

            if(cx1!=undefined amp;amp; cx2!=undefined amp;amp; cy1!=undefined amp;amp; cy2!=undefined){
                if(cx1<cx2amp;amp;cy1<cy2)
                    midpoint(cx1,cy1,cx2,cy2);
                else{
                    alert('cx1 = ' cx1 '  cy1 = ' cy1 'ncx2 = ' cx2 '  cy2 = ' cy2);
                }
            }
        }
    }
    function midpoint(X1,Y1,X2,Y2){
        var dx = X2 - X1; 
        var dy = Y2 - Y1; 

        var d = dy - (dx/2); 
        var x = X1
        var y = Y1;  
    
        while (x < X2) 
        { 
            x  ; 
            if (d < 0) 
                d = d   dy; 
            else
            { 
                d  = (dy - dx); 
                y  ; 
            }
            myvar = setTimeout(Dotfunction,3000,x,y);  
            console.log(x);
            console.log(y);
        } 
    }
    function Dotfunction(x,y){
        var ltpc = document.getElementById('ltpcanvas');
        var context = ltpc.getContext('2d');
        context.fillStyle = 'black';
        context.beginPath();
        context.arc(x,y,1,0*Math.PI,2*Math.PI,true);
        context.closePath();
        context.fill();
    }

</script>  

Я пытаюсь каждый раз откладывать выполнение Dotfunction(), но оно задерживается на 3 секунды, а затем показывает всю строку. Я хочу, чтобы он задерживался после отображения каждой точки.

Ответ №1:

Я хочу отображать точки через определенный интервал времени

Здесь важно то, что мы хотим показывать не «точки», а «каждую точку» через интервал. Это означает, что каждая точка будет нарисована сама по себе. Я предполагаю, что вы хотите, чтобы точки появлялись одна за другой в анимации.

Проблема в том, что в этом коде мы вызываем setTimeout() несколько раз с одной и той же целевой задержкой. Т.Е. Мы говорим движку «сделать это за 3 секунды» много раз в течение одного мгновения. Самое простое решение для получения анимации — пропускать все более высокие таймауты. Поскольку мы вызываем функцию внутри цикла и поскольку в ней уже есть счетная переменная, мы можем просто использовать ее повторно и попросить движок JS отрисовывать каждую точку через 10 миллисекунд после предыдущей.

Следующий код рисует линию со скоростью 100 пикселей в секунду.

PS: Я удалил поле тела, так что больше нет необходимости вычитать его из положения курсора.

 window.onload = function(){
        var ltpc = document.getElementById('ltpcanvas');
        ltpc.width = window.innerWidth;
        ltpc.height = window.innerHeight;
        var context = ltpc.getContext('2d');
        var cx1, cx2, cy1, cy2;
        var count = 0;
        ltpc.addEventListener('mousedown', onDown, false);
        function onDown(event) {
            count  ;
            cx = event.pageX;
            cy = event.pageY;
            if (count == 1) {
                cx1 = cx;
                cy1 = cy;
            }
            else {
                cx2 = cx;
                cy2 = cy;
            }
            var ltpc = document.getElementById('ltpcanvas');
            var context = ltpc.getContext('2d');
            context.fillStyle = 'black';
            context.beginPath();
            context.arc(cx, cy, 2, 0 * Math.PI, 2 * Math.PI, true);
            context.closePath();
            context.fill();

            if (cx1 != undefined amp;amp; cx2 != undefined amp;amp; cy1 != undefined amp;amp; cy2 != undefined) {
                if (cx1 < cx2 amp;amp; cy1 < cy2)
                    midpoint(cx1, cy1, cx2, cy2);
                else {
                    // alert('cx1 = ' cx1 '  cy1 = ' cy1 'ncx2 = ' cx2 '  cy2 = ' cy2);
                }
            }
        }
    }
    function midpoint(X1, Y1, X2, Y2){
        var dx = X2 - X1; 
        var dy = Y2 - Y1; 

        var d = dy - (dx / 2); 
        var x = X1
        var y = Y1;  
    
        while (x < X2) 
        { 
            x  ; 
            if (d < 0) 
                d = d   dy; 
            else { 
                d  = (dy - dx); 
                y  ;
            }
            setTimeout(Dotfunction, x * 10, x, y);  
            //console.log(x);
            //console.log(y);
        } 
    }
    function Dotfunction(x, y) {
        var ltpc = document.getElementById('ltpcanvas');
        var context = ltpc.getContext('2d');
        context.fillStyle = 'black';
        context.beginPath();
        context.arc(x, y, 1,0 * Math.PI, 2 * Math.PI, true);
        context.closePath();
        context.fill();
    }  
 body {
  margin: 0;
}  
 <canvas id="ltpcanvas" style="border: 1px solid #000000;"></canvas>