Layered Circles

63 views
Skip to first unread message

Joe Keohan

unread,
May 1, 2015, 1:58:52 PM5/1/15
to d3...@googlegroups.com
I've created two circles, one layered on the other.  I've configured a mouseover event on the outer circle to increase radius as well as decrease opacity to reveal the inner circle.   I'm now trying to also animate the inner circle to expand it's radius in the same mouseover event but am unable to figure out to define that specific circle.  

I've tried using the following:

var allCircles = d3.selectAll(".innerCircle")

allCircles.filter...
allCircles.each...
allCircles.forEach 

Although these functions return the d value, which is an array of 3 circles, I'm unable to dig any deeper like...d.cx or d["cx"].  I thought if I could filter the circles based on the cx value to d3.select(this).cy.animVal.value then I could get that specific inner circle but digging into d give me nothing but errors or empty arrays.

here is a working jsfiddle of the issue...http://jsfiddle.net/jkeohan/rox5yL88/73/

Ive created another solution by creating the inner circle on mouseover but would like to know if it's possible to do it the other way...

Joe

Ben Lyall

unread,
May 2, 2015, 7:31:24 AM5/2/15
to d3...@googlegroups.com
Did you try:

d3.select(this).attr("cx");

to get the cx value?

Joe Keohan

unread,
May 2, 2015, 10:38:55 AM5/2/15
to d3...@googlegroups.com
Thanks for the tip...but I'm still not sure how to make that work in this context...I did do some some research and found a good stackoverflow thread that uses .each

So i'm now able to reveal all the items but now need to someone query the cx value so I can compare it against the outer circle.  

allCircles.each( function(d,i) { console.log(d, allCircles[0][i] ) })

50 <circle cy=​"150" cx=​"50" r=​"40" class=​"innerCircle" style=​"fill:​ rgb(0, 0, 255)​;​">​</circle>​
100 <circle cy=​"150" cx=​"100" r=​"40" class=​"innerCircle" style=​"fill:​ rgb(0, 0, 255)​;​">​</circle>​

I tried doing the following but it erred out..

allCircles.each( function(d,i) { console.log(d, allCircles[0][i].attr("cx") ) })

Ben Lyall

unread,
May 3, 2015, 12:11:36 AM5/3/15
to d3...@googlegroups.com
.attr(...) works on a selection.  Try:

