字体随着外层尺寸大小而变化

6 篇文章 0 订阅

最近项目新加了个需求,系统文字从接口获取。如登录页面标题,和系统标题。其中发现遇到了一个问题。文字背景是一张图片,图片是自适应缩放的,所以可适应文字的宽度只能是按比列。所以能想到的办法就是标题文字随着外层的宽度变化,字体也跟着变化,显示完整的标题文字。
在这里插入图片描述
在这里插入图片描述
以下方法可以获取文字长度 放入utils文件夹中

const FontUtils = {
  // 获取字符串总长度[半角算0.5]
  getStringLength: (content) => {
    if (!content) return 0
    const regExALL = /[^\x00-\xff]/g
    const regExHalf = /[\x00-\xff]/g
    // 全角
    const allAngle = content.match(regExALL)
    // 半角
    const halfAngle = content.match(regExHalf)
    // 总长度
    return Math.ceil(((halfAngle ? halfAngle.length : 0) * 0.5) + (allAngle ? allAngle.length : 0))
  },
  // 单行最大字数(totalSize:不带换行符的总字数)
  getMaxWordsPerLine: (totalSize) => {
    return Math.ceil(Math.sqrt(2 * totalSize))
  },
  // 计算总行数(totalSize:总字数,maxWordsPerLine:每行最大文字个数)
  getLineNum: (totalSize, maxWordsPerLine) => {
    // return Math.ceil(maxWordsPerLine / 2)
    return Math.ceil(totalSize / maxWordsPerLine)
  },
  // 计算字号(width:屏幕宽度,maxWordsPerLine:每行最大字数)
  getFontSize: (width, height, maxWordsPerLine) => {
    // 设置字体 为了字体更好看不超出,默认再减2
    const fontSize = Math.floor(width / maxWordsPerLine * 0.96)
    if (fontSize > height) {
      return Math.floor(height * 0.96)
    }
    return fontSize
  },
  // 计算行高(height:屏幕高度,lineNum:行数)
  getLineHeight: (height, lineNum) => {
    return Math.floor(height / lineNum)
  }
}
export default FontUtils

封装文字宽度组件,其中登录的文字后边有图片,并且是可以居中的状态,所以图片也封装到组件。

当页面宽度变化的时候文字也会跟着变化。

<template>
  <div id="headerText" class="headerText">{{ title }}<img
    v-if="img&&show"
    class="img"
    src="../../assets/img/SMOOTH .png"
    alt=""
  ></div>
</template>
<script>
import FontViewUtils from '@/utils/FontViewUtils'
import getPageTitle from '@/utils/get-page-title'
export default {
  name: 'HeaderText',
  props: {
    size: {
      type: Number,
      default: 0
    },
    img: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      textWidth: '',
      textlength: '',
      ResizeObserver: '',
      title: this.$store.getters.title,
      show: false
    }
  },
  mounted() {
    this.getTitle()
  },
  beforeDestroy() {
    // 销毁时消除元素的尺寸监听
    this.ResizeObserver.disconnect()
  },
  methods: {
    async getTitle() {
      if (this.img) {
        this.title = await getPageTitle()
      }
      this.$nextTick(() => {
        this.autoFontSize()
      })
    },
    autoFontSize() {
      const el = document.getElementById('headerText')
      this.textlength = FontViewUtils.getStringLength(this.title)
      this.textWidth = this.textlength * this.size
      let boxWidth = document.getElementById('headerText').offsetWidth
      this.compileWidth(this.textWidth, boxWidth)
      this.addResizeListen(el, this.debounce((entries) => {
        const width = entries[0].contentRect.width
        this.compileWidth(this.textWidth, width)
      }, 500))
    },
    compileWidth(textWidth, boxWidth) {
      const el = document.getElementById('headerText')
      if (this.img) {
        boxWidth = boxWidth - 147
        this.show = true
      }
      if (textWidth > boxWidth) {
        el.style.fontSize = Math.floor(boxWidth / this.textlength) + 'px'
        el.style.height = Math.floor(boxWidth / this.textlength) + 'px'
      } else {
        el.style.fontSize = this.size + 'px'
        el.style.height = this.size + 'px'
      }
    },
    // 监听尺寸变化
    addResizeListen(dom, callback) {
      this.ResizeObserver = new ResizeObserver(entries => {
        if (callback) callback(entries)
      })
      this.ResizeObserver.observe(dom)
    },
    // 防抖
    debounce(func, wait) {
      let timer
      return function() {
        const context = this // 注意 this 指向
        const args = arguments // arguments中存着e
        if (timer) clearTimeout(timer)
        timer = setTimeout(() => {
          func.apply(this, args)
        }, wait)
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.headerText {
  width: 100%;
  margin: 0 auto;
  font-family: 'FZMHK';
  font-size: 0px;
  background-image: linear-gradient(to bottom, #2088df, #23a8df);
  -webkit-background-clip: text; /* 背景被裁剪成文字的前景色 */
  -webkit-text-fill-color: transparent; /* 文字填充颜色变透明 */
  letter-spacing: -1.6px;
  display: flex;
  justify-content: center;
  // align-items:baseline;
  .img {
    width: 117px;
    height: 15px;
    margin-left: 30px;
    align-self: flex-end;
  }
}
</style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一枚小米渣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值