AlexayEugine
AlexayEugine

Reputation: 43

How to catch svg element hover event in vue js method and how to combine native javascript hover event to vue method

I have developed vuejs + d3.js + jit library project earlier. Nowadays, I need to attach hover function to d3.js svg element to show popup dialog of hovered element's information. I tried many times following some stackoverflow instructions. But all of them are not suitable for my one. Here is my snippet code.

allNodes.append("circle").attr("@mouseover", "console.log('test');");
allNodes.append("circle").attr(":v-on:mouseover", "console.log('dfdfd');");

The above code doesn't work in anyway because the d3.js element is rendered when vue component is mounted and the vue template parser can't compile the v-on, @mouseover attribute.

But following code works fine.

allNodes.append("circle").attr("onmouseover", "console.log('test');");

So I thought that I would attach native javascript function to vue method to show popup dialog.

But I'm not sure how to config all projects structure and where to place the native function in my project.

Please help me.

Thanks.

Upvotes: 4

Views: 2912

Answers (1)

thibautg
thibautg

Reputation: 2042

You can use .on("mouseover", this.vueMethod) on your d3 selection where this.vueMethod is defined inside the Vue component's methods object.

new Vue({
  el: "#app",
  data: {
    todos: [
      { text: "Learn JavaScript", done: false },
      { text: "Learn Vue", done: false },
      { text: "Play around in JSFiddle", done: true },
      { text: "Build something awesome", done: true }
    ],
    todoHovered: "hover a circle"
  },
  mounted() {
    const svg = d3.select(this.$refs.chart)
      .append("svg")
        .attr("width", 400)
        .attr("height", 100);
    const circles = svg.selectAll("circle")
      .data(this.todos).enter()
      .append("circle")
        .attr("cx", 10)
        .attr("cy", (d,i) => 10 + i * 15)
        .attr("r", 5)
        .style("fill", d => d.done ? "green" : "red");
    circles.on("mouseover", this.showMessage);
    circles.on("mouseout", (e) => d3.select(e.currentTarget).attr("r", 5));
  },
  methods: {
    showMessage(e, d) {
      d3.select(e.currentTarget).attr("r", 8);
      this.todoHovered = `${d.text} is ${d.done ? 'done' : 'not done'}`;
    }
  }
})
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}
<script src="https://d3js.org/d3.v6.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>

<div id="app">
  <div ref="chart">
  </div>
  <p>
    Message: {{ todoHovered }}
  </p>
</div>

Upvotes: 5

Related Questions