D3:通过平滑移动将背景重置为起始位置来进行背景更新

问题描述 投票:0回答:1

我对D3还是很陌生,但是将几个示例放在一起,我几乎满足了我的需要:一个D3量具,其数据在后台进行更新,您可以在操作中看到它here(归功于Kazu对于original pen)(对不起,长代码)

var name = "Test";
var gaugeMaxValue = 100; 

function getrandom() {
    var min=0;
    var max=100;
    var value = (((Math.random() * (max - min) + min)).toFixed(0));
    return value
}

   function moveit() {
     //bpercent=getrandom()/100/2;
     reading=getrandom()
     bpercent=reading/100
     document.getElementById('Name').innerHTML=reading;
     needle.moveTo(bpercent);
     displayValue
    console.log(bpercent + ", " + typeof(percent)); 
 }

var value=getrandom();

////////////////////////

var needleClient;


var barWidth, chart, chartInset, degToRad, repaintGauge,
    height, margin, numSections, padRad, percToDeg, percToRad, 
    percent, radius, sectionIndx, svg, totalPercent, width;

var percent = value / gaugeMaxValue;

  numSections = 1;
  sectionPerc = 1 / numSections / 2;
  padRad = 0.025;
  chartInset = 10;

  // Orientation of gauge:
  totalPercent = .75;

  el = d3.select('.chart-gauge');

  margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 20
  };

  width = el[0][0].offsetWidth - margin.left - margin.right;
  height = width;
  radius = Math.min(width, height) / 2;
  barWidth = 40 * width / 300;

  //Utility methods 

  percToDeg = function(perc) {
    return perc * 360;
  };

  percToRad = function(perc) {
    return degToRad(percToDeg(perc));
  };

  degToRad = function(deg) {
    return deg * Math.PI / 180;
  };

  // Create SVG element
  svg = el.append('svg').attr('width', width + margin.left + margin.right).attr('height', height + margin.top + margin.bottom);

  // Add layer for the panel
  chart = svg.append('g').attr('transform', "translate(" + ((width + margin.left) / 2) + ", " + ((height + margin.top) / 2) + ")");


  chart.append('path').attr('class', "arc chart-first");
  chart.append('path').attr('class', "arc chart-second");
  chart.append('path').attr('class', "arc chart-third");


  arc3 = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth)
  arc2 = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth)
  arc1 = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth)

  repaintGauge = function () 
  {
    perc = 0.5;
    var next_start = totalPercent;
    arcStartRad = percToRad(next_start);
    arcEndRad = arcStartRad + percToRad(perc / 3);
    next_start += perc / 3;


    arc1.startAngle(arcStartRad).endAngle(arcEndRad);

    arcStartRad = percToRad(next_start);
    arcEndRad = arcStartRad + percToRad(perc / 3);
    next_start += perc / 3;

    arc2.startAngle(arcStartRad + padRad).endAngle(arcEndRad);

    arcStartRad = percToRad(next_start);
    arcEndRad = arcStartRad + percToRad(perc / 3);

    arc3.startAngle(arcStartRad + padRad).endAngle(arcEndRad);

    chart.select(".chart-first").attr('d', arc1);
    chart.select(".chart-second").attr('d', arc2);
    chart.select(".chart-third").attr('d', arc3);

  }
/////////

    var dataset = [{metric:name, value: value}]

    var texts = svg.selectAll("text")
                .data(dataset)
                .enter();

    texts.append("text")
         .text(function(){
              return dataset[0].metric;
         })
         .attr('id', "Name")
         .attr('transform', "translate(" + ((width + margin.left) / 6) + ", " + ((height + margin.top) / 1.5) + ")")
         .attr("font-size",25)
         .style("fill", "#000000");


   var trX = 180 - 210 * Math.cos(percToRad(percent / 2)); 
var trY = 195 - 210 * Math.sin(percToRad(percent / 2));
// (180, 195) are the coordinates of the center of the gauge.

