代码之家  ›  专栏  ›  技术社区  ›  Christian

vue组件中的d3.js-如何将鼠标事件挂钩到元素?

  •  2
  • Christian  · 技术社区  · 7 年前

    我有一个用于交互式D3.js映射的普通javascript代码,现在正试图用它创建一个vue.js组件。我已经将所有函数定义为方法,没有收到任何警告或错误消息,但没有任何鼠标事件被钩住。我尝试过这两种方法,D3.js方式(.on(“click”,this.clickBG))和vue(.attr(“v-on:click”,“clickBG”)都没有成功。

        // vorlage: https://dev.to/ignoreintuition/binding-data-to-charts-using-vue-components-and-d3-4i27
        import * as d3 from 'd3';
        
        export default {
            props: ['data','vegbed'], 
            data: function () {
                return {
                    gardenbox: {}
                }
            },
            computed: {
                displaywidth: function() { return 600; },
                displayheight: function() { return this.displaywidth*(this.vegbed.length/this.vegbed.width); },
                margin: function() { return {top: 0, right: 0, bottom: 0, left: 0}; }
            },
            methods: {
                initalizeChart: function () {
                    this.drawGardenBox();
                },
    
                virtDia: function (realDia) {
                    return (this.displaywidth/this.vegbed.width)*realDia;
                },
                
                clickPlant: function() {
                    d3.selectAll(".selected").raise().classed("selected",false);
                    d3.select(_this).selectAll(".plant").raise().classed("selected", true);
                    d3.selectAll("#"+this.id).classed("selected", true);      
                },
                clickBG: function() {
                    console.log("click");
                    d3.selectAll(".selected").raise().classed("selected",false);
                },
                
                draggedPlant: function(d) {
                    d3.select(this).attr("transform","translate("+(d.x = d3.event.x)+","+(d.y = d3.event.y)+")");
                },
                
                dragStartedPlant: function() {
                    d3.selectAll(".selected").raise().classed("selected",false);
                    d3.select(this).selectAll(".plant").raise().classed("selected", true);
                    d3.selectAll("#"+this.id).classed("selected", true);
    
                    //d3.event.sourceEvent.stopPropagation();
                },    
                dragEndedPlant: function(d) {
                    
                },
                refreshBed: function () {
                    let _this = this; // Workaround to call functions from inside callbacks
                    var gplant = this.gardenbox.selectAll("g")
                        .data(this.data).enter().append("g")
                        .attr("id", function(d){ return d.id; })
                        .attr("transform", function(d){ return "translate("+d.x+","+d.y+")";  })
                        .on("click", this.clickPlant)
                        //.attr("v-on:click","this.clickPlant")
                        .call(d3.drag()
                        .on("start", this.draggedPlant)
                        .on("drag", this.dragStartedPlant)
                        .on("end", this.dragEndedPlant));
    
                    gplant.append("circle") // max size
                        .attr('class', 'plant')
                        .attr("cx", function(d) { return d.x; })
                        .attr("cy", function(d) { return d.y; })
                        .attr("r", function(d) { return _this.virtDia(d.plant.adult_diameter); });
    
                    gplant.append("circle") // min size
                        .attr('class', 'plant')
                        .attr("cx", function(d) { return d.x; })
                        .attr("cy", function(d) { return d.y; })
                        .attr("r", function(d) { return _this.virtDia(d.plant.exposure_diameter); });
    
                    gplant.append("image")
                        .attr('class', 'plant')
                        .attr("xlink:href", function(d) { return d.picref; })
                        .attr("x", function(d) { return d.x-(d.picsize/2); })
                        .attr("y", function(d) { return d.y-(d.picsize/2); })
                        .attr("width", function(d) { return d.picsize; })
                        .attr("height", function(d) { return d.picsize; });
                },
                
                drawGardenBox: function () {
                    this.gardenbox = d3.select('#vegbedcontainer').append('svg')
                            .attr("width", this.displaywidth + this.margin.left + this.margin.right)
                            .attr("height", this.displayheight + this.margin.top + this.margin.bottom)
                    // hintergrund für deselect zeichen
                    var bg = this.gardenbox.append("g")
                            //.attr("v-on:click","clickBG");
                            .on("click", this.clickBG); // unselect on background click
    
                    bg.append("rect") 
                        .attr('class', 'bg')
                        .attr("x", this.margin.left)
                        .attr("y", this.margin.top)
                        .attr("width", this.displaywidth + this.margin.left + this.margin.right)
                        .attr("height", this.displayheight + this.margin.top + this.margin.bottom)
                }
            },
    
    
            // lifecycle events
            mounted: function () { // <-- lifecycle events
                console.log('VegBedEditor mounted.')
                this.initalizeChart();
                this.refreshBed();
            },
            // watch functions
            watch: { // <-- watch functions
                'data': {
                    handler: function (val) {
                        this.refreshBed();
                    },
                    deep: true
                }
            },
            template: `<div id="vegbedcontainer"><!-- SVG goes here --></div>`
        }
    1 回复  |  直到 7 年前
        1
  •  1
  •   user9161752 user9161752    7 年前

    以下是在我的Vue应用程序中运行的一些实验的结果。

    在svg背景上设置单击处理程序

    drawGardenBox: function () {
      this.gardenbox = d3.select('#vegbedcontainer').append('svg')
        .attr("width", this.displaywidth + this.margin.left + this.margin.right)
        .attr("height", this.displayheight + this.margin.top + this.margin.bottom)
    
      var bg = d3.select('svg')
        .on("click", this.clickBG); // unselect on background click
    

    停止来自其他处理程序的单击传播

    clickPlant: function() {
      d3.selectAll(".selected").raise().classed("selected",false);
      d3.select(_this).selectAll(".plant").raise().classed("selected", true);
      d3.selectAll("#"+this.id).classed("selected", true); 
      d3.event.stopPropagation(); 
    },
    

    设置d3.0事件

    event ,但最初 d3.event.stopPropagation() d3.event 是空的。

    importing d3.event into a custom build using rollup ,我换了房间 事件

    import { select, selectAll, event, customEvent } from 'd3-selection'
    import { zoom } from 'd3-zoom'
    import { tree, hierarchy } from 'd3-hierarchy'
    
    export const d3 = {
      select,
      selectAll,
      tree,
      hierarchy,
      zoom,
      // event,
      get event() { return event; },
      customEvent
    }