- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
设置:我正在构建一个 globe 应用程序,以更好地直观地表示世界各地区的数据。它是使用 topojson 构建几何体的 d3.js 构建的。
我目前正在实现 ivyywang 实现的拖动 here .(不要迷失在数学函数中,除非你是“数学 Nerd 大师”)
我的项目目前是here .
问题:我得到了正交投影的地球,并且成功地实现了拖动功能......除了。只要我的光标在某个国家/地区的边界内,我就只能单击并拖动地球。如何投影我的 SVG 以便整个 Canvas 响应我的拖动事件?
相关代码:
首先,我从 MySQL 请求中获取一些数据并将其存储在 countryStatistics 中。我通过以下函数运行它以更好地对其进行索引。
var countryStatistics = (returned from mySQL query)
//this function build dataById[] setting data keyed to idTopo
function keyIdToData(d){
countryStatistics.forEach(function(d) {
dataById[d.idTopo] = d;
});
}
function visualize(statisticalData, mapType){
//pass arguments each function call to decide what data to viasually display, and what map type to use
var margin = {top: 100, left: 100, right: 100, bottom:100},
height = 800 - margin.top - margin.bottom,
width = 1200 - margin.left - margin.right;
//a simple color scale to correlate to data
var colorScale = d3.scaleLinear()
.domain([0, 100])
.range(["#646464", "#ffff00"])
//create svg
var svg = d3.select("#map")
.append("svg")
.attr("height", height + margin.top + margin.bottom)
.attr("width", width + margin.left + margin.right)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
//here I attmpt to fill the svg with a different color. but it is unresponsive
.attr("fill", "blue")
正如您在此代码块末尾看到的,我在 SVG 元素上调用了 .attr("fill"... 但无法渲染颜色。也许这与我的光标在这个空间。
继续...
//set projection type to 2D map or 3d globe dependinding on argument passed see function below
var projection = setMapType(mapType, width, height);
//a function to call on visualize() to set projection type for map style.
function setMapType(mapType, width, height) {
if(mapType === "mercator") {
let projection = d3.geoMercator()
.translate([ width / 2, height / 2 ])
.scale(180)
return projection;
}else if (mapType === "orthographic"){
let projection = d3.geoOrthographic()
.clipAngle(90)
.scale(240);
return projection;
}
//pass path lines to projections
var path = d3.geoPath()
.projection(projection);
//here I create and call the drag function only when globe projection is displayed elected
if(mapType == "orthographic"){
var drag = d3.drag()
.on("start", dragstarted)
.on("drag", dragged);
svg.call(drag);
}
//coordinate variables
var gpos0,
o0;
function dragstarted(){
gpos0 = projection.invert(d3.mouse(this));
o0 = projection.rotate();
}
function dragged(){
var gpos1 = projection.invert(d3.mouse(this));
o0 = projection.rotate();
var o1 = eulerAngles(gpos0, gpos1, o0);
projection.rotate(o1);
svg.selectAll("path").attr("d", path);
}
//load in the topojson file
d3.queue()
.defer(d3.json, "world110m.json")
.await(ready)
以上函数是指计算正交旋转所需的数学函数。您可以在顶部第一个链接中 ivyywang 的代码块中看到它们。
function ready (error, data){
if (error) throw error;
//output data to see what is happening
console.log("topojson data: ")
console.log(data);
//I suspect there may be an issue with this code.
countries = topojson.feature(data, data.objects.countries)
//bind dataById data into countries topojson variable
.features.map(function(d) {
d.properties = dataById[d.id];
return d
});
console.log("countries:")
console.log(countries)
我怀疑上面的国家变量可能是罪魁祸首,主要是因为我不完全理解这段代码。在此变量中,我将由 keyIdToData()
处理的 countryStatistics 数据作为嵌套对象“属性”与我的 topojson 数据绑定(bind)。我控制台记录它以查看数据。
svg.selectAll(".country")
.data(countries)
.enter().append("path")
.attr("class", "country")
.attr("d", path)
//make fill gradient depend on data
.attr("fill", function(countries){
//if no data, country is grey
if(countries.properties == undefined){
return "rgb(100 100 100)";
}
//else pass data to colorScale()
return colorScale(countries.properties.literacy)
})
.on('mouseover', function(d) {
//on hover set class hovered which simply changes color with a transition time
d3.select(this).classed("hovered", true)
})
.on('mouseout', function(d) {
d3.select(this).classed("hovered", false)
})
}
};
终于有了这个小功能
//this function build dataById[] setting data keyed to idTopo
function keyIdToData(d){
countryStatistics.forEach(function(d) {
dataById[d.idTopo] = d;
});
}
可能性:我的 SVG 渲染似乎排除了我的空白(非国家/地区)区域。我的 SVG 结构可能有问题吗?或者当我更改数据并将我的 dataById 附加到我的 topojson 时,我可能会干扰 SVG 构造?
感谢您让键盘忍者走到这一步。有什么想法吗?
最佳答案
问题
您的鼠标交互仅在父级内绘制路径的位置 g
,而不是中间的空间。您申请的填充 g
被您应用于子路径的样式覆盖。
看看你有什么,你的变量svg
持有g
:
//create svg
var svg = d3.select("#map")
.append("svg")
...
.append("g") // return a newly created and selected g
...
.attr("fill", "blue") // returns same g
对于鼠标交互,g
只能与其中存在的元素进行交互。对于 g
, fill
属性不会直接做任何事情,它只应用于表示元素(和动画):
As a presentation attribute, it [fill] can be applied to any element but it has effect only on the following eleven elements:
<altGlyph>
,<circle>
,<ellipse>
,<path>
,<polygon>
,<polyline>
,<rect>
,<text>
,<textPath>
,<tref>
, and<tspan>
(MDN)
fill
的使用在 g
上而是为子元素着色,你的路径。虽然你直接给它们上色,所以蓝色没有视觉效果:
var g = d3.select("body")
.append("svg")
.append("g")
.attr("fill","orange");
// Inherit fill:
g.append("rect")
.attr("width",50)
.attr("height",50)
// Override inheritable fill:
g.append("rect")
.attr("x", 100)
.attr("width",50)
.attr("height",50)
.attr("fill","steelblue");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
解决方案
您需要创建一个元素来与之交互,以便在当前没有路径的地方拖动。
现在,我认为您不想将整个 svg 背景设为蓝色,只是将地球上不属于某个国家/地区的部分设为蓝色。您可以使用 geojson 球体执行此操作。从技术上讲,d3 不是 geojson 规范的一部分,d3 将 shere 类型的 geojson 识别为覆盖整个星球(因此它不需要坐标)。在将国家/地区添加到地球之前,添加一个球体,这为拖动事件提供了一个与之交互的元素:
svg.append("path")
.attr("d", path({type:"Sphere"})
.attr("fill","blue");
这充满了海洋(和陆地),我们可以在上面附加国家。现在,球体和国家都属于同一个 g
,我们可以像现在一样在整个地球上实现拖动,但现在没有鼠标交互不起作用的漏洞。
这是一个带有正交投影和最基本的拖动功能的快速演示:
var svg = d3.select("svg").append("g");
var projection = d3.geoOrthographic()
.translate([250,250])
var path = d3.geoPath().projection(projection);
d3.json("https://unpkg.com/world-atlas@1/world/110m.json").then( function(data) {
var world = {type:"Sphere"}
svg.append("path")
.datum(world)
.attr("d", path)
.attr("fill","lightblue");
svg.selectAll(null)
.data(topojson.feature(data,data.objects.land).features)
.enter()
.append("path")
.attr("fill","lightgreen")
.attr("d",path);
svg.call(d3.drag()
.on("drag", function() {
var xy = d3.mouse(this);
projection.rotate(xy)
svg.selectAll("path")
.attr("d",path);
}))
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<script src="https://unpkg.com/topojson-client@3"></script>
<svg width="500" height="500"></svg>
关于javascript - 如何使用 d3.js 拖动和旋转正交 map (地球仪),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55111038/
我正在使用 gridstack 来显示我的小部件。拖动和调整大小适用于 gridstack 卡,但当我将卡拖到底部时,卡的容器不会滚动。我想在拖动卡片时滚动那个容器。该容器只是一个 div 元素,所有
我目前正在构建一个多个处理的 slider 小部件,并且目前正在实现手势检测器。我有一个问题,如果您用第二根手指触摸/拖动屏幕,检测器会识别它并调用 onDragUpdate 函数,这是我试图禁用的功
我是 AngularJS 的新手,我对当前的项目有点压力,这就是我在这里问的原因。 我看到 AngularJS 有 ng-dragstart 事件( http://docs.ng.dart.ant.c
关于缩放大图像和平移有什么建议吗?最好内联在页面上。 我一直在使用PanoJS(又名GSV2),但是现在越来越多的人使用iPhone/iPad/Android类型的设备,这个库要么太慢,要么旧版本不支
我在尝试拖动 JPanel 时遇到问题。如果我纯粹在 MouseDragged 中将其实现为: public void mouseDragged(MouseEvent me) { me.getS
我有一个需要与屏幕底部对齐的 ImageButton,当我单击并拖动它时,它会随着我的手指移动一定距离,超过该距离它不会远离原点,而是继续跟随我的手指从原点开始的方向。 当我松手时,按钮必须滑回原点。
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 9 年前。 Improve this qu
我需要一个解决方案来实现拖动和缩放,在不使用矩阵的情况下围绕屏幕 onTouch 事件路由 ImageView。我搜索了很多但所有答案都是用矩阵完成的,因为我在屏幕矩阵中有多个对象不适合我,我想拖动和
我需要一些帮助来拖动 UIView 以显示主视图下方的菜单 View 。 我有两个 UIView。menuView - 包括菜单按钮和标签 和 mainView - 位于 menuView 之上。 我
谷歌地图即使设为 true 也不可拖动/拖动。 重现步骤:在新选项卡中加载带有 map 的页面,检查并在不执行任何操作的情况下转到移动 View 。现在在移动 View 中左右上下拖动 map ,它将
我在绘制和缩放 ImageView 时遇到问题。请帮帮我.. 当我画一些东西然后拖动或缩放图像时 - 绘图保留在原处,如您在屏幕截图中所见。而且我只需要简单地在图片上绘图,并且可以缩放和拖动这张图片。
所以我试图模拟鼠标左键单击和鼠标左键释放来执行一些自动拖放操作。 它目前在 C# Winforms(是的,winforms :|)中并且有点笨拙。 基本上,一旦发送了点击,我希望它根据 Kinect
我有一个巨大的 HTML5 Canvas,我希望它像谷歌地图一样工作:用户可以拖动它并始终只看到它的一小部分(屏幕大小)。它只呈现您在屏幕上可以看到的部分。我该怎么做?你有想法吗? 最佳答案 2 个简
我有以下拖放应用程序代码,它在桌面上按预期工作,但是当我想在移动设备上使用该应用程序时,拖动事件无法按预期工作。我知道触摸事件是必需的,但我不确定如何设置它们和实现这些功能。 .object
我正在使用 react-leaflet map ,我用状态改变了很多 map 属性,但是当使用状态来改变拖动属性时它不起作用。 { this.map = map}}
我知道我可以轻松地允许用户在OpenLayers中选择多个功能/几何图形,但是随后我希望使用户能够轻松地同时拖动/移动所有选定的功能。 使用ModifyFeature控件一次只能移动一个要素...是否
我有一个 Windows Phone 运行时应用程序,我使用 xaml 在 map 上显示图钉。 当我拖动 map 时,控件试图保持在相同位置时会出现一些滞后。 任何帮助,将不胜感
我通常不会提出此类问题/答案,但我想我会这样做,因为我已经看到这个问题被问了 20 多次,但没有一个答案真正有效。简而言之,问题是,如果您在可拖动 jQuery 项目内的任何位置有可滚动内容(over
我确信一定有一种简单的方法可以做到这一点,但到目前为止,我已经花了很长时间在各种兔子洞中没有成功。 我有一个支持拖放的 Collection View 。被拖动的单元格有 UIImageView在 c
如何在两个virtualtreeview之间复制以复制所有列,而不仅仅是第一列? 复制前: 复制后: 最佳答案 树控件不保存任何数据。它不包含要显示的列数据,因此无法复制它。而是,当树控件想要显示任何
我是一名优秀的程序员,十分优秀!