0

The following code is a D3 snipped put inside a VueJS instance. The snippet creates circles and lets you drag them.

new Vue({
  el: 'body',

  data: {
    x: '',
    y: ''
  },

  computed: {
    pos: function () {
      function click() {

        var point = d3.mouse(this),
          p = { x: point[0], y: point[1] }

        svg.append('circle')
          .attr('transform', 'translate(' + p.x + ',' + p.y + ')')
          .attr('r', '5')
          .attr('class', 'dot')
          .style('cursor', 'pointer')
          .call(drag)

        var dots = d3.selectAll(".dot")

        var svg = d3.select('body').append('svg')
          .attr('width', 400)
          .attr('height', 400)
          .on('click', click)

        var drag = d3.behavior.drag()
          .on('drag', dragmove)

        function dragmove(d) {
          var x = d3.event.x
          var y = d3.event.y
          d3.select(this).attr('transform', 'translate(' + x + ',' + y + ')')
          this.x = x
          console.log('x:', this.x)
      }

    console.log('x:', this.x)
    }
  },

  ready: function () {
  }
})

Now, I'm trying to get position x of the dragged circles. The first console.log('x:', this.x) logs the position: x: 190. But the second long, the one outside of the dragmove() function doesn't log anything.

How can I make the second console.log log the value of this.x?

Here's the JSFiddle: https://jsfiddle.net/alexcheninfo/unejge3k/1

alexchenco
  • 53,565
  • 76
  • 241
  • 413

1 Answers1

1

If you want to access the x outside of the dragmove function the nyou have to define the x in the outer scope.

var x, y;

function dragmove(d) {
          x = d3.event.x
          y = d3.event.y
          d3.select(this).attr('transform', 'translate(' + x + ',' + y + ')')
          this.x = x
          console.log('x:', this.x)
      }
console.log('x:', this.x)

But I really really don't recommend this method.

Since you want the translation of the circle, you can do it like this.

var c = svg.append('circle')
          .attr('transform', 'translate(' + p.x + ',' + p.y + ')')
          .attr('r', '5')
          .attr('class', 'dot')
          .style('cursor', 'pointer')
          .call(drag)
var trans = d3.transform(c.attr('transform')).transalte;

var tx = trans[0];
var ty = trans[1];

Hope this will help you.

Fawzan
  • 4,738
  • 8
  • 41
  • 85
  • Thanks for the answer. I tried your code but I'm getting: `Uncaught TypeError: Cannot read property '0' of undefined`. Maybe I placed the code in the wrong place? https://jsfiddle.net/alexcheninfo/unejge3k/2/ – alexchenco Jan 19 '16 at 03:10
  • Yes, it was in the wrong place. Check this snippet. https://jsfiddle.net/unejge3k/3/ – Fawzan Jan 19 '16 at 03:15
  • Oh, I see. But now there's no way to append circles. – alexchenco Jan 19 '16 at 03:21
  • If you can tell the exact requirement, May be I can help – Fawzan Jan 19 '16 at 03:22
  • Thanks. I want to be able to add circles and drag them around (the behavior of my original fiddle), and then get the position of `x` and `y` of the circle I'm dragging and store them in `this.x` and `this.y` (these last two are defined inside `data : { }`. – alexchenco Jan 19 '16 at 03:26
  • you want to update `this.x` , `this.y` when you drag the circle? – Fawzan Jan 19 '16 at 03:29
  • Yes, that's it, exactly. – alexchenco Jan 19 '16 at 03:44
  • when you say `this.x` do you mean `x` in the `data = { x : '', ..}` ? – Fawzan Jan 19 '16 at 03:46
  • Yes, I mean that this. That's the part of the code belonging to http://vuejs.org/. – alexchenco Jan 19 '16 at 03:51
  • Why don't you put `data.x = x; data.y = y;` inside the `dragmove()` function? – Fawzan Jan 19 '16 at 03:53
  • Hey, it worked. Thanks! But a new `svg` tag is created each time I drag a circle. Do you know why? JSFiddle: https://jsfiddle.net/alexcheninfo/unejge3k/6/ – alexchenco Jan 19 '16 at 04:09
  • yes, That is because the `click event is triggered when you start the drag. – Fawzan Jan 19 '16 at 04:10
  • You can either use this way http://stackoverflow.com/questions/19931307/d3-differentiate-between-click-and-drag-for-an-element-which-has-a-drag-behavior or you can simply check wether an `SVG` exists before you create it. `if(!d3.select('svg').empty()){d3.select('body').append('svg')....} – Fawzan Jan 19 '16 at 04:12