悬停转换会停止初始转换

时间:2014-08-29 08:48:10

标签: javascript d3.js transition

我正在研究d3.js的径向直方图。

问题如下:我有一个初始转换,使条形“增长”到它们的实际高度(eyecandy)。

一切正常。现在我想添加一个悬停过渡,即所有项目的不透明度应该在悬停时转换为.5,并在悬停状态结束时转换为1.

这也可以自行完成。

如果在初始转换仍然发生时触发悬停状态,它将停止正常工作。然后,初始过渡只是停止,并且条形没有达到它们的最终高度。

问题:如何让两个转换一起工作,以便悬停转换不会停止初始转换?

Here is a jsfiddle。以下是代码:

<script src="http://d3js.org/d3.v3.js"></script>

<div id="chart"></div>

<script>
    var margin = {
            top: 0,
            right: 0,
            bottom: 0,
            left: 0
        },
        width = 500 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom;

    var arcMin = 150;
    var arcMax = 250;
    var pi = Math.PI;

    var color = d3.scale.category10();


    var data = [
        {
            "value": 20,
            "category": "category1"
  },
        {
            "value": 24,
            "category": "category1"
  },
        {
            "value": 9,
            "category": "category1"
  },
        {
            "value": 93,
            "category": "category1"
  },
        {
            "value": 82,
            "category": "category1"
  },
        {
            "value": 56,
            "category": "category1"
  },
        {
            "value": 29,
            "category": "category1"
  },
        {
            "value": 6,
            "category": "category1"
  },
        {
            "value": 10,
            "category": "category1"
  },
        {
            "value": 4,
            "category": "category1"
  },
        {
            "value": 45,
            "category": "category1"
  },
        {
            "value": 25,
            "category": "category1"
  },
        {
            "value": 26,
            "category": "category2"
  },
        {
            "value": 53,
            "category": "category2"
  },
        {
            "value": 60,
            "category": "category2"
  },
        {
            "value": 87,
            "category": "category2"
  },
        {
            "value": 77,
            "category": "category2"
  },
        {
            "value": 40,
            "category": "category2"
  },
        {
            "value": 12,
            "category": "category2"
  },
        {
            "value": 80,
            "category": "category2"
  },
        {
            "value": 23,
            "category": "category2"
  },
        {
            "value": 53,
            "category": "category2"
  },
        {
            "value": 26,
            "category": "category2"
  },
        {
            "value": 34,
            "category": "category2"
  },
        {
            "value": 79,
            "category": "category2"
  },
        {
            "value": 98,
            "category": "category3"
  },
        {
            "value": 1,
            "category": "category3"
  },
        {
            "value": 13,
            "category": "category3"
  },
        {
            "value": 80,
            "category": "category3"
  },
        {
            "value": 66,
            "category": "category3"
  },
        {
            "value": 5,
            "category": "category3"
  },
        {
            "value": 36,
            "category": "category3"
  },
        {
            "value": 74,
            "category": "category3"
  },
        {
            "value": 32,
            "category": "category3"
  },
        {
            "value": 4,
            "category": "category3"
  },
        {
            "value": 54,
            "category": "category3"
  },
        {
            "value": 8,
            "category": "category3"
  },
        {
            "value": 64,
            "category": "category3"
  },
        {
            "value": 5,
            "category": "category3"
  },
        {
            "value": 58,
            "category": "category3"
  },
        {
            "value": 41,
            "category": "category3"
  },
        {
            "value": 81,
            "category": "category3"
  },
        {
            "value": 73,
            "category": "category3"
  },
        {
            "value": 20,
            "category": "category3"
  },
        {
            "value": 32,
            "category": "category3"
  },
        {
            "value": 42,
            "category": "category3"
  },
        {
            "value": 55,
            "category": "category3"
  },
        {
            "value": 74,
            "category": "category3"
  },
        {
            "value": 17,
            "category": "category3"
  },
        {
            "value": 6,
            "category": "category3"
  },
        {
            "value": 96,
            "category": "category3"
  },
        {
            "value": 18,
            "category": "category3"
  },
        {
            "value": 1,
            "category": "category3"
  },
        {
            "value": 18,
            "category": "category3"
  },
        {
            "value": 40,
            "category": "category3"
  },
        {
            "value": 9,
            "category": "category3"
  },
        {
            "value": 30,
            "category": "category3"
  },
        {
            "value": 28,
            "category": "category3"
  },
        {
            "value": 25,
            "category": "category3"
  },
        {
            "value": 44,
            "category": "category3"
  },
        {
            "value": 20,
            "category": "category3"
  },
        {
            "value": 99,
            "category": "category3"
  },
        {
            "value": 95,
            "category": "category3"
  },
        {
            "value": 50,
            "category": "category3"
  },
        {
            "value": 65,
            "category": "category3"
  },
        {
            "value": 66,
            "category": "category3"
  },
        {
            "value": 7,
            "category": "category3"
  },
        {
            "value": 70,
            "category": "category4"
  },
        {
            "value": 39,
            "category": "category4"
  },
        {
            "value": 12,
            "category": "category4"
  },
        {
            "value": 94,
            "category": "category4"
  },
        {
            "value": 55,
            "category": "category4"
  },
        {
            "value": 15,
            "category": "category4"
  },
        {
            "value": 84,
            "category": "category4"
  },
        {
            "value": 31,
            "category": "category4"
  },
        {
            "value": 48,
            "category": "category4"
  },
        {
            "value": 26,
            "category": "category4"
  },
        {
            "value": 70,
            "category": "category4"
  },
        {
            "value": 30,
            "category": "category4"
  },
        {
            "value": 26,
            "category": "category4"
  },
        {
            "value": 75,
            "category": "category4"
  },
        {
            "value": 43,
            "category": "category4"
  },
        {
            "value": 83,
            "category": "category4"
  },
        {
            "value": 64,
            "category": "category5"
  },
        {
            "value": 52,
            "category": "category5"
  },
        {
            "value": 37,
            "category": "category5"
  },
        {
            "value": 11,
            "category": "category5"
  },
        {
            "value": 77,
            "category": "category6"
  },
        {
            "value": 94,
            "category": "category6"
  },
        {
            "value": 37,
            "category": "category6"
  },
        {
            "value": 64,
            "category": "category6"
  },
        {
            "value": 92,
            "category": "category6"
  },
        {
            "value": 58,
            "category": "category6"
  },
        {
            "value": 70,
            "category": "category6"
  },
        {
            "value": 47,
            "category": "category6"
  },
        {
            "value": 87,
            "category": "category6"
  },
        {
            "value": 6,
            "category": "category6"
  },
        {
            "value": 87,
            "category": "category6"
  },
        {
            "value": 32,
            "category": "category6"
  },
        {
            "value": 70,
            "category": "category6"
  },
        {
            "value": 38,
            "category": "category6"
  },
        {
            "value": 38,
            "category": "category6"
  },
        {
            "value": 31,
            "category": "category6"
  },
        {
            "value": 82,
            "category": "category6"
  },
        {
            "value": 44,
            "category": "category6"
  },
        {
            "value": 21,
            "category": "category6"
  },
        {
            "value": 78,
            "category": "category6"
  },
        {
            "value": 97,
            "category": "category6"
  },
        {
            "value": 67,
            "category": "category6"
  },
        {
            "value": 29,
            "category": "category6"
  },
        {
            "value": 6,
            "category": "category6"
  }
];


    var vis = d3.select("#chart").append("svg").attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var min = 1;
    var max = data.length;

    var middle = Math.round((max + min) / 2) - 0.5;

    var innerArc = d3.svg.arc()
        .innerRadius(arcMin)
        .outerRadius(arcMin + 10)
        .startAngle(function (d, i) {
            return (i + 0.1 - middle) * (pi / middle);
        })
        .endAngle(function (d, i) {
            return (i + 1 - 0.1 - middle) * (pi / middle);
        });

    var outerArc = d3.svg.arc()
        .innerRadius(arcMin)
        .outerRadius(function (d, i) {
            // Use min-max-normalization to scale value into interval [arcMin, arcMax]
            return (d.value - min) * ((arcMax - arcMin) / (max - min)) + arcMin;
        })
        .startAngle(function (d, i) {
            return (i + 0.1 - middle) * (pi / middle);
        })
        .endAngle(function (d, i) {
            return (i - 0.1 + 1 - middle) * (pi / middle);
        });

    var lines = vis.selectAll(".line")
        .data(data)
        .enter()
        .append("path")
        .attr("class", function (d) {
            return d.category + " line";
        })
        .attr("d", innerArc)
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
        .attr("fill", function (d) {
            return color(d.category);
        })
        .on("mouseleave", function () {
            d3.selectAll(".line")
                .transition()
                .duration(300)
                .style("opacity", 1);
        })
        .on("mouseenter", function (d, i) {
            d3.selectAll(".line")
                .transition()
                .duration(150)
                .style("opacity", .5);
        })
        .transition()
        .duration(2000)
        .delay(function (d) {
            return ((d.value - min) / (max - min)) * 500;
        })
        .attr("d", outerArc);
