如何使用D3.js将图像添加到svg容器
我已经创build了一个示例Asp.Net MVC 4应用程序,我已经使用了D3.js来附加一个SVG元素,然后在SVG里面添加了一个文本元素(见下面的代码)。 这一切工作正常,直到我尝试使用本地PNG文件附加img到SVG。 img被附加到DOM,但img不在页面上呈现。 任何想法我在这里做错了,以及如何去解决它?
@{ ViewBag.Title = "Home Page"; } <script src="~/Scripts/d3.v3.js"></script> <script type="text/javascript"> var svg = d3.select("body") .append("svg") .attr("width", 200) .attr("height", 100) .style("border", "1px solid black"); var text = svg.selectAll("text") .data([0]) .enter() .append("text") .text("Testing") .attr("x", "40") .attr("y", "60"); var imgs = svg.selectAll("img").data([0]); imgs.enter() .append("img") .attr("xlink:href", "@Url.Content("~/Contenthttp://img.dovov.comicons/refresh.png")") .attr("x", "60") .attr("y", "60") .attr("width", "20") .attr("height", "20"); </script>
@Richard Marr – 下面是直接HTML中做同样的事情,这给了我相同的结果。 我不知道我的代码从这种方式从本地驱动器获取refresh.png文件。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <script src="http://d3js.org/d3.v2.js"></script> </head> <body> <script type="text/javascript"> var svg = d3.select("body") .append("svg") .attr("width", 200) .attr("height", 100) .style("border", "1px solid black"); var text = svg.selectAll("text") .data([0]) .enter() .append("text") .text("Testing") .attr("x", "40") .attr("y", "60"); var imgs = svg.selectAll("img").data([0]); imgs.enter() .append("svg:img") .attr("xlink:href", "file:///D:/d3js_projects/refresh.png") .attr("x", "60") .attr("y", "60") .attr("width", "20") .attr("height", "20"); </script> </body> </html>
在SVG(与HTML形成对比)中,您将要使用<image>
而不是<img>
作为元素。
尝试改变你的最后一个块:
var imgs = svg.selectAll("image").data([0]); imgs.enter() .append("svg:image") ...
nodeEnter.append("svg:image") .attr('x', -9) .attr('y', -12) .attr('width', 20) .attr('height', 24) .attr("xlink:href", "resourceshttp://img.dovov.comcheck.png")
我的团队也想在d3绘制的圈子里添加图片,并提出以下( 小提琴 ):
index.html的:
<!doctype html> <html> <head> <link rel="stylesheet" type="text/css" href="timeline.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js"></script> <script src="https://code.jquery.com/jquery-2.2.4.js" integrity="sha256-iT6Q9iMJYuQiMWNd9lDyBUStIq/8PuOW33aOqmvFpqI=" crossorigin="anonymous"></script> <script src="./timeline.js"></script> </head> <body> <div class="timeline"></div> </body> </html>
timeline.css:
.axis path, .axis line, .tick line, .line { fill: none; stroke: #000000; stroke-width: 1px; }
timeline.js:
// container target var elem = ".timeline"; var props = { width: 1000, height: 600, class: "timeline-point", // margins marginTop: 100, marginRight: 40, marginBottom: 100, marginLeft: 60, // data inputs data: [ { x: 10, y: 20, key: "a", image: "https://unsplash.it/300/300", id: "a" }, { x: 20, y: 10, key: "a", image: "https://unsplash.it/300/300", id: "b" }, { x: 60, y: 30, key: "a", image: "https://unsplash.it/300/300", id: "c" }, { x: 40, y: 30, key: "a", image: "https://unsplash.it/300/300", id: "d" }, { x: 50, y: 70, key: "a", image: "https://unsplash.it/300/300", id: "e" }, { x: 30, y: 50, key: "a", image: "https://unsplash.it/300/300", id: "f" }, { x: 50, y: 60, key: "a", image: "https://unsplash.it/300/300", id: "g" } ], // y label yLabel: "Y label", yLabelLength: 50, // axis ticks xTicks: 10, yTicks: 10 } // component start var Timeline = {}; /*** * * Create the svg canvas on which the chart will be rendered * ***/ Timeline.create = function(elem, props) { // build the chart foundation var svg = d3.select(elem).append('svg') .attr('width', props.width) .attr('height', props.height); var g = svg.append('g') .attr('class', 'point-container') .attr("transform", "translate(" + props.marginLeft + "," + props.marginTop + ")"); var g = svg.append('g') .attr('class', 'line-container') .attr("transform", "translate(" + props.marginLeft + "," + props.marginTop + ")"); var xAxis = g.append('g') .attr("class", "x axis") .attr("transform", "translate(0," + (props.height - props.marginTop - props.marginBottom) + ")"); var yAxis = g.append('g') .attr("class", "y axis"); svg.append("text") .attr("class", "y label") .attr("text-anchor", "end") .attr("y", 1) .attr("x", 0 - ((props.height - props.yLabelLength)/2) ) .attr("dy", ".75em") .attr("transform", "rotate(-90)") .text(props.yLabel); // add placeholders for the axes this.update(elem, props); }; /*** * * Update the svg scales and lines given new data * ***/ Timeline.update = function(elem, props) { var self = this; var domain = self.getDomain(props); var scales = self.scales(elem, props, domain); self.drawPoints(elem, props, scales); }; /*** * * Use the range of values in the x,y attributes * of the incoming data to identify the plot domain * ***/ Timeline.getDomain = function(props) { var domain = {}; domain.x = props.xDomain || d3.extent(props.data, function(d) { return dx; }); domain.y = props.yDomain || d3.extent(props.data, function(d) { return dy; }); return domain; }; /*** * * Compute the chart scales * ***/ Timeline.scales = function(elem, props, domain) { if (!domain) { return null; } var width = props.width - props.marginRight - props.marginLeft; var height = props.height - props.marginTop - props.marginBottom; var x = d3.scale.linear() .range([0, width]) .domain(domain.x); var y = d3.scale.linear() .range([height, 0]) .domain(domain.y); return {x: x, y: y}; }; /*** * * Create the chart axes * ***/ Timeline.axes = function(props, scales) { var xAxis = d3.svg.axis() .scale(scales.x) .orient("bottom") .ticks(props.xTicks) .tickFormat(d3.format("d")); var yAxis = d3.svg.axis() .scale(scales.y) .orient("left") .ticks(props.yTicks); return { xAxis: xAxis, yAxis: yAxis } }; /*** * * Use the general update pattern to draw the points * ***/ Timeline.drawPoints = function(elem, props, scales, prevScales, dispatcher) { var g = d3.select(elem).selectAll('.point-container'); var color = d3.scale.category10(); // add images var image = g.selectAll('.image') .data(props.data) image.enter() .append("pattern") .attr("id", function(d) {return d.id}) .attr("class", "svg-image") .attr("x", "0") .attr("y", "0") .attr("height", "70px") .attr("width", "70px") .append("image") .attr("x", "0") .attr("y", "0") .attr("height", "70px") .attr("width", "70px") .attr("xlink:href", function(d) {return d.image}) var point = g.selectAll('.point') .data(props.data); // enter point.enter() .append("circle") .attr("class", "point") .on('mouseover', function(d) { d3.select(elem).selectAll(".point").classed("active", false); d3.select(this).classed("active", true); if (props.onMouseover) { props.onMouseover(d) }; }) .on('mouseout', function(d) { if (props.onMouseout) { props.onMouseout(d) }; }) // enter and update point.transition() .duration(1000) .attr("cx", function(d) { return scales.x(dx); }) .attr("cy", function(d) { return scales.y(dy); }) .attr("r", 30) .style("stroke", function(d) { if (props.pointStroke) { return d.color = props.pointStroke; } else { return d.color = color(d.key); } }) .style("fill", function(d) { if (d.image) { return ("url(#" + d.id + ")"); } if (props.pointFill) { return d.color = props.pointFill; } else { return d.color = color(d.key); } }); // exit point.exit() .remove(); // update the axes var axes = this.axes(props, scales); d3.select(elem).selectAll('gxaxis') .transition() .duration(1000) .call(axes.xAxis); d3.select(elem).selectAll('gyaxis') .transition() .duration(1000) .call(axes.yAxis); }; $(document).ready(function() { Timeline.create(elem, props); })
var svg = d3.select("body") .append("svg") .style("width", 200) .style("height", 100)