如何使用 D3.js 绘制 SVG?
How to make to drawing a SVG with D3.js?
我正在尝试使用我从 API 带来的 GEOJSON 数据在 SVG 中绘制地图,SVG 路径充满了数据,但是,SVG 是空白的,可以执行下面的代码时看到。注意 document.write
,数据返回正确。
var svg = d3.select("svg")
d3.json('https://api.mocki.io/v1/d214eb47')
.then(data => {
svg.append('g')
.selectAll('path')
.data(data.features)
.enter()
.append('path')
.attr('d', d3.geoPath().projection(d3.geoMercator()))
document.write(JSON.stringify(data));
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.6.0/d3.min.js"></script>
<svg width="600" height="600"></svg>
我用另一个 GEOJSON file 对其进行了测试,并成功绘制了 SVG,如下面的代码所示:
const link = "https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/world.geojson";
var svg = d3.select("svg")
d3.json(link)
.then(data => {
svg.append("g")
.selectAll("path")
.data(data.features)
.enter()
.append("path")
.attr("d", d3.geoPath()
.projection(d3.geoMercator())
)
//document.write('data ', JSON.stringify(data))
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.6.0/d3.min.js"></script>
<svg width="600" height="600"></svg>
有人知道第一个代码片段有什么问题吗?
数据没有问题,这里的问题只是您试图绘制一个非常小的区域(旧金山)的地图,这与第二个示例中的世界地图不同。也就是说,您应该设置投影的 scale
和 center
。在你的情况下:
const projection = d3.geoMercator()
.scale(100000)
.center([-122.3, 37.75])
结果代码:
var svg = d3.select("svg");
const projection = d3.geoMercator()
.scale(100000)
.center([-122.3, 37.75])
d3.json('https://api.mocki.io/v1/d214eb47')
.then(data => {
svg.append('g')
.selectAll('path')
.data(data.features)
.enter()
.append('path')
.attr('d', d3.geoPath().projection(projection))
})
path {
fill: wheat;
stroke: darkslateblue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.6.0/d3.min.js"></script>
<svg width="600" height="600"></svg>
但是将 fitExtent
与您的 SVG 宽度和高度一起使用会更容易:
const projection = d3.geoMercator()
.fitExtent([
[0, 0],
[600, 600]
], data)
这是生成的代码:
var svg = d3.select("svg");
d3.json('https://api.mocki.io/v1/d214eb47')
.then(data => {
const projection = d3.geoMercator()
.fitExtent([
[0, 0],
[600, 600]
], data)
svg.append('g')
.selectAll('path')
.data(data.features)
.enter()
.append('path')
.attr('d', d3.geoPath().projection(projection))
})
path {
fill: wheat;
stroke: darkslateblue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.6.0/d3.min.js"></script>
<svg width="600" height="600"></svg>
您的 GeoJSON 文件具有非常小的显示区域,但在给定投影和默认 SVG viewBox 中形状几乎为零。
检查我是如何使用您的地理数据找到 SVG G 元素的边界的。然后我用它来定义 SVG viewBox 属性。如果未设置 SVG 宽度或高度,则 SVG 将扩展到可用的“容器”大小。因此,您可以添加周围的 DIV 元素并根据需要设置其大小(将 SVG 安装在您的容器中,从而安装在您的布局中)。
更新:您甚至可以稍后使用 getBBox() 函数的返回值通过 javascript 更改 SVG viewBox 属性。另一个答案中的另一种可能性当然也很好(适合您的 SVG 范围)。
var svg = d3.select("svg");
const link = "https://api.mocki.io/v1/d214eb47";
//const link = "https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/world.geojson";
d3.json(link)
.then(data => {
svg.append('g')
.selectAll('path')
.data(data.features)
.enter()
.append('path')
.attr('d', d3.geoPath().projection(d3.geoMercator()));
//console.log(data.features);
console.log(document.getElementsByTagName("g")[0].getBBox());
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.6.0/d3.min.js"></script>
<svg viewBox="152.95315551757812 140.7493133544922 0.421722412109375 0.4228363037109375"></svg>
我正在尝试使用我从 API 带来的 GEOJSON 数据在 SVG 中绘制地图,SVG 路径充满了数据,但是,SVG 是空白的,可以执行下面的代码时看到。注意 document.write
,数据返回正确。
var svg = d3.select("svg")
d3.json('https://api.mocki.io/v1/d214eb47')
.then(data => {
svg.append('g')
.selectAll('path')
.data(data.features)
.enter()
.append('path')
.attr('d', d3.geoPath().projection(d3.geoMercator()))
document.write(JSON.stringify(data));
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.6.0/d3.min.js"></script>
<svg width="600" height="600"></svg>
我用另一个 GEOJSON file 对其进行了测试,并成功绘制了 SVG,如下面的代码所示:
const link = "https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/world.geojson";
var svg = d3.select("svg")
d3.json(link)
.then(data => {
svg.append("g")
.selectAll("path")
.data(data.features)
.enter()
.append("path")
.attr("d", d3.geoPath()
.projection(d3.geoMercator())
)
//document.write('data ', JSON.stringify(data))
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.6.0/d3.min.js"></script>
<svg width="600" height="600"></svg>
有人知道第一个代码片段有什么问题吗?
数据没有问题,这里的问题只是您试图绘制一个非常小的区域(旧金山)的地图,这与第二个示例中的世界地图不同。也就是说,您应该设置投影的 scale
和 center
。在你的情况下:
const projection = d3.geoMercator()
.scale(100000)
.center([-122.3, 37.75])
结果代码:
var svg = d3.select("svg");
const projection = d3.geoMercator()
.scale(100000)
.center([-122.3, 37.75])
d3.json('https://api.mocki.io/v1/d214eb47')
.then(data => {
svg.append('g')
.selectAll('path')
.data(data.features)
.enter()
.append('path')
.attr('d', d3.geoPath().projection(projection))
})
path {
fill: wheat;
stroke: darkslateblue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.6.0/d3.min.js"></script>
<svg width="600" height="600"></svg>
但是将 fitExtent
与您的 SVG 宽度和高度一起使用会更容易:
const projection = d3.geoMercator()
.fitExtent([
[0, 0],
[600, 600]
], data)
这是生成的代码:
var svg = d3.select("svg");
d3.json('https://api.mocki.io/v1/d214eb47')
.then(data => {
const projection = d3.geoMercator()
.fitExtent([
[0, 0],
[600, 600]
], data)
svg.append('g')
.selectAll('path')
.data(data.features)
.enter()
.append('path')
.attr('d', d3.geoPath().projection(projection))
})
path {
fill: wheat;
stroke: darkslateblue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.6.0/d3.min.js"></script>
<svg width="600" height="600"></svg>
您的 GeoJSON 文件具有非常小的显示区域,但在给定投影和默认 SVG viewBox 中形状几乎为零。
检查我是如何使用您的地理数据找到 SVG G 元素的边界的。然后我用它来定义 SVG viewBox 属性。如果未设置 SVG 宽度或高度,则 SVG 将扩展到可用的“容器”大小。因此,您可以添加周围的 DIV 元素并根据需要设置其大小(将 SVG 安装在您的容器中,从而安装在您的布局中)。
更新:您甚至可以稍后使用 getBBox() 函数的返回值通过 javascript 更改 SVG viewBox 属性。另一个答案中的另一种可能性当然也很好(适合您的 SVG 范围)。
var svg = d3.select("svg");
const link = "https://api.mocki.io/v1/d214eb47";
//const link = "https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/world.geojson";
d3.json(link)
.then(data => {
svg.append('g')
.selectAll('path')
.data(data.features)
.enter()
.append('path')
.attr('d', d3.geoPath().projection(d3.geoMercator()));
//console.log(data.features);
console.log(document.getElementsByTagName("g")[0].getBBox());
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.6.0/d3.min.js"></script>
<svg viewBox="152.95315551757812 140.7493133544922 0.421722412109375 0.4228363037109375"></svg>