【问题标题】:SVG Text are being truncatedSVG 文本被截断
【发布时间】:2021-12-28 02:50:23
【问题描述】:

我目前致力于 SVG 地图的集成,我尝试了两种技术来渲染这张地图,第一种,第一次尝试效果很好,但关于数据的组织方式确实很混乱。第二个,非常干净,但是现在我渲染地图时文本被截断了。

如你所见,我们的城市 Renn 应该是 RennazChess 应该是 Chessel 和 Corbeyrie 应该是 Corbeyrier

我现在是这样组织数据的:

[
  {
    id: generateRandomId(),
    name: 'Rennaz',
    map: {
      positionX: 42.7303,
      positionY: 230.0168,
      polygonClassModifier: `--lighter`,
      polygonPoints: `61.1,214.8 61.1,220.1 58.2,232.6 58.2,234.7 55.3,237 53.9,234.7 50.8,234.7 42.8,240 42.8,229.7
      42.8,224.4 50.8,222.2 47.8,220.1 55.3,214.8`,
    },
  },
  {
    id: generateRandomId(),
    name: 'Roche',
    map: {
      positionX: 50.8895,
      positionY: 249.4768,
      polygonClassModifier: `--medium-lighter`,
      polygonPoints: `58.2,232.6 65.6,234.7 70.7,232.6 73.6,232.6 75.8,234.7 75.8,237 78.1,240 78.1,242.9 81.1,240
      83.2,242.9 78.1,247.3 70.7,255.4 65.6,256.8 65.6,259.8 50.8,262.8 45.7,262.8 40.5,259.8 42.8,256.8 45.7,255.4 38.3,244.3
      40.5,240 42.8,240 50.8,234.7 53.9,234.7 55.3,237 58.2,234.7`,
    },
  },
...
]