allCircles.each(function(d, i) { console.log(d3.select(this).attr("cx"); });

BTW: the information regarding d3.select(this) is at the bottom of the documentation for the .each(...) method.  See https://github.com/mbostock/d3/wiki/Selections#each
Message has been deleted

cool...@y7mail.com

unread,
May 4, 2015, 2:20:55 AM5/4/15
to d3...@googlegroups.com
Actually, they have a common reference to the data point so you can filter on that...
function mouseover(d) {
	var selection = d3.select(this),
	    sellectionInside = d3.selectAll(".innerCircle").filter(function (d) {
		   return d === selection.datum()
	    })
		
	selection.transition().attr("r", 20).style("opacity", .3)
	 .style("fill", "white")
	 .style("stroke", "blue")
	 .style("stroke-width", 3)
	.each("end.inside", function () {
		sellectionInside.transition().attr("r", 20)
	})
}
 
function mouseout(d) {
	var selection = d3.select(this),
	    sellectionInside = d3.selectAll(".innerCircle").filter(function (d) {
		return d === selection.datum()
	    })
	selection.transition()
		.attr("r", 10)
		.style("opacity", 1)
		.style("fill", "green")
		.style("stroke", "green")
		.style("stroke-width", 1)
	.each("end.inside", function () {
		sellectionInside.transition().attr("r", 5)
	})



On Saturday, May 2, 2015 at 3:58:52 AM UTC+10, Joe Keohan wrote:
Message has been deleted

cool...@y7mail.com

unread,
May 4, 2015, 5:47:33 AM5/4/15
to d3...@googlegroups.com
Here is a working example

Joe Keohan

unread,
Jun 12, 2015, 1:57:11 PM6/12/15
to d3...@googlegroups.com
Cool Blue,

Just reviewed you code again on jsfiddle and was curious how selection is being used in the mouseout function.   

Both the inner and outer vars are calling it and from what I've read about the .call function it's possible to execute another function .call(_trans) or pass variables to a function trans.call(params)but how does the _trans function know how to evaluate the selection parameter.    If selection is removed from the params, the circle still transitions but the outer circle has a stroke of blue and stroke-width of blue.  Also where in the transition does the circle know to once again use green as it's fill? 

function mouseout(d) {
var outer = d3.select(this),
inner = getInner(".innerCircle", outer)

console.log("mouseout\t" + outer.datum())

inner.transition()
.call(_trans, "blue", 1)
.attr("r", 5)
outer.transition()
.call(_trans, "green", 1)
.attr("r", 10)
.attr("fill-opacity", 1)
.delay(250)
function _trans(selection,s, w) {
trans.call(this, 1, 1, s, w, "mouseout")
}
}
Joe

Drew Winget

unread,
Jun 12, 2015, 5:41:48 PM6/12/15
to d3...@googlegroups.com
I'm getting a mixed content error for the jsfiddle example in Chrome. Works in safari though.

--
You received this message because you are subscribed to the Google Groups "d3-js" group.
To unsubscribe from this group and stop receiving emails from it, send an email to d3-js+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Message has been deleted

Cool Blue

unread,
Jun 13, 2015, 5:52:19 PM6/13/15
to d3...@googlegroups.com
Hi Joe, first of all, bear in mind that I'm using two different `call` methods: one on the d3.transition object and the other being the native, JavaScript Function.prototype.call. Of course they are not the same thing.

As you can see in the d3 API Wiki, _trans is a callback function and "blue", 1 are additional arguments accepted by .call which are passed on to the callback after the selection argument (in this case the transition) . transition.call also sets the this context to the transition, which is actualy redundant.

so, in the mouseout function for example...
   outer.transition()
     
.call(_trans, "green", 1)

is equivalent to ...
   _trans.call(inner.transition, "green", 1)

and that brings us to Function.call...
function _trans(selection,s, w) {
   trans
.call(this, 1, 1, s, w, "mouseout")

   console
.log(this === outer.selection) // true
}

Here, this === selection, selection is just a placeholder in the argument list  and it's easier (and more idiomatic) to use `this` instead of `selection`.  trans.call sets the this context to whatever it currently is (in this case inner.transition) and invokes trans passing the rest of the arguments.

In trans...
function trans(o, fo, s, w, name) {
 
this
 
.style("opacity", o)
 
.style("fill-opacity", fo)
 
.style("stroke", s)
 
.style("stroke-width", w)
 
.ease("sin")
 
.duration(300)
 
.each("interrupt", function() {console.log(name + "\tinterrupted*************")})
}
`this` is therefore inner.transition.

In answer to your second question, the fill is never changed from green but the fill-opacity is set to zero in mouseover here...
trans.call(this, 0.3, 0, "blue", w, "mouseover")
and back to one in mouseout here...
trans.call(this, 1, 1, s, w, "mouseout")


Cool Blue

unread,
Jun 13, 2015, 6:01:01 PM6/13/15
to d3...@googlegroups.com
Hi Drew, which version of Chrome are you using? Works fine for me on 43.0.2357.124 m 

Cool Blue

unread,
Jun 18, 2015, 4:16:14 AM6/18/15
to d3...@googlegroups.com


On Saturday, June 13, 2015 at 7:41:48 AM UTC+10, Drew Winget wrote:
I'm getting a mixed content error for the jsfiddle example in Chrome. Works in safari though.




Here is an updated version that should alleviate the mixed content error.  The default d3 cdn in jsfiddle is served over http, I changed to an external resource served over https.  This has fixed the problem when I encountered it on other fiddles.

Reply all
Reply to author
Forward
0 new messages