Why can I create circle but not ellipses in D3? - javascript

I have the following code creating a circle:
SVGTTest.selectAll("circle")
.data(dataset)
.enter().append("circle")
.attr("cx", xScale(300))
.attr("cy", yScale(10))
.attr("r", xScale(100));
When I try to create an ellipse instead of a circle I try the following code, but nothing happens. Any help would be appretiated..
SVGTTest.selectAll("ellipse")
.data(dataset)
.enter().append("ellipse")
.attr("cx", yScale(300))
.attr("cy", yScale(10))
.attr("rx", xScale(100))
.attr("ry", 100);

Related

d3 svg clipping mask on circle arc

Can someone explain to me how to use clipping mask on the circle arc.
To explain what I'm doing. I have a circle and on this circle I add an arc that can be moved around. Now I would like to add like a linear gradient to this circle from left to right. But the gradient should only be seen on the arc, not the circle itself. Also I found one solution here https://www.freshconsulting.com/d3-js-gradients-the-easy-way/ but it's not what I want to do as my gradient should always be the same, but only the arc should display it. For example like this:
This is how you would draw a masked circle with a gradient fill with d3.
const svg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 500)
const defs = svg.append("defs")
const gradient = defs.append("linearGradient")
.attr("id", "exampleGradient")
gradient.append("stop")
.attr("offset", "10%")
.attr("stop-color", "white")
gradient.append("stop")
.attr("offset", "100%")
.attr("stop-color", "red")
const mask = defs.append("mask")
.attr("id", "donutMask")
mask.append("circle")
.attr("cx", 250)
.attr("cy", 250)
.attr("r", 150)
.attr("fill", "white")
mask.append("circle")
.attr("cx", 250)
.attr("cy", 250)
.attr("r", 120)
const circle = svg.append("circle")
.attr("r", 149)
.attr("cx", 250)
.attr("cy", 250)
.attr("stroke", "black")
.attr("mask", "url(#donutMask)")
.attr("fill", "url(#exampleGradient)")
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

On button click open a new window and draw multiple large circles with D3

This question has been answered before here: On button click open a new window and draw a large circle with D3
In the solution given by Mark:
http://jsfiddle.net/aj3g5tqg/38/
sampleSVG.append('svg')
.attr('width', 500)
.attr('height', 500) //<-- give the SVG some size
.append("circle")
.style("stroke", "gray")
.style("fill", "red")
.attr("r", 200)
.attr("cx", 250)
.attr("cy", 250)
...
I'm not able to understand how to append multiple circles to the same svg, say in a for loop.
How to do that? Thanks in advance!
Just extend the part that appends a single circle to append inside of the loop. Cast the result of the first svg append to a variable, then iterate and append to it:
var mySVG = sampleSVG.append('svg')
.attr('width', 500)
.attr('height', 500); //<-- give the SVG some size
for (var i=0; i < 250; i = i+10){
mySVG.append("circle")
.style("stroke", "gray")
.style("fill", "red")
.attr("r", 200)
.attr("cx", i)
.attr("cy", i)
}

d3.js compute path booleans between ellipses and circles

I need to split multiple overlapping ellipses in an SVG by all path intersections. The purpose of this is for a venn diagram. Ben Fredrickson's venn diagram gets you part of the way there by computing intersections, but does not compute all possible intersections between an arbitrary number of ellipses. His methods do not compute convex (difference) areas, only intersections, and do not handle ellipses.
I've created a non-proportional, symmetric venn diagram layout in d3 and would like to generate paths for all the possible regions, not just intersections.
If there is not a javascript method available, if someone could help clarify the math that would also be acceptable.
My approach so far looks like this:
find intersection points of ellipse circumfrence paths (how?)
generate arc segments between those points using ellipse radii
join arc segments to new paths
So in the following fiddle, I would need to split these ellipses by every path intersection, generating 18 separate paths.
fiddle here
var width = 450,
height = 400
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("svg:ellipse")
.attr("cx", 100)
.attr("cy", 100)
.attr("rx", 50)
.attr("ry",100)
.style("fill", 'rgba(128,255,128,0.4)')
.style("stroke", "#777")
.style("stroke-width", '1px');
svg.append("svg:ellipse")
.attr("cx", 150)
.attr("cy", 100)
.attr("rx", 50)
.attr("ry",100)
.style("fill", 'rgba(255,128,128,0.4)')
.style("stroke", "#777")
.style("stroke-width", '1px');
svg.append("svg:ellipse")
.attr("cx", 150)
.attr("cy", 100)
.attr("rx", 100)
.attr("ry",50)
.style("fill", 'rgba(128,128,255,0.4)')
.style("stroke", "#777")
.style("stroke-width", '1px');
svg.append("svg:ellipse")
.attr("cx", 190)
.attr("cy", 130)
.attr("rx", 100)
.attr("ry",50)
.style("fill", 'rgba(255,128,255,0.4)')
.style("stroke", "#777")
.style("stroke-width", '1px');

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>

How do I use enter() correctly in D3.js?

I have some code that create a bunch of circles, updates those circles, removes some of the circles, and lastly I'd like to find out how to use the enter() correctly to add more circles to my current ones.
This is my code for creating circles when there are none:
var circle = SVGbody
.selectAll("circle")
.data(graphDataY/*, function(d){return d;}*/);
circle.enter()
.append("circle");
circle
.attr("cx",xScale(0))
.attr("cy", yScale(minAxisY))
.attr("r",4)
.style('opacity', 0)
.style("fill", colorCircles())
.transition()
.duration(1000)
.attr("cx", function(d, i){ return xScale(graphDataX[i]);})
//.attr("cy", function (d, i){ return yScale(i); })
.style('opacity', 0.8)
.transition()
.duration(1000)
.attr("cy", function(d){return yScale(parseFloat(d));} );
I use the following code to update my circles and remove the ones that aren't being used (sometimes that's the case):
var circle = SVGbody
.selectAll("circle")
.data(graphDataY);
circle
.style("fill", colorCircles())
.transition().duration(1000)
.attr("cx", function(d, i){ return xScale(graphDataX[i]);})
.attr("cy",function(d){return yScale(parseFloat(d));});
circle.exit()
.style("opacity", 1)
.transition()
.duration(300)
.style("opacity", 0)
.remove();
And when lastly, let's assume the last data i used had a length of 100, that means I currently have 100 circles displayed. If I used a new dataset with 120 of length, I use my update code to move the existing circle ( except for the exit().remove() ), and then I try to use the following to "create" the remaining circles out of the remaining unbound data (which in this case would be 20 circles remaining):
circle.enter().append("circle")
.attr("cx", function(d, i){ return xScale(graphDataX[i]);})
.attr("cy",function(d){return yScale(parseFloat(d));})
.style("opacity", 0)
.transition()
.duration(300)
.style("opacity", 1)

Categories

Resources