d3用时钟中的两个指针变换原点

d3 transform-origin with two needles in a clock

本文关键字:两个 指针 变换 原点 时钟 d3      更新时间:2023-09-26

这是我使用D3的第一个项目,我正在使用WebAudioAPI获取麦克风输入,以表示指针指向的位置。我让他们移动,但我的分针正在旋转,没有在特定的点上旋转,也没有静止。

var width = 960,
height = 500,
τ = 2 * Math.PI; 
var arc = d3.svg.arc()
 .innerRadius(180) 
 .outerRadius(240)
 .startAngle(0);

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

var background = svg.append("path")
 .datum({endAngle: 100})
 .style("fill", "#ddd")
 .attr("d", arc);

var foreground = svg.append("path")
 .datum({endAngle: .1 * τ})
 .style("fill", "orange")
 .attr("d", arc);
var gaugeGroup = svg.append("g")
 .datum({endAngle: .1 * τ})
 .attr("class", "hour hands")
.attr("transform", "translate( 0 , 0 )");
var hour = gaugeGroup.append("path")
 .attr("class", "tri")
 .attr("d", "M" + (600/2 + 12) + " " + (240 + 10) + " L" + 600/2 + " 0 L" + (600/2 - 3) + " " + (240 + 10) + " C" + (600/2 - 3) + " " + (240 + 20) + " " + (600/2 + 3) + " " + (240 + 20) + " " + (600/2 + 12) + " " + (240 + 10) + " Z")
// .attr("transform", "rotate(-60, " + -70 + "," + (389) + ")");
.attr("transform", "translate(-300,-250) rotate(0,0,0)");
var minute = gaugeGroup.append("path")
 .attr("class", "tri")
 .attr("d", "M" + (300/2 + 3) + " " + (170 + 10) + " L" + 300/2 + " 0 L" + (300/2 - 3) + " " + (170 + 10) + " C" + (300/2 - 3) + " " + (170 + 20) + " " + (300/2 + 3) + " " + (170 + 20) + " " + (300/2 + 3) + " " + (170 + 10) + " Z")
.attr("transform", "translate(-150,-188) rotate(0,0,0)");

//添加背景弧,从0到100%(τ)。

function setValues(note, detune){
 foreground.transition()
  .duration(190)
  .call(arcTween, note / 10);
 gaugeGroup
 .transition()
 .duration(200)
 .attr("transform", "rotate("+note *τ +",0,0)");
 minute
 .transition()
 .duration(150)
 .attr("transform","rotate("+detune * τ +",200,6)");
}

如果不访问工作代码(或fiddle),几乎不可能对此进行调试。但从一眼望去,有几件事很突出:

  • 将旋转应用于包含时针和分针的整个gaugeGroup,然后将局部旋转应用于minute组。这可能是合适的,但仅当detune是在0+/-n范围内的相对值时(即,当detune == 0时,分针和时针预计会重叠)。如果detune是用绝对值表示的,这意味着您的代码正在转换分针两次——一次是通过gaugeGroup,另一次是经过minute

  • 如果设置为可以简单地围绕原点0,0旋转minute,而不必在rotate("+detune * τ +",200,6)中指定不同的旋转原点,那么您将更容易理解发生了什么并对其进行调试。为此,您需要修改分钟路径的"d"属性(如minute.attr("d", ...)),使其轴心点位于0,0。在此之前,为了调试的目的,您可以将minutes路径简化为从原点向外的一条线——比如M0 0 L150 0(看看它是如何从0,0开始的)——在不偏移旋转原点的情况下使旋转正常工作,然后返回更复杂的路径。