Adding image/icon instead of svg shape in d3 - javascript

I could locate rectangle using the following.
I want to replace these rectangles with image/icon(jpg/url)
for(var i=0; i< tempdata.length; i++)
{
var name = "rect"+i;
d3.select("#floor svg").selectAll('rect')
.data(tempdata).enter()
.append("svg:rect")
.attr("stroke", "black")
.attr("fill", (d,i)=>tempdata[i].SENSOR_COLOR)
//.attr("r", 5)
.attr("width", 20)
.attr("height", 20)
.attr("x", (d,i)=>tempdata[i].CX)
.attr("y", (d,i)=>tempdata[i].CY)
.attr("idCircle",(d,i)=>name)
}

First of all: don't use for loops to retrieve data in D3. D3 already provides all you need to bind and retrieve your data. Indeed, there are several situations where it's a good idea to use a for loop, but this is not one of them.
Regarding your question: instead of append("rect"), you have to use append("image"):
var images = svg.selectAll(".images")
.data(data)
.enter()
.append("image");
In this demo snippet, I set the url of the images in the data array, using a key conveniently named url. Then, you have to append them using:
.attr("xlink:href", function(d){return d.url})
Here is the demo snippet, using favicons:
var svg = d3.select("body")
.append("svg")
.attr("width", 200)
.attr("height", 200);
var data = [{url:"https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2009/02/amazon.gif", x:20, y:40},
{url:"https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2009/02/skype.gif", x:90, y:110},
{url: "https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2009/02/espn.gif", x:150, y:150},
{url: "https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2009/02/twitter.gif", x:180, y:50}];
var images = svg.selectAll(".images")
.data(data)
.enter()
.append("image");
images.attr("xlink:href", function(d){return d.url})
.attr("x", function(d){return d.x})
.attr("y", function(d){return d.y})
.attr("width", 16)
.attr("height", 16);
<script src="https://d3js.org/d3.v4.min.js"></script>

Related

d3 mouseover event wont fire if I append svg to a div

I'm trying to get a simple mouseover to work on some rectangles in d3. If I append the SVG to "body" everything works just fine (first line of code). If I change the select to ".chart1" instead of "body" the mouseovers don't work. Has anyone seen this before?
var chart = d3.select(".chart1").append("svg")
.attr("width", 250)
.attr("height", 50);
data = ["a", "b", "c",]
for(var i = 0; i < data.length; i++){
var rect = chart.append("rect")
.attr("x", 20*i)
.attr("y", 10)
.attr("width", 15)
.attr("height", 15)
chart.selectAll('rect')
.on("mouseover", function() {
d3.select(this)
.attr("opacity", .5)
})
.on("mouseout", function() {
d3.select(this)
.attr("opacity", 1)
});
jsfiddle: https://jsfiddle.net/jasonleehodges/um5f5ysv/
The problem is not because you are appending svg to body or div with class .chart1
The problem of mouseover not working is in here.
var chart = d3.select(".chart1").append("svg")
.attr("width", 250)
.attr("height", 50)
//.style("pointer-events", "none");//WHY DISABLE MOUSE EVENT ON SVG
Fix would be to remove .style("pointer-events", "none");
and it will work on all the cases without any anomaly.
Working code here
On another note you should not use a for loop, well that's not the d3 way(as put by #Gerardo Furtado).
so your code with for:
for(var i = 0; i < data.length; i++){
var rect = chart.append("rect")
.attr("x", 20*i)
.attr("y", 10)
.attr("width", 15)
.attr("height", 15)
instead should be
var rect = chart.selectAll("rect").data(data).enter().append("rect")
.attr("x", function(d,i){return 20*i})
.attr("y", 10)
.attr("width", 15)
.attr("height", 15)
.attr("fill", "#cc004c")
.attr("title","NBC")
.attr("data-toggle","tooltip")
working code here

Getting the value of SVG attributes in D3.js

I am new to D3.js and am trying to build rectangles that represent all nodes from an XML file. So far so good but I want interactivity with each of the rectangles I draw and to be able to capture the nodes that have been touched for further processing. So let's say I click on a rectangle, I can make it react by doing an onclick event (like increasing the font size) but I can't seem to retrieve some of the info. I'd like to create an array with the text of each item that was clicked on.
Here's the code for one instance of the rectangle.
d3.select("#chart")
.append("svg")
.attr("width", 600)
.attr("height", 2000)
.style("background", "#93A1A1")
d3.select("svg")
.append("rect").attr("x", 50)
.attr("y", 25)
.attr("height", 20)
.attr("width", 200)
.attr("title", "resourceDef")
.style("fill", "#CB4B19")
d3.select("svg")
.append("text")
.attr("x", 55)
.attr("y", 37)
.attr("font-size", 11)
.attr("font-family", "sans-serif")
.text("resourceDef")
.on("mouseover", function(d) {
tempText = this.text;
alert(tempText);
d3.select(this)
.attr("font-size", 15)})
.on("mouseout", function(d) {
d3.select(this)
.attr("font-size", 11)})
I can grab style info by using but not the title and I can't find that info anywhere. Thanks for your help, I know it's a long question with probably a simple answer.
You can attach a mouse over event on the rectangle DOM by doing something like this:
d3.select("svg")
.append("rect").attr("x", 50)
.attr("y", 25)
.attr("height", 20)
.attr("width", 200)
.attr("title", "resourceDef")
.style("fill", "#CB4B19")
.on("click", function (d) {
var t = d3.select(this).attr("title");
//pushing the title into the array.
clickedTitles.push(t);
console.log(t);
});
You can get the attribute of a DOM(in your case tite) by doing something like this:
.on("click", function (d) {
var t = d3.select(this).attr("title");
clickedTitles.push(t);
console.log(t)
})
You can store the clicked rectangles title in an array like this:
//create an array
var clickedTitles = [];
//in your click function push the title into the array
clickedTitles.push(t);
//use the clickedTitles where ever you need in the code
Full code is here.

D3.js Circles on Map

I am very new to coding and am trying to learn D3. I have map of France which I am able to make appear in the browser. However, I am trying to display circles on the map based on a csv file. I am not sure what I am doing wrong with the function... Any help/direction would be great.
Here is a Cloud9 of the code and files... https://ide.c9.io/santiallende/d3-map-bubbles-france
I won't sugarcoat, your code's a mess.
You define and append 4 different svg elements to the body and you create 3 different projections. All of it is unnecessary. Just go through and remove all the redundancies.
//Width and height
var w = 800;
var h = 350;
var canvas = d3.select("body").append("svg")
.attr("width", w)
.attr("height", h)
d3.json("france.json", function(data) {
var group = canvas.selectAll("g")
.data(data.features)
.enter()
.append("g")
//Define map projection
var projection = d3.geo.mercator()
.translate([400, 1200])
.scale([1100]);
//Define path generator
var path = d3.geo.path()
.projection(projection);
var areas = group.append("path")
.attr("d", path)
.attr("class", "area")
.attr("fill", "steelblue");
//Load in cities data
d3.csv("wineregions.csv", function(data) {
canvas.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return projection([d.lon, d.lat])[0];
})
.attr("cy", function(d) {
return projection([d.lon, d.lat])[1];
})
.attr("r", 5)
.style("fill", "yellow")
.style("opacity", 0.75);
});
});
Fixed code here.

