在用uniapp做项目时,遇到做地图的需求,但是又不想用echarts,于是找到了一个兼容性很高的图表插件uCharts(秋云uCharts图表组件),下面说一下怎么使用:
基本用法可以参考一下官网,说得非常的详细ucharts官网
安装
1.下载插件ext.dcloud.net.cn/plugin?id=2…,用HBuilderx编译器可以直接导入
2.导入之后会发现uni_modules目录发生了变化,这就是导入的图表组件及其配置
代码演示
<template>
<view>
<view style="height: 400px;">
<qiun-data-charts type="map" @getIndex="getIndex" :opts="{ extra: { map: { mercator: true } } }" :chartData="chartsDataMap1" />
</view>
</view>
</template>
<script>
import mapdata from '../mockdata/mapdata.json';
export default {
data() {
return {
chartsDataMap1: {},
};
},
onReady() {
this.getServerData();
},
methods: {
// 点击事件
getIndex(e) {
console.log(e)
console.log(mapdata.features[e.currentIndex])
},
// 地图渲染
getServerData() {
this.chartsDataMap1 = {
series: mapdata.features
};
},
}
};
</script>
标点:
参考的这位博主的文章 juejin.cn/post/711281…
找对应ucharts的源码
- 打开文件
/uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js
,drawMapDataPoints
函数即绘制地图的函数,直接替换即可。
function drawMapDataPoints(series, opts, config, context) {
var mapOption = assign({}, {
border: true,
mercator: false,
borderWidth: 1,
active: true,
borderColor: '#666666',
fillOpacity: 0.6,
activeBorderColor: '#f04864',
activeFillColor: '#facc14',
activeFillOpacity: 1
}, opts.extra.map);
var coords, point;
var data = series;
var bounds = getBoundingBox(data);
if (mapOption.mercator) {
var max = lonlat2mercator(bounds.xMax, bounds.yMax)
var min = lonlat2mercator(bounds.xMin, bounds.yMin)
bounds.xMax = max[0]
bounds.yMax = max[1]
bounds.xMin = min[0]
bounds.yMin = min[1]
}
var xScale = opts.width / Math.abs(bounds.xMax - bounds.xMin);
var yScale = opts.height / Math.abs(bounds.yMax - bounds.yMin);
var scale = xScale < yScale ? xScale : yScale;
var xoffset = opts.width / 2 - Math.abs(bounds.xMax - bounds.xMin) / 2 * scale;
var yoffset = opts.height / 2 - Math.abs(bounds.yMax - bounds.yMin) / 2 * scale;
for (var i = 0; i < data.length; i++) {
context.beginPath();
context.setLineWidth(mapOption.borderWidth * opts.pix);
context.setStrokeStyle(mapOption.borderColor);
context.setFillStyle(hexToRgb(series[i].color, series[i].fillOpacity || mapOption.fillOpacity));
if (mapOption.active == true && opts.tooltip) {
if (opts.tooltip.index == i) {
context.setStrokeStyle(mapOption.activeBorderColor);
context.setFillStyle(hexToRgb(mapOption.activeFillColor, mapOption.activeFillOpacity));
}
}
var coorda = data[i].geometry.coordinates
for (var k = 0; k < coorda.length; k++) {
coords = coorda[k];
if (coords.length == 1) {
coords = coords[0]
}
for (var j = 0; j < coords.length; j++) {
var gaosi = Array(2);
if (mapOption.mercator) {
gaosi = lonlat2mercator(coords[j][0], coords[j][1])
} else {
gaosi = coords[j]
}
point = coordinateToPoint(gaosi[1], gaosi[0], bounds, scale, xoffset, yoffset)
if (j === 0) {
context.beginPath();
context.moveTo(point.x, point.y);
} else {
context.lineTo(point.x, point.y);
}
}
context.fill();
if (mapOption.border == true) {
context.stroke();
}
}
}
const location = opts.location
const fontSize = 10
location.forEach(item => {
// 经纬度转墨卡托坐标
const mercator = lonlat2mercator('经度', '纬度')
// 转换为当前经纬对应canvas画布上的坐标
const point = coordinateToPoint(mercator[1], mercator[0], bounds, scale, xoffset, yoffset);
// 绘制白点
context.beginPath();
context.arc(point.x, point.y, 1, 0, Math.PI * 2, false)
context.strokeStyle = 'transparent'
context.fillStyle = 'white'
context.fill()
context.closePath();
context.stroke();
// 绘制标记icon
context.beginPath();
context.moveTo(point.x, point.y);
context.arc(point.x, point.y - fontSize * 2, fontSize * 1, 45 * Math.PI / 180, 135 * Math.PI / 180,
true);
context.lineTo(point.x, point.y);
context.fillStyle = '#B9AF57';
context.fill();
context.closePath();
})
if (opts.dataLabel == true) {
for (var i = 0; i < data.length; i++) {
var centerPoint = data[i].properties.centroid;
if (centerPoint) {
// 记录该省的数量
let count = opts.data[data[i].properties.name]
if (mapOption.mercator) {
centerPoint = lonlat2mercator(data[i].properties.centroid[0], data[i].properties.centroid[1])
}
point = coordinateToPoint(centerPoint[1], centerPoint[0], bounds, scale, xoffset, yoffset);
let fontSize = data[i].textSize * opts.pix || config.fontSize;
let fontColor = data[i].textColor || opts.fontColor;
if (mapOption.active && mapOption.activeTextColor && opts.tooltip && opts.tooltip.index == i) {
fontColor = mapOption.activeTextColor;
}
let text = data[i].properties.name;
context.beginPath();
context.textAlign = 'left'
context.setFontSize(fontSize)
context.setFillStyle(fontColor)
const x = point.x - measureText(text, fontSize, context) / 2
context.fillText(text, point.x - measureText(text, fontSize, context) / 2, point.y + fontSize / 2);
context.closePath();
context.stroke();
if (count) {
context.beginPath()
const centerx = point.x - measureText(text, fontSize, context) / 2
const centery = point.y + fontSize / 2
context.moveTo(centerx, centery)
context.arc(centerx, centery - fontSize * 2, fontSize * 1.5, 45 * Math.PI / 180, 135 * Math.PI /
180, true)
context.lineTo(centerx, centery)
context.fillStyle = '#b9af57'
context.fill()
context.closePath()
context.beginPath();
context.textAlign = 'center';
context.setFontSize(fontSize)
context.setFillStyle(data[i].textColor || opts.fontColor)
context.fillStyle = '#FFFFFF'
// 因为icon大小是固定的,数量太大样式会有问题,如果太多的话显示 99+
context.fillText(count < 100 ? count : '99+', centerx, centery - fontSize * 1.5)
context.arc(centerx, centery, 1, 0, Math.PI * 2, false)
context.strokeStyle = 'transparent'
context.fillStyle = 'white'
context.fill()
context.closePath();
context.stroke();
}
}
}
}
opts.chartData.mapData = {
bounds: bounds,
scale: scale,
xoffset: xoffset,
yoffset: yoffset,
mercator: mapOption.mercator
}
drawToolTipBridge(opts, config, context, 1);
context.draw();
}
- 在绘制地图的组件里进行以下处理
<qiun-data-charts type="map" :opts="opts" />
opts: {
location: [],
data: {},
...
};
// 处理中心点
let points = mapData.features.map(item => item.properties.center)
let pointsCenter = points.map(item => item.join(','))
this.opts.location = pointsCenter
// 处理显示名字
let mapName = mapData.features.map(item => item.properties.name)
for (let key in mapName) {
this.opts.data[mapName[key]] = 1;
}
注意:
- 秋云的用法非常之简单,以至于很多朋友不会使用echats,他没有echarts中的配置项option={},所以我还是建议少用
- 标点,只能标记一个地区一个点,而不能实现一个地区多个点(也许是我比较菜,没有搞出来,但是echarts可以) 3.地图的json文件一定是四层数组的,不能用三层数组
如有问题,欢迎留言!!