使用D3对虚拟轮子进行动画处理,如何使其真实旋转? [英] Using D3 to Animate a virtual wheel, How to make it spin realistically?

查看:40
本文介绍了使用D3对虚拟轮子进行动画处理,如何使其真实旋转?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用以下功能补间旋转.如何使这种旋转看起来更真实?

The rotation is tweened using the following function. How can I make this spin look more real?

如何控制速度,使其快速启动然后减速,而不是均匀地加速和减速...

How can I control the speed making it start fast and then slow down instead of speed up and back down evenly...

        function rotTween(to) {
          var i = d3.interpolate(oldrotation % 360, rotation);
          return function(t) {
            return "rotate(" + i(t) + ")";
          };
        }

var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
        var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
        var fs = 33;
        if(w > h){
            w = w / 1.5;
        } else {
            h = h / 1.5;
        }
        
        if(w > h){
            fs = h /25;
        } else {
            fs = w /25;
        }
        var padding = {top:20, right:40, bottom:0, left:0},
            w = w - padding.left - padding.right,
            h = h - padding.top  - padding.bottom,
            r = Math.min(w, h)/2,
            rotation = 0,
            oldrotation = 0,
            picked = 100000,
            oldpick = [],
            color = d3.scale.category20();//category20c()
        var data = [
                    {"label":"100",  "value":1,  "question":"What CSS property is used for specifying the area between the content and its border?"}, // padding
                    {"label":"200",  "value":1,  "question":"What CSS property is used for changing the font?"}, //font-family
                    {"label":"300",  "value":1,  "question":"What CSS property is used for changing the color of text?"}, //color
                    {"label":"400",  "value":1,  "question":"What CSS property is used for changing the boldness of text?"}, //font-weight
                    {"label":"500",  "value":1,  "question":"What CSS property is used for changing the size of text?"}, //font-size
                    {"label":"600",  "value":1,  "question":"What CSS property is used for changing the background color of a box?"}, //background-color
                    {"label":"700",  "value":1,  "question":"Which word is used for specifying an HTML tag that is inside another tag?"}, //nesting
                    {"label":"GRAND",  "value":1,  "question":"Which side of the box is the third number in: margin:1px 1px 1px 1px; ?"}, //bottom
                    {"label":"",  "value":1,  "question":"What are the fonts that don't have serifs at the ends of letters called?"}, //sans-serif
                    {"label":"100", "value":1, "question":"With CSS selectors, what character prefix should one use to specify a class?"}, //period
                    {"label":"200", "value":1, "question":"With CSS selectors, what character prefix should one use to specify an ID?"}, //pound sign
                    {"label":"300", "value":1, "question":"In an HTML document, which tag holds all of the content people see?"}, //<body>
                    {"label":"400", "value":1, "question":"In an HTML document, which tag indicates an unordered list?"}, //<ul>
                    {"label":"500", "value":1, "question":"In an HTML document, which tag indicates the most important heading of your document?"}, //<h1>
                    {"label":"600", "value":1, "question":"What CSS property is used for specifying the area outside a box?"}, //margin
                    {"label":"700", "value":1, "question":"What type of bracket is used for HTML tags?"}, //< >
                    {"label":"", "value":1, "question":"What type of bracket is used for CSS rules?"}, // { }
                    {"label":"100", "value":1, "question":"Which HTML tag is used for specifying a paragraph?"}, //<p>
                    {"label":"200", "value":1, "question":"What should always be the very first line of code in your HTML?"}, //<!DOCTYPE html>
                    {"label":"300", "value":1, "question":"What HTML tag holds all of the metadata tags for your page?"}, //<head>
                    {"label":"400", "value":1, "question":"In CSS, what character separates a property from a value?"}, // colon
                    {"label":"500", "value":1, "question":"What HTML tag holds all of your CSS code?"}, // <style>
                    {"label":"600", "value":1, "question":"What file extension should you use for your web pages?"}, // .html
                    {"label":"700", "value":1, "question":"Which coding language is used for marking up content and structure on a web page?"}, // HTML
                    {"label":"", "value":1, "question":"Which coding language is used for specifying the design of a web page?"}, // CSS
//                    {"label":"SAMSUNG NOTE5", "value":1, "question":"Which coding language is used for adding functionality to a web page?"}, // JavaScript
//                    {"label":"HP DESKTOP", "value":1, "question":"What CSS property is used for making the edges of a box visible?"}, // border
//                    {"label":"15,000,000$", "value":1, "question":"What character symbol is used at the end of each CSS statement?"},//semi-colon
//                    {"label":"BUGGATI", "value":1, "question":"By default, how wide is a <div> box?"}, //100%
//                    {"label":" GOOGLE JOB", "value":1, "question":"What character symbol do I use to specify multiple CSS selectors in one code block?"} //comma
        ];
        var svg = d3.select('#chart')
            .append("svg")
            .data([data])
            //.style("display", "flex")
            .attr("width",  w + padding.left + padding.right)
            .attr("height", h + padding.top + padding.bottom);
        var container = svg.append("g")
            .attr("class", "chartholder")
            .attr("transform", "translate(" + (w/2 + padding.left) + "," + (h/2 + padding.top) + ")");
        var vis = container
            .append("g");
            
        var pie = d3.layout.pie().sort(null).value(function(d){return 1;});
        // declare an arc generator function
        var arc = d3.svg.arc().outerRadius(r);
        // select paths, use arc generator to draw
        var arcs = vis.selectAll("g.slice")
            .data(pie)
            .enter()
            .append("g")
            .attr("class", "slice");
            
        arcs.append("path")
            .attr("fill", function(d, i){ return color(i); })
            .attr("d", function (d) { return arc(d); });
        // add the text
        arcs.append("text")
            .attr("transform", function(d){
                d.innerRadius = 0;
                d.outerRadius = r;
                d.angle = (d.startAngle + d.endAngle)/2;
                return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")translate(" + (d.outerRadius - 10) +")";
            })
            .attr("text-anchor", "end")
            .style("font-size", fs)
            .selectAll(null)
            .data((_,i)=>data[i].label)
            .enter()
            .append("tspan")
            .attr("rotate", "90")
            .attr("dx", (_,i)=> i ? "-1.5em" : null)
            .attr("y", 0)
            .text( function(d) {
                return d
            });

        container.on("click", spin);
        function spin(d){
            
            container.on("click", null);
            //all slices have been seen, all done
            if(oldpick.length == data.length){
                console.log("done");
                container.on("click", null);
                return;
            }
            var  ps       = 360/data.length,
                 pieslice = Math.round(1440/data.length),
                 rng      = Math.floor((Math.random() * 1440) + 360);
                
            rotation = (Math.round(rng / ps) * ps);
            
            picked = Math.round(data.length - (rotation % 360)/ps);
            picked = picked >= data.length ? (picked % data.length) : picked;
            if(oldpick.indexOf(picked) !== -1){
                d3.select(this).call(spin);
                return;
            } else {
                oldpick.push(picked);
            }
            rotation += 90 - Math.round(ps/2);
            vis.transition()
                .duration(3000)
                .attrTween("transform", rotTween)
                .each("end", function(){
                    //mark question as seen
                    d3.select(".slice:nth-child(" + (picked + 1) + ") path")
                        .attr("fill", "#111");
                    //populate question
                    d3.select("#question h1")
                        .text(data[picked].question);
                    oldrotation = rotation;
                
                    container.on("click", spin);
                });
        }
        //make arrow
        svg.append("g")
            .attr("transform", "translate(" + (w + padding.left + padding.right) + "," + ((h/2)+padding.top) + ")")
            .append("path")
            .attr("d", "M-" + (r*.15) + ",0L0," + (r*.05) + "L0,-" + (r*.05) + "Z")
            .style({"fill":"black"});
        //draw spin circle
        container.append("circle")
            .attr("cx", 0)
            .attr("cy", 0)
            .attr("r", 60)
            .style({"fill":"white","cursor":"pointer"});
        //spin text
        container.append("text")
            .attr("x", 0)
            .attr("y", 15)
            .attr("text-anchor", "middle")
            .text("SPIN")
            .style({"font-weight":"bold", "font-size":"30px"});
        
        
        function rotTween(to) {
          var i = d3.interpolate(oldrotation % 360, rotation);
          return function(t) {
            return "rotate(" + i(t) + ")";
          };
        }

