过渡不起作用

时间:2014-12-02 00:12:47

标签: javascript d3.js

我的目标是给定一个以秒为单位的值(resp_time),我想在反锁定方向创建一个计数器,一旦resp_time变为0就结束。

我正在遵循本教程:http://bl.ocks.org/mbostock/1096355来创建一个极地时钟。但我需要电弧减少,因为逆时针方向。我尝试更新endAngle值,但它似乎不起作用。 这是我的代码:

var width = 960,
    height = 800,
    radius = Math.min(width, height) / 1.9,
    spacing = .09;

var resp_time = 61;

var rh = parseInt(resp_time/3600), rm = parseInt((resp_time- rh*3600)/60), rs = parseInt((resp_time- rh*3600 - rm*60)%60);

var color = d3.scale.linear()
    .range(["hsl(-180,50%,50%)", "hsl(180,50%,50%)"])
    .interpolate(interpolateHsl);

var t; 

var arc = d3.svg.arc()
    .startAngle(0)
    .endAngle(function(d) { return d.value * 2 * Math.PI; })
    .innerRadius(function(d) { return d.index * radius; })
    .outerRadius(function(d) { return (d.index + spacing) * radius; });

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

var field = svg.selectAll("g")
    .data(fields)
  .enter().append("g");

field.append("path");

field.append("text");

d3.transition().duration(0).each(tick);

d3.select(self.frameElement).style("height", height + "px");

function tick() {
  field = field
      .each(function(d) { this._value = d.value; })
      .data(fields)
      .each(function(d) { d.previousValue = this._value; });

  field.select("path")
    .transition()
      .ease("elastic")
      .attrTween("d", arcTween)
      .style("fill", function(d) { return color(d.value); });

  field.select("text")
      .attr("dy", function(d) { return d.value < .5 ? "-.5em" : "1em"; })
      .text(function(d) { return d.text; })
    .transition()
      .ease("elastic")
      .attr("transform", function(d) {
        return "rotate(" + 360 * d.value + ")"
            + "translate(0," + -(d.index + spacing / 2) * radius + ")"
            + "rotate(" + (d.value < .5 ? -90 : 90) + ")"
      });

    if (resp_time > 0)
    {
        resp_time = resp_time - 1;
        rh = parseInt(resp_time/3600), rm = parseInt((resp_time- rh*3600)/60), rs = parseInt((resp_time- rh*3600 - rm*60)%60);
        t = setTimeout(tick, 1000);
    }

}

function arcTween(d) {
  console.log(d);
  var i = d3.interpolateNumber(d.previousValue, d.value);
  return function(t) { d.value = i(t); return arc(d); };
}


function fields() {
  console.log(rs);
  return [
    {index: .3, text: rs+"s", value: rs},
    {index: .2, text: rm+"m", value: rm},
    {index: .1, text: rh+"h", value: rh}
  ];
}

function interpolateHsl(a, b) {
  var i = d3.interpolateString(a, b);
  return function(t) {
    return d3.hsl(i(t));
  };
}

这只会导致3个静态同心圆(因为我只绘制分钟,秒和小时)而没有过渡。

我不确定如何从这里开始。我应该做些什么改变才能让它发挥作用?请帮帮我。

1 个答案:

答案 0 :(得分:0)

此代码中的

d.value应在[0,1]范围内,因此您需要除以字段生成器中的最大值:

function fields() {
  console.log(rs);
  return [
    {index: .3, text: rs+"s", value: rs/60},
    {index: .2, text: rm+"m", value: rm/60},
    {index: .1, text: rh+"h", value: rh/24}
  ];
}

我注意到了这一点,因为console.log(rs)打印的值范围为[0,60],而arc.endAngle expects a radian value。如果用代码中的endAngle提供程序替换[0,60],就会得到一个过度伤口的时钟指针。

var arc = d3.svg.arc()
    .startAngle(0)
    .endAngle(function(d) { return d.value * 2 * Math.PI; })

&#13;
&#13;
var width = 960,
    height = 800,
    radius = Math.min(width, height) / 1.9,
    spacing = .09;

var resp_time = 61;

var rh = parseInt(resp_time/3600), rm = parseInt((resp_time- rh*3600)/60), rs = parseInt((resp_time- rh*3600 - rm*60)%60);

var color = d3.scale.linear()
    .range(["hsl(-180,50%,50%)", "hsl(180,50%,50%)"])
    .interpolate(interpolateHsl);

var t; 

var arc = d3.svg.arc()
    .startAngle(0)
    .endAngle(function(d) { return d.value * 2 * Math.PI; })
    .innerRadius(function(d) { return d.index * radius; })
    .outerRadius(function(d) { return (d.index + spacing) * radius; });

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

var field = svg.selectAll("g")
    .data(fields)
  .enter().append("g");

field.append("path");

field.append("text");

d3.transition().duration(0).each(tick);

d3.select(self.frameElement).style("height", height + "px");

function tick() {
  field = field
      .each(function(d) { this._value = d.value; })
      .data(fields)
      .each(function(d) { d.previousValue = this._value; });

  field.select("path")
    .transition()
      .ease("elastic")
      .attrTween("d", arcTween)
      .style("fill", function(d) { return color(d.value); });

  field.select("text")
      .attr("dy", function(d) { return d.value < .5 ? "-.5em" : "1em"; })
      .text(function(d) { return d.text; })
    .transition()
      .ease("elastic")
      .attr("transform", function(d) {
        return "rotate(" + 360 * d.value + ")"
            + "translate(0," + -(d.index + spacing / 2) * radius + ")"
            + "rotate(" + (d.value < .5 ? -90 : 90) + ")"
      });

    if (resp_time > 0)
    {
        resp_time = resp_time - 1;
        rh = parseInt(resp_time/3600), rm = parseInt((resp_time- rh*3600)/60), rs = parseInt((resp_time- rh*3600 - rm*60)%60);
        t = setTimeout(tick, 1000);
    }

}

function arcTween(d) {
  console.log(d);
  var i = d3.interpolateNumber(d.previousValue, d.value);
  return function(t) { d.value = i(t); return arc(d); };
}


function fields() {
  console.log(rs);
  return [
    {index: .3, text: rs+"s", value: rs/60},
    {index: .2, text: rm+"m", value: rm/60},
    {index: .1, text: rh+"h", value: rh/24}
  ];
}

function interpolateHsl(a, b) {
  var i = d3.interpolateString(a, b);
  return function(t) {
    return d3.hsl(i(t));
  };
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;
&#13;
&#13;