<template>
<div
ref="textContainer"
class="text-container"
:style="{
...(textFontSize ? { fontSize: textFontSize } : {}),
visibility: calcEnd || !hideOnCalculating ? 'visible' : 'hidden',
}"
@resize="adjustFontSize"
>
<slot></slot>
</div>
</template>
<script setup lang="ts">
import { nextTick, onMounted, ref, watch } from 'vue'
const emit = defineEmits<{
calcEnd: []
}>()
const props = defineProps({
maxLines: {
type: Number,
default: 2,
},
hideOnCalculating: {
type: Boolean,
default: true,
},
})
const textFontSize = ref<string>()
const calcEnd = ref(false)
const pxToNumber = (str: string) => +str?.replace('px', '') || 0
const textContainer = ref(null)
const adjustFontSize = () => {
if (!textContainer.value) return
const computedStyle = getComputedStyle(textContainer.value)
const fontSize = pxToNumber(computedStyle.fontSize)
const height = pxToNumber(computedStyle.height)
const lineHeight = pxToNumber(computedStyle.lineHeight)
const lines = Math.ceil(height / lineHeight)
if (lines > props.maxLines && fontSize > 1) {
textFontSize.value = `${fontSize - 1}px`
} else {
// 计算完成
calcEnd.value = true
emit('calcEnd')
}
}
onMounted(() => {
adjustFontSize()
})
watch([() => props.maxLines, () => textFontSize.value], () => {
nextTick(() => {
adjustFontSize()
})
})
</script>
<style lang="less" scoped>
.text-container {
width: 100%;
:deep(*) {
line-height: 0 !important;
}
}
</style>
06-14
216
04-29
818
08-02
1491
06-07
1万+
07-17