d3.js D3 linkHorizontal()根据鼠标位置更新

v8wbuo2f  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(196)

我正在尝试用连接线实现拖放功能。连接线有一个起点([x,y]),当点击鼠标时会收集该点,还有一个目标点([x,y]),该点跟随鼠标位置,并在拖动元素时不断更新。项目使用Vue.JS和VUEX存储,并用于连接线D3.js(linkHorizontal方法https://bl.ocks.org/shivasj/b3fb218a556bc15e36ae3152d1c7ec25)。
在主组件中,我有一个插入SVG的div:

  1. <div id="svg_lines"></div>

在main.js文件中,我观察当前鼠标位置(targetPos),从VUEX存储中获取起始位置(sourcePos),并将其传递给connectTheDots(sourcePos,targetPos)。

  1. new Vue({
  2. router,
  3. store,
  4. render: (h) => h(App),
  5. async created() {
  6. window.document.addEventListener('dragover', (e) => {
  7. e = e || window.event;
  8. var dragX = e.pageX, dragY = e.pageY;
  9. store.commit('setConnMousePos', {"x": dragX, "y": dragY});
  10. let sourcePos = this.$store.getters.getConnStartPos;
  11. let targetPos = this.$store.getters.getConnMousePos;
  12. // draw the SVG line
  13. connectTheDots(sourcePos, targetPos);
  14. }, false)
  15. },
  16. }).$mount('#app');

connectTheDots()函数接收sourcePos和targetPos作为参数,并更新D3 linkHorizontal的目标位置。

  1. function connectTheDots(sourcePos, targetPos) {
  2. const offset = 2;
  3. const shapeCoords = [{
  4. source: [sourcePos.y + offset, sourcePos.x + offset],
  5. target: [targetPos.y + offset, targetPos.x + offset],
  6. }];
  7. let svg = d3.select('#svg_lines')
  8. .append('svg')
  9. .attr('class', 'test_svgs');
  10. let link = d3.linkHorizontal()
  11. .source((d) => [d.source[1], d.source[0]])
  12. .target((d) => [d.target[1], d.target[0]]);
  13. function render() {
  14. let path = svg.selectAll('path').data(shapeCoords)
  15. path.attr('d', function (d) {
  16. return link(d) + 'Z'
  17. })
  18. path.enter().append('svg:path').attr('d', function (d) {
  19. return link(d) + 'Z'
  20. })
  21. path.exit().remove()
  22. }
  23. render();
  24. }

我偷了/修改了这篇文章的代码How to update an svg path with d3.js,但无法让它正常工作。而不是更新路径,函数只是不断添加SVG。见附件图片:
Web app: Multiple SVGs are drawn
Console: Multiple SVGs are added to element
我错过了什么?

7hiiyaii

7hiiyaii1#

@BKalra帮我解决了这个问题。
此行会不断追加新的SVG:

  1. let svg = d3.select('#svg_lines') .append('svg') .attr('class', 'test_svgs');

所以我从connectTheDots()函数中删除了它。
下面是我的解决方案:
在主组件中,我添加了一个SVG,路径为:

  1. <div id="svg_line_wrapper">
  2. <svg class="svg_line_style">
  3. <path
  4. d="M574,520C574,520,574,520,574,520Z"
  5. ></path>
  6. </svg>
  7. </div>

在connectTheDots()函数中,我不需要再追加任何内容,我只需要绘制SVG并更新其路径:

  1. function connectTheDots(sourcePos, targetPos) {
  2. const offset = 2;
  3. const data = [{
  4. source: [sourcePos.y + offset, sourcePos.x + offset],
  5. target: [targetPos.y + offset, targetPos.x + offset],
  6. }];
  7. let link = d3.linkHorizontal()
  8. .source((d) => [d.source[1], d.source[0]])
  9. .target((d) => [d.target[1], d.target[0]]);
  10. d3.select('#svg_line_wrapper')
  11. .selectAll('path')
  12. .data(data)
  13. .join('path')
  14. .attr('d', link)
  15. .classed('link', true)
  16. }
展开查看全部

相关问题