D3 fill shape with image using pattern

I'm trying to create a circular avatar with D3.js but I cannot get my image to show up in my circle. I'm using a svg pattern def to attempt to fill the circle with an image.
Can anyone tell me what I'm doing wrong below? Thank you.
var config = {
"avatar_size" : 48
}
var body = d3.select("body");
var svg = body.append("svg")
.attr("width", 500)
.attr("height", 500);
var defs = svg.append('svg:defs');
defs.append("svg:pattern")
.attr("id", "grump_avatar")
.attr("width", config.avatar_size)
.attr("height", config.avatar_size)
.attr("patternUnits", "userSpaceOnUse")
.append("svg:image")
.attr("xlink:href", 'images/avatars/avatar_grumpy.png')
.attr("width", config.avatar_size)
.attr("height", config.avatar_size)
.attr("x", 0)
.attr("y", 0);
var circle = svg.append("circle")
.attr("cx", config.avatar_size)
.attr("cy", config.avatar_size)
.attr("r", config.avatar_size)
.style("fill", "#fff")
.style("fill", "#grump_avatar");
"Fill" is a style property, you have to use CSS url() notation for the reference to the pattern element.
Once you fix that, you'll discover that you also have your sizes wrong -- unless your intention was to have four copies of the avatar tiled in the circle!
P.S. I would normally have left this just as a comment, and marked this for closure as a simple typo, but I wanted to try out Stack Snippets:
var config = {
"avatar_size" : 48
}
var body = d3.select("body");
var svg = body.append("svg")
.attr("width", 500)
.attr("height", 500);
var defs = svg.append('svg:defs');
defs.append("svg:pattern")
.attr("id", "grump_avatar")
.attr("width", config.avatar_size)
.attr("height", config.avatar_size)
.attr("patternUnits", "userSpaceOnUse")
.append("svg:image")
.attr("xlink:href", 'http://placekitten.com/g/48/48')
.attr("width", config.avatar_size)
.attr("height", config.avatar_size)
.attr("x", 0)
.attr("y", 0);
var circle = svg.append("circle")
.attr("cx", config.avatar_size/2)
.attr("cy", config.avatar_size/2)
.attr("r", config.avatar_size/2)
.style("fill", "#fff")
.style("fill", "url(#grump_avatar)");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

Fill rect with pattern

I am using d3.js for graph. at some point i have to show data with some special part of graph for example if the values is cross some boundary then show that part with filling pattern. for more clear is there in and image.
i get the rect part that cross the boundary but how can i fill it with this pattern?
any css or canvas tricks?
Note : this image is just an example not the real one
How about this:
Live Demo
JS
var svg = d3.select("body").append("svg");
svg
.append('defs')
.append('pattern')
.attr('id', 'diagonalHatch')
.attr('patternUnits', 'userSpaceOnUse')
.attr('width', 4)
.attr('height', 4)
.append('path')
.attr('d', 'M-1,1 l2,-2 M0,4 l4,-4 M3,5 l2,-2')
.attr('stroke', '#000000')
.attr('stroke-width', 1);
svg.append("rect")
.attr("x", 0)
.attr("width", 100)
.attr("height", 100)
.style("fill", 'yellow');
svg.append("rect")
.attr("x", 0)
.attr("width", 100)
.attr("height", 100)
.attr('fill', 'url(#diagonalHatch)');
Results
To change the color would be simple, just a conditional if statement. Here's an example i've used before:
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 3.5)
.style("fill", function(d) { // <== Add these
if (d.close >= 50) {return "red"} // <== Add these
else { return "black" } // <== Add these
;}) // <== Add these
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.close); });
To add a pattern would be a little more involved as you first have to add the defs element to your SVG and then add your pattern to it
//first create you SVG or select it
var svg = d3.select("#container").append("svg");
//then append the defs and the pattern
svg.append("defs").append("pattern")
.attr("width", 5)
.attr("height", 5);

Categories

Resources