I'm using d3 behavior api to implement some drag and drop functionality on my chart. There're some circles on the chart, what I want to do is make the circles able to move around when user is dragging them.
But I don't know how to get the reference of the circle which is being dragged by user.
In below code, where and how to get the reference of the selection and the current mouse position?
var drag = d3.behavior.drag()
.on("dragstart", function(){
//do some drag start stuff...
console.log('drag start');
})
.on("drag", function(){
//hey we're dragging, let's update some stuff
})
.on("dragend", function(){
//we're done, end some stuff
console.log('drag end');
});
Somebody please help!
You get the current selection from
d3.selection(this)
If you want to get the current mouse position, use this code
d3.mouse(this)
That returns an array, where [0] returns the x position of the mouse, and [1] returns the y position.
Related
Problem Solved == use d3.drag() instead of d3.behaviour.drag() and use d3-drag.v1.min.js
I have set up a SVG chess board with D3js using for loop to go through each row and each column. I used unicode for chess pieces so each chess pieces is a svg element.
I am trying to drag chess pieces with drag behaviour of D3js but not possible.
All chess pieces have class "draggable". So I created the drag and attached it to all elements with class "draggable"
var drag = d3.behavior.drag()
.origin(function() {
var t = d3.select(this);
return {x: t.attr("x"), y: t.attr("y")};
})
.on("dragstart", function() {
d3.event.sourceEvent.stopPropagation(); // silence other listeners
})
.on("drag", function(d,i) {
d3.select(this)
.attr("x", d3.event.x)
.attr("y", d3.event.y);
});
d3.selectAll(".draggable").call(drag);
My full code is here http://codepen.io/linhnt1516/pen/ZeGoNj?editors=0011
Also, I have tried to use the same drag function with and svg elements in other examples. Check out this code pen http://codepen.io/linhnt1516/pen/VpvobE?editors=0011 and drag the text and the box.
I have been looking through tons of drag examples of D3js but none of them works with the chess piece case.
Anyone has any solution or idea where things may go wrong here.
I haven't fully understand the differences between D3 v4 and D3 v3 drag behaviour or what is the actual problem with behaviour.drag()
Before I used D3 v3 and set up
var drag = d3.behaviour.drag()
This doesn't work as described in the question.
However I found a support d3 script which is d3-drag.v1.min.js
<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
So when I added this one and set up
var drag = d3.drag()
The detailed code of drag is the same as above, just different initialization syntax. The drag functionality now works correctly. If anyone knows why .behaviour.drag() doesn't work and what is the actual differences between my old code and the new working one, please enlighten me.
D3 version 4.2.2
I have a chart where I want the user to be able to keep zooming in with brush selections. I want to clear or reset my brush within the end event so that the user does not see the old brush.
Current TypeScript code:
let brushGroup = this.svg.append('g')
.attr('class', 'brush');
let b = brushX()
.on('start', () => {
console.log('start brush');
brushGroup.style('opacity', 100);
})
.on('end', () => {
console.log('end brush', event.selection);
// remove and display none destroy the brush, so use opacity
brushGroup.style('opacity', 0);
this.updateDateRange(this.xScale.invert(event.selection[0]),
this.xScale.invert(event.selection[1]));
});
brushGroup.call(b);
console.log(brushGroup);
display: none prevents future brush start events
brushGroup.remove() also destroys the brush
opacity works, but the brush is still there (mouse cursor changes on hover)
So what is the correct way to clear or reset the brush?
Should I just move it to 0,0?
Should I destroy the old brush and create a new one every time?
selection.call(brush.move, null);
https://github.com/d3/d3-brush/issues/10
I am probably having some kind of brain damage atm because something like this should be trivial.
I got a bunch of SVG circles rendered manually (via React). I am then attaching d3 drag behavior to all of them. The drag behavior is applied, and the drag function is being executed, but when I drag one of these circles I am not able to respond accordingly because I do not know which one of them was moved. Where can I get the ID of dragged element?
I have checked a few other questions and found just some crazy filter solution... that cannot be it.
I have also peeked at docs and found the subject property.. however that one is null everywhere I tried it.
My code:
componentWillUpdate() {
let nodes = d3.selectAll("circle");
const dragFn = (d,i) => {
d3.event.sourceEvent.stopPropagation();
this.props.onNodeDrag(I_NEED_AN_ID_HERE);
}
const dragBehavior = d3.behavior.drag();
dragBehavior.on('drag', dragFn);
dragBehavior.on('dragstart', () => {
d3.event.sourceEvent.stopPropagation();
});
nodes.call(dragBehavior);
}
I don't know what your "this" is inside the function but in plain js you can get any attribute of the html element with:
d3.select(this).attr("id"); //or class etc.
or if it's wrapped
d3.select(this).select("circle").attr("id");
Here's an example: http://jsfiddle.net/a2QpA/343/
I want to remove stream style (state ? ("Stream", "Stacked" and "Expanded")) on stacked area chart and use this code :
d3.selectAll("g.nv-series")
.filter(function() {
return d3.select(this).select("text").text() == "Stream";
})
.remove();
But it works only the first time.
I tryed to handle events on chart because i want to refresh rendering of chart but it didn't work for the styles click. It works only for the legend click.
chart.legend.dispatch.on('legendClick', function(e){
console.log('legend was clicked', 'no namespace.');
});
How i can i handle click on style event ?
setter
chart.style('stream');
getter
chart.dispatch.on('stateChange', function(e) {
console.log(e); //e.style holds the current style
});
List of available styles can be found here https://github.com/novus/nvd3/blob/master/src/models/stackedArea.js#L299-L318
I also had hard time with this issue so I hope this would help you.
Cheers!
I'm working on some bar charts and need to update the chart values. The only way I've found to do this is to redraw the whole thing. Isn't there a way to simple update the bars? And if so what I'm really hoping to do is animate that change. Any suggestions?
http://jsfiddle.net/circlecube/MVwwq/
Here's what you want (updated Fiddle).
You were on the right track for creating a new bar chart. The only issue is, you don't want to "display" that bar chart, but you want to use its bars for animation. While this does generate a new graph which we later throw away (using remove()), it seems to be Raphael best practice.
function b_animate(){
//First, create a new bar chart
var c2 = bars.g.barchart(200, 0, 300, 400, [bdata], {stacked: false, colors:["#999","#333","#666"]});
//Then for each bar in our chart (c), animate to our new chart's path (c2)
$.each(c.bars[0], function(k, v) {
v.animate({ path: c2.bars[0][k].attr("path") }, 200);
v.value[0] = bdata[k][0];
});
//Now remove the new chart
c2.remove();
}
This is not complete, as we haven't animated the legends to match the new chart, but this technique applied to the labels should get you there. Basically, we need to re-map the hovers to show new labels (and remove the old labels).
Hopefully, this should work exactly like you hoped. Let me know if you have any issues. Enjoy!
I had to adapt the above code to get this to work with Raphaƫl 2.1.0 and g.Raphael 0.51 and JQuery 1.9.1:
function b_animate(){
var c2 = bars.barchart(10, 10, 500, 450, bdata, { colors:custom_colors});
$.each(c.bars, function(k, v) {
v.animate({ path: c2.bars[k][0].attr("path") }, 500);
v[0].value = bdata[k][0];
});
c2.remove();}
Hope this helps!