displayValue = function() {
                texts.append("text")
                    .text(function(){
                        return dataset[0].value;
                    })
                    .attr('id', "Value")
                    .attr('transform', "translate(" + trX + ", " + trY+ ")")
                    .attr("font-size",18)
                    .style("fill", '#000000');
            }


    texts.append("text")
        .text(function(){
            return 0;
        })
        .attr('id', 'scale0')
        .attr('transform', "translate(" + ((width + margin.left) / 100 ) + ", " + ((height + margin.top) / 2) + ")")
        .attr("font-size", 15)
        .style("fill", "#000000");

    texts.append("text")
        .text(function(){
            return gaugeMaxValue/2;
        })
        .attr('id', 'scale10')
        .attr('transform', "translate(" + ((width + margin.left) / 2.15 ) + ", " + ((height + margin.top) / 30) + ")")
        .attr("font-size", 15)
        .style("fill", "#000000");


    texts.append("text")
        .text(function(){
            return gaugeMaxValue;
        })
        .attr('id', 'scale20')
        .attr('transform', "translate(" + ((width + margin.left) / 1.03 ) + ", " + ((height + margin.top) / 2) + ")")
        .attr("font-size", 15)
        .style("fill", "#000000");

  var Needle = (function() {

    //Helper function that returns the `d` value for moving the needle
    var recalcPointerPos = function(perc) {
      var centerX, centerY, leftX, leftY, rightX, rightY, thetaRad, topX, topY;
      thetaRad = percToRad(perc / 2);
      centerX = 0;
      centerY = 0;
      topX = centerX - this.len * Math.cos(thetaRad);
      topY = centerY - this.len * Math.sin(thetaRad);
      leftX = centerX - this.radius * Math.cos(thetaRad - Math.PI / 2);
      leftY = centerY - this.radius * Math.sin(thetaRad - Math.PI / 2);
      rightX = centerX - this.radius * Math.cos(thetaRad + Math.PI / 2);
      rightY = centerY - this.radius * Math.sin(thetaRad + Math.PI / 2);


      return "M " + leftX + " " + leftY + " L " + topX + " " + topY + " L " + rightX + " " + rightY;
    };

    function Needle(el) {
      this.el = el;
      this.len = width / 2.5;
      this.radius = this.len / 8;
    }

    Needle.prototype.render = function() {
      this.el.append('circle').attr('class', 'needle-center').attr('cx', 0).attr('cy', 0).attr('r', this.radius);
      return this.el.append('path').attr('class', 'needle').attr('id', 'client-needle').attr('d', recalcPointerPos.call(this, 0));
    };

    Needle.prototype.moveTo = function(perc) {
      var self,
          oldValue = this.perc || 0;

      this.perc = perc;
      self = this;

      // Reset pointer position
      this.el.transition().delay(100).ease('quad').duration(200).select('.needle').tween('reset-progress', function() {
        return function(percentOfPercent) {
          var progress = (1 - percentOfPercent) * oldValue;
          //var progress = oldValue;



          repaintGauge(progress);
          return d3.select(this).attr('d', recalcPointerPos.call(self, progress));
        };
      });

      this.el.transition().delay(300).ease('bounce').duration(1500).select('.needle').tween('progress', function() {
        return function(percentOfPercent) {
          var progress = percentOfPercent * perc;

          repaintGauge(progress);
          return d3.select(this).attr('d', recalcPointerPos.call(self, progress));
        };
      });

    };

    return Needle;

  })();

  needle = new Needle(chart);
  needle.render();

  moveit();
  setInterval(moveit, 1500);

问题是,每次更新都首先将指针移至0位置,而我希望它从'当前'值移至下一个。

我能否请教一些建议?非常感谢!

javascript css d3.js
1个回答
0
投票

我更改了moveTo()函数。它正在使用从0开始的进度。

我相信它正在按照您想要的方式工作

<!DOCTYPE html>
<html>
<head>
<title>Gradient Background</title>
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<style>
.chart-gauge
{
  width: 400px;
  margin: 100px auto  
 } 
.chart-first
{
	fill: #9FBD35;
}
.chart-second
{
	fill: #F2BA3A;
}
.chart-third
{
	fill: #FB3033;
}

.needle, .needle-center
{
	fill: #000000;
}
.text {
	color: "#112864";
	font-size: 16px;
}


svg {
  font: 10px sans-serif;
}
</style>
</head>
<body id="gradient">
 
<div class="chart-gauge">

<script type="text/javascript">
var name = "Test";
var gaugeMaxValue = 100; 

function getrandom() {
	var min=0;
	var max=100;
	var value = (((Math.random() * (max - min) + min)).toFixed(0));
	return value
}

function moveit() {
	//bpercent=getrandom()/100/2;
	reading=getrandom()
	bpercent=reading/100
	document.getElementById('Name').innerHTML=reading;
	needle.moveTo(bpercent);
}

var value=getrandom();

////////////////////////

var needleClient;


var barWidth, chart, chartInset, degToRad, repaintGauge,
height, margin, numSections, padRad, percToDeg, percToRad, 
percent, radius, sectionIndx, svg, totalPercent, width;

var percent = value / gaugeMaxValue;

numSections = 1;
sectionPerc = 1 / numSections / 2;
padRad = 0.025;
chartInset = 10;

// Orientation of gauge:
totalPercent = .75;

el = d3.select('.chart-gauge');

margin = {
top: 20,
right: 20,
bottom: 30,
left: 20
};

width = el[0][0].offsetWidth - margin.left - margin.right;
height = width;
radius = Math.min(width, height) / 2;
barWidth = 40 * width / 300;

//Utility methods 

percToDeg = function(perc) {
return perc * 360;
};

percToRad = function(perc) {
return degToRad(percToDeg(perc));
};

degToRad = function(deg) {
return deg * Math.PI / 180;
};

// Create SVG element
svg = el.append('svg').attr('width', width + margin.left + margin.right).attr('height', height + margin.top + margin.bottom);

// Add layer for the panel
chart = svg.append('g').attr('transform', "translate(" + ((width + margin.left) / 2) + ", " + ((height + margin.top) / 2) + ")");


