D3.js:使用图像(在数据中指定文件名)作为轴上的刻度值

Posted

技术标签:

【中文标题】D3.js:使用图像(在数据中指定文件名)作为轴上的刻度值【英文标题】:D3.js: Using images (with filenames specified in data) as tick values on axis 【发布时间】:2014-09-05 23:04:08 【问题描述】:

我目前有这些数据:

var dataset = [

 "bank": "Bank 1",
 "img": "Picture1.png"
,

 "bank": "Bank 2",
 "img": "Picture2.png"
,                  

 "bank": "Bank 3",
 "img": "Picture3.png"

];

复杂的现实世界数据,对吧?当然。好的,我目前使用此 D3.js 代码将“bank”作为轴上的刻度值:

var w = 1000;
var h = 700;
var padding = 30;
var wpadding = 120;
var svg = d3.select("body")
            .append("svg")
            .attr("width", w)
            .attr("height", h+padding);

var yScale = d3.scale.ordinal()
                .domain(dataset.map(function (d)  return d.bank; ))
                .rangeRoundBands([0, h], 0.55);

var yAxis = d3.svg.axis()
                .scale(yScale)
                .orient("left");

    svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(" + wpadding + ", 0)")
                .call(yAxis);               

不管怎样,我相信你可以看到我的目标。我现在正试图让我的轴上的刻度值引用我的数据集中的 img 值,而不仅仅是 bank 值。

一开始我以为是使用 axis.tickValues([values]) 和匿名函数来引用 img我的 JSON 数据中的值,但它不起作用。或者我做错了。

然后我以为是使用的情况:

 var imgs = svg.selectAll("img").data([dataset]);

但是我对这种方法的担忧是它不会像正确的刻度值那样正确绑定到轴;就好像它们只是恰好位于我的轴旁边的图像集合,并且我对轴所做的大小/位置更改也必须单独应用于我的图像集合。它看起来不像在我的轴上拥有正确的图像作为刻度值那么优雅。

我做错了什么可怕的事情吗?有人需要我提供更多信息吗?

再次感谢姐妹们!

更新:感谢@larskotthoff,我添加了这个:

svg.select(".axis").selectAll("text").remove();

var ticks = svg.select(".axis").selectAll(".tick")
                    .data(dataset)
                    .append("svg:image")
                    .attr("xlink:href", function (d)  return d.img ; )
                    .attr("width", 100)
                    .attr("height", 100);

而且它(几乎)有效!好吧,它显示图像,但正如您可以猜到的那样,每个图像的原点(即它们的左上角)是每个刻度结束的位置,导致图像现在呈现在图表内部,而不是旁边的图表之外滴答声:

没有足够的 *** 代表就无法插入图片,所以这里是 URL:i.stack.imgur.com/s2CX0.png 刻度图像出现在图表内而不是在刻度旁边

显然我需要操纵图像的 x 和 y,但是相对于单个刻度的位置,我该怎么做呢?换句话说,我在 D3 中怎么说:“取刻度的 x,y 并减去(硬编码值)150,然后将其作为我的图像的新 x,y。”?

再次感谢您的帮助!

更新 #2:在最终发现 this.parentNode 并深入研究之后,我只是新手发现当前图像上设置的 x,y 属性绑定到我的轴是相对于每个相应的刻度!我的意思是,我可以简单地添加:

                    .attr("x", -120)
                    .attr("y", -50);

作为我的图像的附加属性,并将它们定位在各自刻度的左侧(回到轴标签位置,而不是位于图表顶部)。

【问题讨论】:

嗯,听起来您需要选择现有的刻度标签 text 元素,删除它们并替换为 image 元素,根据绑定到 @987654328 的数据设置为正确的 URL @元素。 @LarsKotthoff -- 感谢您的建议!我已经用更多信息更新了我的 OP。 听起来这个问题是你自己回答的。写一个答案来回答你自己的问题是完全可以接受的。我认为这会很有用,因为它不会再出现在未回答的问题中:) 发布 OP 的答案有多合适,因为他们似乎没有跟进这样做? @morganpdx 去吧。完全合适 【参考方案1】:

数据集:

var dataset = [

 "bank": "Bank 1",
 "img": "Picture1.png"
,

 "bank": "Bank 2",
 "img": "Picture2.png"
,                  

 "bank": "Bank 3",
 "img": "Picture3.png"

];

D3 JS 代码:

var w = 1000;
var h = 700;
var padding = 30;
var wpadding = 120;
var svg = d3.select("body")
            .append("svg")
            .attr("width", w)
            .attr("height", h+padding);


svg.select(".axis").selectAll("text").remove();

var ticks = svg.select(".axis").selectAll(".tick")
                    .data(dataset)
                    .append("svg:image")
                    .attr("xlink:href", function (d)  return d.img ; )
                    .attr("width", 100)
                    .attr("height", 100);
                    .attr("x", -120);
                    .attr("y", -50);


var yScale = d3.scale.ordinal()
                .domain(dataset.map(function (d)  return d.bank; ))
                .rangeRoundBands([0, h], 0.55);

var yAxis = d3.svg.axis()
                .scale(yScale)
                .orient("left");

    svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(" + wpadding + ", 0)")
                .call(yAxis);  

【讨论】:

以上是关于D3.js:使用图像(在数据中指定文件名)作为轴上的刻度值的主要内容,如果未能解决你的问题,请参考以下文章

无法在 Qt5/cmake 项目中加载 Qt 资源文件中指定的图像

是否有可能在蚂蚁中指定属性值作为属性?

d3.js 需要在 y 轴上重复值

在代码中指定图像时,不使用 Retina 图标 (@2x)

如何解决d3.js中x轴上的重叠刻度文本

如何在 HTML5 缓存清单中指定通配符以加载目录中的所有图像?