text{
        font-family:Helvetica, Arial, sans-serif;
        font-size:11px;
        pointer-events:none;
    }
    #chart{
        position:absolute;
        width:100vw;
        height:100vh;
        top:0;
        left:0;
        text-align: center;
        
        display: -webkit-flex; /* Safari */  
        display: flex;
        -webkit-align-items: center; /* Safari 7.0+ */
        align-items: center;
        -webkit-justify-content: center;
        justify-content: center;
    }
    #question{
        position: absolute;
        width:100vw;
        height:100vh;   
        top:0;
        left:0;
        pointer-events: none;
    }
    #question h1{
        font-size: 50px;
        font-weight: bold;
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        position: absolute;
        padding: 0;
        margin: 0;
        top:50%;
        -webkit-transform:translate(0,-50%);
                transform:translate(0,-50%);
    }

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Wheel of Fortune Bingo</title>
    
</head>
<body>
    <div id="chart"></div>
    <div id="question"><h1></h1></div>
    <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</body>
</html>

推荐答案

您只需要设置适当的缓动即可.例如,使用D3 v3(根据您的情况),您可以执行以下操作:

You just need to set the adequate easing. For instance, using D3 v3 (your case), you can do:

.ease("cubic-out")

这是您所做的更改的代码:

Here is your code with that change:

