系统门户网站建设常用功能友情贴吧
效果图展示:
1.点击左侧国家,可以高亮并放大右侧地图对应的国家。
2.展示数据球。
下载依赖
yarn add @amcharts/amcharts5
其中,props.countryData的数据格式为
[{
“country”: “加拿大”,
“code”: “CA”,
“deviceCount”: 1
},{
“country”: “瑞士”,
“code”: “CH”,
“deviceCount”: 29
},{
“country”: “中国”,
“code”: “CN”,
“deviceCount”: 10774
},{
“country”: “德国”,
“code”: “DE”,
“deviceCount”: 42
}]
<template><div class="device-distribution-box"><div class="header-title">{{ $t('countryDistributionDevice') }}</div><section class="flex-box"><div class="country-box"><div class="country-list" v-for="country in mapData"><div:class="activeCountry == country.code ? 'active-country' : ''"@click="clickCountry(country.code)"class="sf-ellipsis":title="country.country + '(' + country.deviceCount + ')'">{{ country.country }}({{ country.deviceCount }})</div></div></div><div id="chartdiv"></div> // 地图展示容器</section></div>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref, watch } from 'vue';
import useLocale from '@/utils/i18n/store';
import { storeToRefs } from 'pinia';
import am5geodata_lang_EN from '@amcharts/amcharts5-geodata/lang/EN';// 地图语言包
import am5geodata_lang_cn_ZH from '@amcharts/amcharts5-geodata/lang/cn_ZH';//地图语言包
import am5geodata_lang_PT from '@amcharts/amcharts5-geodata/lang/PT'; // 地图语言包
import * as am5map from '@amcharts/amcharts5/map';
import am5geodata_worldLow from '@amcharts/amcharts5-geodata/worldLow';
import * as am5 from '@amcharts/amcharts5';
import am5themes_Animated from '@amcharts/amcharts5/themes/Animated';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const localeStore = useLocale(); //获取本地语言
const { locale } = storeToRefs(localeStore); //获取本地语言interface Props {countryData: Array<any>;
}
const props = withDefaults(defineProps<Props>(), {countryData: () => {return [];},
});// 数据接口
interface MapData {code: string;deviceCount: number;name: string;country: string;id?: string;
}
const mapData = ref<Array<MapData>>([]);
const activeCountry = ref<string>('');
let polygonSeries = reactive({}); // 地图数据
let root = reactive({}); // 地图根// 数据更新,更新地图
watch(() => props.countryData,(newValue, oldValue) => {mapData.value = props.countryData.map((item) => {item.id = item.code;return item;});refreshAmchartsMap();},
);// 左侧国家点击事件-点击高亮国家
const clickCountry = (countryCode: string) => {activeCountry.value = countryCode;// 根据点击的国家,添加该国家的颜色数据,去除无关国家的颜色数据let tempData = mapData.value.map((item) => {if (item.id == countryCode) item.polygonSettings = { fill: am5.color(0x3a70d3) };else item.polygonSettings = {};return item;});// 绑定数据 高亮该国家颜色polygonSeries.data.setAll(tempData);// 地图放大到该国家polygonSeries.events.on('datavalidated', function () {const zoomTargets = [countryCode];const zoomDataItems = [];zoomTargets.forEach(function (id) {zoomDataItems.push(polygonSeries.getDataItemById(id));});polygonSeries.zoomToDataItems(zoomDataItems);});
};
// 更新相关数据
const refreshAmchartsMap = () => {root.setThemes([am5themes_Animated.new(root)]);// Create the map chart 地图的样式不一样let chart = root.container.children.push(am5map.MapChart.new(root, {projection: am5map.geoNaturalEarth1(),}),);polygonSeries = chart.series.push(am5map.MapPolygonSeries.new(root, {geoJSON: am5geodata_worldLow, // 地图展示的国家区域exclude: ['AQ'], //该操作将会从地图上删除南极洲。fill: am5.color(0xbbbbbb),geodataNames: // 根据本地语言配置地图语言locale.value == 'zh'? am5geodata_lang_cn_ZH: locale.value == 'en'? am5geodata_lang_EN: locale.value == 'pt'? am5geodata_lang_PT: '',}),);// ====================================// Create pins// ====================================// 点符号let pointSeries = chart.series.push(am5map.MapPointSeries.new(root, {// ...// autoScale: true,polygonIdField: 'code', // 根据code值来映射点的位置,code的值就是地图中类似“CN“的国家代码}),);let colorSet = am5.ColorSet.new(root, { step: 2 });// 点符号样式设置pointSeries.bullets.push(function (root, series, dataItem) {let value = dataItem.dataContext.value;let container = am5.Container.new(root, {});let color = colorSet.next();let radius = value / 5 < 15 ? 15 : value / 5 > 50 ? 50 : value / 5; //球的大小!!!!!!!!!!!!需求动态修改let circle = container.children.push(am5.Circle.new(root, {radius: radius,fill: color,dy: -radius * 2,}),);let pole = container.children.push(am5.Line.new(root, {stroke: color,height: -radius * 2,strokeGradient: am5.LinearGradient.new(root, {stops: [{ opacity: 1 }, { opacity: 1 }, { opacity: 0 }],}),}),);let label = container.children.push(am5.Label.new(root, {text: value,fill: am5.color(0xffffff),fontWeight: '400',centerX: am5.p50,centerY: am5.p50,dy: -radius * 2,}),);let titleLabel = container.children.push(am5.Label.new(root, {text: dataItem.dataContext.title,fill: color,fontWeight: '500',fontSize: '1em',centerY: am5.p50,dy: -radius * 2,dx: radius,}),);return am5.Bullet.new(root, {sprite: container,});});// 映射点数据for (var i = 0; i < mapData.value.length; i++) {let d = mapData.value[i];pointSeries.data.push({code: d.code,value: d.deviceCount,});}// 鼠标移入和点击的效果polygonSeries.mapPolygons.template.setAll({tooltipText: '{name}',toggleKey: 'active',interactive: true,templateField: 'polygonSettings', //多边形也可以使用模板字段从数据中获取其设置的值。模板字段允许将系列数据中的对象属性绑定到多边形模板的设置。});// 绑定数据polygonSeries.data.setAll(mapData.value);// hover及active高亮颜色polygonSeries.mapPolygons.template.states.create('hover', {fill: root.interfaceColors.get('primaryButtonHover'),});polygonSeries.mapPolygons.template.states.create('active', {fill: root.interfaceColors.get('primaryButtonHover'),});// Set clicking on "water" to zoom out// 点击背景空白处,恢复到初始大小chart.chartContainer.get('background').events.on('click', function () {chart.goHome();});// Make stuff animate on loadchart.appear(1000, 100);
};//新建国家地图 Create root element
const newAmchartsMap = () => {root = am5.Root.new('chartdiv');
};
onMounted(() => {newAmchartsMap();
});
</script>
<style lang="scss" scoped>
.device-distribution-box {.header-title {font-family:PingFang SC,PingFang SC;font-weight: 500;font-size: 16px;color: #191919;line-height: 24px;margin-bottom: 16px;}.flex-box {display: flex;height: calc(100% - 40px);.country-box {// height: 328px;overflow-y: auto;overflow-x: hidden;.country-list {min-width: 160px;max-width: 200px;div {cursor: pointer;margin-bottom: 16px;font-family:PingFang SC,PingFang SC;font-weight: 500;font-size: 14px;color: #7f7f7f;line-height: 22px;}.active-country {font-weight: bold;font-size: 14px;color: #3a70d3 !important;line-height: 22px;}}}}#chartdiv {width: 100%;// height: 328px;background-color: #fbfbfb;}
}
</style>