动画打印字段,支持html标签
效果图:
方法类的:typing.js
class Typing {
constructor(opts) {
this.opts = opts || {};
this.source = opts.source;
this.output = opts.output;
this.delay = opts.delay || 120;
this.chain = {
parent: null,
dom: this.output,
val: []
};
if (!(typeof this.opts.done === 'function')) this.opts.done = function () {
};
}
init() {
//初始化函数
this.chain.val = this.convert(this.source, this.chain.val);
}
convert(dom, arr) {
//将dom节点的子节点转换成数组,
let children = Array.from(dom.childNodes)
for (let i = 0; i < children.length; i++) {
let node = children[i]
if (node.nodeType === 3) {
arr = arr.concat(node.nodeValue.split('')) //将字符串转换成字符串数组,后面打印时才会一个一个的打印
} else if (node.nodeType === 1) {
let val = []
val = this.convert(node, val)
arr.push({
'dom': node,
'val': val
})
}
}
return arr
}
print(dom, val, callback) {
setTimeout(function () {
dom.appendChild(document.createTextNode(val));
callback();
}, this.delay);
}
play(ele) {
//当打印最后一个字符时,动画完毕,执行done
if (!ele.val.length) {
if (ele.parent) this.play(ele.parent);
else this.opts.done();
return;
}
let current = ele.val.shift() //获取第一个元素,同时删除数组中的第一个元素
if (typeof current === 'string') {
this.print(ele.dom, current, () => {
this.play(ele); //继续打印下一个字符
})
} else {
let dom = current.dom.cloneNode() //克隆节点,不克隆节点的子节点,所以不用加参数true
ele.dom.appendChild(dom)
this.play({
parent: ele,
dom,
val: current.val
})
}
}
start() {
this.init();
this.play(this.chain);
}
}
export default Typing
组件:TypingCard.js
import React from 'react'
import Typing from 'utils/typing'
class TypingCard extends React.Component {
componentDidMount(){
console.log(this.output)
const typing = new Typing({
source:this.source,
output:this.output,
delay:120 //设置的打印速度
})
typing.start()
}
render() {
return (
<div>
<div style={{display:'none'}} ref={el => this.source = el} dangerouslySetInnerHTML={{__html:this.props.source}}/>
<div ref={el => this.output = el}/>
</div>
)
}
}
export default TypingCard
使用:Typing.js
import React,{Component} from 'react'
import TypingCard from './../../components/TypingCard'
class Typing extends Component{
constructor(props){
super(props)
}
render(){
const cardContent = `<ul class="card-ul">
<li>当有大量结构化的数据需要展现时</li>
<li>标当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时</li>
<h6>标当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时</h6>
<h5>标当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时</h5>
<h1>标当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时</h1>
<h4>标当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时</h4>
<h3>标当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时</h3>
<h2>标当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时</h2>
<h7>标当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时</h7>
</ul>`
return(
<div>
<TypingCard id='howUse' source={cardContent} height={178}/>
</div>
)
}
}
export default Typing