Первый взгляд на эффект
Пожалуйста, нажмите здесь для предварительного просмотра
видимый? Не уходи, это другое место
- Оптимизированный опыт для мобильных устройств
- Поддержка пропуска анимации
- Поддержка многосегментной анимации
- Специальная обработка знаков препинания, время пребывания немного больше, чем время знака.
- Машинописный текст
- Функция инкапсулирована и может быть напрямую импортирована и использована.
базовая подготовка
Реализация всплывающего эффекта символов один за другим
Принцип очень простой, замыкание, перехватывающее строки одну за другой,setTimeout
Рендеринг на странице
/**
* @param {HTMLElement} container - 渲染字符的容器
* @param {string} text - 需要渲染的字符串
*/
function loadItem(container, text) {
let num = 0
let sum = text.length
let interval = 16
const startLoad = () => {
setTimeout(() => {
num += 1
if (num <= sum) {
let str = text.substr(0, num)
container.scrollTop = 100000
container.innerHTML = str
setTimeout(() => {
startLoad()
}, interval)
}
}, interval)
}
startLoad()
}
html
ВверхCSS
Персонажи вступают в силу автоматически
Пока строка начинает рендеринг, вhtml
добавитьstyle
метка, которая будет отображатьCSS
Код может быть написан на этикетке
Создаватьstyle
Этикетка
function getStyleEl() {
let newStyle = document.createElement('style')
let head = document.querySelector('head')
head.appendChild(newStyle)
let allStyle = document.querySelectorAll('style')
return allStyle[allStyle.length - 1]
}
будетCSS
код написать
/**
*
* @param {string} style - CSS 代码
* @param {HTMLElement} el - 创建的 style 标签
*/
function handleStyle(style, el) {
el.innerHTML = style
}
CSS
подсветка кода,markdown
автоматическое преобразование
нужна помощь здесьprismjs
иmarked
Две библиотеки обработки кода (конечно, можно использовать и другие)
требуется в вышеуказанномloadTtem
Добавьте суждение к функции
let code
switch (type) {
case 'css':
handleStyle(str, styleEl)
code = Prism.highlight(str, Prism.languages.css)
break
case 'md':
code = marked(str)
break
}
расширенная обработка
анализировать
Основные основные функции готовы
Теперь приступим к процессу анализа и приступим к написанию кода
Требования следующие:
- Поддержка загрузки мультисегментной анимации
- Поддержка пропуска анимации (прямая загрузка завершена)
- Специальная обработка мобильного терминала
Основываясь на вышеуказанных требованиях, нам нужно сначала определить интерфейс.
Мы представляем, что функция будет использоваться так
/**
* @param {HTMLElement} container - 字符渲染的容器
* @param {Object} options - 动画参数
*
* @param {string} options.content.load - 需要渲染的字符串
* @param {'css' | 'md'} options.content.type - 渲染后高亮的方式,当前仅支持 'css' | 'md' 两个参数
* @param {string} options.content.id - 渲染容器的 id
* @param {boolean} options.content.rewrite - 是否需要重写
*
* @param {Object}? options.mobileAnimate - 移动端需要特殊处理
* @param {string} options.mobileAnimate.styleID - css 加载的容器 ,id 应与 content 中 css 容器的 id 相同
* @param {string} options.mobileAnimate.string - markdown 加载的容器,id 应与 content 中 md 容器的 id 相同
*/
let ar = new AnimateResume(container, {
content:[
{
load:'',
type:'css',
id:'',
rewrite:'',
},
...
],
mobileAnimate:{
styleID:'',
resumeID:''
}
})
ar.animate()
ar.skip()
Перед использованием вам необходимо создать экземпляр и передать параметры черезanimate
способ запуска анимации,skip
способ пропустить анимацию
В соответствии с приведенными выше предположениями о параметрах мы можем написать следующееtypescript
интерфейс, не знаюtypescript
Студенты могут пропустить его напрямую, просто взгляните на комментарии к приведенному выше коду.
interface Core {
container: Element
options: CoreOptions
isSkip: boolean
animate: () => void
skip: () => void
}
interface CoreOptions {
content: Array<LoadParams>
mobileAnimate?: {
styleID: string
resumeID: string
}
}
interface LoadParams {
load: string
type: 'css' | 'md'
id: string
rewrite?: boolean
}
выполнить
Базовая архитектура была проанализирована и теперь может быть реализована
загружать по одному
Во-первых, поскольку анимация выполняется в нескольких сегментах, мы передаем параметрcontent
То, что передается, — это двумерный массив, в котором каждый элемент хранит контент, который мы хотим загрузить, и соответствующие требования Как сделать анимацию завершенной по частям? Это естественно думатьPromise
метод, черезPromise.then()
реализовать.
Таким образом, мы можем абстрагироваться от этого требования как: массив неизвестной длины, который должен загружать следующий элемент один за другим через неизвестное время.
Реализация тоже очень простая, код такой:
function load(contents) {
if (contents.length) {
this.loadItem(contents[0])
.then(() => this.load(contents.slice(1)))
}
}
Не исключено, что вышеизложенноеloadItem
метод должен возвращатьnew Promise
, который возвращается при внутренней загрузке строкиresolve()
, затем переходите к следующему абзацуload
метод
поддержка пропустить
Как я могу прервать текущую анимацию и напрямую загрузить ее?
Сначала я попробовал прямой брутфорсloadItem
При проверке количества загруженных слов и глобальной переменной, чтобы определить,setTimeout
,
Но очевидно, что это некрасиво и глючит (но я забыл, что за баг...).
Элегантная реализация: объявить в классеthis.isSkip = false
(эквивалент глобальной переменной), вskip()
Когда метод вызывается, измените его на true, вloadItem
серединаsetTimeout
Проверьте переменную раньше, выбросьте, если она вернаreject()
Итак, вышеload
Метод должен быть добавлен, чтобы стать:
function load(contents) {
if (contents.length) {
this.loadItem(contents[0])
.then(() => this.load(contents.slice(1)))
.catch(() => this.skipAnimate())
}
}
skipAnimate
То есть соответствующий метод пропуска анимации
Обработка мобильного терминала
без гифок... пожалуйстаНажмите, чтобы просмотретьПроверьте это на своем телефоне или в Google Debugging
Чтобы отобразить стиль, мы можем напрямую отобразить егоCSS
Настроено в анимации кода, так что не объясняйте слишком много
Здесь мы говорим только об эффекте скольжения вверх и вниз по двум страницам.
Нам нужна помощьbetter-scroll
Плагины, помогающие оптимизации, соответственно устанавливают событие обновления верхней части страницы и событие обновления нижней части страницы, когда соответствующее событие срабатывает, передайтеtransform:translateY(x)
Чтобы добиться общего скольжения страницы, код выглядит следующим образом
let styleScroll = new BScroll(styleContainer, {
pullUpLoad: {
threshold: 20
}
})
let mdScroll = new BScroll(mdContainer, {
pullDownRefresh: {
threshold: 20,
}
})
styleScroll.on('pullingUp', function () {
mdContainer.style.transform = 'translateY(calc(-100% - 4rem))'
styleContainer.style.transform = 'translateY(calc(-100% - 1rem))'
styleScroll.finishPullUp()
})
mdScroll.on('pullingDown', function () {
mdContainer.style.transform = 'translateY(0)'
styleContainer.style.transform = 'translateY(0)'
mdScroll.finishPullDown()
})
Следует отметить, что если содержимое резюме ниже недостаточно длинное, оно не сработает.better-scroll
Обнаружение скольжения, приводящее к неожиданному эффекту скольжения.
Пунктуация
По пришедшему символу судят о времени задержки появления следующего символа, т.е.setTimeout
Второй параметр метода.
function getInterval(str: string, interval = 16): number {
if (/\D[\,]\s$/.test(str)) return interval * 20
if (/[^\/]\n\n$/.test(str)) return interval * 40
if (/[\.\?\!]\s$/.test(str)) return interval * 60
return 0
}
Ссылка изGitHub.com/стр мл/стр мл…, Это пикап.
Заканчивать
Основные идеи реализации завершены, а конкретный код слишком длинный, чтобы его можно было вставить.Посмотреть исходный код.
не понимаюtypescript
студентов могут видетьздесь, это то, что я использовал в начале годаjs
Написано, но это ориентированное на процесс письмо, без слишком большой инкапсуляции.
напиши в конце
вижу в первый разstrml.net/В то время я был в авангарде новичков месяца три-четыре, тогда я был просто поражен, увидев такую форму отображения, я тогда еще был новичком.highlight
Я не знаю о таком плагине, и я даже не знаю, что его можно использовать вstyle
Настраивать вещи в нем, а уж тем более не знать, что он размещен под сайтомView Source
С таким большим символом я просто хочу написать его сам, поэтому я просто пишу регулярное выражение, загружаю соответствующие теги с помощью различных специальных символов для обработки изменения цвета, а затем устанавливаю его с помощью `dom.style....= ...' Стиль, а потом это было написано так, что я даже осмелился показать это интервьюеру, когда впервые искал работу (смеется).
В начале года я пытался переписать этот проект, и я чувствовал, что это не сложно, но и процессно, и это была просто операция. Новички в наши дниtypescript
Я думал о том, чтобы получить что-то, чтобы тренировать свои руки, поэтому я снова воспользовался этим проектом.ts
Рефакторинг и дальнейшая инкапсуляция. Я чувствую, что могу выйти и лет, поэтому я написал эту статью.