Как l oop через массив после того, как предыдущий зациклен? - PullRequest
1 голос
/ 28 апреля 2020

Я делаю декоративный текст, который печатает одну букву, пока не образует слово, а затем удаляет это слово символ за символом, чтобы написать новое слово. У меня есть все строки, превращаемые в массив, и я знаю, что мне, вероятно, нужно использовать .length, .slice () и .join. но единственное, что меня озадачило, это как запустить следующий массив после зацикливания предыдущего?

const skillData = {
  js: [..."javascript"],
  ts: [..."typescript"],
  reactJS: [..."reactJS"],
  html: [..."HTML5"],
  css: [..."CSS3"],
  reactNative: [..."React Native"],
  node: [..."NodeJS"],
  mongo: [..."MongoDB"],
  phaser: [..."Phaser 3"],
  py: [..."Python"],
};

let arrayClimber = 0;
const moveSkill = () => {
  if (arrayClimber < skillData.js.length) {
    arrayClimber += 1;
    console.log("going up " + arrayClimber);
  }

  //Needs to start going down then one it reaches zero it should change to the typescript, reactJS, etc arrays
  console.log(skillData.js.slice(0, arrayClimber).join(""));

};

setInterval(moveSkill, 150);

Ответы [ 3 ]

1 голос
/ 28 апреля 2020
  • Измените объект skillData на массив
  • Вести запись текущего слова с переменной currentIndex
  • Создать логическое значение 'done', чтобы остановить выполнение setInterval, когда Массив завершен с повторением.

const skillData = [
  [..."javascript"],
  [..."typescript"],
  [..."reactJS"],
  [..."HTML5"],
  [..."CSS3"],
  [..."React Native"],
  [..."NodeJS"],
  [..."MongoDB"],
  [..."Phaser 3"],
  [..."Python"],
];

let arrayClimber = 0;
let currentIndex = 0;
let finished = false;
const moveSkill = () => {
  if (arrayClimber < skillData[currentIndex].length) {
    arrayClimber += 1;
    console.log("going up " + arrayClimber);
  } else {
    currentIndex++;
    arrayClimber = 0;
  }
  
  if (skillData.length == currentIndex) {
    finished = true;
    return;
  }

  //Needs to start going down then one it reaches zero it should change to the typescript, reactJS, etc arrays
  console.log(skillData[currentIndex].slice(0, arrayClimber).join(""));

};

setInterval(() => {
  if (!finished)
    moveSkill();
}, 150);
0 голосов
/ 28 апреля 2020

Вы должны будете знать условие всякий раз, когда одно слово было напечатано (и удалено в вашем случае). Из-за разной длины слова я предлагаю вам использовать обещания . С обещаниями вы можете проверить, что условие слова было напечатано полностью, а затем выполнить обещание.

Это дает вам возможность динамически ожидать печати каждого слова перед началом следующего. С помощью комбинации протокола итератора вы можете l oop для каждого обещания и ждать его завершения, прежде чем начинать следующее слово.

В приведенном ниже примере используется генераторная функция для создания такого итерируемый объект, который дает обещание для каждого слова, которое должно быть напечатано. При зацикливании этого объекта вы печатаете каждое слово, ждете, пока оно не закончится sh, и переходите к следующему слову в списке.

Преимущество этого подхода заключается в том, что вы можете легко контролировать время каждого слова и код не блокирует. Таким образом, другие сценарии будут запускаться без ожидания завершения этого сценария.

const wordElement = document.getElementById('word');

const skillData = {
  js: [..."javascript"],
  ts: [..."typescript"],
  reactJS: [..."reactJS"],
  html: [..."HTML5"],
  css: [..."CSS3"],
  reactNative: [..."React Native"],
  node: [..."NodeJS"],
  mongo: [..."MongoDB"],
  phaser: [..."Phaser 3"],
  py: [..."Python"],
};

const printWord = (word, speed) => new Promise(resolve => {
  let index = 1;
  let wordLength = word.length;
  let interval = setInterval(() => {
    if (index <= wordLength) {
      let partOfWord = word.slice(0, index).join('');
      requestAnimationFrame(() => {
        wordElement.textContent = partOfWord;
      });
      index++
    } else {
      clearInterval(interval);
      resolve(word);
    }
  }, speed);
});

async function* wordPrinter(data) {
  for (const word of Object.values(data)) {
    yield printWord(word, 100);
  }
}

async function printWords() {
  for await (const word of wordPrinter(skillData)) {
    console.log('Word printed:', word.join(''));
  }
  return 'Done printing';
}

printWords().then(console.log);
<p id="word"></p>
0 голосов
/ 28 апреля 2020

Вы можете попробовать что-то вроде этого:

  • L oop поверх клавиш объекта, используя Object.keys или for...in
  • Получить текущий навык.
  • L oop сверх текущего навыка и значений печати. Вы можете использовать .reduce или обычный for loop
    • Создать переменную, которая будет содержать строку для печати. Поскольку он должен содержать значение предыдущих итераций, он должен быть определен вне этой l oop.
    • На каждой итерации вы добавляете в нее текущий символ и печатаете значение.
    • В конце этого l oop, вы можете усечь его или перед l oop, вы можете инициализировать его пустым по умолчанию.

Примечание: Чтобы предотвратить переполнение консоли, я должен использовать setTimeout вместо setInterval

Кроме того, SO имеет ограничение на значения, отображаемые во встроенной консоли. Для правильного результата проверьте актуальную консоль браузера

const skillData = {
  js: [..."javascript"],
  ts: [..."typescript"],
  reactJS: [..."reactJS"],
  html: [..."HTML5"],
  css: [..."CSS3"],
  reactNative: [..."React Native"],
  node: [..."NodeJS"],
  mongo: [..."MongoDB"],
  phaser: [..."Phaser 3"],
  py: [..."Python"],
};

const moveSkill = () => {
  for (const key in skillData) {
    const skill = skillData[key];
    
    skill.reduce((str, char) => {
      str += char;
      console.log(str);
      return str;
    }, '')
  }

};

setTimeout(moveSkill, 150);
...