Это проблема с JavaScript. У нас есть задание, в котором мы должны выразить эмоции с помощью типографики. Я прикрепил к мыши эффект фонарика, при котором вы перемещаете мышь в поисках букв (промежутков). Я хочу, чтобы промежутки останавливались (с задержкой около 5 секунд), но я не знаю, почему промежутки кажутся неостановимыми или что-то в этом роде, потому что я не могу заставить их прекратить анимацию. Они перестают анимироваться, когда я перемещаюсь вокруг фонарика, но не тогда, когда фонарик находится только на них. Я знаю, что код очень запутанный (нам предоставили шаблон для изменения), но, пожалуйста, дайте мне знать, если вам нужно, чтобы я объяснил что-то, что кажется запутанным.
Я пытался изменить функцию цикла, пробовал console.log выйти туда, куда она движется, но не знаю, в чем проблема.
// Состояние должно содержать все «движущиеся» части вашей программы, значения, которые изменяются. пусть состояние = Object.freeze({ последний ключ: неопределенный, isMoving: false, // Флаг отслеживания состояния анимации движения trackTime: 0, // Отслеживание времени перемещения анимации }); // Объект настроек содержит все «фиксированные» части вашего эскиза, // например, статические HTML-элементы, параметры или пороговые значения. константные настройки = Object.freeze({ textElement: document.querySelector("#text"), flashLight: document.querySelector("#flashlight"), range: 20, // Установка диапазона перемещения интервалов motionDuration: 1000, // Продолжительность анимации движения пролета }); /** * Обновите объект состояния, используя свойства, включенные в `newState`. * @param {Object} newState Объект со свойствами, которые необходимо обновить в объекте состояния. */ функция updateState(newState) { состояние = Object.freeze({ ...state, ...newState }); } /** * Возвращаемое значение `num` нормализуется до 0..1 в диапазоне мин..макс. * @param {номер} число * @param {число} мин * @param {число} макс. * @возвращает номер */ масштаб функции (число, мин, максимум) { если (число макс) вернуть 1; возврат (число – мин)/(макс – мин); } /** * Возвращает `num`, преобразованный из нормализованной формы 0..1 обратно в форму min..max. * @param {номер} число * @param {число} мин * @param {число} макс. * @возвращает номер */ функция toAbsolute(num, min, max) { если (число 1) вернуть максимум; return (число * (макс - мин)) + мин; } // Функция генерации случайного местоположения для каждого пролета функция getRandomLocation() { // Генерируем случайное местоположение x и y и вычитаем 100 из внутренней ширины и высоты // так, чтобы случайное местоположение находилось в области нашего браузера const xPosition = Math.min(Math.max(100, Math.random() * (window.innerWidth - 100))); const yPosition = Math.min(Math.max(100, Math.random() * (window.innerHeight - 100))); // Возвращаем координаты x и y через левое и верхнее положение return {слева: xPosition, сверху: yPosition}; } // Функция для перемещения промежутков (букв) функция spanMovementEffect() { const {диапазон} = настройки // Получение всех элементов диапазона const spans = settings.textElement.getElementsByTagName("span"); // Итерируем каждый диапазон... for (const диапазон пролетов) { //...и генерируем случайные значения для перемещения пролета по осям X и Y для каждого пролета const TransformX = Math.random() * (2 * диапазон) — диапазон; const TransformY = Math.random() * (2 * диапазон) — диапазон; //...и установка времени на движение в одну секунду span.style.transition = "преобразование 1с с легкостью"; //... и установив положение промежутков в TransformX и Y span.style.transform = `translate(${transformX}px, ${transformY}px)`; } } // Функция установки положения фонарика в положение нашего курсора функция flashlightMovement(событие) { // Получаем положение курсоров и сохраняем его в flashligtX и Y const flashlightX = event.clientX; const flashlightY = event.clientY; // Устанавливаем положение фонариков в положение курсоров settings.flashLight.style.left = `${flashlightX}px`; settings.flashLight.style.top = `${flashlightY}px`; // Делаем фонарик в центре курсора settings.flashLight.style.transform = `translate(-50%, -50%)`; } // Функция запуска движения пролетов функция startMovement(span) { пусть {isMoving} = состояние; const {motionDuration} = настройки; // Если isMoving имеет значение false... если (!isMoving) { //...обновляем TrackTime, указывая текущее время updateState({trackingTime: Performance.now() }) } // Функция обновления анимации движения функция updateMovement(timeStamp) { const elapsed = timeStamp - state.trackingTime; // Вычисляет время с момента начала анимации const Progress = Math.min(истекло/движениеDuration, 1); // Вычисляет ход анимации со значением от 0 до 1 // Если isMoving имеет значение false... если (!isMoving) { //...начинаем двигаться!! span.style.transition = "преобразование 1с с легкостью"; span.style.transform = "перевести (0)"; // Если прогресс меньше 1... если (прогресс < 1) { // Продолжаем цикл анимации requestAnimationFrame (updateMovement); // В противном случае... } еще { //...анимация не выполняется, и диапазон должен оставаться на своем месте span.style.transform = "перевести (0)"; } } } // Сообщаем ему, что анимация движения продолжается updateState({isMoving: true, trackTime: Performance.now() }); // Продолжение цикла анимации requestAnimationFrame (updateMovement); } // Функция остановки анимации движения пролета функция stopMovement(span) { span.style.transition = «нет»; span.style.transform = "перевести (0)"; updateState({isMoving: false}); } функция checkWithinRange(span) { const flashlightRect = settings.flashLight.getBoundingClientRect(); const spanRect = span.getBoundingClientRect(); const flashlightCenterX = flashlightRect.left + flashlightRect.width / 2; const flashlightCenterY = flashlightRect.top + flashlightRect.height/2; const spanCenterX = spanRect.left + spanRect.width/2; const spanCenterY = spanRect.top + spanRect.height/2; константное расстояние = Math.sqrt( Math.pow(spanCenterX - flashlightCenterX, 2) + Math.pow(spanCenterY - flashlightCenterY, 2) ); обратное расстояние < 70; } // Функция проверки расстояния между элементом фонарика и пролетами и установки их видимости в зависимости от дальности функция checkSpanVisibility() { // Получение всех промежутков const spans = settings.textElement.getElementsByTagName("span"); for (const диапазон пролетов) { const isWithinRange = checkWithinRange (диапазон); const isMoving = getComputedStyle(span).transition !== "none"; если (isWithinRange && isMoving) { stopMovement (пролет); console.log("Движение остановлено"); } else if (!isWithinRange && isMoving) { startMovement (пролет); console.log("Движение началось"); } span.style.visibility = isWithinRange? «видимый»: «скрытый»; } } пусть FrameCounter = 0; пусть updateFrequency = 60; /** * Здесь мы помещаем код, который преобразует и выводит наши данные. * цикл() запускается каждый кадр, при условии, что мы продолжаем вызывать его с помощью `window.requestAnimationFrame`. */ цикл функции() { const {isMoving} = состояние; const {textElement, GrowthFactor} = настройки; если (frameCounter % updateFrequency === 0) { эффектДвиженияПространства(); console.log("Я все еще двигаюсь!") } фреймСчетчик++; window.requestAnimationFrame(цикл); } /** * Установка запускается один раз, при запуске программы. Он нам все устраивает! */ настройка функции() { document.addEventListener("keydown", function (event) { updateState({ ключ: { код: event.code, ключ: event.key, нажата: Performance.now() } }); // Если нажатая клавиша имеет значение 1, это означает, что нажатая клавиша не сдвигается, не вводится и т. д. если (event.key.length === 1) { const { сверху, слева } = getRandomLocation (); // Создаем промежутки const span = document.createElement("span"); // Установка нажатой клавиши в диапазон span.textContent = event.key; span.style.position = "абсолютный"; span.style.top = `${top}px`; span.style.left = `${left}px`; settings.textElement.style.visibility = "скрытый"; // Добавляем диапазон к текстовому элементу settings.textElement.appendChild(диапазон); } }); document.addEventListener('pointermove', (event) => { фонарикДвижение (событие); проверкаSpanVisibility(); }) document.addEventListener("keyup", функция (событие) { // Ничего! }); ` петля(); } настраивать(); // Всегда не забывайте вызывать setup()! Вот изображение вывода, чтобы вы могли наглядно увидеть мою программу:

Мобильная версия