vue2自定义指令实现文字缩放

vue2自定义指令实现文字缩放



前言

当前指令根据浏览器的不同,可缩放到的最小fontsize不同,以浏览器Chrome118+版本为例,谷歌已关闭最小字体大小默认更改,故字体在此环境下可缩放至0px。对于其他浏览器,可以根据需要添加判断,当内容缩放到一定程度后还是溢出, 则可考虑缩略或scale缩放等实现兼容。


一、指令使用方法

通过v-common-table-adaptest绑定至html标签,值为默认字体的大小(即字体开始缩放的大小如’17’),注意需要给绑定的标签设置宽度

<div v-common-table-adaptest="'17'" class="text-wrap">
      {{ text ? text : '请在下方输入框输入内容' }}
</div>
import Vue from 'vue';
//自定义指令
const commonTableAdaptest = {
  update(el, binding) {
    Vue.nextTick(() => {
      adjustFontSize(el, binding.value);
    });
  },
  bind(el, binding) {
    Vue.nextTick(() => {
      adjustFontSize(el, binding.value);
    });
  }
};

function adjustFontSize(el, fontSize) {
  // 更新前先初始化,避免已缩小的内容,更改text后无法还原
  el.style.fontSize = fontSize + 'px';

  // 获取DOM样式
  let computedStyle = window.getComputedStyle(el);
  let paddingLeft = parseFloat(computedStyle.paddingLeft);
  let paddingRight = parseFloat(computedStyle.paddingRight);

  // 计算el的内容宽度
  let elInnerWidth = el.clientWidth - paddingLeft - paddingRight;

  let textContent = el.textContent || el.innerText;
  let currentFontSize = parseFloat(computedStyle.fontSize);
  let fontFamily = computedStyle.fontFamily;

  // 借助canvas获取文本宽度
  const getTextWidth = (text, fontSize, fontFamily) => {
    // 创建canvas元素
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');
    // 设置字体样式,包括字体大小和字体系列
    context.font = `${fontSize}px ${fontFamily}`;
    // 测量文本宽度
    const metrics = context.measureText(text);
    return metrics.width;
  };

  let textWidth = getTextWidth(textContent, currentFontSize, fontFamily);
  while (textWidth > elInnerWidth && currentFontSize > 0) {
    currentFontSize -= 1;
    textWidth = getTextWidth(textContent, currentFontSize, fontFamily);
  }

  el.style.fontSize = currentFontSize + 'px';
}

思路:dom加载、更新时都重新计算dom的宽度和dom里文本的宽度,当文本宽度大于dom宽度时则将dom的字体大小减1px,直至dom宽度大于文本宽度或字体大小为0时结束。其中计算文本宽度时使用canvas协助计算,降低性能损耗。

二、使用步骤

1.完整demo

代码如下(示例):

<template>
  <div class="container">
    <div v-common-table-adaptest="'17'" class="text-wrap">
      {{ text ? text : '请在下方输入框输入内容' }}
    </div>
    <div style="margin-top: 20px">
      <input v-model="text" placeholder="在此输入文本内容" type="text" />
    </div>
  </div>
</template>
<script>
import Vue from 'vue';
//自定义指令
const commonTableAdaptest = {
  update(el, binding) {
    Vue.nextTick(() => {
      adjustFontSize(el, binding.value);
    });
  },
  bind(el, binding) {
    Vue.nextTick(() => {
      adjustFontSize(el, binding.value);
    });
  }
};

function adjustFontSize(el, fontSize) {
  // 更新前先初始化,避免已缩小的内容,更改text后无法还原
  el.style.fontSize = fontSize + 'px';

  // 获取DOM样式
  let computedStyle = window.getComputedStyle(el);
  let paddingLeft = parseFloat(computedStyle.paddingLeft);
  let paddingRight = parseFloat(computedStyle.paddingRight);

  // 计算el的内容宽度
  let elInnerWidth = el.clientWidth - paddingLeft - paddingRight;

  let textContent = el.textContent || el.innerText;
  let currentFontSize = parseFloat(computedStyle.fontSize);
  let fontFamily = computedStyle.fontFamily;

  // 借助canvas获取文本宽度
  const getTextWidth = (text, fontSize, fontFamily) => {
    // 创建canvas元素
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');
    // 设置字体样式,包括字体大小和字体系列
    context.font = `${fontSize}px ${fontFamily}`;
    // 测量文本宽度
    const metrics = context.measureText(text);
    return metrics.width;
  };

  let textWidth = getTextWidth(textContent, currentFontSize, fontFamily);
  while (textWidth > elInnerWidth && currentFontSize > 0) {
    currentFontSize -= 1;
    textWidth = getTextWidth(textContent, currentFontSize, fontFamily);
  }

  el.style.fontSize = currentFontSize + 'px';
}
export default {
  directives: {
    'common-table-adaptest': commonTableAdaptest // 注册自定义指令
  },
  name: 'test',
  data() {
    return {
      text: ''
    };
  },
  methods: {},
  created() {},
  mounted() {}
};
</script>
<style scoped>
.container {
  padding: 20px;
}
.text-wrap {
  padding: 10px;
  display: inline-block;
  background-color: rgb(74, 223, 228);
  width: 180px;
  line-height: 40px;
  white-space: nowrap;
  font-size: 17px;
}
</style>


总结

当前指令只考虑了可以无限缩小的情况,如下其他场景后面陆续再补
1.缩放到一定大小字体后字体缩略(…)
2.浏览器不支持无限缩放,缩放到一定大小时(如12px)使用scale属性兼容

实现方法有很多哈,上述仅做参考,有问题的地方欢迎指正,有更好的方法欢迎指导哈~

  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值