There are a couple issues with your map.
The primary issue is that your projection is not WGS84, that is to say it does not comprise of longitude/latitude pairs. The projection of the geojson is specified in your geojson itself:
"crs":{"type":"name","properties":{"name":"urn:ogc:def:crs:EPSG:32638"}}
CRS stands for spatial reference system
This projection (EPSG:32638) is a UTM system. D3 uses unprojected data (or data that is 'projected' to WGS84), points on a three dimensional ellipsoid, not already projected points on a planar grid (like UTM). If the geojson did not indicate what projection it used, you can still tell that it is not WGS84, or longitude latitude pairs, because the coordinates are not valid longitude/latitudes:
...[1348,4717],[1501,4754],[1572,4753]...
You have two options, one is to use unprojected data (or data in WGS84) and build your map around a d3 projection. The other is to use a geo.transform to show your data.
Solution 1
As noted in the other answer, you'll need to use the path
function to actually display the data, you also shouldn't need an each loop in d3 to append features
For this solution to work, and it is probably the most straight-forward, you'll need to either re-project/un-project the geojson you have (with some tool other than d3) or, alternatively, you'll have to find an new data source (which is probably not too difficult) with the spatial data represented as long/lat pairs.
Also note that coordinates in geojson and d3 are [long,lat] therefore your centering coordinate of [24.679341, 46.680381]
refers to 46.7 degrees North, 24.7 degrees East - this point is not in Saudi Arabia but is in Romania.
Take a look at an example projection suitable for Saudi Arabia here (using a basic geojson - just a country outline) (in d3v4 - slight differences from v3).
Together, that would give you something like:
var projection = d3.geo.mercator()
.center([46.680381,24.679341])
.scale(1000)
.translate([width / 2, height / 2])
.precision(.1);
var path = d3.geo.path().projection(projection)
d3.json("source.json", function(err, data) {
svg.selectAll("path")
.data(data.features)
.enter()
.append('path')
.attr("class", "border")
.attr("stroke", "black")
.attr("fill", "blue")
.attr("d", path);
});
Note that if you really want to keep the conical projection (d3.geo.conicConformal()
), take a look on centering that type of projection here, it's for an albers projection, but the method is the same as they are both conical projections of the same sort.
Solution 2
The other option is to use a geo.transfrom which will translate and scale your data (since it is already planar in this case) to match your desired view. The downside of this approach is that you can't use a lat/long point to indicate anything - the map units will be the projection units and the map units are not degrees longitude or latitude.
The goal is to translate/scale/shift coordinates such as these:
...[1348,4717],[1501,4754],[1572,4753]...
to [x,y] pixel values that are within your SVG bounds.
This is more complex, you can try to figure out the translate manually (like I demonstrate with your data in this bl.ock, (uses d3v4, which has slightly different method names, but otherwise is the same for this type of operation), or use an automated function to determine the appropriate transform you need to use.