var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
var fs = 33;
if (w > h) {
  w = w / 1.5;
} else {
  h = h / 1.5;
}

if (w > h) {
  fs = h / 25;
} else {
  fs = w / 25;
}
var padding = {
    top: 20,
    right: 40,
    bottom: 0,
    left: 0
  },
  w = w - padding.left - padding.right,
  h = h - padding.top - padding.bottom,
  r = Math.min(w, h) / 2,
  rotation = 0,
  oldrotation = 0,
  picked = 100000,
  oldpick = [],
  color = d3.scale.category20(); //category20c()
var data = [{
    "label": "100",
    "value": 1,
    "question": "What CSS property is used for specifying the area between the content and its border?"
  }, // padding
  {
    "label": "200",
    "value": 1,
    "question": "What CSS property is used for changing the font?"
  }, //font-family
  {
    "label": "300",
    "value": 1,
    "question": "What CSS property is used for changing the color of text?"
  }, //color
  {
    "label": "400",
    "value": 1,
    "question": "What CSS property is used for changing the boldness of text?"
  }, //font-weight
  {
    "label": "500",
    "value": 1,
    "question": "What CSS property is used for changing the size of text?"
  }, //font-size
  {
    "label": "600",
    "value": 1,
    "question": "What CSS property is used for changing the background color of a box?"
  }, //background-color
  {
    "label": "700",
    "value": 1,
    "question": "Which word is used for specifying an HTML tag that is inside another tag?"
  }, //nesting
  {
    "label": "GRAND",
    "value": 1,
    "question": "Which side of the box is the third number in: margin:1px 1px 1px 1px; ?"
  }, //bottom
  {
    "label": "",
    "value": 1,
    "question": "What are the fonts that don't have serifs at the ends of letters called?"
  }, //sans-serif
  {
    "label": "100",
    "value": 1,
    "question": "With CSS selectors, what character prefix should one use to specify a class?"
  }, //period
  {
    "label": "200",
    "value": 1,
    "question": "With CSS selectors, what character prefix should one use to specify an ID?"
  }, //pound sign
  {
    "label": "300",
    "value": 1,
    "question": "In an HTML document, which tag holds all of the content people see?"
  }, //<body>
  {
    "label": "400",
    "value": 1,
    "question": "In an HTML document, which tag indicates an unordered list?"
  }, //<ul>
  {
    "label": "500",
    "value": 1,
    "question": "In an HTML document, which tag indicates the most important heading of your document?"
  }, //<h1>
  {
    "label": "600",
    "value": 1,
    "question": "What CSS property is used for specifying the area outside a box?"
  }, //margin
  {
    "label": "700",
    "value": 1,
    "question": "What type of bracket is used for HTML tags?"
  }, //< >
  {
    "label": "",
    "value": 1,
    "question": "What type of bracket is used for CSS rules?"
  }, // { }
  {
    "label": "100",
    "value": 1,
    "question": "Which HTML tag is used for specifying a paragraph?"
  }, //<p>
  {
    "label": "200",
    "value": 1,
    "question": "What should always be the very first line of code in your HTML?"
  }, //<!DOCTYPE html>
  {
    "label": "300",
    "value": 1,
    "question": "What HTML tag holds all of the metadata tags for your page?"
  }, //<head>
  {
    "label": "400",
    "value": 1,
    "question": "In CSS, what character separates a property from a value?"
  }, // colon
  {
    "label": "500",
    "value": 1,
    "question": "What HTML tag holds all of your CSS code?"
  }, // <style>
  {
    "label": "600",
    "value": 1,
    "question": "What file extension should you use for your web pages?"
  }, // .html
  {
    "label": "700",
    "value": 1,
    "question": "Which coding language is used for marking up content and structure on a web page?"
  }, // HTML
  {
    "label": "",
    "value": 1,
    "question": "Which coding language is used for specifying the design of a web page?"
  }, // CSS
  //                    {"label":"SAMSUNG NOTE5", "value":1, "question":"Which coding language is used for adding functionality to a web page?"}, // JavaScript
  //                    {"label":"HP DESKTOP", "value":1, "question":"What CSS property is used for making the edges of a box visible?"}, // border
  //                    {"label":"15,000,000$", "value":1, "question":"What character symbol is used at the end of each CSS statement?"},//semi-colon
  //                    {"label":"BUGGATI", "value":1, "question":"By default, how wide is a <div> box?"}, //100%
  //                    {"label":" GOOGLE JOB", "value":1, "question":"What character symbol do I use to specify multiple CSS selectors in one code block?"} //comma
];
var svg = d3.select('#chart')
  .append("svg")
  .data([data])
  //.style("display", "flex")
  .attr("width", w + padding.left + padding.right)
  .attr("height", h + padding.top + padding.bottom);
