这次综合网上的一些方法找到了获取象征级别genjson数据的方法。比前面一篇更加合理。
先上一个效果图。
首先需要站在巨人的肩膀上,下载几个依赖。
svg2genjson 依靠这个可以将svg转为可使用的genjson。尽量用 yarn 来安装依赖,npm 会有问题(你的node.js版本在11以下或者gulp版本>4就没问题)
可以在package.json中加这个代码解决
// 锁定版本
"resolutions": {
"graceful-fs": "4.2.2"
},
乡镇的svg数据获取可以在这里获取 获取乡镇的svg图片。
这里获取的svg 并不能直接通过 svg2geojson 来进行转化,因为他只支持矢量地图。
这里是我自己写的一个方法将下载的svg 转化成可使用的 矢量地图。
这里的svg标签是在 上面获取的乡镇的 svg 。用记事本打开后直接复制到代码里面。
记得给svg 加一个 id=‘svgEl’ 不然会报错。
这是script 的代码
yarn add svg-path-parser
init() {
const svgEl = document.getElementById('svgEl')
const nameList = []
const data = []
;[...svgEl.children[1].children].forEach((v) => {
nameList.push(v)
})
nameList.pop()
let postion = nameList.reverse().findIndex((el) => el.nodeName === 'path')
nameList.slice(0, postion).forEach((el) => {
data.push({
id: el.innerHTML.trim(),
})
})
nameList.slice(postion, 2 * postion).forEach((el, i) => {
data[i] = { ...data[i], path: el.attributes[1].value }
})
data.forEach((v) => {
this.svg(v)
})
// 这个log 输出的东西就是我们需要的矢量地图 直接在控制台copy 一下
console.log(
`
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="727px" height="911px" viewBox="-100 0 727 911" enable-background="new -297.5 420.5 727 911" xml:space="preserve">
${this.list}
</svg>
`.trim()
)
},
svg(svgData) {
const { parseSVG, makeAbsolute } = require('svg-path-parser')
function svgPathToPolygons(svgPathString, opts = {}) {
if (!opts.tolerance) opts.tolerance = 1
const polys = []
const tolerance2 = opts.tolerance * opts.tolerance
let poly = []
let prev
makeAbsolute(parseSVG(svgPathString)).forEach((cmd) => {
let x1 = 0,
y1 = 0
switch (cmd.code) {
case 'M':
polys.push((poly = []))
// intentional flow-through
break
case 'L':
case 'H':
case 'V':
case 'Z':
add(cmd.x, cmd.y)
if (cmd.code === 'Z') poly.closed = true
break
case 'C':
sampleCubicBézier(
cmd.x0,
cmd.y0,
cmd.x1,
cmd.y1,
cmd.x2,
cmd.y2,
cmd.x,
cmd.y
)
add(cmd.x, cmd.y)
break
case 'S':
if (prev) {
if (prev.code === 'C') {
x1 = prev.x * 2 - prev.x2
y1 = prev.y * 2 - prev.y2
} else {
x1 = prev.x
y1 = prev.y
}
}
sampleCubicBézier(
cmd.x0,
cmd.y0,
x1,
y1,
cmd.x2,
cmd.y2,
cmd.x,
cmd.y
)
add(cmd.x, cmd.y)
break
default:
console.error(
'Our deepest apologies, but ' +
cmd.command +
' commands (' +
cmd.code +
') are not yet supported.'
)
process.exit(2)
}
prev = cmd
})
return polys
function sampleCubicBézier(x0, y0, x1, y1, x2, y2, x3, y3) {
const x01 = (x0 + x1) / 2,
y01 = (y0 + y1) / 2,
x12 = (x1 + x2) / 2,
y12 = (y1 + y2) / 2,
x23 = (x2 + x3) / 2,
y23 = (y2 + y3) / 2,
x012 = (x01 + x12) / 2,
y012 = (y01 + y12) / 2,
x123 = (x12 + x23) / 2,
y123 = (y12 + y23) / 2,
x0123 = (x012 + x123) / 2,
y0123 = (y012 + y123) / 2
const dx = x3 - x0,
dy = y3 - y0
const d1 = Math.abs((x1 - x3) * dy - (y1 - y3) * dx),
d2 = Math.abs((x2 - x3) * dy - (y2 - y3) * dx)
if ((d1 + d2) * (d1 + d2) < tolerance2 * (dx * dx + dy * dy))
add(x0123, y0123)
else {
sampleCubicBézier(x0, y0, x01, y01, x012, y012, x0123, y0123)
sampleCubicBézier(x0123, y0123, x123, y123, x23, y23, x3, y3)
}
}
function add(x, y) {
if (opts.decimals && opts.decimals >= 0) {
x = x.toFixed(opts.decimals) * 1
y = y.toFixed(opts.decimals) * 1
}
poly.push([x, y])
}
}
function compare(pathData, opts = {}) {
var polys = svgPathToPolygons(pathData, opts)
var minX = Infinity,
maxX = -Infinity,
minY = Infinity,
maxY = -Infinity,
cx,
cy
polys.forEach((poly) => {
poly.forEach((pt) => {
if (pt[0] < minX) minX = pt[0]
if (pt[1] < minY) minY = pt[1]
if (pt[0] > maxX) maxX = pt[0]
if (pt[1] > maxY) maxY = pt[1]
})
})
return `
<g id="${svgData.id}">
${polys
.map((poly) => {
const cxArr = []
const cyArr = []
poly.forEach((el) => {
cxArr.push(el[0])
cyArr.push(el[1])
})
cx = (
(Math.max.apply(null, cxArr) + Math.min.apply(null, cxArr)) /
2
).toFixed(3)
cy = (
(Math.max.apply(null, cyArr) + Math.min.apply(null, cyArr)) /
2
).toFixed(3)
return ` <${
poly.closed ? 'polygon' : 'polyline'
} fill="none" stroke="#000000" stroke-miterlimit="10" points="${poly.join(
' '
)} "/>`
})
.join('\n')}
<circle fill="none" stroke="#EAC613" stroke-miterlimit="10" cx="${cx}" cy="${cy}" r="8.083"/>
</g>
`.trim()
}
let str = compare(`${svgData.path}`)
this.list += str
},
通过这里获取init函数在控制台获取到的就是我们需要的矢量地图(大概就是这样)直接粘贴到 svg2geojson 的svg 中,可以直接覆盖他的zhongshan.svg的内容,也可以自己新建一个svg然后粘贴进去,然后运行 gulp
在dist 中就可以获取到想要的 genjson 数据了。可以在echarts,g6 等其他的可视化工具使用了。
生成的文件是没有 code 码 的,要用的话需要手动配置了。