效果图:
安装:
安装echarts-gl
cnpm install echarts-gl // 或者指定版本echarts-gl@2.0.9
安装jQuery
cnpm install jquery // 或者指定版本jquery@3.7.1
安装echarts
cnpm install echarts // 或者指定版本echarts@5.4.3
对应的vue文件
<template>
<div id="main" style="width: 100vw;height: 100vh;">
</div>
</template>
<script>
import * as echarts from 'echarts'
import $ from 'jquery'
import 'echarts-gl'
export default {
name: 'my-earth',
mounted () {
this.initEchart()
},
methods: {
initEchart () {
const config = {
color: '#c0101a',
levels: 1,
intensity: 4,
threshold: 0.01
}
const chartDom = document.getElementById('main')
const myChart = echarts.init(chartDom)
const canvas = document.createElement('canvas')
canvas.width = 4096
canvas.height = 2048
let context = canvas.context
context = canvas.getContext('2d')
context.lineWidth = 0.5
context.strokeStyle = config.color
context.fillStyle = config.color
context.shadowColor = config.color
$.when(
$.getScript(
'https://fastly.jsdelivr.net/npm/d3-array@2.8.0/dist/d3-array.js'
),
$.getScript(
'https://fastly.jsdelivr.net/npm/d3-contour@2.0.0/dist/d3-contour.js'
),
$.getScript('https://fastly.jsdelivr.net/npm/d3-geo@2.0.1/dist/d3-geo.js'),
$.getScript('https://fastly.jsdelivr.net/npm/d3-timer@2.0.0/dist/d3-timer.js')
).done(function () {
image('/api/data-gl/asset/bathymetry_bw_composite_4k.jpg').then(
function (image) {
const m = image.height
const n = image.width
const values = new Array(n * m)
// eslint-disable-next-line no-undef
const contours = d3.contours().size([n, m]).smooth(true)
// eslint-disable-next-line no-undef
const projection = d3.geoIdentity().scale(canvas.width / n)
// eslint-disable-next-line no-undef
const path = d3.geoPath(projection, context)
// StackBlur.R(image, 5);
for (let j = 0, k = 0; j < m; ++j) {
for (let i = 0; i < n; ++i, ++k) {
values[k] = image.data[k << 2] / 255
}
}
const opt = {
image: canvas
}
let results = []
function update (threshold, levels) {
// eslint-disable-next-line no-undef
context.clearRect(0, 0, canvas.width, canvas.height)
const thresholds = []
for (let i = 0; i < levels; i++) {
thresholds.push((threshold + (1 / levels) * i) % 1)
}
results = contours.thresholds(thresholds)(values)
redraw()
}
function redraw () {
results.forEach(function (d, idx) {
// eslint-disable-next-line no-undef
context.beginPath()
path(d)
// eslint-disable-next-line no-undef
context.globalAlpha = 1
// eslint-disable-next-line no-undef
context.stroke()
if (idx > (config.levels / 5) * 3) {
// eslint-disable-next-line no-undef
context.globalAlpha = 0.01
// eslint-disable-next-line no-undef
context.fill()
}
})
opt.onupdate()
}
// eslint-disable-next-line no-undef
d3.timer(function (t) {
const threshold = (t % 10000) / 10000
update(threshold, 1)
})
initCharts(opt)
update(config.threshold, config.levels)
}
)
function image (url) {
return new Promise(function (resolve) {
const image = new Image()
image.src = url
image.crossOrigin = 'Anonymous'
image.onload = function () {
const canvas = document.createElement('canvas')
canvas.width = image.width / 8
canvas.height = image.height / 8
const context = canvas.getContext('2d')
context.drawImage(image, 0, 0, canvas.width, canvas.height)
resolve(context.getImageData(0, 0, canvas.width, canvas.height))
}
})
}
function initCharts (opt) {
const contourChart = echarts.init(document.createElement('canvas'), null, {
width: 4096,
height: 2048
})
const img = new echarts.graphic.Image({
style: {
image: opt.image,
x: -1,
y: -1,
width: opt.image.width + 2,
height: opt.image.height + 2
}
})
contourChart.getZr().add(img)
opt.onupdate = function () {
img.dirty()
}
// eslint-disable-next-line no-undef
myChart.setOption({
backgroundColor: '#000',
globe: {
environment: '/api/data-gl/asset/starfield.jpg',
heightTexture: '/api/data-gl/asset/bathymetry_bw_composite_4k.jpg',
displacementScale: 0.05,
displacementQuality: 'high',
baseColor: '#000',
shading: 'realistic',
realisticMaterial: {
roughness: 0.2,
metalness: 0
},
postEffect: {
enable: true,
depthOfField: {
// enable: true
}
},
light: {
ambient: {
intensity: 0
},
main: {
intensity: 0.1,
shadow: false
},
ambientCubemap: {
texture: '/api/data-gl/asset/lake.hdr',
exposure: 1,
diffuseIntensity: 0.5,
specularIntensity: 2
}
},
viewControl: {
autoRotate: false
},
layers: [
{
type: 'blend',
blendTo: 'emission',
texture: contourChart,
intensity: config.intensity
}
]
}
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
</style>
注意:
我这里的/api是代理的https://echarts.apache.org/examples,因为如果在源文件直接写的话会产生跨域问题,所以我就用代理的方式进行了改变把我的localhost:8080代理成https://echarts.apache.org/examples这个地址
代码:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
// port: 80,
// host: '0.0.0.0',
proxy: {
// 代理
'/api': {
target: 'https://echarts.apache.org/examples',
changeOrigin: true,
pathRewrite: { // 路径重写
'^/api': '' // 选择忽略拦截器里面的内容
}
}
}
}
})