情况:
我正在用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
事件中,使用绝对定位(left
和top
样式)来定位每个svg元素。
显然,如果要移动与数据点关联的svg图形,则需要更改<svg>
元素的位置。您正试图使用x
和y
属性来实现这一点,但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生成新的随机顶部/左侧等。我不确定是否有解决办法,或者这是否真的会有所帮助。但它很有趣,所以我想我无论如何都会发布它。