d3.js用悸动的外线绘制圆圈

时间:2014-02-13 17:15:17

标签: javascript d3.js alarms

我正在尝试创建与此类似的东西 http://demo.joostkiens.com/het-parool-4g/

Alarm throbbing points

绘制圆圈的外线向外悸动。

到目前为止,这是我的演示。

http://jsfiddle.net/NYEaX/95/

我用一些虚拟数据绘制了圆圈。最重要的是基于红色的圆圈。如何根据警报数据调用动画并使其更加生动。例如。警报等级。

我不确定如何创建一个循环动画,半径从圆周反弹然后逐渐消失 - 根据alarmLevel阈值进行此变化

理想情况下,需要在循环中进行转换。http://jsfiddle.net/pnavarrc/udMUx/

var speedLineGroup = sampleSVG.append("g")
                                        .attr("class", "speedlines");

                            speedLineGroup.selectAll("circle.dl-speed-static")
                                .data(dataset)
                                .enter().append("circle")
                                .style("stroke", "red")
                                .style("fill", "black")
                                .attr("r", function(d){
                                    return d.value;
                                })
                                .attr("cx", function(d){
                                    return d.xcoord;
                                })
                                .attr("cy", function(d){
                                    return d.ycoord;
                                })
                                .attr("class", "dl-speed-static")
                                .attr("stroke-opacity", function (e) {
                                    return 1;
                                    //return var
                                })
                                .attr("fill-opacity", function (e) {
                                    return 1;
                                    //return var
                                })
                                .transition()
                                .ease("linear")
                                .duration(200)
                                .attr("r", function (e) {
                                    return 1;
                                    //return var
                                })

我已经合并了帖子中的想法。我已将环创建放在其自己的功能中并删除了超时。我也开始尝试连接每个标记的警报阈值。

http://jsfiddle.net/NYEaX/102/

但应用程序似乎仍然延迟/错误 - 不像在主要示例中那样清晰。怎么可以进一步改善。一些警报计数很低 - 但这种方法导致戒指太快或者闪烁。它几乎就像我需要将值反转为低警报 - 创建一个较慢的响应。

            function makeRings() {
                var datapoints = circleGroup.selectAll("circle");
                var radius = 1;

                    function myTransition(circleData){

                        var transition = d3.select(this).transition();

                            speedLineGroup.append("circle")
                              .attr({"class": "ring",
                                     "fill":"red",
                                     "stroke":"red",
                                     "cx": circleData.xcoord,
                                     "cy": circleData.ycoord,
                                     "r":radius,
                                     "opacity": 0.4,
                                     "fill-opacity":0.1
                                    })
                              .transition()
                              .duration(function(){                 
                                return circleData.alarmLevel*100;
                              })
                              .attr("r", radius + 100 )
                              .attr("opacity", 0)
                              .remove();


                        transition.each('end', myTransition);
                    }

              datapoints.each(myTransition);
            } 

这是最新的代码..

makeRings()

var t = window.setInterval(makeRings, 10000);

                function makeRings() {
                        var datapoints = mapSVG.selectAll("circle.location");
                        var radius = 1;

                            function myTransition(circleData){

                                console.log("circleData", circleData);

                                var transition = d3.select(this).transition();

                                    speedLineGroup.append("circle")
                                      .attr({"class": "ring",
                                             "fill":"red",
                                             "stroke":"red",
                                             "cx": circleData.x * ratio,
                                             "cy": circleData.y * ratio,
                                             "r":radius,
                                             "opacity": 0.4,
                                             "fill-opacity":0.1
                                            })
                                      .transition()
                                      .duration(function(){                 
                                        return (circleData.redSum * 100);
                                      })
                                      .attr("r", radius + 30 )
                                      .attr("opacity", 0)
                                      .remove();


                                transition.each('end', myTransition);
                            }

                      datapoints.each(myTransition);
                    } 

2 个答案:

答案 0 :(得分:1)

您链接的示例使用缩小代码,因此弄清楚他们正在做什么有点痛苦。但是,如果您只是观察DOM检查器中的更改,您会看到每个环都是一个新的圆圈,它会被添加,增大并且面朝外,然后被删除。不同的点在它们消失之前环的大小有所不同(因此它们一次可见多少环,因为它们都以相同的速度生长)。

我将采取的方法无限期地继续:

  1. 使用'setInterval'定期调用一个函数(例如,每秒一次或两次),这将在每个数据循环周围创建一个新的环。

  2. 在数据圈中使用.each()调用创建响铃,但是将它们添加到不同的<g>元素和/或使用不同的类名称,以便环之间不会混淆和数据点。

  3. 将环的初始半径设置为与数据点相同,但随后立即开始转换。使转换的持续时间成为关联数据圆的“强度”数据值的函数,并且还使最终半径成为该数据值的函数。同时将不透明度转换为值0。

  4. 为环.remove()设置转换的最后一行,以便每个环在完成展开后自行移除。

  5. 基本代码:

    window.setInterval(makeRings, 1000);
    
    function makeRings() {
    
      datapoints.each(function(circleData){  
           //datapoints is your d3 selection of circle elements
    
        speedLineGroup.append("circle")
          .attr({"class": "ring",
                 "fill":"red", //or use CSS to set fill and stroke styles
                 "stroke":"red",
                 "cx": circleData.xCoord,
                 "cy": circleData.yCoord,
                     //position according to this circle's position
                 "r":radius, //starting radius, 
                             //set according to the radius used for data points
                 "opacity": 0.8, //starting opacity
                 "fill-opacity":0.5 //fill will always be half of the overall opacity
                })
          .transition()
          .duration( intensityTimeScale(circleData.intensity) )
              //Use an appropriate linear scale to set the time it takes for 
              //the circles to expand to their maximum radius.
              //Note that you *don't* use function(d){}, since we're using the data
              //passed to the .each function from the data point, not data
              //attached to the ring
          .attr("r", radius + intensityRadiusScale(circleData.intensity) )
              //transition radius
              //again, create an appropriate linear scale
          .attr("opacity", 0) //transition opacity
          .remove(); //remove when transition is complete
    
      });
    }
    

    由于半径的变化和转换的持续时间都是强度值的线性函数,因此所有数据点的变化速度都是恒定的。

答案 1 :(得分:0)

在d3中创建循环转换所需要做的就是在转换时使用end回调。创建两个函数,每个函数创建一个数据转换,一个从起点到终点,另一个返回,让它们在完成时互相调用,如下所示:

function myTransition(d){
    var transition = d3.select(this).transition();

    //Forward transition behavior goes here
    //Probably create a new circle, expand all circles, fade out last circle

    transition.each('end', myTransition); //This calls the backward transition
}

d3.select('myFlashingElement').each(myTransition);

这将封装所有内容,并在转换的持续时间内保持循环。在转换结束之前,下一次转换将始终触发,因此您不必担心同步任何内容。