</script>

4 个答案:

答案 0 :(得分:2)

在其他过渡开始后添加的过渡总是取消那些早期过渡,参见the documentation

  

在给定时间,给定元素上只能有一个转换处于活动状态。但是,可以在同一元素上调度多个转换;如果它们在时间上交错,每个过渡将按顺序进行。如果在给定元素上运行较新的转换,则它会隐式取消任何较旧的转换,包括已安排但尚未运行的任何转换。

特别是:

  

这允许新的转换(例如响应新用户事件的转换)取代较旧的转换,即使这些较旧的转换已暂存或交错延迟。

因此,您正在寻找的用例明确不受D3支持。

实现您想要的功能将涉及在第二次转换开始时捕获状态并手动合并转换(请参阅here以获取指针),或转换到不同的元素。

答案 1 :(得分:1)

它只是一个d3&#34;限制&#34;。无论是由悬停还是其他东西触发,转换都无法同时运行。

尝试将悬停过渡移至CSS,并在d3中保持高度转换。

http://jsfiddle.net/w21gunej/

.hovertest {
    background: steelblue;
    transition: background 1s ease;
}

.hovertest:hover {
    background: gray;    
}

答案 2 :(得分:1)

更新:自D3版本3.5(2014年10月)以来,可以通过使用命名转换对元素执行并发转换。

