在SVG中绘制多行文本并不像HTML中的<p>
或<div>
元素那样直接支持换行。那么,如果需要在svg中显示多行文本,该怎么实现呢?
方法一:使用<tspan>
元素
<tspan>
元素是SVG中用于在<text>
元素内部创建文本片段(如多行文本)的元素。你可以通过改变每个<tspan>
元素的x
和y
属性(或者仅改变y
属性以保持水平对齐)来实现换行。
<svg width="400" height="200">
<text x="50" y="50" font-size="20" fill="black">
<tspan>第一行文本</tspan>
<tspan x="50" y="80">第二行文本</tspan>
<tspan x="50" y="110">第三行文本</tspan>
</text>
</svg>
实现效果:
弊端:需要将一段文字,拆分为多条,计算位置再展示。
方法二:使用foreignObject
<foreignObject>
元素是一个容器,它允许你将非SVG内容(如HTML、XHTML或其他XML命名空间的内容)嵌入到SVG图形中。这使得你可以在SVG图形中集成HTML元素,如文本输入框、按钮、表格等,从而扩展SVG的交互性和表现能力。
// 动态的demo 示例
<!DOCTYPE html>
<html>
<head>
<title>Vue Draggable Example</title>
<!-- 引入Vue和Vue.Draggable -->
<script src="https://www.itxst.com/package/vue/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/interactjs/dist/interact.min.js"></script>
</head>
<body>
<div id="app">
<svg width="400" height="300">
<g v-for="(elementData, index) in elements" :key="index">
<!-- 根据元素类型渲染内容 -->
<g v-if="elementData.type === 'TeatArea'">
<foreignObject :width="elementData.width" :height="elementData.height" :x="elementData.x" :y="elementData.y"
:fill="elementData.color">
<p contenteditable="true" :style="{ fontSize: elementData.fontSize + 'px', color: elementData.color, }">
{{elementData.label}}</p>
</foreignObject>
</g>
<g v-else-if="elementData.type === 'Text'">
<text ref="textElement" :style="elementData.selected ? 'pointer-events: none' : ''" font-weight="normal"
:font-size="elementData.fontSize" :fill="elementData.color" :font-family="elementData.fontFamily"
:x="elementData.x" :y="elementData.y" dominant-baseline="text-before-edge">
{{elementData.label}}
</text>
</g>
<g v-else-if="elementData.type === 'Line'">
<line :x1="elementData.x1" :y1="elementData.y1" :x2="elementData.x2" :y2="elementData.y2"
:stroke="elementData.color" :stroke-width="elementData.strokeWidth" class="svg_select_points_rot_line">
</line>
</g>
</g>
</svg>
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
elements:
// 初始元素,可以根据需要添加
[{ "type": "Text", "x": 9, "y": 25, "width": 206, "height": 60, "fontSize": 16, "fontFamily": "Microsoft YaHei", "label": "会议室名称:", "color": "#000000", "selected": false, "rotate": 0, "isDynamic": false, "dynamicKey": "key" },
{ "type": "TeatArea", "x": 112, "y": -10, "width": 240, "height": 110, "fontSize": 30, "fontFamily": "Microsoft YaHei", "label": "第null会议室之在海一方", "color": "#9A2835", "selected": false, "rotate": 0, "isDynamic": true, "dynamicKey": "roomName" },
{ "type": "Text", "x": 220, "y": 227, "width": 96, "height": 21, "fontSize": 16, "fontFamily": "Microsoft YaHei", "label": "可容纳人数:", "color": "#000000", "selected": false, "rotate": 0, "isDynamic": false, "dynamicKey": "key" },
{ "type": "Text", "x": 331, "y": 219, "width": 54.328125, "height": 33, "fontSize": 25, "fontFamily": "Microsoft YaHei", "label": "16人", "color": "#000000", "selected": false, "rotate": 0, "isDynamic": true, "dynamicKey": "personNum" },
{ "type": "Text", "x": 192, "y": 265, "width": 96, "height": 21, "fontSize": 16, "fontFamily": "Microsoft YaHei", "label": "会议室类型:", "color": "#000000", "selected": false, "rotate": 0, "isDynamic": false, "dynamicKey": "key" },
{ "type": "Text", "x": 291, "y": 262, "width": 100, "height": 26, "fontSize": 20, "fontFamily": "Microsoft YaHei", "label": "普通会议室", "color": "#000000", "selected": false, "rotate": 0, "isDynamic": true, "dynamicKey": "roomType" },
{ "type": "Text", "x": 46, "y": 209, "width": 96, "height": 21, "fontSize": 16, "fontFamily": "Microsoft YaHei", "label": "【当前状态】", "color": "#000000", "selected": false, "rotate": 0, "isDynamic": false, "dynamicKey": "key" },
{ "type": "Text", "x": 16, "y": 103, "width": 80, "height": 21, "fontSize": 16, "fontFamily": "Microsoft YaHei", "label": "会议内容:", "color": "#000000", "selected": false, "rotate": 0, "isDynamic": false, "dynamicKey": "key" },
{ "type": "Text", "x": 109, "y": 102, "width": 208.2509765625, "height": 33, "fontSize": 25, "fontFamily": "Microsoft YaHei", "label": "关于XX主题的讨论", "color": "#9A2835", "selected": false, "rotate": 0, "isDynamic": true, "dynamicKey": "msg" },
{ "type": "Text", "x": 24, "y": 229, "width": 135, "height": 60, "fontSize": 45, "fontFamily": "Microsoft YaHei", "label": "进行中", "color": "#9A2835", "selected": false, "rotate": 0, "isDynamic": true, "dynamicKey": "roomStatus" },
{ "type": "Line", "x1": -1, "y1": 204, "x2": 398, "y2": 204, "strokeWidth": 2, "color": "#000000", "selected": false, "rotate": 0, "zIndex": 0 }, { "type": "Line", "x1": 234, "y1": 203, "x2": 169, "y2": 302, "strokeWidth": 2, "color": "#000000", "selected": false, "rotate": 0, "zIndex": 0 },
{ "type": "Text", "x": 6, "y": 172, "width": 100, "height": 26, "fontSize": 20, "fontFamily": "Microsoft YaHei", "label": "使用部门:", "color": "#000000", "selected": false, "rotate": 0, "isDynamic": false, "dynamicKey": "key" },
{ "type": "Text", "x": 337, "y": 168, "width": 50, "height": 33, "fontSize": 25, "fontFamily": "Microsoft YaHei", "label": "向往", "color": "#9A2835", "selected": false, "rotate": 0, "isDynamic": true, "dynamicKey": "nickName" },
{ "type": "Text", "x": 104, "y": 169, "width": 125, "height": 33, "fontSize": 25, "fontFamily": "Microsoft YaHei", "label": "技术部", "color": "#9A2835", "selected": false, "rotate": 0, "isDynamic": true, "dynamicKey": "deptName" },
{ "type": "Text", "x": 252, "y": 174, "width": 80, "height": 26, "fontSize": 20, "fontFamily": "Microsoft YaHei", "label": "使用人:", "color": "#000000", "selected": false, "rotate": 0, "isDynamic": false, "dynamicKey": "key" }]
,
},
});
</script>
<style>
svg {
border: 2px solid black;
}
</style>
</body>
</html>
实现效果:
优点:定好宽高后,内容过长会自动换行,可实现动态新增回显等需求。