如何在<a> elements?

时间:2018-07-18 00:19:58

标签: javascript d3.js svg

Basic Problem:

I have some scale

var y = d3.scalePoint().domain(['a','b','c']).range([0,100]);

I can make an axis for that scale

var y_axis = svg.append("g").attr("class", "axis").call(d3.axisLeft(y));

How can I make the ticks be links?

Complication:

It's pretty straightforward to

d3.selectAll('.tick').on('click', (d) => open_link_related_to(d))

But since I want to be able to download an SVG of the plot and have the links continue to work, the strategy would need to look more like:

d3.selectAll('.tick').insert("a").attr("xlink:href", (d) => text_link_related_to(d))

However, insert doesn't wrap the tick in the <a> element -- it gets inserted below. Is it possible to wrap the label with tickformat or by some other means?

1 个答案:

答案 0 :(得分:3)

我认为最干净,惯用的方式是使用each()。您始终可以使用tickFormat()来完成此操作,但似乎有点尴尬。

使用each()方法,我们可以选择轴中的所有<text>元素,然后选择其父元素(即<g>),将<a>元素附加到父项,最后将this(即文本本身)移至<a>元素:

d3.selectAll(".tick text").each(function(d) {
  const a = d3.select(this.parentNode).append("a")
    .attr("xlink:href", "https://www." + d + ".com");//change this for your function
  a.node().appendChild(this);
});

这是一个演示(顺便说一下,堆栈片段不会打开链接):

const w = 500,
  h = 100;

const svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("heiht", h);

const scale = d3.scalePoint()
  .domain(['google', 'stackOverflow', 'amazon'])
  .range([50, w - 50]);

const axis = svg.append("g")
  .attr("transform", "translate(0,50)")
  .call(d3.axisBottom(scale))

d3.selectAll(".tick text").each(function(d) {
  const a = d3.select(this.parentNode).append("a")
    .attr("xlink:href", "https://www." + d + ".com")
    .attr("target", "_blank");
  a.node().appendChild(this);
})
<script src="https://d3js.org/d3.v5.min.js"></script>

这里是一个JSFiddle,您可以在其中实际打开链接:https://jsfiddle.net/xmtdfcks/

如果您检查刻度线,您会发现类似以下的内容:

<g class="tick" opacity="1" transform="translate(250.5,0)">
    <line stroke="#000" y2="6"></line>
    <a href="https://www.stackOverflow.com" target="blank">
        <text fill="#000" y="9" dy="0.71em">stackOverflow</text>
    </a>
</g>