本篇将手把手带你用echarts实现一个超级炫酷惊艳的动态3D地球,废话不多说 上效果图
实现步骤:
1. 绘制想要的地球包材
思路: 使用echarts的 geo-map 绘制一个世界地图,通过调整参数样式可绘制出期望的包材效果
经过多次实验 最合适的包材尺寸是:6260*2925 只要是这个比例就可以 1252:585
最终效果如下:
核心代码:
<div class="chinaContainer" id="chinaContainer"></div>
</template>
<script>
import * as echarts from 'echarts';
import 'echarts-gl';
import '@/utils/world.js';// 引入的世界地图文件
export default {
data() {
return {
chart: null,
data: undefined,
};
},
watch: {},
methods: {
async initChart() {
var dom = document.getElementById('chinaContainer');
this.chart = await echarts.init(dom, null, {
devicePixelRatio: 4,
});
},
dataChange() {
let option = {
backgroundColor: '#072460',
tooltip: {
trigger: 'item',
},
geo: {
map: 'world',
aspectScale: 1, //'长宽比'
label: {
show: false,
},
tooltip: {
show: false,
},
itemStyle: {
areaColor: '#0c3497',
borderColor: 'rgba(38,254,255, 0.7)',
borderWidth: 1,
shadowBlur: 2,
shadowColor: '#0c3497',
shadowOffsetX: 0,
shadowOffsetY: 2,
emphasis: { disabled: true }, // 关闭高亮状态
},
},
};
this.chart && this.chart.setOption(option, true);
},
},
async mounted() {
await this.initChart();
await this.dataChange();
},
};
</script>
<style lang="less" scoped>
.chinaContainer {
width: 100vw;
height: 100vh;
color: '#7abbff';
pointer-events: none;
}
</style>
word.js来源:ecahrts 示例中 随便找一个使用了世界地图的如: echarts.apache.org/examples/zh…
打开控制台可以在加载的资源中找到word.js down下来在代码中引入就好啦
到这里,代码执行成功后 将浏览器内容窗口尺寸调整为2252*1193打开控制台 找到地图绘制的dom 鼠标右键点击dom找到截取屏幕截图 就可以得到一个 尺寸是2252*1193的高清图片了
但是这样得到的图片有很多留白,无法直接作为地图包材,下一步我们需要裁剪掉多余的留白 这可能是个数学题 不想计算的同学裁剪的时候 可以直接拿最终的包材图 作为参考依据 放大到内容尺寸吻合后裁剪 或者有条件的话直接把难题丢给ui童鞋 罒ω罒(不要说是我说的啦~
But 细心的话就可以发现 这个地图没有南极的部分o(╥﹏╥)o...那怎么办呢,这里我是请UI同学帮忙ps拼上去的,嘻嘻毕竟专业的事情还是要交给专业的人去做~当然如果你的需求里这部分要求不高也可以不弄。
到这里你就获得了一个属于你的包材,这个包材的优点一是自定义风格另外就是 扎点配坐标的时候可以非常很好的吻合,不用担心坐标跟位置对不上
2. 绘制基本的echarts3D地球并给它,穿上我们精心准备的包材,再给它配一个美丽的背景
这里提供3个可选的背景效果放在最后 可以根据你的主题自己选择我的效果图中背景选择的是pic3
3. 准备数据+添加地球高亮点及地球飞线
这里数据只提供一小部分示意,想要炫酷的点高亮效果数据量要够才可以哦~
<template>
<div class="globalEarthContainer" id="globalEarthContainer"></div>
</template>
<script>
import * as echarts from 'echarts';
import 'echarts-gl';
import '@/utils/world.js';
import texture from '@/assets/newdashboard/global.jpg';//
import env_star from '@/assets/dashboard/global/env_star3.jpg';
var chart = null;
export default {
data() {
return {
map_2d: null,
trajectory_data: [
{
coords: [
[-43.36898, -21.776951],
[6.037305, 46.304153],
],
value: 79,
},
{
coords: [
[-71.965149, 45.406967],
[2.263994, 48.847603],
],
value: 47,
},
{
coords: [
[120.405823, 22.727173],
[-72.526711, 42.391155],
],
value: 41,
},
{
coords: [
[77.117668, 28.750074],
[12.521381, 55.785576],
],
value: 37,
},
{
coords: [
[8.670249, 49.41914],
[-83.167488, 41.114845],
],
value: 35,
},
{
coords: [
[151.704178, -32.892773],
[-1.614661, 54.979187],
],
value: 34,
},
{
coords: [
[7.212825, 51.488232],
[8.54767, 47.376312],
],
value: 33,
},
{
coords: [
[7.84595, 47.993546],
[-81.665985, 41.500916],
],
value: 29,
},
{
coords: [
[4.86572, 52.333755],
[4.394886, 50.821659],
],
value: 29,
},
{
coords: [
[0.135048, 52.194889],
[-95.888664, 36.072567],
],
value: 28,
},
{
coords: [
[11.353998, 44.496365],
[-72.876297, 40.87479],
],
value: 28,
},
{
coords: [
[9.227277, 45.478107],
[-99.13456, 19.501354],
],
value: 26,
},
{
coords: [
[150.878433, -34.405403],
[-72.920235, 41.315128],
],
value: 25,
},
{
coords: [
[20.457567, 44.818436],
[-122.250031, 37.875927],
],
value: 25,
},
{
coords: [
[-87.111984, 37.76894],
[10.217297, 45.537838],
],
value: 24,
},
{
coords: [
[144.965118, -37.808945],
[130.425049, 33.626659],
],
value: 24,
},
{
coords: [
[-3.189241, 55.944515],
[37.189461, 56.746433],
],
value: 24,
},
{
coords: [
[-87.627007, 41.834873],
[87.310532, 22.314928],
],
value: 23,
},
{
coords: [
[6.052951, 46.234032],
[6.037305, 46.304153],
],
value: 23,
},
{
coords: [
[126.653114, 37.449627],
[-86.801865, 36.141346],
],
value: 23,
},
{
coords: [
[-84.396698, 33.779884],
[114.265465, 22.336399],
],
value: 20,
},
{
coords: [
[-121.925842, 37.477684],
[108.913795, 34.243614],
],
value: 20,
},
{
coords: [
[-73.579025, 45.497265],
[-122.636887, 45.57019],
],
value: 20,
},
{
coords: [
[23.307348, 42.683857],
[16.35157, 48.220345],
],
value: 20,
},
{
coords: [
[2.345169, 48.842205],
[6.566758, 46.519054],
],
value: 19,
},
{
coords: [
[-92.068733, 32.530979],
[9.955582, 48.42223],
],
value: 19,
},
{
coords: [
[-83.167488, 41.114845],
[8.670249, 49.41914],
],
value: 19,
},
{
coords: [
[-80.114861, 26.883827],
[14.391284, 50.103035],
],
value: 19,
},
{
coords: [
[121.192513, 24.969481],
[-118.290001, 34.019714],
],
value: 18,
},
{
coords: [
[-81.665985, 41.500916],
[7.84595, 47.993546],
],
value: 18,
},
{
coords: [
[-74.451057, 40.494221],
[2.340761, 48.85125],
],
value: 18,
},
{
coords: [
[5.342293, 50.933533],
[140.874069, 38.253834],
],
value: 17,
},
{
coords: [
[-84.328011, 33.799316],
[116.456879, 39.873989],
],
value: 17,
},
{
coords: [
[2.211292, 48.714298],
[6.566758, 46.519054],
],
value: 17,
},
{
coords: [
[-76.998695, 38.936882],
[4.700295, 50.877956],
],
value: 17,
},
{
coords: [
[106.688606, 10.786378],
[2.311249, 48.840374],
],
value: 17,
},
{
coords: [
[14.504155, 46.049194],
[-80.114861, 26.883827],
],
value: 17,
},
],
thermodynamic: [
{
name_zh: '美国',
name: 'United States',
geo: { lat: 37.9992177, lng: -97.00002479999999 },
expert_num: 26323,
},
{
name_zh: '中国',
name: 'China',
geo: { lat: 35.0073952, lng: 104.9866713 },
expert_num: 7171,
},
{
name_zh: '英国',
name: 'United Kingdom',
geo: { lat: 53.981364, lng: -1.9953132 },
expert_num: 6711,
},
{
name_zh: '日本',
name: 'Japan',
geo: { lat: 36.0002914, lng: 138.0064397 },
expert_num: 5650,
},
{
name_zh: '意大利',
name: 'Italy',
geo: { lat: 42.8339394, lng: 12.8327414 },
expert_num: 4407,
},
{
name_zh: '德国',
name: 'Germany',
geo: { lat: 50.9991135, lng: 8.9987249 },
expert_num: 4725,
},
],
};
},
methods: {
init() {
chart = echarts.init(document.getElementById('globalEarthContainer'));
},
async dataChange() {
const lines = this.trajectory_data;
const value = this.thermodynamic;
let dataArr = [];
lines.forEach((item) => {
// item.value 的作用是控制 点距离地球表面的垂直距离
dataArr.push([...item.coords[0], item.value]);
dataArr.push([...item.coords[1], item.value]);
});
let series = value.map((item) => {
// 首都点
return {
name: item.name,
type: 'scatter3D',
coordinateSystem: 'globe',
blendMode: 'lighter',
symbolSize: 10, // 点位大小
itemStyle: {
color: '#1890ff', // 各个点位的颜色设置
opacity: 1, // 透明度
borderWidth: 1, // 边框宽度
borderColor: 'rgba(255,255,255,0.8)', //rgba(180, 31, 107, 0.8)
},
label: {
show: true, // 是否显示字体
position: 'left', // 字体位置。top、left、right、bottom
formatter: item.name_zh, // 具体显示的值
textStyle: {
color: '#fff', // 字体颜色
borderWidth: 0, // 字体边框宽度
borderColor: '#fff', // 字体边框颜色
fontFamily: 'sans-serif', // 字体格式
fontSize: 18, // 字体大小
fontWeight: 700, // 字体加粗
},
},
data: [[item.geo.lng, item.geo.lat, 0]], // 数据来源
};
});
let linesSeries = [
// 飞线
{
type: 'lines3D',
coordinateSystem: 'globe',
blendMode: 'lighter',
effect: {
show: true,
constantSpeed: 15,
},
data: lines
.map((item) => ({
lineStyle: {
width: 1,
color: 'rgb(255,255,255)',
opacity: 0.7,
trailWidth: 1,
trailLength: 0.001,
},
...item,
}))
.slice(0, 50),
},
{
name: '点', // 高亮
type: 'scatter3D',
coordinateSystem: 'globe',
blendMode: 'lighter',
symbolSize: 2, // 点位大小
itemStyle: {
color: '#1890ff',
opacity: 1, // 透明度
borderWidth: 0, // 边框宽度
},
data: dataArr, // 数据
},
];
let option = {
globe: {
baseTexture: texture,
environment: env_star,
shading: 'realistic',
globeOuterRadius: 120,
realisticMaterial: {
roughness: 0.9,
},
postEffect: {
enable: true,
},
light: {
ambient: {
color: '#ffffff',
intensity: 1,
},
},
viewControl: {
autoRotate: true,
autoRotateSpeed: 5,
targetCoord: [116.46, 39.92],
alpha: 30,
zoomSensitivity: 0,
},
},
series: series.concat(linesSeries),
};
chart.setOption(option, true);
},
},
async mounted() {
await this.init();
await this.dataChange();
},
};
</script>
<style lang="less" scoped>
.globalEarthContainer {
width: 100%;
height: 100%;
}
</style>
pic1:
pic2:
pic3: