zoukankan      html  css  js  c++  java
  • D3——Updates, Transitions, and Motion


    <script type="text/javascript"> var w = 500; var h = 100; var barPadding = 1; var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; //create svg var svg = d3.select("body").append("svg") .attr("width", w).attr("height", h); svg.selectAll("rect") .data(dataset).enter() .append("rect") .attr("x",function(d,i){ return i * (w/dataset.length);}) .attr("y", function(d){ return h - (d*4);}) .attr("width", function(d,i){return w/dataset.length - barPadding;}) .attr("height", function(d){return d*4;}) .attr("fill", function(d){return "rgb(0,0," +(d*10)+ ")";}) //set label svg.selectAll("text") .data(dataset).enter() .append("text") .text(function(d){return d;}) .attr("text-anchor","middle") .attr("x",function(d,i){ return i*(w/dataset.length)+(w/dataset.length-barPadding)/2;}) .attr("y",function(d){return h-(d*4)+14;}) .attr("font-family", "sans-serif") .attr("font-size", "11px") .attr("fill","rgb(255,255,255)") </script>

    前面的直方图使用的数据都是static datasets, 但现实世界中数据大多都是随时间变化的。有时我们希望图表能反映那些变化。在D3中,通过updates可以更新数据,changes可视化可以通过transitions,motion表现出来

    有序的数据(ordinal data: typically categories with some inherent order to them),例如:

    • freshman, sophomore, junior, senior
    • grade B, grade A, grade AA
    • strongly dislike, dislike, neutral, like, strongly like

    We don’t have true ordinal data for use with this bar chart. Instead, we just want the bars to be drawn from left to right using the same order in which values occur in our dataset. 

     对这类数据需要用ordinal scale(序数比例尺);

    var xScale = d3.scale.ordinal();
    线性比例尺的定义域需要设置一个有两个值得数组,分别是最小值和最大值,例如var xScale = d3.scale.linear().domain([0,100]);
    而序数比例尺的定义域的设置和线性比例尺不一样,可以指定an array with the category names,例如:.domain(["freshman","sophomore","junior","senior"])
    上面直方图中数据设置序数比例尺:
    .domain(d3.range(dataset.length))  
    
    //等价于
    .domain([0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
             10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
    
    
    //d3.range(10)返回一个数组[0,1,2,3,4,5,6,7,8,9]

     ordinal scales 使用离散 ranges, meaning输出值是预先定义好的,可以数值化或不数值化;

    可以使用range()函数定义值域, 或者使用更平滑的 rangeBands()函数, 它利用最小值和最大值,根据domain的length自动分割成均匀的chunks or “bands。 For example:

    .rangeBands([0, w])
    /*
    this says “calculate even bands starting at 0 and ending at w, then set this scale’s range to those bands.” In our case, we specified 20 values in the domain, so D3 will calculate:
    
    (w - 0) / xScale.domain().length
    (600 - 0) / 20
    600 / 20
    30
    
    */

    In the end, each band will be 30 “wide.”

    也可以加入第二个参数,以设置每个band之间的间隔; Here, I’ve used 0.2, meaning that 20 percent of the width of each band will be used for spacing in between bands:

    .rangeBands([0, w], 0.2)

    还可以使用 rangeRoundBands(), 类似于 rangeBands(), 只是此函数的输出值是舍入后最接近的整数, so 12.3456 becomes just 12, for example. This is helpful for keeping visual elements lined up precisely on the pixel grid, for clean, sharp edges.

    .rangeRoundBands([0, w], 0.05);    //This gives us nice, clean pixel values, with a teensy bit of visual space between them.

    Interaction via Event Listeners

    <p>Click on this text to update the chart with new data values (once).</p>
    //On click, update with new data
    d3.select("p")
        .on("click", function() {
    
            //New values for dataset
            dataset = [ 11, 12, 15, 20, 18, 17, 16, 18, 23, 25,
                        5, 10, 13, 19, 21, 25, 22, 18, 15, 13 ];
    
            //Update all rects
            svg.selectAll("rect")
               .data(dataset)
               .attr("y", function(d) {
                    return h - yScale(d);
               })
               .attr("height", function(d) {
                    return yScale(d);
               });
                .attr("fill", function(d) {   // <-- Down here!
                    return "rgb(0, 0, " + (d * 10) + ")";
              });
    });

     设置新的label text

    svg.selectAll("text")
       .data(dataset)
       .text(function(d) {
            return d;
       })
       .attr("x", function(d, i) {
            return xScale(i) + xScale.rangeBand() / 2;
       })
       .attr("y", function(d) {
            return h - yScale(d) + 14;
       });

     

    Transitions

    .transition()   //过渡效果

    Without transition(), D3 evaluates every attr() statement immediately, so the changes in height and fill happen right away. When you add transition(), D3 introduces the element of time. Rather than applying new values all at once, D3 interpolates between the old values and the new values, meaning it normalizes the beginning and ending values, and calculates all their in-between states. D3 is also smart enough to recognize and interpolate between different attribute value formats. For example, if you specified a height of 200px to start but transition to just 100 (without the px). Or if a blue fill turns rgb(0,255,0). You don’t need to fret about being consistent; D3 takes care of it.

    //Update all rects
    svg.selectAll("rect")
       .data(dataset)
       .transition()    // <-- This is new! Everything else here is unchanged.
        .duration(1000)  // <-- Now this is new!
       .attr("y", function(d) {
            return h - yScale(d);
       })
       .attr("height", function(d) {
            return yScale(d);
       })
       .attr("fill", function(d) {
            return "rgb(0, 0, " + (d * 10) + ")";
       });
    //Update all labels
    svg.selectAll("text")
       .data(dataset)
       .transition()        // <-- This is new,
       .duration(5000)      //     and so is this.
       .text(function(d) {
            return d;
       })
       .attr("x", function(d, i) {
            return xScale(i) + xScale.rangeBand() / 2;
       })
       .attr("y", function(d) {
            return h - yScale(d) + 14;
       });

    duration() 定义过渡时间

    The duration() must be specified after the transition(), and durations are always specified in milliseconds, so duration(1000) is a one-second duration.

    ease()定义过渡类型

    ease() must also be specified after transition(), but before the attr() statements to which the transition applies. ease() can come before or after duration(), but this sequence makes the most sense to me:

    //Selection statement(s)
    .transition()
    .duration(2000)
    .ease("linear")
    …   //attr() statements

    其他内置的 easing functions有,例如:

    circleGradual ease in and acceleration until elements snap into place.

    elasticThe best way to describe this one is “sproingy.”

    bounceLike a ball bouncing, then coming to rest.

    delay()设置过渡什么时候开始,可以指定一个值, 毫秒级,也可以指定一个函数

    …
    .transition()
    .delay(1000)     //1,000 ms or 1 second
    .duration(2000)  //2,000 ms or 2 seconds
    …
    .transition()
    .delay(function(d, i) {
        return i * 100;
    })
    .duration(500)
    …
    
    


  • 相关阅读:
    Debugging Kafka connect
    android O 蓝牙设备默认名称更改
    qualcomm sdm450 tinymix mic record
    QACT 在线调试 Android O
    Android O seLinux 编译错误
    Android seLinux 设置
    高通 fastboot 显示
    高通 双MIC 设置
    高通 添加 cmdline
    高通 mixer_paths.xml 音频配置文件 初始化过程
  • 原文地址:https://www.cnblogs.com/xuepei/p/7562780.html
Copyright © 2011-2022 走看看