我如何渲染它(Vue.js)

  <svg
    :class="INTERACTIVE_MAP_CSS_CLASSES.svg"
    xmlns="http://www.w3.org/2000/svg"
    x="0px"
    y="0px"
    viewBox="0 0 345.7 468.1"
    xml:space="preserve"
    pointer-events="auto"
  >
    <g v-for="city in communes" :key="city.id">
      <g>
        <polygon
          class="interactive-map__polygon"
          :points="city.map.polygonPoints"
          @click="$emit('onCommuneClick', city)"
        />
      </g>

      <text
        :transform="`matrix(1 0 0 1 ${city.map.positionX} ${city.map.positionY})`"
      >
        {{ city.name }}
      </text>

      <g
        v-if="city.map.hasPoint"
        :transform="`matrix(
          1 0 0 1 ${city.map.positionX - 6} ${city.map.positionY - 3.5}
        )`"
        stroke-width="3"
      >
        <circle cx="1" cy="1" r="2.5" />
      </g>
    </g>
  </svg>

在它工作之前(混乱的解决方案)

我会在一个对象中有 3 个属性

  • 城市名称
  • 引脚(黑色实心圆圈)
  • 多边形
export const interactiveMap = {
citiesName: [
    {
      id: generateRandomId(),
      name: 'Rennaz',
      transform: 'matrix(0.92 0 0 1 42.7303 230.0168)',
    },
    {
      id: generateRandomId(),
      name: 'Roche',
      transform: 'matrix(0.92 0 0 1 50.8895 249.4768)',
    },
],
pins: [
   {
      id: generateRandomId(),
      paths: [
        `M169.5,384.4L169.5,384.4c1.4,0,2.5,1.1,2.5,2.5l0,0c0,1.4-1.1,2.5-2.5,2.5l0,0c-1.4,0-2.5-1.1-2.5-2.5l0,0
        C167,385.5,168.1,384.4,169.5,384.4z`,
        `M169.5,386.1L169.5,386.1c0.4,0,0.8,0.3,0.8,0.7l0,0c0,0.4-0.3,0.7-0.7,0.7l0,0c-0.4,0-0.7-0.3-0.7-0.7l0,0
        C168.7,386.5,169,386.1,169.5,386.1z`,
      ],
    },
],
polygons: [
    {
      id: generateRandomId(),
      cssClass: `${POLYGONS_BASE_CSS_CLASS}--lighter`,
      points: `61.1,214.8 61.1,220.1 58.2,232.6 58.2,234.7 55.3,237 53.9,234.7 50.8,234.7 42.8,240 42.8,229.7
      42.8,224.4 50.8,222.2 47.8,220.1 55.3,214.8`,
    },
    {
      id: generateRandomId(),
      cssClass: `${POLYGONS_BASE_CSS_CLASS}--medium-lighter`,
      points: `58.2,232.6 65.6,234.7 70.7,232.6 73.6,232.6 75.8,234.7 75.8,237 78.1,240 78.1,242.9 81.1,240
      83.2,242.9 78.1,247.3 70.7,255.4 65.6,256.8 65.6,259.8 50.8,262.8 45.7,262.8 40.5,259.8 42.8,256.8 45.7,255.4 38.3,244.3
      40.5,240 42.8,240 50.8,234.7 53.9,234.7 55.3,237 58.2,234.7`,
    },

]
}

凌乱的解决方案渲染:

 <svg
    id="aas-map"
    class="interactive-map"
    version="1.1"
    xmlns="http://www.w3.org/2000/svg"
    x="0px"
    y="0px"
    viewBox="0 0 345.7 468.1"
    xml:space="preserve"
    pointer-events="auto"
  >
    <g>
      <polygon
        v-for="polygon in polygons"
        :key="polygon.id"
        class="interactive-map__polygon"
        :points="polygon.points"
      />
    </g>

    <text
      v-for="city in cities"
      :key="city.id"
      :transform="city.transform"
      class="interactive-map__city-name"
    >
      {{ city.name }}
    </text>

    <g
      v-for="pin in pins"
      :key="pin.id"
      class="interactive-map__pin"
    >
      <path v-for="path in pin.paths" :key="path" :d="path" />
    </g>
  </svg>

我相信这与我做 v-for 的主要部分有关,这是两个比较逻辑在组织上的唯一区别。

到目前为止,我已经尝试了各种方法:

  • 编辑一些 CSS 属性(溢出:可见、z-index、...)不起作用
  • 试图将文本放在多边形之前,但它们只是被多边形隐藏了
  • 在变换中编辑矩阵,对我也没有帮助

如果有人有线索,感谢您与我们联系 :) 谢谢

【问题讨论】:

  • 我已经尝试这样做了,但是添加 zindex 和相对位置并没有改变任何可悲的...
  • 文本与下一个形状重叠。一种解决方案是将所有文本放在 svg 末尾的一组它自己的组中。另外我建议将字体大小更改为更小的字体。由于有人评论了 z-index :z-index 在 SVG 中不起作用

标签: javascript css svg text polygon


【解决方案1】:

正如 @enxaneta 指出的那样:
您必须确保您的标签“在顶部”(减小字体大小也很有意义)。

在 svg 中(如在 html 中),这些标签元素将写在 svg 标记的末尾/底部。

因此,您需要将标签输出与常规形状循环分开。
vue.js 中可能有更好的方法来避免第二次列表渲染。
这个 sn-p 的主要思想:城市区域和标签都添加到相应的&lt;g&gt; 元素中。 (&lt;g id="city-areas" &gt;&lt;g id="city-labels"&gt;)。

var cities =
    [
  {
    id: 123,
    name: 'Rennaz',
    map: {
      positionX: 42.7303,
      positionY: 230.0168,
      polygonClassModifier: `--lighter`,
      polygonPoints: `61.1,214.8 61.1,220.1 58.2,232.6 58.2,234.7 55.3,237 53.9,234.7 50.8,234.7 42.8,240 42.8,229.7
      42.8,224.4 50.8,222.2 47.8,220.1 55.3,214.8`,
    },
  },
  {
    id: 456,
    name: 'Roche',
    map: {
      positionX: 50.8895,
      positionY: 249.4768,
      polygonClassModifier: `--medium-lighter`,
      polygonPoints: `58.2,232.6 65.6,234.7 70.7,232.6 73.6,232.6 75.8,234.7 75.8,237 78.1,240 78.1,242.9 81.1,240
      83.2,242.9 78.1,247.3 70.7,255.4 65.6,256.8 65.6,259.8 50.8,262.8 45.7,262.8 40.5,259.8 42.8,256.8 45.7,255.4 38.3,244.3
      40.5,240 42.8,240 50.8,234.7 53.9,234.7 55.3,237 58.2,234.7`,
    },
  },
];


var svgmap = new Vue({
  el: '#svgmap',
  data: {
    communes: cities
  }
})
text {
    font-size: 7px;
    fill: red;
    font-weight: bold;
    font-family: 'Segoe UI'
}

svg{
  border:1px solid red;
 max-width :50vw;
}

polygon{
  fill: #ccc;
  stroke: #000;
  stroke-width: 0.5;
}
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>
<svg id="svgmap"
    xmlns="http://www.w3.org/2000/svg"
    x="0px"
    y="0px"
    viewBox="0 200 200 400"
    xml:space="preserve"
    pointer-events="auto"
  >
    <g id="city-areas" >
        <polygon v-for="city in communes"
          class="interactive-map__polygon"
          :points="city.map.polygonPoints"
        />
    </g>
  
    <g id="city-labels">
      <text  v-for="city in communes" :key="city.id"
        :transform="`matrix(1 0 0 1 ${city.map.positionX} ${city.map.positionY})`"
      >
        {{ city.name }}
      </text>   
    </g>
</svg>

【讨论】:

  • 我明白了,我会试试的,我已经重构了代码以避免进行第二次循环,但这似乎是不可避免的
猜你喜欢
  • 1970-01-01
  • 2018-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多