user3359706
user3359706

Reputation: 511

d3 version 4 drag and zoom update

The code below works with v3 but not v4. I have tried taking out behaviour from the zoom event but it still doesn't work. I have also found there is an issue with this line; transMat = circle[0][0].getCTM() in version 4. Any suggestions would be appreciated.

var tooltipCounter = 0;

var svgElement = d3.select('body')
    .append("svg:svg")
    .attr('width', '100%')
    .attr('height', '100%');

var container = svgElement.append('svg:g');

var circle = container.append('svg:circle')
    //.attr('cx', 100)
    //.attr('cy', 100)
    .attr('transform', 'translate(100,100)')
    .attr('r', 30)
    .attr('fill', 'red')
    .on('click', createTooltip);

svgElement.call(d3.behavior.zoom().on('zoom', redrawOnZoom));

function redrawOnZoom() {
    var scrolling = false
    //console.log('event scale', d3.event.scale, 'container scale', container[0][0].getCTM().d)
    if ((d3.event.scale).toFixed(4) != (container[0][0].getCTM().d).toFixed(4)) {
        console.log('scrolling')
        scrolling = true
    }
    var dx = d3.event.translate[0] - container[0][0].getCTM().e;
    var dy = d3.event.translate[1] - container[0][0].getCTM().f;

    container.attr('transform', 'translate(' + d3.event.translate + ')' + ' scale(' + d3.event.scale + ')')
    var tooltips = $("[id$=tooltip] ");
    for (var i = 0; i < tooltips.length; i++) {
        var tooltip = tooltips[i];
        if (scrolling) {
            tooltip.parentNode.removeChild(tooltip)
        }
        else {
            tooltipTransMat = $('#' + tooltip.id).css("-webkit-transform").match(/(-?[0-9\.]+)/g);
            tooltip.style['-webkit-transform'] = "translate(" + (parseFloat(tooltipTransMat[4]) + dx) + "px," + (parseFloat(tooltipTransMat[5]) + dy) + "px)"
        }
    }
};

function createTooltip() {
    tooltipCounter++
    var tooltipId = tooltipCounter + '_tooltip'
    // get the transformation matrix of the circle
    var transMat = circle[0][0].getCTM();
    var x = transMat.e;
    var y = transMat.f;
    var scale = transMat.d;
    var radius = parseInt(circle.attr('r'))

    var margin = parseInt(d3.select('body').style('margin'))

    //x = x + (scale * radius) + margin
    //y = y + (scale * radius/2) + margin
    //console.log("translate(" + x + "px," + y + "px)")

    var tooltip = d3.select('body').append('xhtml:div')
        .attr('id', tooltipId)
        .style('position', 'absolute')
        .style('background', 'gray')
        .style('left', x + (scale * radius) + margin + 'px')
        .style('top', y + (scale * radius / 2) + margin + 'px')
        .style('-webkit-transform', "translate(" + 0 + "px," + 0 + "px)")
        .html('<- This is tooltip.');

}

Upvotes: 0

Views: 522

Answers (1)

altocumulus
altocumulus

Reputation: 21578

In D3 v4 a selection no longer is an array of arrays but an object. Therefore, you can't use circle[0][0] to access the first node; use circle.node() instead. Or, if you are looking for all nodes contained in the selection, use circle.nodes().

Upvotes: 1

Related Questions