2013-09-23 3 views
3

Я понимаю, что здесь что-то не так. Все письма распечатываются сразу. Я хочу эффект пишущей машинки в HTML-холсте. (В конечном счете, я хотел бы, чтобы буквы следовали линии, прорисованной внутри холста, но это большая головоломка.) Я думаю, что проблема в цикле for, но я не уверен, как это исправить ... Любая помощь оценили!Можно ли комбинировать цикл for с setTimeOut в javascript?

<html> 
<head> 
<style> 
canvas { 
    border: 2px solid #f00; 
} 
</style> 
</head> 

<label>Your message here:</label> 
<br> 
<input class="textBox" style="width: 50em; height: 2em;" id="userInput" /> 
<button id="sub_btn">Submit</button> 

<body> 
<canvas width="360" height="400" id="canvas"></canvas> 

<script type="text/javascript"> 

var canvas, ctx; 

function typeOut(str, startX, startY, lineHeight, padding) { 
    var random = Math.floor((Math.random()*100)+40); 
    var cursorX = startX || 0; 
    var cursorY = startY || 0; 
    var lineHeight = lineHeight || 32; 
    padding = padding || 10; 
    var i = 0; 

    for (i = 0; i <= str.length; i++){ 

    var w = ctx.measureText(str.charAt(i)).width; 
    if(cursorX + w >= canvas.width - padding) { 
      cursorX = startX; 
      cursorY += lineHeight; 
     } 

    if (str.charAt(i) === '\n' || str.charAt(i) === '\r'){ 
      ctx.fillText(str.charAt(i), cursorX, cursorY); 
      setTimeout(typeOut, 20); 
      cursorX = startX; 
    } else if (str.charAt(i) === ' '){ 
      ctx.fillText(str.charAt(i), cursorX, cursorY); 
      setTimeout(typeOut, 20); 
      cursorX += w; 
    } else if (str.charAt(i) === ',' || str.charAt(i) === '.' || str.charAt(i) === '?'){ 
      ctx.fillText(str.charAt(i), cursorX, cursorY); 
      setTimeout(typeOut, 220); 
      cursorX += w; 
    } else if (str.charAt(i) === '@') { 
      ; 
      setTimeout(typeOut, 300); 
    } else { 
      ctx.fillText(str.charAt(i), cursorX, cursorY); 
      setTimeout(typeOut, random); 
      cursorX += w; 
    } 
    } 
} 

(document.getElementById('sub_btn').onclick = function() { 
    canvas = document.getElementById('canvas'); 
    ctx = canvas.getContext('2d'); 
    ctx.fillStyle = '#000000'; 
    ctx.font = '24px sans-serif'; 
    var str = document.getElementById('userInput').value; 
    typeOut(str, 25, 25, 32, 10); 

})(); 

</script> 
</body> 
</html> 
+0

Вы будете иметь чтобы дать больше, чем «не работает». Говорит ли консоль что-нибудь? Каков ожидаемый и фактический результат? –

+0

настроить живой пример на jsfiddle, чтобы проиллюстрировать вашу проблему. Буквы будут печататься сразу, поскольку цикл является синхронным, но setTimeout является асинхронным, одним из решений будет использование значения i цикла for для увеличения задержки таймаута с каждой итерацией. – mpm

+0

@tryingToGetProgrammingStraight. Он присваивает '0'' cursorX 'если' startX' является ложным. @tremstat Используйте рекурсивную функцию (например, вы почти делаете с setTimeout), а не цикл. Передайте итератор при следующем вызове функции после задержки и просто отбросьте цикл for. – Chad

ответ

3

setTimeout() не является функцией «сна». Он не приостанавливает сценарий. Когда вы говорите:.

setTimeout(typeOut, 220); 

Вы говорите, что «Расписание другой вызов typeOut() в 220ms, а тем временем продолжать идти с петлей for, как и прежде

Вы хотите обработать символ, а затем вызвать продолжение функция (в правом интервале), чтобы обработать следующий Что-то вроде:.

function typeOut(str, startX, startY, lineHeight, padding) { 
    var random = Math.floor((Math.random()*100)+40); 
    var cursorX = startX || 0; 
    var cursorY = startY || 0; 
    var lineHeight = lineHeight || 32; 
    padding = padding || 10; 
    var i = 0; 

    // this will be called once per character 
    var processNext = function() { 
     if (i >= str.length) 
     return; 
     var timeout = random; 

     var w = ctx.measureText(str.charAt(i)).width; 
     if(cursorX + w >= canvas.width - padding) { 
      cursorX = startX; 
      cursorY += lineHeight; 
     } 

     if (str.charAt(i) === '\n' || str.charAt(i) === '\r'){ 
      ctx.fillText(str.charAt(i), cursorX, cursorY); 
      timeout = 20; 
      cursorX = startX; 
     } else if (str.charAt(i) === ' '){ 
      ctx.fillText(str.charAt(i), cursorX, cursorY); 
      timeout = 20; 
      cursorX += w; 
     } else if (str.charAt(i) === ',' || str.charAt(i) === '.' || str.charAt(i) === '?'){ 
      ctx.fillText(str.charAt(i), cursorX, cursorY); 
      timeout = 220; 
      cursorX += w; 
     } else if (str.charAt(i) === '@') { 
      timeout = 300; 
     } else { 
      ctx.fillText(str.charAt(i), cursorX, cursorY); 
      cursorX += w; 
     } 

     ++i; 

     setTimeout(processNext, timeout); 
    }; 

    // now start typing 
    processNext(); 
} 

Пример CodePen: http://codepen.io/paulroub/pen/EDqok

+0

@tremstat Вы также можете отслеживать timeOuts в переменной, поэтому вы можете отменить рисунок, вызвав 'clearTimeout()'. – jcbelanger

Смежные вопросы