感谢原文作者的小程序原生版本
// index.tsx
import './style.css';
import { View, Text } from '@tarojs/components';
import Taro from '@tarojs/taro';
import { FC, useEffect, useState } from 'react';
interface ContentProps {
content?: string;
maxLine?: number;
position?: 'left' | 'right';
foldable?: boolean;
onFoldText?: string;
unFoldText?: string;
lineHeight?: number;
}
const TextOverflow: FC<ContentProps> = ({
content,
maxLine = 1,
position = 'left',
foldable = true,
onFoldText = '展开',
unFoldText = '收起',
lineHeight,
}) => {
const [width, setWidth] = useState<number | null>(null);
const [onFold, setOnFold] = useState(false);
const [showFold, setShowFold] = useState(false);
const [onReady, setOnReady] = useState(false);
useEffect(() => {
getNodeClientReact();
setOnReady(true);
}, []);
useEffect(() => {
if (onReady) {
getNodeClientReact();
}
}, [maxLine, lineHeight]);
const changeRpxToPx = (rpxInteger: number): number => {
return (Taro.getSystemInfoSync().windowWidth / 750) * rpxInteger;
};
const getNodeClientReact = () => {
setTimeout(() => checkFold(), 100);
};
const checkFold = () => {
const query = Taro.createSelectorQuery();
query
.selectAll('.showArea, .hideArea')
.boundingClientRect(res => {
let showFold = res[0].height < res[1].height;
const lineHeightToPx = changeRpxToPx(lineHeight);
const showAreaHeight = res[0].height;
const hideAreaHeight = res[1].height;
const maxHeight = lineHeightToPx * maxLine;
if (lineHeight && showAreaHeight <= maxHeight) {
showFold = hideAreaHeight > maxHeight;
}
let onFold = false;
if (showAreaHeight == hideAreaHeight && showAreaHeight > maxHeight) {
showFold = true;
onFold = true;
}
setWidth(res[0].width);
setShowFold(showFold);
setOnFold(onFold);
})
.exec();
};
const handleFold = () => {
setOnFold(!onFold);
};
return (
<View className="content">
<View
className={`contentInner content-inner-class showArea ${
!onFold ? `text-clamp${maxLine}` : ''
}`}
>
{content}
</View>
<View className="contentInner content-inner-class hideArea" style={{ width: `${width}px` }}>
{content}
</View>
{showFold && (
<View className={`foldInner fold-class ${position === 'right' ? 'flex-end' : 'flex'}`}>
<Text className="fold" onClick={handleFold}>
{onFold ? unFoldText : onFoldText}
</Text>
</View>
)}
</View>
);
};
export default TextOverflow;
// style.css
.content {
/* background-color: #ffffff; */
width: 100%;
position: relative;
overflow: hidden;
}
.contentInner {
word-break: break-all;
width: 100%;
color: #2f3033;
font-size: 30rpx;
line-height: 1.35;
/* text-align: justify; */
}
.hideArea {
display: -webkit-box;
overflow: hidden;
/* position: fixed;
top: 100vh;
left: -100vw; */
position: absolute;
top: 0;
left: 0;
z-index: -1;
color: #fff;
}
.foldInner {
padding-top: 10rpx;
color: #6676bd;
font-size: 28rpx;
}
.foldInner .fold {
cursor: pointer;
}
.text-clamp1 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
}
.text-clamp2 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.text-clamp3 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
}
.text-clamp4 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 4;
}
.text-clamp5 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 5;
}
.flex {
display: -webkit-box;
display: -webkit-flex;
display: flex;
}
.flex-center {
display: -webkit-box;
display: -webkit-flex;
display: flex;
align-items: center;
justify-content: center;
-webkit-align-items: center;
-webkit-justify-content: center;
}
.flex-alignStart {
display: -webkit-box;
display: -webkit-flex;
display: flex;
align-items: flex-start;
-webkit-align-items: flex-start;
}
.flex-alignCenter {
display: -webkit-box;
display: -webkit-flex;
display: flex;
align-items: center;
-webkit-align-items: center;
}
.flex-alignEnd {
display: -webkit-box;
display: -webkit-flex;
display: flex;
align-items: flex-end;
-webkit-align-items: flex-end;
}
.flex-between {
display: -webkit-box;
display: -webkit-flex;
display: flex;
justify-content: space-between;
-webkit-justify-content: space-between;
}
.flex-around {
display: -webkit-box;
display: -webkit-flex;
display: flex;
justify-content: space-around;
-webkit-justify-content: space-around;
}
.flex-middle {
display: -webkit-box;
display: -webkit-flex;
display: flex;
justify-content: center;
-webkit-justify-content: center;
}
.flex-end {
display: -webkit-box;
display: -webkit-flex;
display: flex;
justify-content: flex-end;
-webkit-justify-content: flex-end;
}