资讯专栏INFORMATION COLUMN

又双叒叕是一个动态简历

firim / 951人阅读

摘要:标点处理根据传入的字符来判断下一个字符出现的延迟时间,即方法的第二个参数。年初的时候试着重写了这个项目,感觉已是没有什么难度了,不过也是面向过程,一顿操作罢了。

先看效果

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

见过了?别走,这是与众不同的地方

针对移动端优化了体验

支持动画跳过

支持多段动画

标点字符特殊处理,停留时间略长于字符时间

typescript 编写

对功能进行了封装处理,可以直接引入使用

基本准备 字符逐个弹出效果的实现

原理很简单,一个闭包,逐一截取字符串,setTimeout 渲染在页面上即可

</>复制代码

  1. /**
  2. * @param {HTMLElement} container - 渲染字符的容器
  3. * @param {string} text - 需要渲染的字符串
  4. */
  5. function loadItem(container, text) {
  6. let num = 0
  7. let sum = text.length
  8. let interval = 16
  9. const startLoad = () => {
  10. setTimeout(() => {
  11. num += 1
  12. if (num <= sum) {
  13. let str = text.substr(0, num)
  14. container.scrollTop = 100000
  15. container.innerHTML = str
  16. setTimeout(() => {
  17. startLoad()
  18. }, interval)
  19. }
  20. }, interval)
  21. }
  22. startLoad()
  23. }
html 上的 CSS 字符自动生效

只要在字符串开始渲染时,在 html 中添加一个 style 标签,将渲染的 CSS 代码写入到标签中即可

创建一个 style 标签

</>复制代码

  1. function getStyleEl() {
  2. let newStyle = document.createElement("style")
  3. let head = document.querySelector("head")
  4. head.appendChild(newStyle)
  5. let allStyle = document.querySelectorAll("style")
  6. return allStyle[allStyle.length - 1]
  7. }

CSS 代码写入

</>复制代码

  1. /**
  2. *
  3. * @param {string} style - CSS 代码
  4. * @param {HTMLElement} el - 创建的 style 标签
  5. */
  6. function handleStyle(style, el) {
  7. el.innerHTML = style
  8. }
CSS 代码高亮,markdown 自动转换

这里需要借助 prismjsmarked 两个代码处理库(当然也可以用其他的)

需要在上述的 loadTtem 函数中添加判断

</>复制代码

  1. let code
  2. switch (type) {
  3. case "css":
  4. handleStyle(str, styleEl)
  5. code = Prism.highlight(str, Prism.languages.css)
  6. break
  7. case "md":
  8. code = marked(str)
  9. break
  10. }
进阶处理 分析

基本的核心功能已经准备好了

下面我们开始分析过程,开始编写代码

需求如下:

支持多段动画加载

支持动画跳过(直接加载完成)

移动端特殊处理

基于上述需求,我们需要先对接口进行定义

我们设想函数是这样使用的

</>复制代码

  1. /**
  2. * @param {HTMLElement} container - 字符渲染的容器
  3. * @param {Object} options - 动画参数
  4. *
  5. * @param {string} options.content.load - 需要渲染的字符串
  6. * @param {"css" | "md"} options.content.type - 渲染后高亮的方式,当前仅支持 "css" | "md" 两个参数
  7. * @param {string} options.content.id - 渲染容器的 id
  8. * @param {boolean} options.content.rewrite - 是否需要重写
  9. *
  10. * @param {Object}? options.mobileAnimate - 移动端需要特殊处理
  11. * @param {string} options.mobileAnimate.styleID - css 加载的容器 ,id 应与 contentcss 容器的 id 相同
  12. * @param {string} options.mobileAnimate.string - markdown 加载的容器,id 应与 contentmd 容器的 id 相同
  13. */
  14. let ar = new AnimateResume(container, {
  15. content:[
  16. {
  17. load:"",
  18. type:"css",
  19. id:"",
  20. rewrite:"",
  21. },
  22. ...
  23. ],
  24. mobileAnimate:{
  25. styleID:"",
  26. resumeID:""
  27. }
  28. })
  29. ar.animate()
  30. ar.skip()

使用前需要实例化一个并传入参数,通过 animate 方法开始动画,skip 方法跳过动画

根据上述参数设想,我们可以写出如下的 typescript 接口,不了解 typescript 的同学可以直接跳过,只看上面代码的注释即可

</>复制代码

  1. interface Core {
  2. container: Element
  3. options: CoreOptions
  4. isSkip: boolean
  5. animate: () => void
  6. skip: () => void
  7. }
  8. interface CoreOptions {
  9. content: Array
  10. mobileAnimate?: {
  11. styleID: string
  12. resumeID: string
  13. }
  14. }
  15. interface LoadParams {
  16. load: string
  17. type: "css" | "md"
  18. id: string
  19. rewrite?: boolean
  20. }
实现

基本的架构已经分析好了,现在可以开始实现了

逐一加载

首先,因为动画是多段完成的,所以我们通过参数 content 传入的是一个二维数组,其中每个 item 存放着我们想要加载的内容和对应要求,如何让动画一段一段的完成呢?很自然的能想到 Promise 方法,通过 Promise.then() 来实现。

