Это динамическое резюме

JavaScript

Первый взгляд на эффект

Пожалуйста, нажмите здесь для предварительного просмотра

вот код

видимый? Не уходи, это другое место

  • Оптимизированный опыт для мобильных устройств
  • Поддержка пропуска анимации
  • Поддержка многосегментной анимации
  • Специальная обработка знаков препинания, время пребывания немного больше, чем время знака.
  • Машинописный текст
  • Функция инкапсулирована и может быть напрямую импортирована и использована.

базовая подготовка

Реализация всплывающего эффекта символов один за другим

Принцип очень простой, замыкание, перехватывающее строки одну за другой,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
}

расширенная обработка

анализировать

Основные основные функции готовы

Теперь приступим к процессу анализа и приступим к написанию кода

Требования следующие:

  1. Поддержка загрузки мультисегментной анимации
  2. Поддержка пропуска анимации (прямая загрузка завершена)
  3. Специальная обработка мобильного терминала

Основываясь на вышеуказанных требованиях, нам нужно сначала определить интерфейс.

Мы представляем, что функция будет использоваться так

/**
 * @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Рефакторинг и дальнейшая инкапсуляция. Я чувствую, что могу выйти и лет, поэтому я написал эту статью.