У меня есть svg rect и svg text, созданные с помощью React.Текст может быть коротким или очень длинным, я хочу просто обрезать (с помощью многоточия) текст, если его ширина превышает пороговое значение.
Я знаю, что есть много вопросов по этому поводу (например, этот ) но я пока не смог решить проблему.
Это мой код:
interface Props extends InterfaceState {
rectWidth: number
spaceBetweenRects: number
}
export class Labels extends React.Component<Props> {
render() {
const { rectWidth, labelRectHeight, spaceBetweenRects } = this.props
const names = ['Cher', 'Madonna', 'Band Names That Are Ridiculously Long', 'U2']
const rectHeight = labelRectHeight
const paddingLeftRight = 0.05 * rectWidth
const plusWidth = rectHeight / 2
return (
<g>
{names.map((name, i) => {
const y = i * labelRectHeight + i * spaceBetweenRects
const maxTextwidth = rectWidth - plusWidth - 3 * paddingLeftRight // this is the maximum length that text can have
return (
<g key={i}>
<React.Fragment>
<rect x={0} y={y} width={rectWidth} height={rectHeight} fill={'#E4E9EB'} />
</React.Fragment>
<text
ref={this.textRef}
x={rectWidth - paddingLeftRight}
y={y + rectHeight / 2}
textAnchor="end"
alignmentBaseline="middle"
>
{name}
</text>
</g>
)
})}
</g>
)
}
}
Это результат:
Как видите, Band Names That Are Ridiculously Long
слишком длинный, поэтому я хочу что-то вроде Band Names That Are Ridiculously...
.
Я пытаюсь использовать React Ref:
export class Labels extends React.Component<Props> {
textRef = React.createRef<SVGTextElement>()
/**
* Places textString in textObj and adds an ellipsis (...) if text can't fit in width.
* TODO: type of textObject (RefObject<SVGTextElement> doesn't work)
*/
placeTextWithEllipsis(textObj: any, textString: string, width: number) {
console.log('textObj: ', textObj) // null :()
textObj.textContent = textString
if (textObj.getSubStringLength(0, textString.length) >= width) {
for (let x = textString.length - 3; x > 0; x -= 3) {
if (textObj.getSubStringLength(0, x) <= width) {
textObj.textContent = textString.substring(0, x) + '...'
return
}
}
textObj.textContent = '...' // can't place at all
}
}
render() {
const { rectWidth, labelRectHeight, spaceBetweenRects } = this.props
const names = ['Cher', 'Madonna', 'Band Names That Are Ridiculously Long', 'U2']
const rectHeight = labelRectHeight
const paddingLeftRight = 0.05 * rectWidth
const plusWidth = rectHeight / 2
return (
<g>
{names.map((name, i) => {
const y = i * labelRectHeight + i * spaceBetweenRects
const maxTextwidth = rectWidth - plusWidth - 3 * paddingLeftRight // this is the maximum length that text can have
this.placeTextWithEllipsis(this.textRef, name, maxTextwidth)
return (
<g key={i}>
<React.Fragment>
<rect x={0} y={y} width={rectWidth} height={rectHeight} fill={'#E4E9EB'} />
</React.Fragment>
<text
ref={this.textRef}
x={rectWidth - paddingLeftRight}
y={y + rectHeight / 2}
textAnchor="end"
alignmentBaseline="middle"
>
{name}
</text>
</g>
)
})}
</g>
)
}
}
В этом случае textObj
равно нулю ...
Последняя альтернатива, которую я попробовал, - это использование textPath , но в этом случаеЯ бы обрезал только строку, а не 3 последние точки, поэтому мне не очень нравится это решение.
Я был бы рад, если бы кто-нибудь помог мне, потому что я не знаю, что попробовать.Большое спасибо