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 开始的)——让旋转正常工作不偏移旋转原点,然后带回更复杂的路径。
这是我使用 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 开始的)——让旋转正常工作不偏移旋转原点,然后带回更复杂的路径。