js 文字溢出时,改变文字大小

433 阅读1分钟
副标题:

(1)文字长度变化,改变文字的大小

(2)根据文本长度,自适应文字大小

(3)判断文字是否溢出

需求:

当文字溢出时,改变文字的大小,而不让文字溢出。

效果:文字不可以溢出

图1:

image.png

图2:

image.png

图3:

image.png

关键点:判断文字是否溢出

参考文章: javascript - HTML 文本溢出省略号 检测 - 堆栈溢出 (stackoverflow.com)

对于文字溢出的判断,我并没有按照上面这个讨论来写。

可以使用以下方法来判断文本是否溢出:

  1. 获取文本的实际宽度和容器的宽度。
let textWidth = document.getElementById('text').offsetWidth;
let containerWidth = document.getElementById('container').offsetWidth;
  1. 比较文本的宽度和容器的宽度。
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>

`