Here你可以看到问题的原始jsfiddle与命名过渡。

var lines = vis.selectAll(".line")
    .data(data)
    .enter()
    .append("path")
    .attr("class", function (d) {
        return d.category + " line";
    })
    .attr("d", innerArc)
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
    .attr("fill", function (d) {
        return color(d.category);
    })
    .on("mouseleave", function () {
        d3.selectAll(".line")
            .transition("opacity") // NAMED TRANSITION
            .duration(300)
            .style("opacity", 1);
    })
    .on("mouseenter", function (d, i) {
        d3.selectAll(".line")
            .transition("opacity") // NAMED TRANSITION
            .duration(150)
            .style("opacity", .5);
    })
    .transition("creation")  // NAMED TRANSITION
    .duration(2000)
    .delay(function (d) {
        return ((d.value - min) / (max - min)) * 500;
    })
    .attr("d", outerArc);

Bostock的另一个例子: http://bl.ocks.org/mbostock/5d8039fb983a29e2ad49

答案 3 :(得分:0)

作为我的具体问题的解决方法,我只是延迟了在初始转换的相同持续时间内添加了负责悬停效果的代码:

setTimeout(function () {
    lines.on("mouseleave", function () {
        tip.hide();

        d3.selectAll(".line")
            .transition()
            .duration(300)
            .style("opacity", 1);
    })
        .on("mouseenter", function (d, i) {
            tip.show(d, container.node());

            d3.selectAll(".line")
                .transition()
                .duration(150)
                .style("opacity", .5);
        })
}, 2000);

有关一般解决方案,请参阅Pablo EMLars Kotthoff的答案。