所以我们可以将这个需求抽象为:一个未知长度的数组,需要逐一的在未知时间后加载下一项。

实现也很简单,代码如下:

</>复制代码

  1. function load(contents) {
  2. if (contents.length) {
  3. this.loadItem(contents[0])
  4. .then(() => this.load(contents.slice(1)))
  5. }
  6. }

可以想到,上述中的 loadItem 方法应该返回一个 new Promise ,内部当字符串加载完成后返回 resolve(),然后继续执行下一段 load 方法

支持跳过

如何才能中断当前的动画,直接加载完成呢?

最初我尝试直接暴力的通过在 loadItem 时检查加载字数和一个全局变量来判断是否 setTimeout
但很明显这么做及其不优雅,而且有 bug(但我忘了是什么 bug 了...)。

优雅实现:在类中声明 this.isSkip = false(相当于全局变量),在 skip() 方法调用时,将其改变为 true,在 loadItemsetTimeout 前检查该变量,如果为 true 则抛出 reject()

所以上述的 load 方法需要添加变为:

</>复制代码

  1. function load(contents) {
  2. if (contents.length) {
  3. this.loadItem(contents[0])
  4. .then(() => this.load(contents.slice(1)))
  5. .catch(() => this.skipAnimate())
  6. }
  7. }

skipAnimate 即为对应的跳过动画方法

移动端处理

没有动图…… 请点击预览在手机或者谷歌调试中自行查看

展示样式我们可以直接在渲染的 CSS 代码动画中自定义,所以不过多解释

这里只说一下两个页面上下滑动的效果实现

我们需要借助 better-scroll 插件来帮助优化,分别设置上部分页面上拉刷新事件和下部分页面的下拉刷新事件,在对应事件触发时,通过 transform:translateY(x) 来实现页面的整体滑动,代码如下

</>复制代码

  1. let styleScroll = new BScroll(styleContainer, {
  2. pullUpLoad: {
  3. threshold: 20
  4. }
  5. })
  6. let mdScroll = new BScroll(mdContainer, {
  7. pullDownRefresh: {
  8. threshold: 20,
  9. }
  10. })
  11. styleScroll.on("pullingUp", function () {
  12. mdContainer.style.transform = "translateY(calc(-100% - 4rem))"
  13. styleContainer.style.transform = "translateY(calc(-100% - 1rem))"
  14. styleScroll.finishPullUp()
  15. })
  16. mdScroll.on("pullingDown", function () {
  17. mdContainer.style.transform = "translateY(0)"
  18. styleContainer.style.transform = "translateY(0)"
  19. mdScroll.finishPullDown()
  20. })

需要注意的是如果下方简历内容长度不够,不会触发 better-scroll 的滑动检测,导致无法出现预想的滑动效果。

标点处理

根据传入的字符来判断下一个字符出现的延迟时间,即 setTimeout 方法的第二个参数。

</>复制代码

  1. function getInterval(str: string, interval = 16): number {
  2. if (/D[,]s$/.test(str)) return interval * 20
  3. if (/[^/]
  4. $/.test(str)) return interval * 40
  5. if (/[.?!]s$/.test(str)) return interval * 60
  6. return 0
  7. }

参考自 https://github.com/STRML/strm... ,算是拾人牙慧了。

结束

基本的实现思路已经说完,具体的代码贴上来实在是篇幅太长,请查看源码。

不了解 typescript 的同学可以看这里,这是我年初时用 js 写的,不过算是面向过程编写,没有做过多的封装处理。

写在最后

第一次见到http://strml.net/ 时,是在初学前端大概三四个月的样子,当时看到这样的展现形式着实是被惊艳到了,那时还是个小白,连 highlight 这样的插件都不知道,更不知道还能在style里自定义东西,更更更不知道网站下面就放着View Source这么个大字,只是一心想的要自己也写一个,就那么硬生生自己写正则,通过不同的特殊符号加载对应的标签处理变色,再通过 `dom.style....=..." 设置样式,然后居然还写的有模有样,第一次找工作时还居然敢拿出来给面试官看了(笑)。

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/117111.html

相关文章

  • 又双叕是一个动态简历

    摘要:标点处理根据传入的字符来判断下一个字符出现的延迟时间,即方法的第二个参数。年初的时候试着重写了这个项目,感觉已是没有什么难度了,不过也是面向过程,一顿操作罢了。 先看效果 请戳这里看预览这里是代码 见过了?别走,这是与众不同的地方 针对移动端优化了体验 支持动画跳过 支持多段动画 标点字符特殊处理,停留时间略长于字符时间 typescript 编写 对功能进行了封装处理,可以直接引入...

    iKcamp 评论0 收藏0
  • 又双叕是一个动态简历

    摘要:标点处理根据传入的字符来判断下一个字符出现的延迟时间,即方法的第二个参数。年初的时候试着重写了这个项目,感觉已是没有什么难度了,不过也是面向过程,一顿操作罢了。 先看效果 请戳这里看预览这里是代码 见过了?别走,这是与众不同的地方 针对移动端优化了体验 支持动画跳过 支持多段动画 标点字符特殊处理,停留时间略长于字符时间 typescript 编写 对功能进行了封装处理,可以直接引入...

    levius 评论0 收藏0

发表评论

0条评论

firim

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<