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

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

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

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

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

new Vue({
router,
store,
render: (h) => h(App),
async created() {
    window.document.addEventListener('dragover', (e) => {
        e = e || window.event;
        var dragX = e.pageX, dragY = e.pageY;
        store.commit('setConnMousePos', {"x": dragX, "y": dragY});

        let sourcePos = this.$store.getters.getConnStartPos;
        let targetPos = this.$store.getters.getConnMousePos;

        // draw the SVG line
        connectTheDots(sourcePos, targetPos);

    }, false)
  },
 }).$mount('#app');

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

function connectTheDots(sourcePos, targetPos) {
const offset = 2;
const shapeCoords = [{
    source: [sourcePos.y + offset, sourcePos.x + offset],
    target: [targetPos.y + offset, targetPos.x + offset],
}];

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

let link = d3.linkHorizontal()
    .source((d) => [d.source[1], d.source[0]])
    .target((d) => [d.target[1], d.target[0]]);

function render() {
    let path = svg.selectAll('path').data(shapeCoords)
    path.attr('d', function (d) {
        return link(d) + 'Z'
    })
    path.enter().append('svg:path').attr('d', function (d) {
        return link(d) + 'Z'
    })
    path.exit().remove()
}

render();
}

我偷了/修改了这篇文章的代码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:

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

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

<div id="svg_line_wrapper">
  <svg class="svg_line_style">
    <path
        d="M574,520C574,520,574,520,574,520Z"
    ></path>
  </svg>
</div>

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

function connectTheDots(sourcePos, targetPos) {
  const offset = 2;
  const data = [{
    source: [sourcePos.y + offset, sourcePos.x + offset],
    target: [targetPos.y + offset, targetPos.x + offset],
  }];
  let link = d3.linkHorizontal()
    .source((d) => [d.source[1], d.source[0]])
    .target((d) => [d.target[1], d.target[0]]);

  d3.select('#svg_line_wrapper')
    .selectAll('path')
    .data(data)
    .join('path')
    .attr('d', link)
    .classed('link', true)
}

相关问题