javascript - 向 d3 SVG map 添加点

标签 javascript d3.js svg

我是 d3 的新手,在向我的 SVG map 添加点时遇到了一些问题。我正在加载 SVG map ,然后尝试从我的数据中附加坐标,这是一个格式如下的对象数组:

{schoolName: "Harvard University", gpa: 4, state: "MA", city: "Cambridge", longitude: -71.10973349999999, latitude: 42.3736158}

下面代码的结果是,我在 SVG 标记下方附加了一组圆圈,但没有一个圆圈出现在 map 上,而且我收到了我在代码中没有看到的语法错误。

翻译错误: Translate Error

我在这里做错了什么?

var coords = require('./data/coordinates')

document.addEventListener("DOMContentLoaded", () => {

    // loads svg map
    d3.xml('src/data/usa2.svg', function(data){
        document.body.append(data.documentElement)
    })

    // adjusts data to include coordinates for each city
    cities = cities.default
    let schoolData = []
    d3.json("src/data/schoolInfo.json", function(schools){
        schools.map(el => {
            let currentCity = cities.filter(function(cities){return cities.city === el.city})
            el["hs-gpa-avg"] !== null && currentCity.length > 0 ? schoolData.push({"schoolName": el["displayName"], "gpa": el["hs-gpa-avg"], "state": el["state"], "city": el["city"], "longitude": currentCity[0]["longitude"], "latitude": currentCity[0]["latitude"]}) : ''
        })


    var width = 1200,
        height = 720;

    var albersProjection = d3.geoAlbers()
        .scale(1000)
        .rotate([70, 0])
        .center([-15, 35])
        .translate([width/2, height/2]);

    var svg = d3.select('svg')

    svg.selectAll("circle")
        .data(schoolData).enter()
        .append("circle")
        .attr("transform", function(d) {
            let coords = albersProjection([ d.longitude, d.latitude ]);
            return `translate(${coords[0]}px, ${coords[1]}px)`
        })
        .attr("r", "8px")
        .attr("fill", "red")   
    })

})

在解决与翻译相关的错误时,我仍然将圆圈放错了位置,正如本 answer 中预测的那样:

错位点: Misaligned points to coordinates on map

最佳答案

SVG 转换属性需要数字,没有单位的普通数字。但是,如果您使用 CSS(style="transform: ..." 而不是指定 transform 属性:transform = "..."),则可以指定单位。

下面的代码片段比较了设置单位和 CSS 样式属性,直接设置不带单位的转换属性,以及直接设置带单位的转换属性。它应该在最后一个矩形上引起相同的错误(由于错误而没有正确定位,它应该在蓝色矩形下方):

<svg>
   <rect style="transform:translate(200px,0px)" width="20" height="20" fill="steelblue"></rect>
   <rect transform="translate(100,0)" width="20" height="20" fill="crimson"></rect>   
   <rect transform="translate(200px,50px)" width="20" height="20" fill="orange"></rect>
</svg>

我的错误,在最后一个矩形上:“Error: <rect> attribute transform: Expected ')', "translate(200px,50px)".

这和你一样,解决方法是简单地删除px从你的翻译值(value)。 您还可以使用 .style() 指定 CSS 属性而不是 .attr() .


至于你的下一个问题:为什么圆圈仍然没有正确放置,但现在你没有错误,那么这是一个不同的问题。这是一个常见问题。

您有 US 的 SVG 版本 - 此 SVG 由二维平面上的顶点组成:以像素为单位的投影点。由于 SVG 已经投影,因此您的 SVG 特征是预先投影的。

您的地理数据由单位为度的 3D 点(球体上的点)组成。在不知道用于创建 SVG 的投影的情况下,您无法对齐地理点和预投影点。

这是预投影 topojson/geojson 的常见问题(其中坐标位于二维空间,单位为像素)。解决方法是一样的:

  • 在其上投影地理点时尝试复制用于创建 SVG 的投影(困难)

  • 在绘制 map 时仅对两个图层使用未投影的坐标(不要使用预制的 SVG,除非您自己制作)。 (简单)

  • 在绘制 map 时仅对两个图层使用预投影坐标(但要为点制作此坐标,您仍然需要知道用于创建 SVG 的投影)。 (不值得)

这些问题和答案解决了类似的问题,只是使用预投影的 topojson/geojson 而不是 SVG(比较公平,因为 geoPath 通常会生成 SVG 向量):

第二个包含指向美国未投影的 topojson 的链接:

https://bl.ocks.org/mbostock/raw/4090846/us.json

我们可以将其用于未投影的点 - 我们只需对点和面积使用相同的投影。

我们可以将它与 topojson.js 一起使用来生成一个 geojson 数组:

 var geojson = topojson.feature(data,data.objects.states).features;

一旦我们定义了投影,就可以使用 projection([long,lat])到项目点,和d3.geoPath(projection)转换 geojson。

在哪里data是解析后的 JSON - 传递给 d3.json 回调函数的值。

关于javascript - 向 d3 SVG map 添加点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58424356/

相关文章:

javascript - for 循环中的 if 语句同时执行,而不是只执行一个

javascript - 如何在 v-carousel 中获取当前项目索引?

d3.js - 将许多可能的输入值映射到离散的颜色域

javascript - D3 V4多系列折线图: Adding data points to lines with same color as lines

image - Inkscape - 未完全将 png 转换为 svg

javascript - 变量对象构造函数

javascript - 在 javascript onClick 中设置字体颜色的简单方法?

javascript - 在没有 jquery 的情况下在 DOM 上运行 D3 代码

css - 从左到右动画 SVG 填充

css - svg 填充动画在 firefox 中不起作用