又双叒叕是一个动态简历

先看结果

请戳这里看预览
这里是代码

见过了?别走,这是异乎寻常的处所

  • 针对挪动端优化了体验
  • 支撑动画跳过
  • 支撑多段动画
  • 标点字符特别处置惩罚,停留时刻略善于字符时刻
  • typescript 编写
  • 对功用举行了封装处置惩罚,能够直接引入运用

基础预备

字符一一弹出结果的完成

道理很简单,一个闭包,一一截取字符串,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 自动转换

这里须要借助 prismjsmarked 两个代码处置惩罚库(固然也能够用其他的)

须要在上述的 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 传入的是一个二维数组,个中每一个 item 存放着我们想要加载的内容和对应请求,怎样让动画一段一段的完成呢?很天然的能想到 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
但很明显这么做及其不文雅,而且有 bug(但我忘了是什么 bug 了…)。

文雅完成:在类中声明 this.isSkip = false(相当于全局变量),在 skip() 要领调用时,将其改变成 true,在 loadItemsetTimeout 前搜检该变量,假如为 true 则抛出 reject()

所以上述的 load 要领须要增加变成:

function load(contents) {
  if (contents.length) {
    this.loadItem(contents[0])
      .then(() => this.load(contents.slice(1)))
      .catch(() => this.skipAnimate())
  }
}

skipAnimate 即为对应的跳过动画要领

挪动端处置惩罚

没有动图…… 请点击预览在手机或许谷歌调试中自行检察

展示款式我们能够直接在衬着的 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
}

参考自 https://github.com/STRML/strm… ,算是拾人涕唾了。

完毕

基础的完成思绪已说完,详细的代码贴上来实在是篇幅太长,请检察源码

不相识 typescript 的同砚能够看这里,这是我年终时用 js 写的,不过算是面向历程编写,没有做过量的封装处置惩罚。

写在末了

第一次见到http://strml.net/ 时,是在初学前端也许三四个月的模样,当时看到如许的展示情势着实是被冷艳到了,当时照样个小白,连 highlight 如许的插件都不晓得,更不晓得还能在style里自定义东西,更更更不晓得网站下面就放着View Source这么个大字,只是一心想的要本身也写一个,就那末硬生生本身写正则,经由过程差别的特别符号加载对应的标签处置惩罚变色,再经由过程 `dom.style….=…’ 设置款式,然后竟然还写的有模有样,第一次找工作时还竟然敢拿出来给面试官看了(笑)。

年终的时刻试着重写了这个项目,觉得已经是没有什么难度了,不过也是面向历程,一顿操纵罢了。这些天初学 typescript 想着拿个什么东西练个手,所以又把这个项目用 ts 重构了,而且进一步的举行了封装。觉得能够出来溜溜了,所以写下了这篇文章。

    原文作者:DemonQ
    原文地址: https://segmentfault.com/a/1190000017489212
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