Как сделать так, чтобы если div в области видимости окна устройства, срабатывала анимация написания текста?

Здравствуйте! Такая проблема, все срабатывает, но когда продолжаешь прокручивать он опять включает эту функцию и получается, что выводит undefind

/* появление текста секция 2 */
let cont = $('.js--text-cont'),
        text = 'Я знаю, как защитить Ваш бизнес, недвижимость, интеллектуальную собственность и цифровые права',
        p = 0,
        one_call = false
        function printSmbl() {
            let timeout = Math.round(Math.random() * 100);
            cont.html(cont.html()+text[p]);
            p++;
            console.log(text.length);
            console.log(p);
            if (p < text.length) {
                setTimeout(printSmbl, timeout);
            } else{
                setTimeout = () => {}
            }
        }


window.addEventListener('scroll', function() {
    if(pageYOffset = '500'){
        setTimeout(printSmbl, 50)
    }
})


выводит: Я знаю, как защитить Ваш бизнес, недвижимость, интеллектуальную собственность и цифровые праваundefinedundefinedundefined
Подскажите, как исправить
  • Вопрос задан
  • 117 просмотров
Пригласить эксперта
Ответы на вопрос 2
yarkov
@yarkov Куратор тега JavaScript
Помог ответ? Отметь решением.
if(pageYOffset = '500'
Вы понимаете что тут происходит? Мало того что вместо сравнения выполняется присваивание, так ещё и строка вместо числа.
Ответ написан
@ImagineTables
Во-первых. Для определения видимости есть специальный API. Он страшен, как жизнь простого программиста, но это, всё-таки, стандарт. Вот небольшая обёртка, которую я написал для себя:

// Starts observing visibility of the given element. On change,
// the callback is called with Boolean visibility as argument.
System.attachOnVisibilityChangedHandler = function (element, callback, visiblePart = 0.5)
{
	const options =
	{
		root: null,
		threshold: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1],
	};

	const observer = new IntersectionObserver((entries, observer) =>
	{
		entries.forEach(entry =>
		{
			callback(entry.target, entry.intersectionRatio >= visiblePart);
		});
	}, options);

	observer.observe(element);
}


Во-вторых. Он тоже даёт ложноположительные срабатывания (я думаю, в этом ваша проблема). Это by design. Поэтому надо проверять предыдущее состояние, чтобы понять, изменилось ли оно:

// For all elements, marked with 'autoplay' and 'autoplay-once' classes, adds 'start-autoplaying' class when visible first time.
// For all elements, marked with 'autoplay' only, adds 'start-autoplaying' class every time, when visible, and removes it, when not.
function autoplayAnyWhenVisible()
{
	$('.autoplay').each(function ()
	{
		const startAutoplayingClass = 'start-autoplaying';
		const visiblePart = $(this).data('visible-part') ?? 0.5;

		const onElementVisibilityChanged = function (element, isVisible)
		{
			const autoplayOnce = $(element).hasClass('autoplay-once');
			const wasVisible = $(element).data('is-visible');

			if (isVisible && !wasVisible)
			{
				$(element)
					.addClass(startAutoplayingClass)
					.data('is-visible', true);
			}

			if (autoplayOnce)
				return;

			if (!isVisible && wasVisible)
			{
				$(element)
					.removeClass(startAutoplayingClass)
					.data('is-visible', false);
			}
		};

		System.attachOnVisibilityChangedHandler(this, onElementVisibilityChanged, visiblePart);
	});
}


С этим кодом просто маркируете элементы при помощи класса autoplay (плюс autoplay-once если надо проигрывать анимацию только один раз), указываете долю видимости, и при реальном показе/сокрытии будет добавляться/убираться класс start-autoplaying (куда и засовываете анимацию написания текста):

<div class="… autoplay autoplay-once" data-is-visible="false" data-visible-part="0.3">
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы