简体   繁体   中英

d3 drag function returning error

I'm struggling with this, its a piece of code that's almost identical to one I've used a number of times before, and I really can't find the problem. I'm appending some text that I want to be able to click on and drag around. However, when I start the drag I get the following errors:

annotations.js:106 Uncaught TypeError: Cannot read property 'x' of null

This is the code I'm using

let radius;
        let yOffset = 0;
        let xOffset = 0;

        let textLabel = parent.append('text')
            .on('mouseover', pointer)
            .attr('class', 'highlighted-label')
            .attr('x',d => xScale(d.x))
            .attr('y',d => yScale(d.y))
            .attr("dy",0)
            .text((d) => {
                radius = sizeScale(d.value)
                return d.label + ' '+ formatDecimal(d.value)
            })
            .call(d3.drag()
                .on('start', dragstarted)
                .on('drag', dragged)
                .on('end', dragended))
            // .call(wrap,lineWidth,(d => xScale(d.x)),"highlighted-label")
            // .call(offset)

and these are the functions:

function pointer() {
            this.style.cursor = 'pointer';
        }

        function dragstarted() {
            d3.select(this).raise().classed('active', true);
        }

        function dragged() {
            d3.select(this).attr('transform', `translate(${d3.event.x}, ${d3.event.y})`);
        }

        function dragended() {
            d3.select(this).classed('active', false);
        }

Any help gratefully receuved

I found that adding ag element first then calling the drag on that element nearly work perfectly. As long as you target the elements in the dragstart function directly. It also allows you to wrap the text. But it does make the text jump on the first drag. If I click and drag the text a second time it behaves perfectly. Code no looks like this:

textLabel.append('g')
        .append('text')
            .attr('class', 'highlighted-label')
            .attr('x',d => xScale(d.targetX))
            .attr('y',d => yScale(d.targetY))
            .attr('dy',0)
            .text((d) => {
                if (intersect) {
                    radius = sizeScale(d.radius);
                }
                else {radius = d.radius};
                return d.title + ' '+ d.note
            })


            .call(wrap,lineWidth,(d => xScale(d.targetX)),"highlighted-label")
            //.call(offset)

       textLabel.call(d3.drag()
            .on('start', dragstarted)
            .on('drag', dragged)
            .on('end', dragended));

function wrap(text, width,x, media) {
            text.each(function() {
                var text = d3.select(this),
                words = text.text().split(/\s+/).reverse(),
                word,
                line = [],
                lineNumber = 0,
                lineHeight = 1.0,
                y = text.attr("y"),
                dy = parseFloat(text.attr("dy")),
                tspan = text.text(null).append("tspan").attr("class", media).attr("x", x).attr("y", y).attr("dy", dy + "em");
                while (word = words.pop()) {
                    line.push(word);
                    tspan.text(line.join(" "));
                    if (tspan.node().getComputedTextLength() > width) {
                        tspan.text(line.join(" "));
                        line = [word];
                        tspan = text.append("tspan").attr("class", media).attr("x", x).attr("y", y).attr("dy",++lineNumber * lineHeight + dy + "em").text(word);
                    }
                }
            });
        }
        function pointer(d) {
            this.style.cursor = 'pointer';
        }

        function dragstarted(d) {
            d3.select(this).raise().classed('active', true);
        }

        function dragged(d) {

            d3.select(this).selectAll('tspan').attr("x", d.x = d3.event.x).attr("y", d.y = d3.event.y);
            d3.select(this).selectAll('text').attr("x", d.x = d3.event.x).attr("y", d.y = d3.event.y);
        }

        function dragended(d) {
            d3.select(this).classed('active', false);
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM