首先界说了一个RectAndText组件,这个组件实现了在矩形中表现居中的文本(矩形可以根据自己需求要或者不要)
- <template>
- <rect :x="x" :y="y" :width="width" :height="height" :stroke="stroke" :stroke-width="strokeWidth"></rect>
- <g v-if="lines.length <= 1">
- <text :x="getRectangleCenter(x, y, width, height).centerX + skewX"
- :y="getRectangleCenter(x, y, width, height).centerY + skewY"
- :font-size="fontSize" :fill="fill" :font-family="fontFamily" text-anchor="middle" alignment-baseline="middle">
- {{ title }}</text>
- </g>
- <g v-if="lines.length > 1" :transform="`translate(${getRectangleCenter(x, y, width, height).centerX + skewX},${getRectangleCenter(x, y, width, height).centerY + skewY - (lines.length - 1) * fontSize / 4})`">
- <text v-for="(line, index) in lines" :key="index" :x="0" :y="index * fontSize * 1.2" :font-size="fontSize" :fill="fill" :font-family="fontFamily" text-anchor="middle" alignment-baseline="ideographic">
- {{ line }}
- </text>
- </g>
- </template>
- <script setup>
- //自定义组件 绘制矩形的同时渲染一个居中的文本
- import {onMounted, ref} from "vue";
- const props = defineProps({
- fontSize: {
- type: Number,
- default: () => 40
- },
- fontFamily: {
- type: String,
- default: () => 'NSimSun'
- },
- stroke: {
- type: String,
- default: () => '#ffffff'
- },
- fill: {
- type: String,
- default: () => '#ffffff'
- },
- title: {
- type: [String, Number],
- default: () => ''
- },
- x: {
- type: Number,
- default: () => 100
- },
- y: {
- type: Number,
- default: () => 100
- },
- height: {
- type: Number,
- default: () => 100
- },
- width: {
- type: Number,
- default: () => 100
- },
- strokeWidth: {
- type: String,
- default: () => '2'
- },
- //偏移量:有时候不一定会居中显示,有可能偏移
- skewX: {
- type: Number,
- default: () => 0
- },
- skewY: {
- type: Number,
- default: () => 0
- },
- });
- // 使用computed属性来将title字符串分割成多行
- const lines = computed(() => {
- // 检查 props.title 是否是一个字符串
- if (typeof props.title === 'string') {
- // 如果是字符串,则按换行符分割
- return props.title.split('\n');
- } else {
- // 如果不是字符串,返回一个空数组或包含默认值的数组
- return [''];
- }
- });
- onMounted(() => {
- });
- //计算文字在矩形居中的位置
- function getRectangleCenter(x, y, width, height) {
- // 计算中心点的x坐标
- const centerX = x + width / 2;
- // 计算中心点的y坐标
- const centerY = y + height / 2;
- // 返回中心点坐标
- return { centerX, centerY };
- }
- </script>
复制代码 第一个g里面实现了默认的一行居中表现文本。重点是第二个g,如果检测到了文本中存在换行符\n,则渲染第二个g,这里通过transform实现y坐标的偏移,偏移量是根据fontSize文本巨细来盘算的,这是为了保证在偏移时不超出矩形边框。这时你只必要传入一个包含\n的文本字符串就可以实现动态换行了。结果如下:


至于如何换行的逻辑,这里就必要自己去实现,我举个例子:
我这边有个字符串"IG,IIG,3G,4G,4DG,8DG,4G,4DG",我必要把他拆分为两行表现,我通过,分割出来的字符串确认要从哪里举行拆分,(同时拆分后要把文字巨细减小,否则会超出矩形边框,这个根据自己的需求去写就行)。
- /**
- * 文本换行逻辑
- * 动态的通过\n分割文本
- * 同时计算文本的大小(比如文本默认大小是40,那么分为两行就要变为30,三行变为20...)
- */
- function getTextLineAndSize(text, fontSize, devicesPerLine) {
- let devices = text.split(',');
- let lines = Math.ceil(devices.length / devicesPerLine); // 计算需要的行数
- let decreaseSize = 10 * (lines - 1); // 每增加一行,字体大小减少10
- let result = { content: text, size: fontSize - decreaseSize };
- // 根据每行的设备数量添加换行符
- for (let i = devicesPerLine; i < devices.length; i += devicesPerLine) {
- devices[i] = '\n' + devices[i];
- }
- result.content = devices.join(',');
- return result;
- }
复制代码 末了是调用这个组件的例子,这里的变量自己传入就可以
- <RectAndText :x="rectX" :y="rectY" :width="rectWidth" :height="100" :stroke="stroke" :strokeWidth="strokeWidth" :fontSize="getTextLineAndSize(devName, fontSize, 4).size" :title="getTextLineAndSize(devName, fontSize, 4).content"/>
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |