圆形SVG菜单中的水平文本 [英] Horizontal text in a circular SVG menu

查看:64
本文介绍了圆形SVG菜单中的水平文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要做一个圆形菜单,其中元素的数量为未知/可变(我强调这一点是因为对3或4个元素的静态解决方案不感兴趣).

I need to do a circular menu, with an unknown/variable number of elements (I underline this point because not interested in 3 or 4 elements static solutions).

我决定使用SVG.当我使用服务器端代码构建具有SVG路径的HTML/SVG时,可以使用startOffset = "@(100/items.Count)%"

I decided to use SVG. As I build the HTML/SVG with the server side code, having a SVG path, I can put the text on that path with startOffset = "@(100/items.Count)%"

.container { width: 300px; }
svg { border: 1px solid; }
a:hover { fill: red; }

<div class="container">
  <svg viewBox="0 0 200 200">
<defs>
   <desc>The path used for the text</desc>
   <path id="c" d="M150,100 A50,50 0 1 1 150,99.99z" />
</defs>
     <use xlink:href="#c" stroke="#d9d9d9" fill="none"/>
     <text font-size="20" >
      <textPath xlink:href="#c" startOffset="33%">
            <a xlink:href="https://stackoverflow.com">Our products</a>
      </textPath>
  </text>
  
  <text font-size="20" text-anchor="middle">
      <textPath xlink:href="#c" startOffset="66%">
            <a xlink:href="https://stackoverflow.com">Services</a>
      </textPath>
  </text>
  
  <text font-size="20" text-anchor="end">
      <textPath xlink:href="#c" startOffset="99%">
            <a xlink:href="https://stackoverflow.com">Achievements</a>
      </textPath>
  </text>
</svg>
</div>

我的问题是如何使文本对用户可读(不会重叠,倒置,难以阅读)? 具体的问题是如何使文本水平,并保持其位置/基点"在圆的路径上? 之后,我将使用类似

My question is how to make the text readable for the user (not be superposed, inverted, hard to read) ? The concrete question would be how to make the text horizontal, keeping its position/"base point" on the circle's path? After that I will use something like

.textbox    { 
    max-width: 200px; 
    white-space: nowrap; 
    overflow: hidden;
    text-overflow: ellipsis;
}

PS.我对SVG/CSS/HTML简单解决方案而不是JS复杂图形库更感兴趣.

PS. I am interested more in SVG/CSS/HTML simple solutions rather that JS complex drawing libraries.

推荐答案

像这样吗?

let links = [
  {
    text: "Our products",
    url: "https://stackoverflow.com"
  },
  {
    text: "Services",
    url: "https://stackoverflow.com"
  },
  {
    text: "Achievements",
    url: "https://stackoverflow.com"
  },
  {
    text: "something else",
    url: "https://stackoverflow.com"
  },
  {
    text: "test",
    url: "https://stackoverflow.com"
  },
  {
    text: "more stuff",
    url: "https://stackoverflow.com"
  }
];


const RADIUS_PADDING = 10;



function makeMenu(circleElementId, linksData)
{
  var circle = document.getElementById(circleElementId);
  var svg = circle.ownerSVGElement;
  var r = circle.r.baseVal.value + RADIUS_PADDING;
  var cx = circle.cx.baseVal.value;
  var cy = circle.cx.baseVal.value;

  for (var i = 0; i < linksData.length; i++)
  {
    var angle = i * 2 * Math.PI / linksData.length;
    var o = {'x': cx + r * Math.sin(angle),
             'y': cy - r * Math.cos(angle),
             'text-anchor': (angle <= Math.PI) ? "start" : "end"};


    // Make a link (a) element
    var aLink = addLink(linksData[i].url, svg);
    
    // Make a text element for the link text
    addText(o, linksData[i].text, aLink);
    
  }
}


function addLink(url, parent)
{
  var link = document.createElementNS(parent.namespaceURI, "a");
  link.setAttributeNS("http://www.w3.org/1999/xlink", "href", url);
  parent.appendChild(link);
  return link;
}


function addText(o, txt, parent)
{
  var text = document.createElementNS(parent.namespaceURI, "text");
  for (var name in o) {
    if (o.hasOwnProperty(name)) {
      text.setAttribute(name, o[name]);
    }
    text.textContent = txt;
  }
  parent.appendChild(text);
  return text;
}



makeMenu("menu-circle", links)

svg {
  border: 1px solid;
  width:90vh;
}
circle {
  fill: none;
  stroke: #d9d9d9;
}
text {
  font-size: 8px;
  font-family:consolas;
  dominant-baseline: middle;
}
a:hover{fill:red}

<div class="container">
  <svg viewBox="-10 0 220 200">

   <circle id="menu-circle" r="60" cx="100" cy="100" stroke="black" fill="none"/>

  </svg>
</div>

这篇关于圆形SVG菜单中的水平文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