D3.js 拖动D3 v4中的旋转投影

D3.js 拖动D3 v4中的旋转投影,d3.js,D3.js,我无法通过d3.drag()使正交投影旋转。它没有反应: var projection = d3.geoOrthographic() .scale(100) .translate([500, 300]) .rotate([55,-40]) .center([0,0]) .clipAngle(90); var geoPath = d3.geoPath().projection(projection); svg.call(d3.drag().on('drag', dragge

我无法通过
d3.drag()
使正交投影旋转。它没有反应:

var projection = d3.geoOrthographic()
  .scale(100)
  .translate([500, 300])
  .rotate([55,-40])
  .center([0,0])
  .clipAngle(90);

var geoPath = d3.geoPath().projection(projection);

svg.call(d3.drag().on('drag', dragged));

function dragged() {
    var transform = d3.event.transform;
    var r = {x: λ(transform.x), y: φ(transform.y)};
    projection.rotate([origin.x + r.x * k, origin.y + r.y]);
    updatePaths(svg, graticule, geoPath);
};
我尝试用
console.log()
替换
draugd()
,但即使在这种情况下也没有发生任何事情(显然没有调用该函数)。我以类似的方式实现了
d3.zoom()
,没有任何问题。我做错了什么


jsiddle:

拖动没有响应的原因是您已经在调用SVG上的缩放,并且缩放处理平移。因此,要使
d3.drag
工作,必须使拖动行为优先于平移

除此之外,拖动事件没有
d3.event.transform
。根据,以下是事件对象中的属性:

  • 目标-关联的拖动行为
  • 键入-字符串“开始”、“拖动”或“结束”;见drag.on
  • 主题-拖动主题,由drag.subject定义
  • x——主体的新x坐标;请参见drag.container
  • y—主体的新y坐标;请参见drag.container
  • dx-自上次拖动事件以来x坐标的变化
  • dy-自上次拖动事件以来y坐标的变化
  • 标识符-字符串“鼠标”或数字触摸标识符
  • active—当前活动的拖动手势数
  • sourceEvent—基础输入事件,如mousemove或 触摸移动
因此,您的
转换
将是
未定义的
。。。如果可以调用
拖动

解决方案1 只需放下
d3。拖动
,使用缩放的点击和拖动(平移)来旋转地球仪

这是您的代码,改动很小(我将所有内容都放在缩放的
中)。使用鼠标滚轮进行缩放,然后单击地球仪进行拖动:

函数createMap(){
可变宽度=400,
高度=300,
比例=100,
lastX=0,
lastY=0,
原点={
x:55,
y:-40
};
var svg=d3。选择('body')。追加('svg'))
.样式(“宽度”,400)
.style('height',300)
.style('边框','1px浅灰色实心')
var projection=d3.geoporthographic()
.比例尺(比例尺)
.translate([宽度/2,高度/2])
.旋转([origin.x,origin.y])
.center([0,0])
.clipAngle(90);
var geoPath=d3.geoPath()
.投影(投影);
变量分划=d3.地理分划();
//缩放和旋转
调用(d3.zoom().on('zoom',zomed));
//源代码段http://stackoverflow.com/questions/36614251
varλ=d3.scaleLinear()
.domain([-width,width])
.范围([-180180])
varφ=d3.scaleLinear()
.domain([-高度,高度])
.范围([90,-90]);
append('path')
.基准面(分划)
.attr('类','分划')
.attr('d',地理路径);
函数缩放(){
var transform=d3.event.transform;
变量r={
x:λ(变换x),
y:φ(变换y)
};
var k=Math.sqrt(100/projection.scale());
if(d3.event.sourceEvent.wheelDelta){
投影.缩放(缩放*变换.k)
transform.x=lastX;
transform.y=lastY;
}否则{
投影旋转([origin.x+r.x,origin.y+r.y]);
lastX=transform.x;
lastY=transform.y;
}
更新路径(svg、分划、地理路径);
};
};
函数更新路径(svg、分划、地理路径){
svg.selectAll('path.gracile').datum(gracile.attr('d',geoPath));
};
createMap()
分划{
填充:无;
行程:777;
笔划宽度:.5px;
笔画不透明度:.5;
}

它看起来应该可以工作了-你能发布一个完整的代码片段或带有一个坏拖拽的bl.ock吗?谢谢!解决方案2非常有效。但使用解决方案1,缩放后尝试拖动时,位置会跳跃。你知道为什么吗?@Siralen这很奇怪,它不会跳到我身上。不会吧?尝试放大,然后单击任意位置-@siralen现在我看到了。这是因为
transform.x
transform.y
在缩放时会发生变化。我现在没有时间更好地修复它(可以自由地发布一个新问题),但这里有一个黑客:。我也编辑了答案。@PBrockmann:代码不是我的,我只是给OP提供了一个解决方案。这样做时,我不会整体修改他们的代码。