副标题:
(1)文字长度变化,改变文字的大小
(2)根据文本长度,自适应文字大小
(3)判断文字是否溢出
需求:
当文字溢出时,改变文字的大小,而不让文字溢出。
效果:文字不可以溢出
图1:
图2:
图3:
关键点:判断文字是否溢出
参考文章: javascript - HTML 文本溢出省略号 检测 - 堆栈溢出 (stackoverflow.com)
对于文字溢出的判断,我并没有按照上面这个讨论来写。
可以使用以下方法来判断文本是否溢出:
- 获取文本的实际宽度和容器的宽度。
let textWidth = document.getElementById('text').offsetWidth;
let containerWidth = document.getElementById('container').offsetWidth;
- 比较文本的宽度和容器的宽度。
if (textWidth > containerWidth)
{ console.log('文本溢出');
} else {
console.log('文本未溢出');
}
如果文本的宽度大于容器的宽度,则表示文本溢出;否则表示文本未溢出。
需要注意的是:一定要对容器设置css文字溢出时,不换行
white-space: nowrap;
对于offsetWidth、clientWidth、scrollWidth等的理解:html - Understanding offsetWidth, clientWidth, scrollWidth and -Height, respectively - Stack Overflow
通过Vue3 TS实现的,代码如下:
<script setup lang="ts">
import { nextTick, ref, watch } from "vue";
const wrapRef = ref();
const spanRef = ref();
const val = ref("");
watch(val, () => {
nextTick(() => {
setWrapFontSize();
});
});
function getTextOffsetWidth() {
return spanRef.value.offsetWidth || 0;
}
function getDivOffsetWidth() {
return parseFloat(getComputedStyle(wrapRef.value).width) || 0;
}
function isEllipsisActive() {
const textWith = getTextOffsetWidth();
const divWith = getDivOffsetWidth();
return textWith - divWith;
}
function setWrapFontSize() {
// 多出的宽度
const moreWidth = isEllipsisActive();
// 当前字体大小
const curFontSize = parseFloat(wrapRef.value.style.fontSize);
if (moreWidth >= 0 && curFontSize <= 12) {
setFontSize(12);
return;
}
if (moreWidth <= 0 && curFontSize >= 30) {
setFontSize(30);
return;
}
const textNum = val.value.length;
const diffFontSize = Math.ceil(moreWidth / textNum);
console.log("fontsize差值:", diffFontSize);
setFontSize(curFontSize - diffFontSize);
// 字符或字母计算不准,需要多次计算
const newMoreWidth = isEllipsisActive();
if (newMoreWidth > 0) {
setWrapFontSize();
}
}
function setFontSize(num: number) {
wrapRef.value.style.fontSize = `${num}px`;
}
</script>
<template>
<!-- <img alt="Vue logo" src="./assets/logo.png" /> -->
<div ref="wrapRef" class="wrap" style="font-size: 30px">
<span ref="spanRef">{{ val }}</span>
</div>
<!-- <HelloWorld msg="Hello Vue 3 + TypeScript + Vite" /> -->
<p></p>
<input ref="inputRef" type="url" name="" v-model="val" id="" />
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.wrap {
width: 200px;
height: 40px;
background-color: #2ca553;
display: inline-block;
white-space: nowrap;
padding: 10px;
}
</style>
`