重新定位SVG:使用d3.js创建的rect元素(使用d3或jQuery)



情况:

我正在用d3覆盖谷歌地图。它主要基于Mike Bostock的这个例子:http://bl.ocks.org/mbostock/899711

我正在从Rails 4应用程序中运行它,并从CDN加载到d3.js库中。因此,您可以访问d3.js和jQuery库,并希望避免添加更多库。

任务:

数据点(由svg:rect元素表示)有时会模糊谷歌地图上的地名。我希望它能让用户将光标放在这些数据点上,让它们瞬间弹出。

我应该注意的是,我试图让点随机重新定位,所以不能真正走悬停CSS路线。

所以。。。

  • 在SVG上放置一个事件侦听器(或rect,具体取决于实际操作的元素)

  • 编写一个回调函数,重新定位(偏移?动画?转换?)触发事件的元素

  • 等待setTimeout(或使用d3.each("end",function())),然后将元素返回到其先前的位置

简单吗

尝试次数:

因此,尝试使用d3,然后尝试使用jQuery。求助于jQuery,因为它似乎不处理SVG(尽管如果d3.js没有提供商品,我可能不得不使用jQuery SVG库)

对于d3尝试,事件处理程序的分配是可以的。我已经将处理程序分配给svg父元素,而不是rect子元素。

.on('mouseover', scatter)

这产生了事件触发的预期行为,以及当我鼠标悬停时调用的散射函数。

然而,我还没能对我想要的行为做出任何合理的表达。

我试过改变x,y的值。我尝试过更改顶部和左侧的值。对象上的值似乎发生了变化,但没有任何移动。我已经尝试过直接d3风格选择和d3风格转换。

我已经在rect子元素上尝试了相同的更改。这移动了rect元素,但没有附带SVG,因此它不会显示。

相关代码:

将SVG附加到每个数据点,为SVG设置正确的x和y,并为每个数据点添加一个事件侦听器。

var marker = layer.selectAll("svg")
.data(data)
.each(transformMarker)
.enter().append("svg:svg")
.each(transformMarker)
.on('mouseover', scatter);

另外,我对SVG父元素进行了样式设置,使其包含rect子元素,并对rects进行了样式设计,这样就可以在屏幕上实际显示一些内容。

transformMarker函数,您可能需要了解标记的定位方式。

function transformMarker(d) {
d = new google.maps.LatLng(J.lat(d), J.lon(d));
d = projection.fromLatLngToDivPixel(d);
return d3.select(this)
.style("left", (d.x) + "px")
.style("top", (d.y) + "px");

分散功能(带有一船console.log,这样你就可以看到发生了什么)

function scatter(d){
console.log("the event has fired")
d = new google.maps.LatLng(J.lat(d), J.lon(d));
d = projection.fromLatLngToDivPixel(d);
console.log(d.x)
console.log((d.x + 15) + "px")
console.log(this)
d3.select(this)
.attr("x", (d.x + 15))
.attr("y", (d.y + 15))
console.log(this)

控制台日志输出的

the event has fired
602.0032221842557
617.0032221842557px
<svg style=​"left:​ 602.0032221842557px;​ top:​ 230.00228557549417px;​" 
x="617.0032221842557" y=​"245.00228557549417">​
<rect height=​"7" width=​"7" fill=​"#138770" stroke=​"#0f0f02" stroke-width=​"0.5">​</rect>​
</svg>​
<svg style=​"left:​ 602.0032221842557px;​ top:​ 230.00228557549417px;​"
x="617.0032221842557" y=​"245.00228557549417">​
<rect height=​"7" width=​"7" fill=​"#138770" stroke=​"#0f0f02" stroke-width=​"0.5">​</rect>​
</svg>​

还有SVG的CSS,因为这可能会在中抛出扳手

.overlay, .overlay svg {
position: absolute;
}
.wrapper, .overlay svg {
/*border: 1px solid black;*/
width: 7px;
height: 7px;
transform: translateZ(0px);
-webkit-transform: translateZ(0px);
-moz-transform: translateZ(0px);
}

我离文明还有几天的时间,所以我希望能解决这个问题,并从Stack Overflow和d3谷歌小组那里得到一些新的方法和建议。

如果您有任何其他问题或需要更多信息,请告诉我。

回顾:

每个数据点矩形都在其自己的、独立的<svg>元素内。在transformMarker事件中,使用绝对定位(lefttop样式)来定位每个svg元素。

显然,如果要移动与数据点关联的svg图形,则需要更改<svg>元素的位置。您正试图使用xy属性来实现这一点,但SVG最初并不是这样定位的。只有当<svg>元素嵌入另一个SVG中时,这些属性才相关。你的是完全位于页面上的独立元素。因此,您需要更改绝对定位样式值:

function scatter(d){
d = new google.maps.LatLng(J.lat(d), J.lon(d));
d = projection.fromLatLngToDivPixel(d);
d3.select(this)
.style("left", (d.x + 15) + "px")
.style("top", (d.y + 15) + "px")
}

此外,我不确定为什么在初始化时调用transformMarker两次;你只需要它一次,但要确保你保留的版本是在创建元素后被称为的版本:

var marker = layer.selectAll("svg")
.data(data)
.enter().append("svg:svg")
.each(transformMarker)
.on('mouseover', scatter);

我会为Sass 检查这个漂亮的随机函数

module Sass::Script::Functions
def random(max = Sass::Script::Number.new(100))
Sass::Script::Number.new(rand(max.value), max.numerator_units, max.denominator_units)
end
end

要在sass中添加随机函数,请查看本指南。如果你想让你的项目在mousever上随机重新定位,我只需要使用random函数创建一个具有随机位置的类,并将该类移除/添加到元素中。当然,在我提供的链接中也有一些使用随机函数的例子。

当然,这很简单,只需将上面的代码添加到sass.rb中的配置/初始化程序中即可

它的一个问题是,如果你在类中设置它,它只会生成一次随机数。在刷新和重新加载时,它不会为它生成的css生成新的随机顶部/左侧等。我不确定是否有解决办法,或者这是否真的会有所帮助。但它很有趣,所以我想我无论如何都会发布它。

相关内容

  • 没有找到相关文章

最新更新