var container = svg.append("g")
  .attr("class", "chartholder")
  .attr("transform", "translate(" + (w / 2 + padding.left) + "," + (h / 2 + padding.top) + ")");
var vis = container
  .append("g");

var pie = d3.layout.pie().sort(null).value(function(d) {
  return 1;
});
// declare an arc generator function
var arc = d3.svg.arc().outerRadius(r);
// select paths, use arc generator to draw
var arcs = vis.selectAll("g.slice")
  .data(pie)
  .enter()
  .append("g")
  .attr("class", "slice");

arcs.append("path")
  .attr("fill", function(d, i) {
    return color(i);
  })
  .attr("d", function(d) {
    return arc(d);
  });
// add the text
arcs.append("text")
  .attr("transform", function(d) {
    d.innerRadius = 0;
    d.outerRadius = r;
    d.angle = (d.startAngle + d.endAngle) / 2;
    return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")translate(" + (d.outerRadius - 10) + ")";
  })
  .attr("text-anchor", "end")
  .style("font-size", fs)
  .selectAll(null)
  .data((_, i) => data[i].label)
  .enter()
  .append("tspan")
  .attr("rotate", "90")
  .attr("dx", (_, i) => i ? "-1.5em" : null)
  .attr("y", 0)
  .text(function(d) {
    return d
  });

container.on("click", spin);

function spin(d) {

  container.on("click", null);
  //all slices have been seen, all done
  if (oldpick.length == data.length) {
    console.log("done");
    container.on("click", null);
    return;
  }
  var ps = 360 / data.length,
    pieslice = Math.round(1440 / data.length),
    rng = Math.floor((Math.random() * 1440) + 360);

  rotation = (Math.round(rng / ps) * ps);

  picked = Math.round(data.length - (rotation % 360) / ps);
  picked = picked >= data.length ? (picked % data.length) : picked;
  if (oldpick.indexOf(picked) !== -1) {
    d3.select(this).call(spin);
    return;
  } else {
    oldpick.push(picked);
  }
  rotation += 90 - Math.round(ps / 2);
  vis.transition()
    .duration(3000)
    .attrTween("transform", rotTween)
    .ease("cubic-out")
    .each("end", function() {
      //mark question as seen
      d3.select(".slice:nth-child(" + (picked + 1) + ") path")
        .attr("fill", "#111");
      //populate question
      d3.select("#question h1")
        .text(data[picked].question);
      oldrotation = rotation;

      container.on("click", spin);
    });
}
//make arrow
svg.append("g")
  .attr("transform", "translate(" + (w + padding.left + padding.right) + "," + ((h / 2) + padding.top) + ")")
  .append("path")
  .attr("d", "M-" + (r * .15) + ",0L0," + (r * .05) + "L0,-" + (r * .05) + "Z")
  .style({
    "fill": "black"
  });
//draw spin circle
container.append("circle")
  .attr("cx", 0)
  .attr("cy", 0)
  .attr("r", 60)
  .style({
    "fill": "white",
    "cursor": "pointer"
  });
//spin text
container.append("text")
  .attr("x", 0)
  .attr("y", 15)
  .attr("text-anchor", "middle")
  .text("SPIN")
  .style({
    "font-weight": "bold",
    "font-size": "30px"
  });


function rotTween(to) {
  var i = d3.interpolate(oldrotation % 360, rotation);
  return function(t) {
    return "rotate(" + i(t) + ")";
  };
}

text {
  font-family: Helvetica, Arial, sans-serif;
  font-size: 11px;
  pointer-events: none;
}

#chart {
  position: absolute;
  width: 100vw;
  height: 100vh;
  top: 0;
  left: 0;
  text-align: center;
  display: -webkit-flex;
  /* Safari */
  display: flex;
  -webkit-align-items: center;
  /* Safari 7.0+ */
  align-items: center;
  -webkit-justify-content: center;
  justify-content: center;
}

#question {
  position: absolute;
  width: 100vw;
  height: 100vh;
  top: 0;
  left: 0;
  pointer-events: none;
}

#question h1 {
  font-size: 50px;
  font-weight: bold;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  position: absolute;
  padding: 0;
  margin: 0;
  top: 50%;
  -webkit-transform: translate(0, -50%);
  transform: translate(0, -50%);
}

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>Wheel of Fortune Bingo</title>

</head>

<body>
  <div id="chart"></div>
  <div id="question">
    <h1></h1>
  </div>
  <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</body>

</html>

这篇关于使用D3对虚拟轮子进行动画处理,如何使其真实旋转?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