1. 介绍
实现首页字机效果,需要实现一个hooks函数,它需要实现下面功能:
- 一串字符从有到无
- 一串字符串从无到有
- 前两条状态来回切换
- 支持多一个字符串类型的数组进行打字机效果展示
2. 分析
根据上面的功能介绍,需要实现的hooks函数需要包含至少三个方法,即addText,descText,toggleText,使用这三个函数的前提是先初始化hooks,指定哪个字符串需要在多久内完成打字机效果展示。
3 实现
enum StatusEnum {
ADD = "add",
DESC = "desc",
}
/**
* 初始化hooks
* @param str 需要处理的字符
* @param duration 在多少事件内完成
* @returns
*/
export default function useStepText(str: string, duration: number) {
let result = ""; // 结果字符串
let strIndex = 0; // 字符串索引
let status = StatusEnum.ADD; // 增加或减少字符
let tempStr = str; // 操作的字符串,不直接操作初始化hooks传来的参数
// 计算多少时间间隔增加或减少一个字符
let diffTime = duration / str.length;
/**
* 字符增加
* @param callback 每次增加字符后的回调
* @param onFinished 字符增加到最大长度后的回调
*/
const addText = (callback: (value: string) => void, onFinished?: () => void) => {
let timer = setInterval(() => {
if (status == StatusEnum.ADD) {
result += tempStr[strIndex++];
callback(result);
if (strIndex > tempStr.length - 1) {
onFinished && onFinished();
clearInterval(timer);
}
}
}, diffTime);
};
/**
* 字符减少
* @param callback 每次减少字符后的回调
* @param onFinished 字符减少为0后的回调
*/
const descText = (callback: (value: string) => void, onFinished?: () => void) => {
strIndex = tempStr.length - 1;
status = StatusEnum.DESC;
result = tempStr;
let timer = setInterval(() => {
if (status == StatusEnum.DESC) {
result = result.slice(0, strIndex--);
callback(result);
if (strIndex < 0) {
strIndex = 0;
onFinished && onFinished();
clearInterval(timer);
}
}
}, diffTime);
};
/**
* 先增加再减少
* @param callback 字符串每次变化后的对调
* @param onFinished 字符串经过一轮增减、减少后的回调
*/
const toggleText = (callback: (value: string) => void, onFinished?: () => void) => {
if (status == StatusEnum.ADD) {
addText(callback, () => {
status = StatusEnum.DESC;
// 增加完毕后,3秒后再减少
setTimeout(() => {
toggleText(callback, onFinished);
}, 3000);
});
} else {
descText(callback, () => {
status = StatusEnum.ADD;
onFinished && onFinished();
});
}
};
/**
* 重复列表中的字符先增加再减少
* @param strList 需要循环展示的字符列表
* @param callback 当前字符变化时触发
* @param onFinished 当列表中的字符循环完成一边后触发
*/
const toggleTextList = (
strList: string[],
callback: (value: string) => void,
onFinished?: () => void,
) => {
// console.log(strList);
let index = 0;
tempStr = strList[index];
diffTime = duration / tempStr.length;
const innerFn = () => {
tempStr = strList[index];
toggleText(callback, () => {
index++;
if (index > strList.length - 1) {
index = 0;
onFinished && onFinished();
}
innerFn();
});
};
innerFn();
};
return { addText, descText, toggleText, toggleTextList };
}
4. 使用
import useStepText from "@/hooks/useStepText";
let { toggleTextList } = useStepText("", 2000);
let strList = [
"一年之际在于春,一日之际在于晨。",
"花有重开日,人无再少年。",
];
let [scrollText, setScrollText] = useState("");
toggleTextList(strList, newValue => setScrollText(newValue));
return(
{scrollText}
)