d3 transform-origin 时钟中有两个指针

d3 transform-origin with two needles in a clock

这是我使用 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。在你这样做之前,为了调试的目的,你可以将分钟路径简化为从原点开始的一条线——类似 M0 0 L150 0 的东西(看看它是如何从 0,0 开始的)——让旋转正常工作不偏移旋转原点,然后带回更复杂的路径。