chart.append('path').attr('class', "arc chart-first");
chart.append('path').attr('class', "arc chart-second");
chart.append('path').attr('class', "arc chart-third");


arc3 = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth)
arc2 = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth)
arc1 = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth)

repaintGauge = function () {
	perc = 0.5;
	var next_start = totalPercent;
	arcStartRad = percToRad(next_start);
	arcEndRad = arcStartRad + percToRad(perc / 3);
	next_start += perc / 3;
	arc1.startAngle(arcStartRad).endAngle(arcEndRad);

	arcStartRad = percToRad(next_start);
	arcEndRad = arcStartRad + percToRad(perc / 3);
	next_start += perc / 3;

	arc2.startAngle(arcStartRad + padRad).endAngle(arcEndRad);

	arcStartRad = percToRad(next_start);
	arcEndRad = arcStartRad + percToRad(perc / 3);

	arc3.startAngle(arcStartRad + padRad).endAngle(arcEndRad);

	chart.select(".chart-first").attr('d', arc1);
	chart.select(".chart-second").attr('d', arc2);
	chart.select(".chart-third").attr('d', arc3);
}
/////////

var dataset = [{metric:name, value: value}]

var texts = svg.selectAll("text")
		.data(dataset)
		.enter();

texts.append("text")
 .text(function(){
	  return dataset[0].metric;
 })
 .attr('id', "Name")
 .attr('transform', "translate(" + ((width + margin.left) / 6) + ", " + ((height + margin.top) / 1.5) + ")")
 .attr("font-size",25)
 .style("fill", "#000000");


var trX = 180 - 210 * Math.cos(percToRad(percent / 2)); 
var trY = 195 - 210 * Math.sin(percToRad(percent / 2));
// (180, 195) are the coordinates of the center of the gauge.

displayValue = function() {
	texts.append("text")
		.text(function(){
			return dataset[0].value;
		})
		.attr('id', "Value")
		.attr('transform', "translate(" + trX + ", " + trY+ ")")
		.attr("font-size",18)
		.style("fill", '#000000');
}


texts.append("text")
.text(function(){
	return 0;
})
.attr('id', 'scale0')
.attr('transform', "translate(" + ((width + margin.left) / 100 ) + ", " + ((height + margin.top) / 2) + ")")
.attr("font-size", 15)
.style("fill", "#000000");

texts.append("text")
.text(function(){
	return gaugeMaxValue/2;
})
.attr('id', 'scale10')
.attr('transform', "translate(" + ((width + margin.left) / 2.15 ) + ", " + ((height + margin.top) / 30) + ")")
.attr("font-size", 15)
.style("fill", "#000000");


texts.append("text")
.text(function(){
	return gaugeMaxValue;
})
.attr('id', 'scale20')
.attr('transform', "translate(" + ((width + margin.left) / 1.03 ) + ", " + ((height + margin.top) / 2) + ")")
.attr("font-size", 15)
.style("fill", "#000000");

var Needle = (function() {

	//Helper function that returns the `d` value for moving the needle
	var recalcPointerPos = function(perc) {
		var centerX, centerY, leftX, leftY, rightX, rightY, thetaRad, topX, topY;
		thetaRad = percToRad(perc / 2);
		centerX = 0;
		centerY = 0;
		topX = centerX - this.len * Math.cos(thetaRad);
		topY = centerY - this.len * Math.sin(thetaRad);
		leftX = centerX - this.radius * Math.cos(thetaRad - Math.PI / 2);
		leftY = centerY - this.radius * Math.sin(thetaRad - Math.PI / 2);
		rightX = centerX - this.radius * Math.cos(thetaRad + Math.PI / 2);
		rightY = centerY - this.radius * Math.sin(thetaRad + Math.PI / 2);


		return "M " + leftX + " " + leftY + " L " + topX + " " + topY + " L " + rightX + " " + rightY;
	};

	function Needle(el) {
		this.el = el;
		this.len = width / 2.5;
		this.radius = this.len / 8;
	}

	Needle.prototype.render = function() {
		this.el.append('circle').attr('class', 'needle-center').attr('cx', 0).attr('cy', 0).attr('r', this.radius);
		return this.el.append('path').attr('class', 'needle').attr('id', 'client-needle').attr('d', recalcPointerPos.call(this, 0));
	};

	Needle.prototype.moveTo = function(perc) {
		var self,
		oldValue = (this.perc) ? this.perc : 0;

		this.perc = perc;
		self = this;


		this.el.transition().delay(300).ease('bounce').duration(1500).select('.needle').tween('progress', function() {
			return function(percentOfPercent) {
				var progress = oldValue + (percentOfPercent * (perc - oldValue));

				repaintGauge(progress);
				return d3.select(this).attr('d', recalcPointerPos.call(self, progress));
			};
		});

	};

	return Needle;

})();

needle = new Needle(chart);
needle.render();

moveit();
setInterval(moveit, 1500);

</script>
</body>
</html>
© www.soinside.com 2019 - 2024. All rights reserved.