Appearance
ui 组件库
datav
移动端滚动动画 better-scroll 参考 https://www.bilibili.com/video/BV1LV411z72g?p=118 2:00
无感刷新 token
ts
// 记录当前是否正在刷新 token
let is401 = false
// 创建一个新的请求模块避免死循环
const requestToken = axios.create()
export const instance = axios.create({
timeout: 4000
})
function gotoLogin() {
// 代码能走到这里说明本地要么没有存储 refresh_token 或者调用换 token 接口出错
// 此处书写跳转登录页重新登录的逻辑
}
//配置响应拦截器
instance.interceptors.response.use(
response => {
if (response?.data?.code === 500) {
message.error(response?.data?.message || '系统异常')
return Promise.reject(response?.data)
} else {
// 当请求成功时重置状态
is401 = false
return response?.data
}
},
async error => {
if (error.response?.status === 401) {
// 无感刷新token
const refresh_token = localStorage.getItem('refresh_token')
if (!refresh_token) return gotoLogin()
// 请求新的 token
const res = await requestToken({
url: 'refresh_token',
params: { refresh_token }
}).catch(() => {
gotoLogin()
})
if (res?.data?.code !== 200) return gotoLogin()
return instance(error.config)
}
return Promise.reject(error)
}
)
上传 exsl 整个文件请求方式
vue
<template>
<el-dialog
custom-class="uploader-dialog"
width="25%"
:title="title"
:visible.sync="visible"
:append-to-body="true"
:close-on-click-modal="false"
:close-on-press-escape="false"
:before-close="beforeClose"
>
<el-upload
ref="upload"
class="upload-demo"
:before-upload="beforeUpload"
accept=".xlsx, .xls"
drag
action="http://10.126.18.85:8083/enterprise/importInvestOrgExcel"
:on-error="uploadFail"
:limit="1"
:multiple="false"
:auto-upload="false"
:http-request="myUpload"
>
<img
class="el-icon-upload"
src="../../../static/images/container.png"
alt=""
/>
<div class="el-upload__text">点击或将文件拖拽到这里上传</div>
<div class="el-upload__tip">
导入文件不能超过20M,仅允许导入.xls或.xlsx格式文件 !
</div>
</el-upload>
<span slot="footer" class="dialog-footer">
<el-button size="small" @click="buttonLoading ? '' : (visible = false)"
>取 消</el-button
>
<el-button
size="small"
type="primary"
:loading="buttonLoading"
@click="submit"
>确 定</el-button
>
</span>
</el-dialog>
</template>
<script>
// 导入解析 excel 表格插件
// import XLSX from 'xlsx'
export default {
props: {
title: {
type: String,
default: '覆盖导入数据'
},
// 判断是否是上传组织树信息
isExportTree: {
type: Boolean,
default: false
}
},
data() {
return {
visible: false,
buttonLoading: false,
file: ''
}
},
methods: {
beforeUpload(file) {
this.file = file
if (file) {
this.buttonLoading = true
}
if (
file.name.split('.')[1].includes('xls' || 'xlsx') &&
file.size < 20 * 1024 * 1024
) {
} else {
this.$message('请上传符合要求的文件!')
this.buttonLoading = false
return false
}
},
myUpload() {
let param = new FormData()
param.append('file', this.file)
// 上传企业基本信息数据
if (!this.isExportTree) {
// console.log('上传企业基本信息数据')
this.$axios
.post(`/api/enterprise/batchUpateByExcel`, param, {
headers: { 'Content-Type': 'multipart/form-data' }
})
.then(res => {
if (res.data.success) {
this.$message.success('上传成功!')
} else {
this.$message.error(res.data.message)
}
console.log(res.data)
})
} else {
// 上传组织树信息
// console.log('上传组织树信息')
this.$axios
.post(`/api/enterprise/importInvestOrgExcel`, param, {
headers: { 'Content-Type': 'multipart/form-data' }
})
.then(res => {
if (res.data.success) {
this.$message.success('上传成功!')
} else {
this.$message.error(res.data.message)
}
console.log(res.data)
})
}
},
// 上传 exsl 数据
submit() {
this.$refs.upload.submit()
},
uploadFail() {
this.$message('上传失败')
this.buttonLoading = false
},
beforeClose(done) {
this.buttonLoading ? '' : (this.visible = false)
}
// 获取读取到的 exsl 表格数据,header 表示所有表头数据,results 表示每一行的数据
// generateData({ header, results }) {
// this.excelData.header = header
// this.excelData.results = results
// this.onSuccess && this.onSuccess(this.excelData)
// this.$nextTick(() => {
// this.$axios
// .post(`/api/enterprise/importInvestOrgExcel`, this.blob, {
// // responseType: 'blob'
// })
// .then(res => {
// console.log(res)
// })
// console.log(this.blob)
// })
// },
// 读取 exsl
// readerData(rawFile) {
// this.loading = true
// return new Promise((resolve, reject) => {
// const reader = new FileReader()
// reader.onload = e => {
// const data = e.target.result
// const workbook = XLSX.read(data, { type: 'array' })
// const firstSheetName = workbook.SheetNames[0]
// const worksheet = workbook.Sheets[firstSheetName]
// const header = this.getHeaderRow(worksheet)
// const results = XLSX.utils.sheet_to_json(worksheet)
// this.generateData({ header, results })
// this.loading = false
// resolve()
// this.blob = data
// // console.log(data)
// // this.$axios
// // .post(`/api/enterprise/importInvestOrgExcel`, data, {
// // // responseType: 'blob'
// // })
// // .then(res => {
// // console.log(res)
// // })
// }
// reader.readAsArrayBuffer(rawFile)
// })
// },
// 设置表头数据
// getHeaderRow(sheet) {
// const headers = []
// const range = XLSX.utils.decode_range(sheet['!ref'])
// let C
// const R = range.s.r
// /* start in the first row */
// for (C = range.s.c; C <= range.e.c; ++C) {
// /* walk every column in the range */
// const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
// /* find the cell in the first row */
// let hdr = 'UNKNOWN ' + C // <-- replace with your desired default
// if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
// headers.push(hdr)
// }
// return headers
// }
}
}
</script>
<style lang="less" scoped>
.uploader-dialog {
.upload-demo {
text-align: center;
/deep/.el-upload {
width: 100%;
}
/deep/.el-upload-dragger {
width: 100%;
background: rgba(0, 0, 0, 0.03);
}
.el-upload__tip {
color: rgba(0, 0, 0, 0.45);
}
}
}
</style>
- 在其他组件中使用上传组件
vue
<Uploader ref="uploader" />
<script>
// 点击批量导入
showDialog() {
this.$refs.uploader.visible = true
},
</script>
导出 excel 和导入
js
// 导出
handleExportXls(fileName) {
if (!fileName || typeof fileName != 'string') {
fileName = '导出文件'
}
let param = { ...this.queryParam }
if (this.selectedRowKeys && this.selectedRowKeys.length > 0) {
param['selections'] = this.selectedRowKeys.join(',')
}
downFile(this.url.exportXlsUrl, param).then((data) => {
if (!data) {
this.$message.warning('文件下载失败')
return
}
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(new Blob([data], { type: 'application/vnd.ms-excel' }), fileName + '.xls')
} else {
let url = window.URL.createObjectURL(new Blob([data], { type: 'application/vnd.ms-excel' }))
let link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', fileName + '.xls')
document.body.appendChild(link)
link.click()
document.body.removeChild(link) //下载完成移除元素
window.URL.revokeObjectURL(url) //释放掉blob对象
}
})
},
/* 导入 */
handleImportExcel(info) {
if (info.file.status !== 'uploading') {
console.log(info.file, info.fileList)
}
if (info.file.status === 'done') {
if (info.file.response.success) {
// this.$message.success(`${info.file.name} 文件上传成功`);
if (info.file.response.code === 201) {
let {
message,
result: { msg, fileUrl, fileName },
} = info.file.response
let href = window._CONFIG['domianURL'] + fileUrl
this.$warning({
title: message,
content: (
<div>
<span>{msg}</span>
<br />
<span>
具体详情请{' '}
<a href={href} target="_blank" download={fileName}>
点击下载
</a>{' '}
</span>
</div>
),
})
} else {
this.$message.success(info.file.response.message || `${info.file.name} 文件上传成功`)
}
this.loadData()
} else {
this.$message.error(`${info.file.name} ${info.file.response.message}.`)
}
} else if (info.file.status === 'error') {
this.$message.error(`文件上传失败: ${info.file.msg} `)
}
},
注意在导出时对应 api 应加上如下配置
js
export function downFile(url, params) {
return axios({
url,
method: 'get',
// 注意必须加上这条配置
responseType: 'blob',
params
})
}
利用递归根据 id 查询数据
js
var data = [
{
id: 1,
name: '家电',
goods: [
{
id: 11,
gname: '冰箱',
goods: [
{
id: 111,
gname: '海尔'
},
{
id: 112,
gname: '美的'
}
]
},
{
id: 12,
gname: '洗衣机',
// #1
goods: [
{
id: 666
}
]
}
]
},
{
id: 2,
name: '服饰'
// #2
// goods: [{
// id: 888
// }]
}
]
function getID(json, id, callback) {
json.some(function (item) {
if (item.id == id) {
callback(item)
return true
} else if (item.goods && item.goods.length > 0) {
getID(item.goods, id, callback)
}
})
}
getID(data, 11, function (data) {
console.log(data)
})
结合 elementUI 读取 exsl 数据
vue
<template>
<el-upload
ref="upload"
class="upload-demo"
:before-upload="beforeUpload"
accept=".xlsx, xls"
drag
action="https://jsonplaceholder.typicode.com/posts/"
:on-error="uploadFail"
:limit="1"
:multiple="false"
:auto-upload="false"
>
</template>
<script>
// 导入解析 excel 表格插件
import XLSX from 'xlsx'
methods: {
beforeUpload(file) {
this.file = file
if (file) {
this.buttonLoading = true
}
if (
file.name.split('.')[1].includes('xls' || 'xlsx') &&
file.size < 20 * 1024 * 1024
) {
let param = new FormData()
param.append('file', file)
this.$axios
.post(`/api/enterprise/importInvestOrgExcel`, param, {
headers: { 'Content-Type': 'multipart/form-data' }
})
.then(res => {
if (res.data.success) {
this.$message.success('上传成功!')
} else {
this.$message.error(res.data.message)
}
console.log(res.data)
})
} else {
this.$message('请上传符合要求的文件!')
this.buttonLoading = false
return false
}
},
// 上传 exsl 数据
submit() {
this.$refs.upload.submit()
},
uploadFail() {
this.$message('上传失败')
this.buttonLoading = false
},
beforeClose(done) {
this.buttonLoading ? '' : (this.visible = false)
}
// 获取读取到的 exsl 表格数据,header 表示所有表头数据,results 表示每一行的数据
generateData({ header, results }) {
this.excelData.header = header
this.excelData.results = results
this.onSuccess && this.onSuccess(this.excelData)
},
// 读取 exsl
readerData(rawFile) {
this.loading = true
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = e => {
const data = e.target.result
const workbook = XLSX.read(data, { type: 'array' })
const firstSheetName = workbook.SheetNames[0]
const worksheet = workbook.Sheets[firstSheetName]
const header = this.getHeaderRow(worksheet)
const results = XLSX.utils.sheet_to_json(worksheet)
this.generateData({ header, results })
this.loading = false
resolve()
}
reader.readAsArrayBuffer(rawFile)
})
},
// 设置表头数据
getHeaderRow(sheet) {
const headers = []
const range = XLSX.utils.decode_range(sheet['!ref'])
let C
const R = range.s.r
/* start in the first row */
for (C = range.s.c; C <= range.e.c; ++C) {
/* walk every column in the range */
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
/* find the cell in the first row */
let hdr = 'UNKNOWN ' + C // <-- replace with your desired default
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
headers.push(hdr)
}
return headers
}
}
</script>
导出 excel 带下拉框
js
import ExcelJS from 'exceljs'
async function ecportExcel() {
const wb = new ExcelJS.Workbook()
const Sheet1 = wb.addWorksheet('企业基本信息')
const Sheet2 = wb.addWorksheet('Sheet2')
// 定义下拉框数据表头
Sheet2.columns = [
{
header: '企业编码',
key: 'enterpriseNum',
width: 20
},
{
header: '集团名称',
key: 'groupName',
width: 20
}
]
// 定义下拉框数据
const Sheet2_data = [
{
enterpriseNum: '女',
groupName: '1111'
},
{
enterpriseNum: '男',
groupName: '2222'
}
]
Sheet2.addRows(Sheet2_data)
Sheet1.columns = sheeHeader // 需要导出的数据表头
Sheet1.addRows(sheeData) // 将 sheeData (需要导出的数据)
// 添加性别管理器
/*const _data = sheeData.reduce((p, c) => {
if (!p.has(c.enterpriseNum)) {
p.set(c.enterpriseNum, [c.groupName])
} else {
const arr = p.get(c.enterpriseNum)
arr.push(c.groupName)
}
return p
}, new Map())*/
// 添加下拉框
new Array(1000).fill(0).forEach((_, idx) => {
const row = idx + 2
// 表示在第一列添加下拉框
Sheet1.getCell(row, 1).dataValidation = {
type: 'list',
// 下拉框选项,Sheet2 表示要从这个工作表读取下拉框数据
formulae: [`=Sheet2!$A$2:$A${Sheet2_data.length + 1}`]
}
// 使用indirect函数添加引用, 渲染性别值
Sheet1.getCell(row, 2).dataValidation = {
type: 'list',
formulae: [`=Sheet2!$B$2:$B${Sheet2_data.length + 1}`]
}
})
const buffer = await wb.xlsx.writeBuffer()
const blob = new Blob([buffer], {
type: 'application/octet-stream'
})
let url = blob,
saveName = '企业信息表.xlsx'
if (typeof url == 'object' && url instanceof Blob) {
url = URL.createObjectURL(url) // 创建blob地址
}
const aLink = document.createElement('a')
aLink.href = url
aLink.download = saveName || '' // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
var event
if (window.MouseEvent) event = new MouseEvent('click')
else {
event = document.createEvent('MouseEvents')
event.initMouseEvent(
'click',
true,
false,
window,
0,
0,
0,
0,
0,
false,
false,
false,
false,
0,
null
)
}
aLink.dispatchEvent(event)
return
}
ecportExcel()
大屏适配方案
在 app.vue 中添加全局页面比例
vue
<template>
<div id="app" :style="style">
<router-view />
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
style: {
transform: 'scale(1)',
width: '1920px',
height: '1080px',
transformOrigin: '0 0'
}
}
},
mounted() {
this.setScale()
window.addEventListener('resize', this.setScale)
this.$once('hook:beforeDestroy', () => {
window.removeEventListener('resize', this.setScale)
})
},
methods: {
setScale() {
const w = window.innerWidth / 1920
const h = window.innerHeight / 1080
this.style.transform = `scale(${w},${h})`
this.style.transformOrigin = '0 0'
}
}
}
</script>
<style>
#app {
transition: 0.5s;
}
</style>
在其他组件中使用
js
created() {
// 控制页面缩放
this.resize()
window.addEventListener('resize', () => {
this.resize()
})
window.onload = () => {
return this.resize()
}
// 控制页面缩放
},
methods: {
// 控制页面缩放
resize() {
let appDom = document.querySelector('#app')
appDom.style.transform = 'scale(1,1)'
appDom.style.width = 100 + '%'
appDom.style.height = 100 + '%'
},
原生 js 实现视频
vue
<template>
<div class="video">
<video
ref="myvideo"
class="videoContent"
@canplay="canplay"
@timeupdate="timeupdate"
@pause="videoisplay = false"
@play="videoisplay = true"
v-if="url !== ''"
>
<source :src="url" />
</video>
<div class="sess" v-if="url !== ''">
<div class="star" @click="star">
<i
:class="
videoisplay
? 'icon-24gf-pause2 iconfont'
: 'icon-24gf-play iconfont'
"
style="font-size: 25px;"
></i>
</div>
<div class="time">{{ startime }}/{{ totaltime }}</div>
<div ref="jin" class="jin" @click="progress">
<div class="hua" :style="jinprease"></div>
<div
class="point"
:style="jinprease === '' ? 'margin-left: 0;' : ''"
></div>
</div>
<div class="yin" @click="voice">
<i
:class="
isvoice
? 'icon-mn_shengyinwu_fill iconfont'
: 'icon-shengyin iconfont'
"
></i>
</div>
<div
ref="yin"
class="jin"
style="width: 100px; margin: 0 15px;"
@click="yinprease"
>
<div class="hua" :style="yinpreasestyle"></div>
<div class="point"></div>
</div>
<div class="full" @click="fullview">
<i class="icon-quanping iconfont"></i>
</div>
</div>
<div class="videocontent">
<div class="title">{{ videoinfo }}</div>
<div class="title2">
<p class="span1">投资总额</p>
<p class="span2">10000<span class="span3">亿元</span></p>
</div>
<div class="content">
<echartsBox
ref="layoutCharts4"
refName="layoutCharts4"
eChartsType="5"
:chartsLoading="true"
></echartsBox>
</div>
<div class="content2">
<div class="text">
<p>本年计划投资</p>
<div>80000<span>万元</span></div>
</div>
<div class="text">
<p>本年计划投资</p>
<div>80000<span>万元</span></div>
</div>
</div>
<div class="content3">
<p class="project" @click="selectitem(0)">
项目概要<i
class="icon-xiangxiajiantou iconfont"
:style="select ? '' : 'transform: rotateZ(-90deg)'"
></i>
</p>
<div class="projectcontent" v-if="select">
项目包括新建战勤保障综合楼1栋地下1层,地上由A座、B座和综合修理楼共3栋建筑组成油料供应站1个及室外配套工作项目包括新建战勤保障综合楼1
</div>
<p class="project" @click="selectitem(1)">
问题跟踪<i
class="icon-xiangxiajiantou iconfont"
:style="select2 ? '' : 'transform: rotateZ(-90deg)'"
></i>
</p>
<div class="projectcontent" v-if="select2">
项目包括新建战勤保障综合楼1栋地下1层,地上由A座、B座和综合修理楼共3栋建筑组成油料供应站1个及室外配套工作项目包括新建战勤保障综合楼1
</div>
</div>
</div>
</div>
</template>
<script>
import echartsBox from '../../components/ChartsDemo/index.vue'
export default {
components: {
echartsBox
},
// 用户点击的视频信息
props: {
videoinfo: {
type: String
}
},
data() {
return {
videoisplay: false, // 记录视频是否播放
url: '',
startime: 0, // 记录已播放
totaltime: 0, // 总时长
totaltimestring: '', // 总时长时间秒数
isvoice: false, // 是否静音
voicenum: 20, // 默认音量大小
clientwidth: 0, // 记录视频进度条长度
clientwidth2: 0, // 记录音量进度条长度
jinprease: '', // 控制视频进度条位置
yinpreasestyle: '', // 控制音量进度条位置
flag: true, // 控制进度条节流阀
select: true, // 记录视频上手风琴当前选择的文本(项目概要/问题跟踪)代表是否展开
select2: false // 记录视频上手风琴当前选择的文本(问题跟踪)代表是否展开
}
},
created() {
this.geturl()
},
methods: {
// 获取视频链接
geturl() {
setTimeout(() => {
this.url =
'https://api.dogecloud.com/player/get.mp4?vcode=5ac682e6f8231991&userId=17&ext=.mp4'
}, 1000)
},
// 控制视频暂停播放
star() {
this.videoisplay = !this.videoisplay
if (this.videoisplay) {
this.$refs.myvideo.play()
} else {
this.$refs.myvideo.pause()
}
},
// 视频加载完毕
canplay() {
this.totaltime = this.formatTime(this.$refs.myvideo.duration)
this.totaltimestring = this.$refs.myvideo.duration
this.startime = this.formatTime(this.$refs.myvideo.currentTime)
this.clientwidth = this.$refs.jin.clientWidth
this.clientwidth2 = this.$refs.yin.clientWidth
},
// 获取已播放时间
timeupdate(e) {
this.startime = this.formatTime(e.target.currentTime)
if (this.flag) {
this.flag = false
setTimeout(() => {
this.jinprease = `width:${(
(e.target.currentTime / this.totaltimestring) *
100
).toFixed(2)}%`
this.flag = true
}, 1500)
}
},
// 调节音量
voice() {
this.isvoice = !this.isvoice
if (this.isvoice) {
this.$refs.myvideo.volume = 0
} else {
this.$refs.myvideo.volume = this.voicenum / 100
}
},
// 控制全屏
fullview() {
this.$refs.myvideo.requestFullscreen()
},
// 视频进度条交互
progress(e) {
// 根据用户点击区域控制进度条长度
let fen = e.offsetX / this.clientwidth
let bo = this.formatTime(fen * this.totaltimestring)
this.jinprease = `width:${(fen * 100).toFixed(2)}%`
// 修改已播放文本
this.startime = bo
// 修改视频到对应位置
this.$refs.myvideo.currentTime = fen * this.totaltimestring
},
// 音量进度条交互
yinprease(e) {
// 根据用户点击区域控制进度条长度
let fen = e.offsetX / this.clientwidth2
this.yinpreasestyle = `width:${(fen * 100).toFixed(1)}%`
this.$refs.myvideo.volume = fen
this.voicenum = fen
},
// 视频上手风琴切换
selectitem(i) {
if (i) {
// 当前选中的是问题跟踪
if (this.select && !this.select2) {
this.select = !this.select
this.select2 = !this.select2
} else {
this.select2 = !this.select2
}
} else {
// 当前选中的是项目概要
if (!this.select && this.select2) {
this.select = !this.select
this.select2 = !this.select2
} else {
this.select = !this.select
}
}
},
initCharts() {
let value = 50 // 数值
let seriesData = [
{
type: 'gauge',
startAngle: 180,
endAngle: 0,
z: 10,
min: 0,
max: 100,
radius: '180%',
// radius: ['100%', '50%'],
center: ['50%', '100%'],
axisLine: {
show: false
// lineStyle: {
// color: [
// [1, '#0a1f4a']
// ],
// width: 1,
// opacity: 1
// }
},
title: {
show: false
},
detail: {
// backgroundColor: '#fff',
// borderColor: '#999',
// borderWidth: 2,
width: '100%',
// borderRadius: 4,
offsetCenter: [0, '-20%'],
formatter: function (value) {
return (
'{value|' + value.toFixed(0) + '}{unit|%}\n{unit2|形象进度}'
)
},
rich: {
value: {
fontSize: 25,
// fontWeight: 'bolder',
color: '#fff'
},
unit: {
fontSize: 10,
color: '#fff',
padding: [0, 0, 5, 0]
},
unit2: {
fontSize: 10,
color: '#fff'
// padding: [0, 0, 15, 6]
}
}
},
// axisLine: {
// show: false
// },
axisTick: {
// show:false,
length: 3,
lineStyle: {
color: '#999'
}
},
splitLine: {
length: 0,
lineStyle: {
color: '#999',
width: 3
}
},
axisLabel: {
show: false,
color: '#999'
},
pointer: {
show: false
// width: 5,
// length: '80%',
},
itemStyle: {
color: '#0a204b'
// shadowColor: '#eef2f6',
// shadowBlur: 10,
// shadowOffsetX: 2,
// shadowOffsetY: 2
},
markPoint: {
show: false
// data: [
// {
// x: '50%',
// y: '100%',
// symbol: 'circle',
// symbolSize: 8,
// itemStyle: {
// color: '#fff'
// }
// }
// ]
},
data: [
{
value: value
}
]
},
{
// 内层
type: 'gauge',
startAngle: 180,
endAngle: 0,
// splitNumber:20,
min: 0,
max: 100,
radius: '145%',
// radius: ['60%', '30%'],
center: ['50%', '100%'],
// axisLine: {
// show: false,
// // lineStyle: {
// // color: [
// // [1, '#999']
// // ],
// // width: 1,
// // opacity: 1
// // }
// },
title: {
show: false
},
detail: {
show: false
},
axisLine: {
show: false
},
axisTick: {
length: 5,
lineStyle: {
color: '#999'
}
},
splitLine: {
length: 10,
lineStyle: {
color: '#999',
width: 2
}
},
axisLabel: {
show: false,
color: '#999'
},
pointer: {
width: 3,
length: '80%'
},
itemStyle: {
color: '#2b4f7d',
shadowColor: 'rgba(0,138,255,0.45)',
shadowBlur: 5
// shadowOffsetX: 2,
// shadowOffsetY: 2
},
markPoint: {
show: false
// data: [
// {
// x: '50%',
// y: '50%',
// symbol: 'circle',
// symbolSize: 1,
// itemStyle: {
// color: '#fff'
// }
// }
// ]
},
data: [
{
value: value
}
]
},
{
type: 'gauge',
radius: '160%',
// radius: ['90%', '90%'],
center: ['50%', '100%'],
startAngle: 180,
endAngle: 0,
min: 0,
max: 100,
title: {
show: false
},
detail: {
show: false
},
axisLine: {
show: true,
lineStyle: {
width: 6,
color: [
[value / 100, '#00FFE6'],
[1, '#324e9c']
]
}
},
axisTick: {
show: false
},
splitLine: {
show: false
},
axisLabel: {
show: false
},
pointer: {
show: false
},
itemStyle: {
normal: {
color: '#54F200'
}
}
}
]
let extraOption = {}
this.$refs.layoutCharts4.mergeOptoptions(seriesData, extraOption)
},
// 时间格式化
formatTime(seconds) {
let h = 0,
m = 0,
s = 0
const formatNumber = n => (n > 9 ? n : `0${n}`)
if (seconds > 3600) {
h = parseInt(seconds / 3600)
seconds = seconds - h * 3600
h = formatNumber(h)
}
if (seconds > 60) {
m = parseInt(seconds / 60)
seconds = seconds - m * 60
m = formatNumber(m)
}
s = formatNumber(parseInt(seconds))
return `${h ? `${h}:` : ''}${m ? m : '00'}:${s ? s : '00'}`
}
},
mounted() {
this.initCharts()
}
}
</script>
<style scoped lang="less">
.video {
width: 100%;
height: 100%;
position: relative;
video {
width: 100%;
height: 90%;
object-fit: fill;
}
.sess {
height: 46px;
display: flex;
align-items: center;
.star {
width: 30px;
height: 30px;
font-size: 15px;
cursor: pointer;
margin-left: 20px;
}
.time {
margin: 0 25px;
color: #ffffff;
font-size: 15px;
}
.jin {
width: 475px;
height: 10px;
border-radius: 5px;
background-color: #43567f;
// position: relative;
cursor: pointer;
display: flex;
align-items: center;
.hua {
width: 0;
height: 10px;
border-radius: 5px;
background-color: #f05636;
transition: 0.1s;
// position: absolute;
// left: 0;
}
.point {
width: 15px;
height: 15px;
border-radius: 50%;
background-color: #fff;
margin-left: -10px;
}
}
.yin {
width: 30px;
height: 30px;
font-size: 15px;
cursor: pointer;
margin-left: 15px;
}
.full {
width: 30px;
height: 30px;
font-size: 15px;
cursor: pointer;
}
}
.videocontent {
position: absolute;
left: 0;
top: 0;
width: 272px;
height: 395px;
background: rgba(0, 11, 46, 0.5);
box-sizing: border-box;
padding: 0 15px;
.title {
height: 32px;
background: linear-gradient(
270deg,
rgba(76, 59, 255, 0) 0%,
#899eff 48%,
rgba(76, 59, 255, 0) 100%
);
filter: blur(0px);
font-size: 17px;
font-weight: 600;
color: #ffffff;
line-height: 32px;
}
.title2 {
display: flex;
align-items: center;
font-size: 14px;
font-weight: 400;
color: #c2cde7;
.span1 {
margin: 5px 10px 0 0;
}
.span2 {
max-width: 175px;
font-size: 28px;
color: #00d3ff;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
.span3 {
font-size: 14px;
}
}
}
.content {
width: 180px;
height: 90px;
margin: 0 auto;
// background-color: cadetblue;
}
.content2 {
height: 50px;
display: flex;
justify-content: space-between;
margin-top: 10px;
.text {
width: 90px;
height: 100%;
color: #c2cde7;
font-size: 14px;
div {
color: #00d3ff;
font-size: 20px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
span {
font-size: 12px;
}
}
}
}
.content3 {
height: 165px;
.project {
font-size: 14px;
color: #ffffff;
margin: 10px 0 5px 0;
display: flex;
align-items: center;
cursor: pointer;
}
.projectcontent {
height: 90px;
font-size: 12px;
color: #c2cde7;
}
}
}
}
.icon-xiangxiajiantou {
height: 14px;
width: 14px;
font-size: 14px !important;
color: #00d3ff !important;
margin-left: 5px;
// margin: 2px 0 0 5px;
// transition: 0.3s;
// transform: rotateZ(90deg);
}
@font-face {
font-family: 'iconfont'; /* Project id 3274792 */
src: url('//at.alicdn.com/t/font_3274792_4l5ykunhnm5.woff2?t=1648171585990')
format('woff2'), url('//at.alicdn.com/t/font_3274792_4l5ykunhnm5.woff?t=1648171585990')
format('woff'),
url('//at.alicdn.com/t/font_3274792_4l5ykunhnm5.ttf?t=1648171585990') format('truetype');
}
.iconfont {
font-family: 'iconfont' !important;
font-size: 28px;
font-style: normal;
color: #fff;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-xiangxiajiantou:before {
content: '\e689';
}
.icon-quanping:before {
content: '\e61f';
}
.icon-mn_shengyinwu_fill:before {
content: '\e600';
}
.icon-24gf-pause2:before {
content: '\ea81';
}
.icon-24gf-play:before {
content: '\ea82';
}
.icon-shengyin:before {
content: '\e637';
}
</style>
在 vue 中使用 ECharts
- 先在 main.js 中引入
js
import * as echarts5 from 'echarts5'
import * as echarts4 from 'echarts4'
Vue.use(echarts4)
Vue.use(echarts5)
- 在组件中使用
vue
<div class="right_content">
<div class="ChartsBox2" ref="ChartsBox2"></div>
</div>
<script>
export default {
data() {
//这里存放数据
return {
// 环状图数据
option2: {
grid: {
left: "10%",
right: "10",
containLabel: true
},
series: [
{
type: "pie",
center: ["50%", "50%"],
radius: [30, 45],
selectedMode: "single",
data: [],
label: {
formatter: "{name|{b}}{val|{d}}{name|%}\n",
minMargin: 15,
lineHeight: 25,
padding: [0, -45],
rich: {
val: {
fontSize: 14
},
name: {
fontSize: 10,
color: "#FFFFFF"
}
}
},
labelLine: {
length: 20,
length2: 50,
maxSurfaceAngle: 80
}
}
],
color: ["#FFCF29", "#DB4537"]
}
};
},
//监听属性 类似于data概念
computed: {},
created() {},
mounted() {
let data2 = [
{ value: 55, name: "巡听" },
{ value: 45, name: "旁听" }
];
this.initCharts2(data2);
},
//监控data中的数据变化
watch: {},
//方法集合
methods: {
// 环状图
initCharts2(data) {
let param = $.extend(true, {}, this.option2, {
series: [
{
data: data
}
]
});
let $dom = this.$refs["ChartsBox2"];
this.chartTrend = this.$echarts.init($dom);
this.chartTrend.resize();
this.chartTrend.clear();
this.option2 && this.chartTrend.setOption(param);
}
}
};
</script>
ECharts 配置
js
theme = {
// 全图默认背景
// backgroundColor: 'rgba(0,0,0,0)',
// 默认色板
color: [
'#ff7f50',
'#87cefa',
'#da70d6',
'#32cd32',
'#6495ed',
'#ff69b4',
'#ba55d3',
'#cd5c5c',
'#ffa500',
'#40e0d0',
'#1e90ff',
'#ff6347',
'#7b68ee',
'#00fa9a',
'#ffd700',
'#6699FF',
'#ff6666',
'#3cb371',
'#b8860b',
'#30e0e0'
],
// 图表标题
title: {
x: 'left', // 水平安放位置,默认为左对齐,可选为:
// 'center' ¦ 'left' ¦ 'right'
// ¦ {number}(x坐标,单位px)
y: 'top', // 垂直安放位置,默认为全图顶端,可选为:
// 'top' ¦ 'bottom' ¦ 'center'
// ¦ {number}(y坐标,单位px)
//textAlign: null // 水平对齐方式,默认根据x设置自动调整
backgroundColor: 'rgba(0,0,0,0)',
borderColor: '#ccc', // 标题边框颜色
borderWidth: 0, // 标题边框线宽,单位px,默认为0(无边框)
padding: 5, // 标题内边距,单位px,默认各方向内边距为5,
// 接受数组分别设定上右下左边距,同css
itemGap: 10, // 主副标题纵向间隔,单位px,默认为10,
textStyle: {
fontSize: 18,
fontWeight: 'bolder',
color: '#333' // 主标题文字颜色
},
subtextStyle: {
color: '#aaa' // 副标题文字颜色
}
},
// 图例
legend: {
orient: 'horizontal', // 布局方式,默认为水平布局,可选为:
// 'horizontal' ¦ 'vertical'
x: 'center', // 水平安放位置,默认为全图居中,可选为:
// 'center' ¦ 'left' ¦ 'right'
// ¦ {number}(x坐标,单位px)
y: 'top', // 垂直安放位置,默认为全图顶端,可选为:
// 'top' ¦ 'bottom' ¦ 'center'
// ¦ {number}(y坐标,单位px)
backgroundColor: 'rgba(0,0,0,0)',
borderColor: '#ccc', // 图例边框颜色
borderWidth: 0, // 图例边框线宽,单位px,默认为0(无边框)
padding: 5, // 图例内边距,单位px,默认各方向内边距为5,
// 接受数组分别设定上右下左边距,同css
itemGap: 10, // 各个item之间的间隔,单位px,默认为10,
// 横向布局时为水平间隔,纵向布局时为纵向间隔
itemWidth: 20, // 图例图形宽度
itemHeight: 14, // 图例图形高度
textStyle: {
color: '#333' // 图例文字颜色
}
},
// 值域
dataRange: {
orient: 'vertical', // 布局方式,默认为垂直布局,可选为:
// 'horizontal' ¦ 'vertical'
x: 'left', // 水平安放位置,默认为全图左对齐,可选为:
// 'center' ¦ 'left' ¦ 'right'
// ¦ {number}(x坐标,单位px)
y: 'bottom', // 垂直安放位置,默认为全图底部,可选为:
// 'top' ¦ 'bottom' ¦ 'center'
// ¦ {number}(y坐标,单位px)
backgroundColor: 'rgba(0,0,0,0)',
borderColor: '#ccc', // 值域边框颜色
borderWidth: 0, // 值域边框线宽,单位px,默认为0(无边框)
padding: 5, // 值域内边距,单位px,默认各方向内边距为5,
// 接受数组分别设定上右下左边距,同css
itemGap: 10, // 各个item之间的间隔,单位px,默认为10,
// 横向布局时为水平间隔,纵向布局时为纵向间隔
itemWidth: 20, // 值域图形宽度,线性渐变水平布局宽度为该值 * 10
itemHeight: 14, // 值域图形高度,线性渐变垂直布局高度为该值 * 10
splitNumber: 5, // 分割段数,默认为5,为0时为线性渐变
color: ['#1e90ff', '#f0ffff'], //颜色
//text:['高','低'], // 文本,默认为数值文本
textStyle: {
color: '#333' // 值域文字颜色
}
},
toolbox: {
orient: 'horizontal', // 布局方式,默认为水平布局,可选为:
// 'horizontal' ¦ 'vertical'
x: 'right', // 水平安放位置,默认为全图右对齐,可选为:
// 'center' ¦ 'left' ¦ 'right'
// ¦ {number}(x坐标,单位px)
y: 'top', // 垂直安放位置,默认为全图顶端,可选为:
// 'top' ¦ 'bottom' ¦ 'center'
// ¦ {number}(y坐标,单位px)
color: ['#1e90ff', '#22bb22', '#4b0082', '#d2691e'],
backgroundColor: 'rgba(0,0,0,0)', // 工具箱背景颜色
borderColor: '#ccc', // 工具箱边框颜色
borderWidth: 0, // 工具箱边框线宽,单位px,默认为0(无边框)
padding: 5, // 工具箱内边距,单位px,默认各方向内边距为5,
// 接受数组分别设定上右下左边距,同css
itemGap: 10, // 各个item之间的间隔,单位px,默认为10,
// 横向布局时为水平间隔,纵向布局时为纵向间隔
itemSize: 16, // 工具箱图形宽度
featureImageIcon: {}, // 自定义图片icon
featureTitle: {
mark: '辅助线开关',
markUndo: '删除辅助线',
markClear: '清空辅助线',
dataZoom: '区域缩放',
dataZoomReset: '区域缩放后退',
dataView: '数据视图',
lineChart: '折线图切换',
barChart: '柱形图切换',
restore: '还原',
saveAsImage: '保存为图片'
}
},
// 提示框
tooltip: {
trigger: 'item', // 触发类型,默认数据触发,见下图,可选为:'item' ¦ 'axis'
showDelay: 20, // 显示延迟,添加显示延迟可以避免频繁切换,单位ms
hideDelay: 100, // 隐藏延迟,单位ms
transitionDuration: 0.4, // 动画变换时间,单位s
backgroundColor: 'rgba(0,0,0,0.7)', // 提示背景颜色,默认为透明度为0.7的黑色
borderColor: '#333', // 提示边框颜色
borderRadius: 4, // 提示边框圆角,单位px,默认为4
borderWidth: 0, // 提示边框线宽,单位px,默认为0(无边框)
padding: 5, // 提示内边距,单位px,默认各方向内边距为5,
// 接受数组分别设定上右下左边距,同css
axisPointer: {
// 坐标轴指示器,坐标轴触发有效
type: 'line', // 默认为直线,可选为:'line' | 'shadow'
lineStyle: {
// 直线指示器样式设置
color: '#48b',
width: 2,
type: 'solid'
},
shadowStyle: {
// 阴影指示器样式设置
width: 'auto', // 阴影大小
color: 'rgba(150,150,150,0.3)' // 阴影颜色
}
},
textStyle: {
color: '#fff'
}
},
// 区域缩放控制器
dataZoom: {
orient: 'horizontal', // 布局方式,默认为水平布局,可选为:
// 'horizontal' ¦ 'vertical'
// x: {number}, // 水平安放位置,默认为根据grid参数适配,可选为:
// {number}(x坐标,单位px)
// y: {number}, // 垂直安放位置,默认为根据grid参数适配,可选为:
// {number}(y坐标,单位px)
// width: {number}, // 指定宽度,横向布局时默认为根据grid参数适配
// height: {number}, // 指定高度,纵向布局时默认为根据grid参数适配
backgroundColor: 'rgba(0,0,0,0)', // 背景颜色
dataBackgroundColor: '#eee', // 数据背景颜色
fillerColor: 'rgba(144,197,237,0.2)', // 填充颜色
handleColor: 'rgba(70,130,180,0.8)' // 手柄颜色
},
// 网格
grid: {
x: 80,
y: 60,
x2: 80,
y2: 60,
// width: {totalWidth} - x - x2,
// height: {totalHeight} - y - y2,
backgroundColor: 'rgba(0,0,0,0)',
borderWidth: 1,
borderColor: '#ccc'
},
// 类目轴
categoryAxis: {
position: 'bottom', // 位置
nameLocation: 'end', // 坐标轴名字位置,支持'start' | 'end'
boundaryGap: true, // 类目起始和结束两端空白策略
axisLine: {
// 坐标轴线
show: true, // 默认显示,属性show控制显示与否
lineStyle: {
// 属性lineStyle控制线条样式
color: '#48b',
width: 2,
type: 'solid'
}
},
axisTick: {
// 坐标轴小标记
show: true, // 属性show控制显示与否,默认不显示
interval: 'auto',
// onGap: null,
inside: false, // 控制小标记是否在grid里
length: 5, // 属性length控制线长
lineStyle: {
// 属性lineStyle控制线条样式
color: '#333',
width: 1
}
},
axisLabel: {
// 坐标轴文本标签,详见axis.axisLabel
show: true,
interval: 'auto',
rotate: 0,
margin: 8,
// formatter: null,
textStyle: {
// 其余属性默认使用全局文本样式,详见TEXTSTYLE
color: '#333'
}
},
splitLine: {
// 分隔线
show: true, // 默认显示,属性show控制显示与否
// onGap: null,
lineStyle: {
// 属性lineStyle(详见lineStyle)控制线条样式
color: ['#ccc'],
width: 1,
type: 'solid'
}
},
splitArea: {
// 分隔区域
show: false, // 默认不显示,属性show控制显示与否
// onGap: null,
areaStyle: {
// 属性areaStyle(详见areaStyle)控制区域样式
color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)']
}
}
},
// 数值型坐标轴默认参数
valueAxis: {
position: 'left', // 位置
nameLocation: 'end', // 坐标轴名字位置,支持'start' | 'end'
nameTextStyle: {}, // 坐标轴文字样式,默认取全局样式
boundaryGap: [0, 0], // 数值起始和结束两端空白策略
splitNumber: 5, // 分割段数,默认为5
axisLine: {
// 坐标轴线
show: true, // 默认显示,属性show控制显示与否
lineStyle: {
// 属性lineStyle控制线条样式
color: '#48b',
width: 2,
type: 'solid'
}
},
axisTick: {
// 坐标轴小标记
show: false, // 属性show控制显示与否,默认不显示
inside: false, // 控制小标记是否在grid里
length: 5, // 属性length控制线长
lineStyle: {
// 属性lineStyle控制线条样式
color: '#333',
width: 1
}
},
axisLabel: {
// 坐标轴文本标签,详见axis.axisLabel
show: true,
rotate: 0,
margin: 8,
// formatter: null,
textStyle: {
// 其余属性默认使用全局文本样式,详见TEXTSTYLE
color: '#333'
}
},
splitLine: {
// 分隔线
show: true, // 默认显示,属性show控制显示与否
lineStyle: {
// 属性lineStyle(详见lineStyle)控制线条样式
color: ['#ccc'],
width: 1,
type: 'solid'
}
},
splitArea: {
// 分隔区域
show: false, // 默认不显示,属性show控制显示与否
areaStyle: {
// 属性areaStyle(详见areaStyle)控制区域样式
color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)']
}
}
},
polar: {
center: ['50%', '50%'], // 默认全局居中
radius: '75%',
startAngle: 90,
splitNumber: 5,
name: {
show: true,
textStyle: {
// 其余属性默认使用全局文本样式,详见TEXTSTYLE
color: '#333'
}
},
axisLine: {
// 坐标轴线
show: true, // 默认显示,属性show控制显示与否
lineStyle: {
// 属性lineStyle控制线条样式
color: '#ccc',
width: 1,
type: 'solid'
}
},
axisLabel: {
// 坐标轴文本标签,详见axis.axisLabel
show: false,
textStyle: {
// 其余属性默认使用全局文本样式,详见TEXTSTYLE
color: '#333'
}
},
splitArea: {
show: true,
areaStyle: {
color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)']
}
},
splitLine: {
show: true,
lineStyle: {
width: 1,
color: '#ccc'
}
}
},
// 柱形图默认参数
bar: {
barMinHeight: 0, // 最小高度改为0
// barWidth: null, // 默认自适应
barGap: '30%', // 柱间距离,默认为柱形宽度的30%,可设固定值
barCategoryGap: '20%', // 类目间柱形距离,默认为类目间距的20%,可设固定值
itemStyle: {
normal: {
// color: '各异',
barBorderColor: '#fff', // 柱条边线
barBorderRadius: 0, // 柱条边线圆角,单位px,默认为0
barBorderWidth: 1, // 柱条边线线宽,单位px,默认为1
label: {
show: false
// position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
// 'inside'|'left'|'right'|'top'|'bottom'
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
}
},
emphasis: {
// color: '各异',
barBorderColor: 'rgba(0,0,0,0)', // 柱条边线
barBorderRadius: 0, // 柱条边线圆角,单位px,默认为0
barBorderWidth: 1, // 柱条边线线宽,单位px,默认为1
label: {
show: false
// position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
// 'inside'|'left'|'right'|'top'|'bottom'
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
}
}
}
},
// 折线图默认参数
line: {
itemStyle: {
normal: {
// color: 各异,
label: {
show: false
// position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
// 'inside'|'left'|'right'|'top'|'bottom'
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
},
lineStyle: {
width: 2,
type: 'solid',
shadowColor: 'rgba(0,0,0,0)', //默认透明
shadowBlur: 5,
shadowOffsetX: 3,
shadowOffsetY: 3
}
},
emphasis: {
// color: 各异,
label: {
show: false
// position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
// 'inside'|'left'|'right'|'top'|'bottom'
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
}
}
},
//smooth : false,
//symbol: null, // 拐点图形类型
symbolSize: 2, // 拐点图形大小
//symbolRotate : null, // 拐点图形旋转控制
showAllSymbol: false // 标志图形默认只有主轴显示(随主轴标签间隔隐藏策略)
},
// K线图默认参数
k: {
// barWidth : null // 默认自适应
// barMaxWidth : null // 默认自适应
itemStyle: {
normal: {
color: '#fff', // 阳线填充颜色
color0: '#00aa11', // 阴线填充颜色
lineStyle: {
width: 1,
color: '#ff3200', // 阳线边框颜色
color0: '#00aa11' // 阴线边框颜色
}
},
emphasis: {
// color: 各异,
// color0: 各异
}
}
},
// 散点图默认参数
scatter: {
//symbol: null, // 图形类型
symbolSize: 4, // 图形大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2
//symbolRotate : null, // 图形旋转控制
large: false, // 大规模散点图
largeThreshold: 2000, // 大规模阀值,large为true且数据量>largeThreshold才启用大规模模式
itemStyle: {
normal: {
// color: 各异,
label: {
show: false
// position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
// 'inside'|'left'|'right'|'top'|'bottom'
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
}
},
emphasis: {
// color: '各异'
label: {
show: false
// position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
// 'inside'|'left'|'right'|'top'|'bottom'
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
}
}
}
},
// 雷达图默认参数
radar: {
itemStyle: {
normal: {
// color: 各异,
label: {
show: false
},
lineStyle: {
width: 2,
type: 'solid'
}
},
emphasis: {
// color: 各异,
label: {
show: false
}
}
},
//symbol: null, // 拐点图形类型
symbolSize: 2 // 可计算特性参数,空数据拖拽提示图形大小
//symbolRotate : null, // 图形旋转控制
},
// 饼图默认参数
pie: {
center: ['50%', '50%'], // 默认全局居中
radius: [0, '75%'],
clockWise: false, // 默认逆时针
startAngle: 90,
minAngle: 0, // 最小角度改为0
selectedOffset: 10, // 选中是扇区偏移量
itemStyle: {
normal: {
// color: 各异,
borderColor: '#fff',
borderWidth: 1,
label: {
show: true,
position: 'outer'
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
},
labelLine: {
show: true,
length: 20,
lineStyle: {
// color: 各异,
width: 1,
type: 'solid'
}
}
},
emphasis: {
// color: 各异,
borderColor: 'rgba(0,0,0,0)',
borderWidth: 1,
label: {
show: false
// position: 'outer'
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
},
labelLine: {
show: false,
length: 20,
lineStyle: {
// color: 各异,
width: 1,
type: 'solid'
}
}
}
}
},
map: {
mapType: 'china', // 各省的mapType暂时都用中文
mapLocation: {
x: 'center',
y: 'center'
// width // 自适应
// height // 自适应
},
showLegendSymbol: true, // 显示图例颜色标识(系列标识的小圆点),存在legend时生效
itemStyle: {
normal: {
// color: 各异,
borderColor: '#fff',
borderWidth: 1,
areaStyle: {
color: '#ccc' //rgba(135,206,250,0.8)
},
label: {
show: false,
textStyle: {
color: 'rgba(139,69,19,1)'
}
}
},
emphasis: {
// 也是选中样式
// color: 各异,
borderColor: 'rgba(0,0,0,0)',
borderWidth: 1,
areaStyle: {
color: 'rgba(255,215,0,0.8)'
},
label: {
show: false,
textStyle: {
color: 'rgba(139,69,19,1)'
}
}
}
}
},
force: {
// 数据map到圆的半径的最小值和最大值
minRadius: 10,
maxRadius: 20,
density: 1.0,
attractiveness: 1.0,
// 初始化的随机大小位置
initSize: 300,
// 向心力因子,越大向心力越大
centripetal: 1,
// 冷却因子
coolDown: 0.99,
// 分类里如果有样式会覆盖节点默认样式
itemStyle: {
normal: {
// color: 各异,
label: {
show: false
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
},
nodeStyle: {
brushType: 'both',
color: '#f08c2e',
strokeColor: '#5182ab'
},
linkStyle: {
strokeColor: '#5182ab'
}
},
emphasis: {
// color: 各异,
label: {
show: false
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
},
nodeStyle: {},
linkStyle: {}
}
}
},
chord: {
radius: ['65%', '75%'],
center: ['50%', '50%'],
padding: 2,
sort: 'none', // can be 'none', 'ascending', 'descending'
sortSub: 'none', // can be 'none', 'ascending', 'descending'
startAngle: 90,
clockWise: false,
showScale: false,
showScaleText: false,
itemStyle: {
normal: {
label: {
show: true
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
},
lineStyle: {
width: 0,
color: '#000'
},
chordStyle: {
lineStyle: {
width: 1,
color: '#666'
}
}
},
emphasis: {
lineStyle: {
width: 0,
color: '#000'
},
chordStyle: {
lineStyle: {
width: 2,
color: '#333'
}
}
}
}
},
island: {
r: 15,
calculateStep: 0.1 // 滚轮可计算步长 0.1 = 10%
},
markPoint: {
symbol: 'pin', // 标注类型
symbolSize: 10, // 标注大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2
//symbolRotate : null, // 标注旋转控制
itemStyle: {
normal: {
// color: 各异,
// borderColor: 各异, // 标注边线颜色,优先于color
borderWidth: 2, // 标注边线线宽,单位px,默认为1
label: {
show: true,
position: 'inside' // 可选为'left'|'right'|'top'|'bottom'
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
}
},
emphasis: {
// color: 各异
label: {
show: true
// position: 'inside' // 'left'|'right'|'top'|'bottom'
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
}
}
}
},
markLine: {
// 标线起始和结束的symbol介绍类型,如果都一样,可以直接传string
symbol: ['circle', 'arrow'],
// 标线起始和结束的symbol大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2
symbolSize: [2, 4],
// 标线起始和结束的symbol旋转控制
//symbolRotate : null,
itemStyle: {
normal: {
// color: 各异, // 标线主色,线色,symbol主色
// borderColor: 随color, // 标线symbol边框颜色,优先于color
borderWidth: 2, // 标线symbol边框线宽,单位px,默认为2
label: {
show: false,
// 可选为 'start'|'end'|'left'|'right'|'top'|'bottom'
position: 'inside',
textStyle: {
// 默认使用全局文本样式,详见TEXTSTYLE
color: '#333'
}
},
lineStyle: {
// color: 随borderColor, // 主色,线色,优先级高于borderColor和color
// width: 随borderWidth, // 优先于borderWidth
type: 'solid',
shadowColor: 'rgba(0,0,0,0)', //默认透明
shadowBlur: 5,
shadowOffsetX: 3,
shadowOffsetY: 3
}
},
emphasis: {
// color: 各异
label: {
show: false
// position: 'inside' // 'left'|'right'|'top'|'bottom'
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
},
lineStyle: {}
}
}
},
textStyle: {
decoration: 'none',
fontFamily: 'Arial, Verdana, sans-serif',
fontFamily2: '微软雅黑', // IE8- 字体模糊并且不支持不同字体混排,额外指定一份
fontSize: 12,
fontStyle: 'normal',
fontWeight: 'normal'
},
// 默认标志图形类型列表
symbolList: [
'circle',
'rectangle',
'triangle',
'diamond',
'emptyCircle',
'emptyRectangle',
'emptyTriangle',
'emptyDiamond'
],
loadingText: 'Loading...',
// 可计算特性配置,孤岛,提示颜色
calculable: false, // 默认关闭可计算特性
calculableColor: 'rgba(255,165,0,0.6)', // 拖拽提示边框颜色
calculableHolderColor: '#ccc', // 可计算占位提示颜色
nameConnector: ' & ',
valueConnector: ' : ',
animation: true,
animationThreshold: 2500, // 动画元素阀值,产生的图形原素超过2500不出动画
addDataAnimation: true, // 动态数据接口是否开启动画效果
animationDuration: 2000,
animationEasing: 'ExponentialOut' //BounceOut
}
ECharts 折线与柱状图结合双 y 轴
vue
<!-- 责任追究处理情形分析 -->
<template>
<div class="dynamic">
<div class="left">
<h3>违规经营投资资产损失趋势分析</h3>
<div>
<div class="lineChartBox" ref="lineChartBox"></div>
</div>
</div>
</div>
</template>
<script>
import * as echarts from 'echarts4'
export default {
//import引入的组件需要注入到对象中才能使用
components: {},
data() {
//这里存放数据
return {
yesterday: 561.22,
lastMonth: '13,467.15',
lineOptNum: {
grid: {
left: '2%',
top: '18%',
right: '8%',
bottom: '0%',
containLabel: true
},
tooltip: {
trigger: 'axis',
axisPointer: {
// 坐标轴指示器,坐标轴触发有效
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
legend: {
data: ['违规资产损失金额(万元)', '重大', '较大', '一般'],
textStyle: {
color: '#fff', // 图例文字颜色
fontSize: '10'
}
},
xAxis: {
type: 'category',
// axisLabel:{
// interval:0 x 轴信息全部展示
//}
data: [],
axisLabel: {
interval: 0,
textStyle: {
color: '#fff',
fontSize: 8,
width: 50
}
}
},
yAxis: [
//这里两个坐标轴,因为下面用的数据有柱状图和折线图,而他们的一个是数值,一个是百分比因此数的范围不一样,因此这里要加入id来定义坐标轴的标记下面 yAxisIndex 相对应其标记号就可以取这个坐标轴线了
{
type: 'value',
id: 0,
interval:400 // 设置 y 轴间隔值大小
axisLabel: {
show: true,
textStyle: {
color: '#fff'
}
},
splitLine: {
//网格线
lineStyle: {
type: 'dashed', //设置网格线类型 dotted:虚线 solid:实线
color: '#44AAFF'
},
show: true //隐藏或显示
}
},
{
nameLocation: 'end',
id: 1,
type: 'value',
axisLabel: {
show: true,
textStyle: {
color: '#fff'
}
},
splitLine: {
//网格线
lineStyle: {
type: 'dashed', //设置网格线类型 dotted:虚线 solid:实线
color: '#44AAFF'
},
show: true //隐藏或显示
}
}
],
series: [
{
name: '违规资产损失金额(万元)',
yAxisIndex: 0, //对应y轴的那一组坐标
data: [],
type: 'bar',
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(
0,
1,
0,
0,
[
{
offset: 0,
color: '#1DB4FF' // 0% 处的颜色
},
{
offset: 1,
color: '#3EDBFF' // 100% 处的颜色
}
],
false
)
}
},
barWidth: 24 //柱图宽度
},
{
name: '重大',
type: 'line',
yAxisIndex: 1,
itemStyle: {
/*设置折线颜色*/
normal: {
color: '#DB4537'
}
},
data: [9, 5, 3, 4, 4, 2, 1, 0]
},
{
name: '较大',
type: 'line',
yAxisIndex: 1,
itemStyle: {
/*设置折线颜色*/
normal: {
color: '#FBDB00'
}
},
data: [6, 7, 6, 8, 5, 3, 5, 2]
},
{
name: '一般',
type: 'line',
yAxisIndex: 1,
itemStyle: {
/*设置折线颜色*/
normal: {
color: '#00B091'
}
},
data: [12, 13, 9, 6, 7, 5, 4, 5]
}
]
}
}
},
//监听属性 类似于data概念
computed: {},
created() {},
mounted() {
let name = ['2014', '2015', '2016', '2017', '2018', '2019', '2020', '2021']
let data = [13, 12, 11, 8, 7, 6, 6, 6]
this.initCharts(data, name)
},
//监控data中的数据变化
watch: {},
//方法集合
methods: {
initCharts(data, time) {
let param = $.extend(true, {}, this.lineOptNum, {
xAxis: {
data: time
},
series: [
{
data: data
}
]
})
let $dom = this.$refs['lineChartBox']
this.chartTrend = this.$echarts.init($dom)
this.chartTrend.resize()
this.chartTrend.clear()
this.chartTrend.setOption(param)
}
}
}
</script>
<style scoped lang="less">
.dynamic {
width: 100%;
height: 100%;
& > div {
width: 100%;
height: 100%;
float: left;
background-image: url(../../../static/images/finance.png);
background-size: 100% 100%;
background-repeat: no-repeat;
h3 {
height: 32px;
font-size: 20px;
font-weight: 400;
color: #ffffff;
opacity: 0.8;
line-height: 32px;
text-indent: 34px;
text-shadow: 0px 0px 5px #2cc5ff;
}
div {
width: 100%;
height: calc(100% - 32px);
.lineChartBox {
margin-left: 3%;
width: 100%;
height: 100%;
}
}
}
}
</style>
地图图表(中国)
- 代码中所需文件可在本目录下 ditu(中国)文件夹找到
vue
<template>
<div>
<div
id="myChart1"
:style="{ width: width + 'px', height: height + 'px' }"
></div>
</div>
</template>
<script>
import { MapData } from '@/api'
// import { mapState } from 'vuex'
// import geoCoordMap from '@/assets/geoCoordMap.js'
// let geoCoordMap = {
// 新疆玛纳斯基地: [86.22, 44.3],
// 九江: [116.0, 29.7],
// 新乡: [116.402217, 35.311657],
// 若羌县: [88.17, 39.02],
// 上海: [121.4648, 31.2891],
// 东莞: [113.8953, 22.901],
// 东营: [118.7073, 37.5513],
// 中山: [113.4229, 22.478],
// 临汾: [111.4783, 36.1615],
// 临沂: [118.3118, 35.2936],
// 丹东: [124.541, 40.4242],
// 丽水: [119.5642, 28.1854],
// 乌鲁木齐: [87.9236, 43.5883],
// 佛山: [112.8955, 23.1097],
// 保定: [115.0488, 39.0948],
// 兰州: [103.5901, 36.3043],
// 包头: [110.3467, 41.4899],
// 北京: [116.4551, 40.2539],
// 北海: [109.314, 21.6211],
// 南京: [118.8062, 31.9208],
// 南宁: [108.479, 23.1152],
// 南昌: [116.0046, 28.6633],
// 南通: [121.1023, 32.1625],
// 厦门: [118.1689, 24.6478],
// 台州: [121.1353, 28.6688],
// 合肥: [117.29, 32.0581],
// 呼和浩特: [111.4124, 40.4901],
// 咸阳: [108.4131, 34.8706],
// 哈尔滨: [127.9688, 45.368],
// 唐山: [118.4766, 39.6826],
// 嘉兴: [120.9155, 30.6354],
// 大同: [113.7854, 39.8035],
// 大连: [122.2229, 39.4409],
// 天津: [117.4219, 39.4189],
// 太原: [112.3352, 37.9413],
// 威海: [121.9482, 37.1393],
// 宁波: [121.5967, 29.6466],
// 宝鸡: [107.1826, 34.3433],
// 宿迁: [118.5535, 33.7775],
// 常州: [119.4543, 31.5582],
// 广州: [113.5107, 23.2196],
// 廊坊: [116.521, 39.0509],
// 延安: [109.1052, 36.4252],
// 张家口: [115.1477, 40.8527],
// 徐州: [117.5208, 34.3268],
// 德州: [116.6858, 37.2107],
// 惠州: [114.6204, 23.1647],
// 成都: [103.9526, 30.7617],
// 扬州: [119.4653, 32.8162],
// 承德: [117.5757, 41.4075],
// 拉萨: [91.1865, 30.1465],
// 无锡: [120.3442, 31.5527],
// 日照: [119.2786, 35.5023],
// 昆明: [102.9199, 25.4663],
// 杭州: [119.5313, 29.8773],
// 枣庄: [117.323, 34.8926],
// 柳州: [109.3799, 24.9774],
// 株洲: [113.5327, 27.0319],
// 武汉: [114.3896, 30.6628],
// 汕头: [117.1692, 23.3405],
// 江门: [112.6318, 22.1484],
// 沈阳: [123.1238, 42.1216],
// 沧州: [116.8286, 38.2104],
// 河源: [114.917, 23.9722],
// 泉州: [118.3228, 25.1147],
// 泰安: [117.0264, 36.0516],
// 泰州: [120.0586, 32.5525],
// 济南: [117.1582, 36.8701],
// 济宁: [116.8286, 35.3375],
// 海口: [110.3893, 19.8516],
// 淄博: [118.0371, 36.6064],
// 淮安: [118.927, 33.4039],
// 深圳: [114.5435, 22.5439],
// 清远: [112.9175, 24.3292],
// 温州: [120.498, 27.8119],
// 渭南: [109.7864, 35.0299],
// 湖州: [119.8608, 30.7782],
// 湘潭: [112.5439, 27.7075],
// 滨州: [117.8174, 37.4963],
// 潍坊: [119.0918, 36.524],
// 烟台: [120.7397, 37.5128],
// 玉溪: [101.9312, 23.8898],
// 珠海: [113.7305, 22.1155],
// 盐城: [120.2234, 33.5577],
// 盘锦: [121.9482, 41.0449],
// 石家庄: [114.4995, 38.1006],
// 福州: [119.4543, 25.9222],
// 秦皇岛: [119.2126, 40.0232],
// 绍兴: [120.564, 29.7565],
// 聊城: [115.9167, 36.4032],
// 肇庆: [112.1265, 23.5822],
// 舟山: [122.2559, 30.2234],
// 苏州: [120.6519, 31.3989],
// 莱芜: [117.6526, 36.2714],
// 菏泽: [115.6201, 35.2057],
// 营口: [122.4316, 40.4297],
// 葫芦岛: [120.1575, 40.578],
// 衡水: [115.8838, 37.7161],
// 衢州: [118.6853, 28.8666],
// 西宁: [101.4038, 36.8207],
// 西安: [109.1162, 34.2004],
// 贵阳: [106.6992, 26.7682],
// 连云港: [119.1248, 34.552],
// 邢台: [114.8071, 37.2821],
// 邯郸: [114.4775, 36.535],
// 郑州: [113.4668, 34.6234],
// 鄂尔多斯: [108.9734, 39.2487],
// 重庆: [107.7539, 30.1904],
// 金华: [120.0037, 29.1028],
// 铜川: [109.0393, 35.1947],
// 银川: [106.3586, 38.1775],
// 镇江: [119.4763, 31.9702],
// 长春: [125.8154, 44.2584],
// 长沙: [113.0823, 28.2568],
// 长治: [112.8625, 36.4746],
// 阳泉: [113.4778, 38.0951],
// 青岛: [120.4651, 36.3373],
// 韶关: [113.7964, 24.7028],
// 浙江: [120.5313, 29.0773]
// }
let china = require('@/assets/china.json')
export default {
name: 'hello',
data() {
return {
// 数据流出
GZData: [
[
{
name: '浙江'
},
{
name: '浙江',
value: 200
}
],
[
{
name: '浙江'
},
{
name: '呼和浩特',
value: 90
}
],
[
{
name: '浙江'
},
{
name: '昆明',
value: 40
}
],
[
{
name: '浙江'
},
{
name: '成都',
value: 10
}
],
[
{
name: '浙江'
},
{
name: '兰州',
value: 95
}
],
[
{
name: '浙江'
},
{
name: '银川',
value: 90
}
],
[
{
name: '浙江'
},
{
name: '西宁',
value: 80
}
]
],
// 数据流入
ZJData: [
[
{
name: '郑州',
value: 90
},
{
name: '浙江'
}
],
[
{
name: '连云港',
value: 100
},
{
name: '浙江'
}
],
[
{
name: '贵阳',
value: 10
},
{
name: '浙江'
}
],
[
{
name: '营口',
value: 90
},
{
name: '浙江'
}
],
[
{
name: '石家庄',
value: 80
},
{
name: '浙江'
}
]
]
}
},
props: {
width: Number,
height: Number,
mapStyle: Object
},
computed: {
// ...mapState(['MapData']) // 读取 vuex 中保存的地图信息
},
created() {
this.MapData() // 获取 大额资金大额资金省内地图
this.$echarts5.registerMap('china', china)
},
mounted() {
// this.drawMap()
},
methods: {
// 获取 大额资金大额资金省内地图
async MapData() {
const { data } = await MapData({
payFlag: '1'
})
if (data.result === 401 && data.result !== 0) {
if (data.result === 401) {
this.$router.push('/')
}
return this.$message.error(data.msg)
}
let geoCoordMap = {} // 准备地区经纬度
let outData = [] // 准备数据流出地区
let inData = [] // 准备数据流入地区
data.data.rows.forEach(item => {
geoCoordMap[item.from_province] = item.from_info.split(',')
geoCoordMap[item.to_province] = item.to_info.split(',')
// 1 为支出,0 为收入
if (item.pay_flag == 1) {
outData.push([
{ name: item.from_province },
{ name: item.to_province, value: 120 }
])
} else {
inData.push([
{ name: item.to_province, value: 120 },
{ name: item.from_province }
])
}
})
this.GZData = outData
this.ZJData = inData
this.drawMap(geoCoordMap)
// console.log(geoCoordMap)
// this.$store.commit('setMapData', data.data.rows) // 将获取到的数据存入 vuex 中
},
drawMap(geoCoordMap) {
// 基于准备好的dom,初始化echarts实例
let myChart1 = this.$echarts5.init(document.getElementById('myChart1'))
var convertData = function (data) {
var res = []
for (var i = 0; i < data.length; i++) {
var dataItem = data[i]
var fromCoord = geoCoordMap[dataItem[0].name]
var toCoord = geoCoordMap[dataItem[1].name]
if (fromCoord && toCoord) {
res.push([
{
coord: fromCoord
},
{
coord: toCoord
}
])
}
}
return res
}
var color = ['#00E686', '#fb4e4d']
var series = []
;[
['数据流出', this.GZData],
['数据流入', this.ZJData]
].forEach(function (item, i) {
series.push(
{
name: item[0],
type: 'lines',
zlevel: 1,
effect: {
show: true,
period: 5,
trailLength: 0.5,
color: '#fff',
symbolSize: 1,
borderColor: color[i],
borderWidth: 4,
shadowBlur: 1,
shadowColor: color[i],
shadowOffsetX: 0,
shadowOffsetY: 0,
delay: function () {
return Math.random() * 5000
}
},
lineStyle: {
normal: {
color: color[i],
width: 1,
curveness: -0.2
}
},
data: convertData(item[1])
},
{
name: item[0],
type: 'effectScatter',
coordinateSystem: 'geo',
zlevel: 2,
rippleEffect: {
brushType: 'stroke'
},
label: {
normal: {
show: true,
position: 'right',
formatter: '{b}',
color: '#fff',
fontSize: 10
}
},
symbolSize: function (val) {
return val[2] / 8
},
itemStyle: {
normal: {
color: color[i]
}
},
// 当鼠标移入地区时显示弹框信息
tooltip: {
formatter: res => {
const _html = `<div>${res.seriesName}</div>
${res.marker}
${res.name}
<b style="padding-left:10px">${res.data.value[2]}</b>`
return _html
}
},
data: item[1].map(function (dataItem) {
let name, value
if (dataItem[0].value) {
name = dataItem[0].name
value = geoCoordMap[dataItem[0].name].concat([
dataItem[0].value
])
} else {
name = dataItem[1].name
value = geoCoordMap[dataItem[1].name].concat([
dataItem[1].value
])
}
return {
name: name,
value: value
}
})
}
)
})
// 绘制图表
let option = {
// backgroundColor: "#031439",
backgroundColor: 'rgba(0,0,0,0)',
title: {
left: 'left',
textStyle: {
color: '#fff'
}
},
tooltip: {
trigger: 'item'
},
geo: {
map: 'china',
zoom: 1.2,
label: {
emphasis: {
show: false
}
},
roam: false,
itemStyle: {
normal: {
areaColor: 'rgba(35, 95, 157, 1)',
borderColor: '#18cdfe',
borderWidth: 1,
shadowBlur: 0,
shadowColor: '#18cdfe',
shadowOffsetX: 0.5,
shadowOffsetY: 1
},
emphasis: {
label: {
show: false
},
areaColor: 'rgba(0, 255, 255, .1)'
}
}
},
center: [109, 29],
series: series
}
myChart1.setOption(option)
}
}
}
</script>
<style>
#myChart1 {
margin: 0 auto;
left: -30px;
top: -16px;
}
</style>
地图图表(浙江)
- 代码中所需文件可在本目录下 ditu(浙江)文件夹找到
vue
<template>
<div>
<div
id="myChartProvince"
:style="{ width: width + 'px', height: height + 'px' }"
></div>
</div>
</template>
<script>
let zhejiang = require('@/assets/zhejiang.json')
let geoCoordMap = {
杭州: [120.206886, 30.271798],
淳安县: [119.039233, 29.63997],
慈溪: [121.272205, 30.173936],
桐庐县: [119.676239, 29.793543],
衢州: [118.866758, 28.971757],
丽水: [119.930352, 28.477114],
舟山: [122.217366, 30.004943],
台州市: [121.429732, 28.657811],
绍兴市: [120.586905, 30.053971],
嘉兴市: [120.754781, 30.749698],
温州市: [120.716836, 27.992368],
宁波市: [121.559662, 29.888779]
}
export default {
name: 'hello',
data() {
return {
GZData: [
[
{
name: '杭州'
},
{
name: '杭州',
value: 200
}
],
[
{
name: '杭州'
},
{
name: '淳安县',
value: 90
}
],
[
{
name: '杭州'
},
{
name: '慈溪',
value: 40
}
],
[
{
name: '杭州'
},
{
name: '桐庐县',
value: 10
}
],
[
{
name: '杭州'
},
{
name: '衢州',
value: 95
}
],
[
{
name: '杭州'
},
{
name: '丽水',
value: 90
}
],
[
{
name: '杭州'
},
{
name: '舟山',
value: 80
}
]
],
ZJData: [
[
{
name: '台州市',
value: 90
},
{
name: '杭州'
}
],
[
{
name: '绍兴市',
value: 100
},
{
name: '杭州'
}
],
[
{
name: '嘉兴市',
value: 10
},
{
name: '杭州'
}
],
[
{
name: '温州市',
value: 90
},
{
name: '杭州'
}
],
[
{
name: '宁波市',
value: 80
},
{
name: '杭州'
}
]
]
}
},
props: {
width: Number,
height: Number
},
created() {
this.$echarts5.registerMap('zhejiang', zhejiang)
},
mounted() {
this.drawMap()
},
methods: {
drawMap() {
// 基于准备好的dom,初始化echarts实例
let myChart = this.$echarts5.init(
document.getElementById('myChartProvince')
)
var convertData = function (data) {
var res = []
for (var i = 0; i < data.length; i++) {
var dataItem = data[i]
var fromCoord = geoCoordMap[dataItem[0].name]
var toCoord = geoCoordMap[dataItem[1].name]
if (fromCoord && toCoord) {
res.push([
{
coord: fromCoord
},
{
coord: toCoord
}
])
}
}
return res
}
var color = ['#00E686', '#fb4e4d']
var series = []
;[
['数据流出', this.GZData],
['数据流入', this.ZJData]
].forEach(function (item, i) {
series.push(
{
name: item[0],
type: 'lines',
zlevel: 1,
effect: {
show: true,
period: 5,
trailLength: 0.5,
color: '#fff',
symbolSize: 1,
borderColor: color[i],
borderWidth: 4,
shadowBlur: 1,
shadowColor: color[i],
shadowOffsetX: 0,
shadowOffsetY: 0,
delay: function () {
return Math.random() * 5000
}
},
lineStyle: {
normal: {
color: color[i],
width: 1,
curveness: -0.2
}
},
data: convertData(item[1])
},
{
name: item[0],
type: 'effectScatter',
coordinateSystem: 'geo',
zlevel: 2,
rippleEffect: {
brushType: 'stroke'
},
label: {
normal: {
show: true,
position: 'right',
formatter: '{b}',
color: '#fff',
fontSize: 10
}
},
symbolSize: function (val) {
return val[2] / 8
},
itemStyle: {
normal: {
color: color[i]
}
},
data: item[1].map(function (dataItem) {
let name, value
if (dataItem[0].value) {
name = dataItem[0].name
value = geoCoordMap[dataItem[0].name].concat([
dataItem[0].value
])
} else {
name = dataItem[1].name
value = geoCoordMap[dataItem[1].name].concat([
dataItem[1].value
])
}
return {
name: name,
value: value
}
})
}
)
})
// 绘制图表
let option = {
// backgroundColor: "#031439",
backgroundColor: 'rgba(0,0,0,0)',
title: {
left: 'left',
textStyle: {
color: '#fff'
}
},
tooltip: {
trigger: 'item'
},
geo: {
map: 'zhejiang',
zoom: 1.2,
label: {
emphasis: {
show: false
}
},
roam: false,
aspectScale: 0.88,
itemStyle: {
normal: {
areaColor: 'rgba(35, 95, 157, 1)',
borderColor: '#18cdfe',
borderWidth: 1,
shadowBlur: 0,
shadowColor: '#18cdfe',
shadowOffsetX: 0.5,
shadowOffsetY: 1
},
emphasis: {
label: {
show: false
},
areaColor: 'rgba(0, 255, 255, .1)'
}
}
},
series: series
}
myChart.setOption(option)
}
}
}
</script>
<style>
#myChartProvince {
left: 75px;
}
</style>
地图自定义文字
vue
<template>
<div>
<div
id="myChart"
:style="{ width: width + 'px', height: height + 'px' }"
></div>
</div>
</template>
<script>
let zhejiang = require('@/assets/zhejiang.json')
export default {
data() {
return {
// 地图各省数据
dataArr: [
{ name: '杭州市', value: 12 },
{ name: '湖州市', value: 3 },
{ name: '嘉兴市', value: 0 },
{ name: '绍兴市', value: 2 },
{ name: '宁波市', value: 2 },
{ name: '金华市', value: 0 },
{ name: '台州市', value: 0 },
{ name: '丽水市', value: 2 },
{ name: '温州市', value: 2 },
{ name: '舟山市', value: 2 },
{ name: '衢州市', value: 6 }
]
}
},
props: {
width: {
type: Number,
default: 1200
},
height: {
type: Number,
default: 600
},
mapData: {
type: Array,
default() {
return [
{
name: '浙江省国有资本运营有限公司',
adress: '杭州市求是路'
}
]
}
}
},
created() {
this.$echarts5.registerMap('china', zhejiang)
},
mounted() {
this.$nextTick(() => {
this.drawMap()
})
},
methods: {
drawMap() {
// console.log(this.dataArr)
// 基于准备好的dom,初始化echarts实例
let myChart = this.$echarts5.init(document.getElementById('myChart'))
// 绘制图表
let option = {
// backgroundColor: 'rgba(1, 20, 57, 1)', // 编辑地图背景
grid: {
// top: '30%'
},
// 控制地图图例样式
visualMap: {
show: false,
type: 'piecewise',
right: '100',
top: 'bottom',
// orient: 'vertical',
orient: 'horizontal',
color: '#fff',
itemGap: 10,
align: 'left',
pieces: [
{ gt: 10, lte: 100, label: '10以上' },
{ gt: 1, lte: 10, label: '1到10以内' },
{ gt: -1, lte: 1, label: '1以内' }
],
inRange: {
color: ['#64bfff', '#00b5ff', '#266bff'],
symbol: 'rect'
},
textStyle: {
color: '#fff',
fontSize: '15'
}
},
// 当鼠标移动到对应地区时会显示提示框
// tooltip: {
// padding: 0,
// enterable: true,
// transitionDuration: 1,
// textStyle: {
// color: '#000',
// decoration: 'none'
// },
// position: 'top',
// className: 'tooltips',
// formatter: function(params) {
// var tipHtml = ''
// if (!params.data) {
// return tipHtml
// }
// tipHtml = `<div class="tooltip">
// <span class="name">${params.data.name}</span>
// <span class="value">${params.data.value}家</span>
// </div>`
// return tipHtml
// }
// },
series: [
{
name: '',
type: 'map',
mapType: 'china',
// top: '25%',
center: [120, 29.1], // 控制地图对齐位置
zoom: 3.5,
label: {
normal: {
show: true,
color: '#ffffff',
fontSize: 18,
/////////////////////////////// 控制地区自定义文字
formatter(params) {
return `${params.data.name}\n${params.data.value}家`
}
}
///////////////////////////////////////////////// 控制地区自定义文字
// emphasis: {
// show: false,
// color: '#ffffff',
// fontSize: 25,
// // 控制地区自定义文字
// formatter(params) {
// return `${params.data.name}\n${params.data.value}家`
// }
// }
},
itemStyle: {
normal: {
label: {
show: false
},
borderWidth: 2,
borderColor: '#5c97ff'
},
emphasis: {
label: {
show: true
},
areaColor: '#18cdfe',
color: '#fff'
}
},
data: this.dataArr
}
]
}
myChart.setOption(option)
// function showTooltip() {
// myChart.dispatchAction({
// type: 'showTip',
// seriesIndex: 0,
// dataIndex: 0
// })
// }
// showTooltip()
}
}
}
</script>
<style lang="less" scoped>
// 控制提示框样式
// /deep/ .tooltipbg {
// background-color: rgba(250, 87, 87, 0) !important;
// border: none !important;
// padding: 0 !important;
// box-shadow: none !important;
// }
// /deep/ .tooltipLine {
// position: absolute;
// top: 0;
// left: 0;
// width: 109px;
// height: 52px;
// background: url(../../assets/img/tooltipLine.png) no-repeat;
// }
// /deep/ .tooltipBox {
// border: 1px solid #3793de;
// font-size: 10px;
// color: #ffffff;
// padding: 10px;
// margin: 25px 0 0 89px;
// background: rgba(7, 34, 76, 0.5);
// box-shadow: -2px -2px 20px #3793de inset;
// border-radius: 5px;
// .tooltipName {
// padding: 0 10px 0 20px;
// font-size: 16px;
// line-height: 30px;
// border-bottom: 1px solid #3793de;
// margin-bottom: 10px;
// }
// .tooltipItem {
// border-left: 3px solid #3793de;
// line-height: 30px;
// padding-left: 5%;
// span {
// display: inline-block;
// text-align: left;
// }
// span:nth-child(1) {
// width: 25%;
// }
// span:nth-child(2) {
// width: 40%;
// }
// span:nth-child(3) {
// width: 30%;
// color: #00a58b;
// }
// }
// .companyName {
// display: flex;
// justify-content: space-between;
// font-size: 14px;
// line-height: 25px;
// margin: 10px 0 10px 0;
// border-bottom: 1px solid #3793de;
// span:nth-child(1) {
// margin-right: 20px;
// }
// span:nth-child(2) {
// width: calc(50% - 20px);
// margin-right: 20px;
// text-align: left;
// }
// }
// .companyList {
// height: 115px;
// overflow: auto;
// }
// ::-webkit-scrollbar {
// width: 0;
// }
// .companyItme {
// display: flex;
// justify-content: space-between;
// line-height: 28px;
// span:nth-child(1) {
// margin-right: 20px;
// }
// span:nth-child(2) {
// width: calc(50% - 20px);
// margin-right: 20px;
// text-align: left;
// }
// }
// }
// /deep/ .tooltips {
// height: 100px;
// width: 200px;
// background: url(../../assets/img/tooltip2.png) no-repeat center transparent !important;
// border: none !important;
// box-shadow: none !important;
// div {
// display: none;
// }
// .tooltip {
// display: block;
// color: #ffffff;
// padding: 28px 0 28px 75px;
// span {
// display: block;
// }
// .name {
// font-size: 24px;
// padding-bottom: 20px;
// }
// .value {
// font-size: 18px;
// }
// }
// }
</style>
实现图例两端排列
vue
<!-- 省国资财务动态统计 -->
<template>
<div>
<div class="organization">
<div class="checkbtn">
<div
:style="{
backgroundImage:
type == 1
? clickStyle.style
: 'url(../../../static/images/select_left.png)'
}"
@click="handelClick(1)"
>
组织概况
</div>
<div
:style="{
backgroundImage:
type == 2
? clickStyle.style
: 'url(../../../static/images/select_content.png)'
}"
@click="handelClick(2)"
>
星级组织
</div>
<div
:style="{
backgroundImage:
type == 3
? clickStyle.style
: 'url(../../../static/images/select_right.png)'
}"
@click="handelClick(3)"
>
预警列表
</div>
</div>
<div v-if="type == 1">
<div class="ChartsBox" ref="ChartsBox"></div>
</div>
<div v-if="type == 2">
<div class="ChartsRing" ref="ChartsRing1"></div>
</div>
<div v-if="type == 3">
<div class="ChartsBox" ref="ChartsBox2"></div>
</div>
</div>
</div>
</template>
<script>
//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
//例如:import 《组件名称》 from '《组件路径》';
import { mapState } from 'vuex'
import * as echarts from 'echarts4'
export default {
//import引入的组件需要注入到对象中才能使用
components: {},
data() {
//这里存放数据
return {
Clcik_Style: {
1: {
style: 'url(../../../static/images/checked.png)'
},
2: {
style: 'url(../../../static/images/checked_center.png)'
},
3: {
style: 'url(../../../static/images/checked_right.png)'
}
},
type: 1,
option: {
textStyle: {
color: 'white'
},
grid: {
left: '5%',
right: '10%',
bottom: '-20%',
top: '5%',
containLabel: true
},
xAxis: [
{
type: 'value',
show: false
}
],
yAxis: {
type: 'category',
data: []
},
series: [
{
type: 'bar',
data: [],
barWidth: 15,
itemStyle: {
//通常情况下:
normal: {
//每个柱子的颜色即为colorList数组里的每一项,如果柱子数目多于colorList的长度,则柱子颜色循环使用该数组
color: function (params) {
var colorList = [
['#00B091', '#00D8C4'],
['#D85700', '#EE9000'],
['#DB4537', '#EF7B68']
]
var index = params.dataIndex
if (params.dataIndex >= colorList.length) {
index = params.dataIndex - colorList.length
}
return new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{
offset: 0,
color: colorList[index][0]
},
{
offset: 1,
color: colorList[index][1]
}
])
},
label: {
show: true, //开启显示
position: 'right', //在上方显示
formatter: '{c}人',
textStyle: {
//数值样式
color: '#FFFFFF',
fontSize: 12
}
}
}
}
}
]
},
option2: {
legend: {
icon: 'circle',
orient: 'vertical',
y: 'center', //延Y轴居中
x: '50%', //居右显示
align: 'left',
itemHeight: 8
},
series: [
{
name: '访问来源',
type: 'pie',
radius: ['40%', '70%'],
center: ['50%', '50%'],
avoidLabelOverlap: false,
hoverAnimation: false,
itemStyle: {
borderRadius: 10,
borderColor: '#010a1e',
borderWidth: 3
},
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: false,
fontSize: '40',
fontWeight: 'bold'
}
},
labelLine: {
show: false
},
data: [],
color: [
'#00ACD8',
'#FEC825',
'#FC4D4C',
'#FEA413',
'#39C3AB',
'#72DA80'
]
}
]
},
option3: {
textStyle: {
color: 'white'
},
grid: {
left: '-5%',
right: '5',
bottom: '-10%',
top: '30%',
containLabel: true
},
xAxis: {
type: 'category',
show: false
},
yAxis: {
type: 'value',
show: false,
data: []
},
series: [
{
type: 'bar',
data: [],
barWidth: 30,
itemStyle: {
normal: {
label: {
show: true,
position: 'top',
formatter: '{b}\n{c}个'
},
color: function (params) {
var colorlist = [
'#00ACD8',
'#FEC825',
'#FC4D4C',
'#FEA413',
'#39C3AB'
]
return colorlist[params.dataIndex]
}
}
}
}
],
color: ['#D85700', '#1DB4FF', '#FEA212', '#39C3AB']
}
}
},
//监听属性 类似于data概念
computed: {
...mapState(['PartyInfo']), // 获取最新的页面右上角公司数据
clickStyle() {
return this.Clcik_Style[this.type]
}
},
created() {
console.log(echarts)
},
mounted() {
// let name = ['党务工作者', '班子成员', '政治宣传员']
// let data = [11, 14, 18]
// this.initCharts(name, data)
},
//监控data中的数据变化
watch: {
PartyInfo(val) {
// 组织概况
let name = ['党务工作者', '班子成员', '政治宣传员']
let data = [val[0].worker, val[0].teamMember, val[0].propagandist]
this.initCharts(name, data)
// 组织概况
// 星级组织
let dataRing1 = [
{ value: val[0].zeroStar, name: '无星' },
{ value: val[0].oneStar, name: '一星' },
{ value: val[0].twoStar, name: '二星' },
{ value: val[0].threeStar, name: '三星' },
{ value: val[0].fourStar, name: '四星' },
{ value: val[0].fiveStar, name: '五星' }
]
this.initChartsRing(dataRing1)
// 星级组织
// 预警列表
let name2 = [
'逾期未换届的标黄预警',
'联合支部预警的标黄预警',
'组织不健全预警',
'支部超员预警'
]
let data2 = [
this.val[0].overdueBranch,
this.val[0].unionYellowBranch,
this.val[0].incompleteBranch,
this.val[0].overcrowdBranch
]
this.initCharts2(name2, data2)
// 预警列表
}
},
//方法集合
methods: {
handelClick(type) {
this.type = type
setTimeout(() => {
if (type == 1) {
let name = ['党务工作者', '班子成员', '政治宣传员']
let data = [
this.PartyInfo[0].worker,
this.PartyInfo[0].teamMember,
this.PartyInfo[0].propagandist
]
this.initCharts(name, data)
} else if (type == 2) {
let dataRing1 = [
{ value: this.PartyInfo[0].zeroStar, name: '无星' },
{ value: this.PartyInfo[0].oneStar, name: '一星' },
{ value: this.PartyInfo[0].twoStar, name: '二星' },
{ value: this.PartyInfo[0].threeStar, name: '三星' },
{ value: this.PartyInfo[0].fourStar, name: '四星' },
{ value: this.PartyInfo[0].fiveStar, name: '五星' }
]
this.initChartsRing(dataRing1)
} else if (type == 3) {
let name = [
'逾期未换届的标黄预警',
'联合支部预警的标黄预警',
'组织不健全预警',
'支部超员预警'
]
let data = [
this.PartyInfo[0].overdueBranch,
this.PartyInfo[0].unionYellowBranch,
this.PartyInfo[0].incompleteBranch,
this.PartyInfo[0].overcrowdBranch
]
this.initCharts2(name, data)
}
})
},
initCharts(name, data) {
let param = $.extend(true, {}, this.option, {
yAxis: {
data: name
},
series: [
{
data: data
}
]
})
let $dom = this.$refs['ChartsBox']
this.chartTrend = this.$echarts.init($dom)
this.chartTrend.resize()
this.chartTrend.clear()
this.option && this.chartTrend.setOption(param)
},
////////////////////////////////////////////////////////////////
// 将需要分开的数据定义样式和数据 data
initChartsRing(data) {
let param = $.extend(true, {}, this.option2, {
// 定义图例
legend: [
{
icon: 'circle',
orient: 'vertical',
y: 'center', //延Y轴居中
// x: '50%', //居右显示
left: '1%',
itemHeight: 8,
data: data.slice(0, 3),
// textStyle: {
// color: '#ffffff',
// fontSize: 8
// },
textStyle: {
rich: {
a: {
verticalAlign: 'right',
fontSize: 15,
align: 'left',
color: '#ffffff',
// padding:[0,28,0,0],
width: 30
},
b: {
fontSize: 15,
align: 'left',
color: '#ffffff',
// padding:[0,28,0,0],
width: 50
},
c: {
fontSize: 15,
align: 'left',
color: '#ffffff',
width: 30
}
}
},
formatter: name => {
let total = 0
let target
for (let i = 0; i < data.length; i++) {
total += parseFloat(data[i].value)
if (data[i].name === name) {
target = parseFloat(data[i].value)
}
}
let arr = [
'{a|' +
name +
'}{b|' +
target +
'个}{c|' +
((target / total) * 100).toFixed(2) +
'%}'
]
return arr.join('\n')
}
},
{
icon: 'circle',
orient: 'vertical',
y: 'center', //延Y轴居中
// x: '50%', //居右显示
right: '5%',
itemHeight: 8,
data: data.slice(3, 6),
// textStyle: {
// color: '#ffffff',
// fontSize: 8
// },
textStyle: {
rich: {
a: {
verticalAlign: 'right',
fontSize: 15,
align: 'left',
color: '#ffffff',
// padding:[0,28,0,0],
width: 30
},
b: {
fontSize: 15,
align: 'left',
color: '#ffffff',
// padding:[0,28,0,0],
width: 50
},
c: {
fontSize: 15,
align: 'left',
color: '#ffffff',
width: 30
}
}
},
formatter: name => {
let total = 0
let target
for (let i = 0; i < data.length; i++) {
total += parseFloat(data[i].value)
if (data[i].name === name) {
target = parseFloat(data[i].value)
}
}
let arr = [
'{a|' +
name +
'}{b|' +
target +
'个}{c|' +
((target / total) * 100).toFixed(2) +
'%}'
]
return arr.join('\n')
}
}
],
////////////////////////////////////////////////////////////////
series: [
{
data: data
}
]
})
let $dom = this.$refs['ChartsRing1']
this.chartTrend = this.$echarts.init($dom)
this.chartTrend.resize()
this.chartTrend.clear()
this.option2 && this.chartTrend.setOption(param, true)
},
initCharts2(name, data) {
let param = $.extend(true, {}, this.option3, {
xAxis: {
data: name
},
series: [
{
data: data
}
]
})
let $dom = this.$refs['ChartsBox2']
this.chartTrend = this.$echarts.init($dom)
this.chartTrend.resize()
this.chartTrend.clear()
this.option3 && this.chartTrend.setOption(param)
}
}
}
</script>
<style scoped lang="less">
.organization {
width: 100%;
height: 150px;
display: flex;
flex-direction: column;
justify-content: space-between;
box-sizing: border-box;
.checkbtn {
height: 21px;
display: flex;
margin-top: 20px;
justify-content: space-evenly;
div {
cursor: pointer;
width: 30%;
text-align: center;
background-image: url(../../../static/images/select_content.png);
background-size: 136px 21px;
background-repeat: no-repeat;
pointer-events: auto;
}
}
& > div:last-child {
width: 100%;
height: 100%;
// .organization_right{
// width:50%;
// height: 100%;
// float: left;
// }
}
.ChartsBox {
height: 108px;
width: 100%;
margin: 0 auto;
overflow: hidden;
}
.ChartsRing {
height: 108px;
width: 100%;
float: left;
overflow: hidden;
}
}
</style>
地图飞线效果修改数值
vue
<template>
<div>
<div
id="myChart1"
:style="{ width: width + 'px', height: height + 'px' }"
></div>
</div>
</template>
<script>
import { MapData, provinceMap2 } from '@/api'
import { mapState } from 'vuex'
// import geoCoordMap from '@/assets/geoCoordMap.js'
// let geoCoordMap = {
// 新疆玛纳斯基地: [86.22, 44.3],
// 九江: [116.0, 29.7],
// 新乡: [116.402217, 35.311657],
// 若羌县: [88.17, 39.02],
// 上海: [121.4648, 31.2891],
// 东莞: [113.8953, 22.901],
// 东营: [118.7073, 37.5513],
// 中山: [113.4229, 22.478],
// 临汾: [111.4783, 36.1615],
// 临沂: [118.3118, 35.2936],
// 丹东: [124.541, 40.4242],
// 丽水: [119.5642, 28.1854],
// 乌鲁木齐: [87.9236, 43.5883],
// 佛山: [112.8955, 23.1097],
// 保定: [115.0488, 39.0948],
// 兰州: [103.5901, 36.3043],
// 包头: [110.3467, 41.4899],
// 北京: [116.4551, 40.2539],
// 北海: [109.314, 21.6211],
// 南京: [118.8062, 31.9208],
// 南宁: [108.479, 23.1152],
// 南昌: [116.0046, 28.6633],
// 南通: [121.1023, 32.1625],
// 厦门: [118.1689, 24.6478],
// 台州: [121.1353, 28.6688],
// 合肥: [117.29, 32.0581],
// 呼和浩特: [111.4124, 40.4901],
// 咸阳: [108.4131, 34.8706],
// 哈尔滨: [127.9688, 45.368],
// 唐山: [118.4766, 39.6826],
// 嘉兴: [120.9155, 30.6354],
// 大同: [113.7854, 39.8035],
// 大连: [122.2229, 39.4409],
// 天津: [117.4219, 39.4189],
// 太原: [112.3352, 37.9413],
// 威海: [121.9482, 37.1393],
// 宁波: [121.5967, 29.6466],
// 宝鸡: [107.1826, 34.3433],
// 宿迁: [118.5535, 33.7775],
// 常州: [119.4543, 31.5582],
// 广州: [113.5107, 23.2196],
// 廊坊: [116.521, 39.0509],
// 延安: [109.1052, 36.4252],
// 张家口: [115.1477, 40.8527],
// 徐州: [117.5208, 34.3268],
// 德州: [116.6858, 37.2107],
// 惠州: [114.6204, 23.1647],
// 成都: [103.9526, 30.7617],
// 扬州: [119.4653, 32.8162],
// 承德: [117.5757, 41.4075],
// 拉萨: [91.1865, 30.1465],
// 无锡: [120.3442, 31.5527],
// 日照: [119.2786, 35.5023],
// 昆明: [102.9199, 25.4663],
// 杭州: [119.5313, 29.8773],
// 枣庄: [117.323, 34.8926],
// 柳州: [109.3799, 24.9774],
// 株洲: [113.5327, 27.0319],
// 武汉: [114.3896, 30.6628],
// 汕头: [117.1692, 23.3405],
// 江门: [112.6318, 22.1484],
// 沈阳: [123.1238, 42.1216],
// 沧州: [116.8286, 38.2104],
// 河源: [114.917, 23.9722],
// 泉州: [118.3228, 25.1147],
// 泰安: [117.0264, 36.0516],
// 泰州: [120.0586, 32.5525],
// 济南: [117.1582, 36.8701],
// 济宁: [116.8286, 35.3375],
// 海口: [110.3893, 19.8516],
// 淄博: [118.0371, 36.6064],
// 淮安: [118.927, 33.4039],
// 深圳: [114.5435, 22.5439],
// 清远: [112.9175, 24.3292],
// 温州: [120.498, 27.8119],
// 渭南: [109.7864, 35.0299],
// 湖州: [119.8608, 30.7782],
// 湘潭: [112.5439, 27.7075],
// 滨州: [117.8174, 37.4963],
// 潍坊: [119.0918, 36.524],
// 烟台: [120.7397, 37.5128],
// 玉溪: [101.9312, 23.8898],
// 珠海: [113.7305, 22.1155],
// 盐城: [120.2234, 33.5577],
// 盘锦: [121.9482, 41.0449],
// 石家庄: [114.4995, 38.1006],
// 福州: [119.4543, 25.9222],
// 秦皇岛: [119.2126, 40.0232],
// 绍兴: [120.564, 29.7565],
// 聊城: [115.9167, 36.4032],
// 肇庆: [112.1265, 23.5822],
// 舟山: [122.2559, 30.2234],
// 苏州: [120.6519, 31.3989],
// 莱芜: [117.6526, 36.2714],
// 菏泽: [115.6201, 35.2057],
// 营口: [122.4316, 40.4297],
// 葫芦岛: [120.1575, 40.578],
// 衡水: [115.8838, 37.7161],
// 衢州: [118.6853, 28.8666],
// 西宁: [101.4038, 36.8207],
// 西安: [109.1162, 34.2004],
// 贵阳: [106.6992, 26.7682],
// 连云港: [119.1248, 34.552],
// 邢台: [114.8071, 37.2821],
// 邯郸: [114.4775, 36.535],
// 郑州: [113.4668, 34.6234],
// 鄂尔多斯: [108.9734, 39.2487],
// 重庆: [107.7539, 30.1904],
// 金华: [120.0037, 29.1028],
// 铜川: [109.0393, 35.1947],
// 银川: [106.3586, 38.1775],
// 镇江: [119.4763, 31.9702],
// 长春: [125.8154, 44.2584],
// 长沙: [113.0823, 28.2568],
// 长治: [112.8625, 36.4746],
// 阳泉: [113.4778, 38.0951],
// 青岛: [120.4651, 36.3373],
// 韶关: [113.7964, 24.7028],
// 浙江: [120.5313, 29.0773]
// }
let china = require('@/assets/china.json')
export default {
name: 'hello',
data() {
return {
panyName: {
省国资委: '浙江省人民政府国有资产监督管理委员会',
省国资运营公司: '浙江省国有资本运营有限公司',
物产中大: '物产中大集团股份有限公司',
省建设集团: '浙江省建设投资集团股份有限公司',
省机电集团: '浙江省机电集团有限公司',
省国贸集团: '浙江省国际贸易集团有限公司',
省旅投集团: '浙江省旅游投资集团有限公司',
杭钢集团: '杭州钢铁集团有限公司',
巨化集团: '巨化集团有限公司',
省能源集团: '浙江省能源集团有限公司',
省交投集团: '浙江省交通投资集团有限公司',
省农发集团: '浙江省农村发展集团有限公司',
省机场集团: '浙江省机场集团有限公司',
省海港集团: '浙江省海港投资运营集团有限公司',
省二轻集团: '浙江省二轻集团有限责任公司',
安邦护卫集团: '安邦护卫集团股份有限公司',
浙大控股: '浙江大学控股集团有限公司'
},
// 数据流出
GZData: [
[
{
name: '浙江'
},
{
name: '浙江',
value: 200
}
],
[
{
name: '浙江'
},
{
name: '呼和浩特',
value: 90
}
],
[
{
name: '浙江'
},
{
name: '昆明',
value: 40
}
],
[
{
name: '浙江'
},
{
name: '成都',
value: 10
}
],
[
{
name: '浙江'
},
{
name: '兰州',
value: 95
}
],
[
{
name: '浙江'
},
{
name: '银川',
value: 90
}
],
[
{
name: '浙江'
},
{
name: '西宁',
value: 80
}
]
],
// 数据流入
ZJData: [
[
{
name: '郑州',
value: 90
},
{
name: '浙江'
}
],
[
{
name: '连云港',
value: 100
},
{
name: '浙江'
}
],
[
{
name: '贵阳',
value: 10
},
{
name: '浙江'
}
],
[
{
name: '营口',
value: 90
},
{
name: '浙江'
}
],
[
{
name: '石家庄',
value: 80
},
{
name: '浙江'
}
]
]
}
},
props: {
width: Number,
height: Number,
mapStyle: Object
},
computed: {
// ...mapState(['MapData']) // 读取 vuex 中保存的地图信息
...mapState(['headerData']) // 获取最新的页面右上角公司数据
},
watch: {
// 监听页面右上角公司名称变化,动态修改标题
headerData(val) {
this.MapData() // 获取 大额资金大额资金省内地图
this.$echarts5.registerMap('china', china)
}
},
created() {
this.MapData() // 获取 大额资金大额资金省内地图
this.$echarts5.registerMap('china', china)
},
mounted() {
// this.drawMap()
},
methods: {
// 获取 大额资金大额资金省内地图
async MapData() {
if (this.headerData == '省国资委') {
const { data } = await MapData({
payFlag: '1'
})
if (data.result === 401 && data.result !== 0) {
if (data.result === 401) {
this.$router.push('/')
}
return this.$message.error(data.msg)
}
console.log(data.data.rows)
let geoCoordMap = {} // 准备地区经纬度
let outData = [] // 准备数据流出地区
let inData = [] // 准备数据流入地区
data.data.rows.forEach(item => {
geoCoordMap[item.from_province] = item.from_info.split(',')
geoCoordMap[item.to_province] = item.to_info.split(',')
// 1 为支出,0 为收入
if (item.pay_flag == 1) {
outData.push([
{ name: item.from_province },
//////////////////////////在这里准备数据
{ name: item.to_province, value: 120, num: item.amt_cny }
])
} else {
inData.push([
//////////////////////////在这里准备数据
{ name: item.to_province, value: 120, num: item.amt_cny },
{ name: item.from_province }
])
}
})
this.GZData = outData
this.ZJData = inData
this.drawMap(geoCoordMap)
} else {
const { data } = await provinceMap2({
pay_flag: '1',
corp_name: this.panyName[this.headerData]
})
if (data.result === 401 && data.result !== 0) {
if (data.result === 401) {
this.$router.push('/')
}
return this.$message.error(data.msg)
}
let geoCoordMap = {} // 准备地区经纬度
let outData = [] // 准备数据流出地区
let inData = [] // 准备数据流入地区
data.data.rows.forEach(item => {
geoCoordMap[item.from_province] = item.from_info.split(',')
geoCoordMap[item.to_province] = item.to_info.split(',')
// 1 为支出,0 为收入
if (item.pay_flag == 1) {
outData.push([
{ name: item.from_province },
//////////////////////////在这里准备数据
{ name: item.to_province, value: 120, num: item.amt_cny }
])
} else {
inData.push([
//////////////////////////在这里准备数据
{ name: item.to_province, value: 120, num: item.amt_cny },
{ name: item.from_province }
])
}
})
this.GZData = outData
this.ZJData = inData
this.drawMap(geoCoordMap)
}
// console.log(geoCoordMap)
// this.$store.commit('setMapData', data.data.rows) // 将获取到的数据存入 vuex 中
},
drawMap(geoCoordMap) {
// 基于准备好的dom,初始化echarts实例
let myChart1 = this.$echarts5.init(document.getElementById('myChart1'))
var convertData = function (data) {
var res = []
for (var i = 0; i < data.length; i++) {
var dataItem = data[i]
var fromCoord = geoCoordMap[dataItem[0].name]
var toCoord = geoCoordMap[dataItem[1].name]
if (fromCoord && toCoord) {
res.push([
{
coord: fromCoord
},
{
coord: toCoord
}
])
}
}
return res
}
var color = ['#00E686', '#fb4e4d']
var series = []
;[
['数据流出', this.GZData],
['数据流入', this.ZJData]
].forEach(function (item, i) {
series.push(
{
name: item[0],
type: 'lines',
zlevel: 1,
effect: {
show: true,
period: 5,
trailLength: 0.5,
color: '#fff',
symbolSize: 1,
borderColor: color[i],
borderWidth: 4,
shadowBlur: 1,
shadowColor: color[i],
shadowOffsetX: 0,
shadowOffsetY: 0,
delay: function () {
return Math.random() * 5000
}
},
lineStyle: {
normal: {
color: color[i],
width: 1,
curveness: -0.2
}
},
data: convertData(item[1])
},
{
name: item[0],
type: 'effectScatter',
coordinateSystem: 'geo',
zlevel: 2,
rippleEffect: {
brushType: 'stroke'
},
label: {
normal: {
show: true,
position: 'right',
formatter: '{b}',
color: '#fff',
fontSize: 10
}
},
symbolSize: function (val) {
return val[2] / 8
},
itemStyle: {
normal: {
color: color[i]
}
},
// 当鼠标移入地区时显示弹框信息
tooltip: {
formatter: res => {
// 在这里就可以拿到下面准备的数值///////////////////////////////////////
const _html = `<div>${res.seriesName}</div>
${res.marker}
${res.name}
<b style="padding-left:10px">${res.data.num}</b>`
return _html
}
},
data: item[1].map(function (dataItem) {
// 在这里准备需要展示的数据 num 需要展示的值 //////////////////////////
let name, value, num
if (dataItem[0].value) {
name = dataItem[0].name
value = geoCoordMap[dataItem[0].name].concat([
dataItem[0].value
])
num = dataItem[0].num
} else {
name = dataItem[1].name
value = geoCoordMap[dataItem[1].name].concat([
dataItem[1].value
])
num = dataItem[1].num
}
return {
name: name,
value: value,
// 在这里返回////////////////////////////////////////////////////
num: num
}
})
}
)
})
// 绘制图表
let option = {
// backgroundColor: "#031439",
backgroundColor: 'rgba(0,0,0,0)',
title: {
left: 'left',
textStyle: {
color: '#fff'
}
},
tooltip: {
trigger: 'item'
},
geo: {
map: 'china',
zoom: 1.2,
label: {
emphasis: {
show: false
}
},
roam: false,
itemStyle: {
normal: {
areaColor: 'rgba(35, 95, 157, 1)',
borderColor: '#18cdfe',
borderWidth: 1,
shadowBlur: 0,
shadowColor: '#18cdfe',
shadowOffsetX: 0.5,
shadowOffsetY: 1
},
emphasis: {
label: {
show: false
},
areaColor: 'rgba(0, 255, 255, .1)'
}
}
},
center: [109, 29],
series: series
}
myChart1.setOption(option)
}
}
}
</script>
<style>
#myChart1 {
margin: 0 auto;
left: -30px;
top: -16px;
}
</style>
自定义 tooltip
vue
<template>
<div class="page">
<div class="content">
<p class="legend">
<span class="rect"></span>
<span>完成数量</span>
</p>
<h3>任务完成情况</h3>
<div>
<div class="radarChartBox" ref="radarChartBox"></div>
</div>
</div>
</div>
</template>
<script>
import { TaskCompletion } from '@/api'
import { mapState } from 'vuex'
export default {
data() {
return {
TaskData: [], // 保存获取到的数据
radarOption: {
radar: {
indicator: [],
radius: 65
},
tooltip: {
show: true,
position: [0, 0],
////////////////////////////////////////////////////////////////////////////////自定义显示数据
formatter: series => {
let DataName = ''
series.data.name2.forEach((item, index) => {
DataName += `${item}:${series.data.value[index]}%<br>`
})
return DataName
}
////////////////////////////////////////////////////////////////////////////////自定义显示数据
},
series: [
{
name: '完成情况',
type: 'radar',
data: [],
axisLabel: {
show: true,
textStyle: { fontSize: 8, color: '#333' }
}
}
]
}
}
},
computed: {
...mapState(['headerData']), // 获取最新的页面右上角公司数据
...mapState(['setheaderId']) // 获取最新的页面右上角公司数据
},
watch: {
headerData(val) {
this.TaskCompletion()
}
},
created() {
this.TaskCompletion() // 获取企业改革页面主要任务完成情况概览数据
},
methods: {
// 获取企业改革页面主要任务完成情况概览数据
async TaskCompletion() {
const { data } = await TaskCompletion({
// id: this.setheaderId
id: -1
})
// if (!data.success)
// return this.$message.error('当前公司无数据或者请求公司数据失败!')
if (data.result === 401 && data.result !== 0) {
if (data.result === 401) {
this.$router.push('/')
}
return this.$message.error(data.msg)
}
this.TaskData = data.data.rows
let data2 = [{ value: [], name2: [] }]
let time2 = []
this.TaskData.forEach(item => {
////////////////////////////////////////////////////////////////////////////////添加数据
data2[0].value.push(item.wcbl)
data2[0].name2.push(item.flmc)
////////////////////////////////////////////////////////////////////////////////添加数据
time2.push({ name: item.flmc })
})
this.initCharts(data2, time2)
},
initCharts(data, time) {
let param = $.extend(true, {}, this.radarOption, {
radar: {
name: {
textStyle: {
color: '#FFF',
fontSize: '10'
}
// lineHeight: 8,
// padding: [-10, -5, -10, -10]
},
indicator: time,
axisLabel: {
// 坐标轴文本标签,详见axis.axisLabel
show: true,
textStyle: {
color: 'white', // 坐标轴刻度文字的样式
fontSize: '5'
}
}
},
series: [
{
symbol: 'none',
axisLabel: {
show: true,
textStyle: { fontSize: 12, color: '#333' }
},
data: data,
areaStyle: {
color: '#1890FF'
},
lineStyle: {
color: '#1890FF',
type: 'solid'
}
}
]
})
let $dom = this.$refs['radarChartBox']
let chartTrend = this.$echarts.init($dom)
chartTrend.resize()
chartTrend.clear()
chartTrend.setOption(param)
}
},
mounted() {
// let data = [{ value: [5, 10, 15, 20, 25, 30, 35, 40, 45, 50] }]
// let time = [
// { name: '落实一批重大项目', max: 100 },
// { name: '长三角一体化发展', max: 100, axisLabel: { show: false } },
// { name: '自贸试验区', max: 100, axisLabel: { show: false } },
// { name: '业合作发展', max: 100, axisLabel: { show: false } },
// { name: '控股公司章程建设', max: 100, axisLabel: { show: false } },
// { name: '企业改革发展', max: 100, axisLabel: { show: false } },
// { name: '建立董事会向总经理授权', max: 100, axisLabel: { show: false } },
// { name: '管理提升运动', max: 100, axisLabel: { show: false } },
// { name: '深入参与一带一路', max: 100, axisLabel: { show: false } },
// { name: '推进项目开工和建设', max: 100, axisLabel: { show: false } }
// ]
// this.initCharts(data, time)
}
}
</script>
<style lang="less" scoped>
.page {
width: 100%;
height: 100%;
.content {
width: 100%;
height: 100%;
float: left;
// background-image: url(../../../static/images/finance@2x.png);
background-image: url(../../../static/images/left2@.png);
// background-image: url(../../../static/images/dangjianghbbg.png);
background-size: 100% 105%;
background-repeat: no-repeat;
position: relative;
.legend {
position: absolute;
top: 20%;
right: 5%;
font-size: 10px;
.rect {
display: inline-block;
width: 15px;
height: 9px;
background: #1890ff;
}
span:nth-of-type(2) {
opacity: 0.5;
}
}
h3 {
height: 32px;
font-size: 20px;
font-weight: 400;
color: #ffffff;
opacity: 0.8;
line-height: 25px;
text-indent: 34px;
text-shadow: 0px 0px 5px #2cc5ff;
padding-top: 5px;
}
& > div {
margin-top: 10px;
width: 100%;
height: calc(100% - 40px);
.radarChartBox {
margin: 0 auto;
width: 100%;
height: 100%;
}
}
}
}
</style>
地图下载
http://datav.aliyun.com/tools/atlas/#&lat=31.840232667909365&lng=104.2822265625&zoom=4
地图默认选中与取消选中以及复杂地图
vue
<template>
<div>
<div class="map2" id="myChart2"></div>
<div
id="myChart"
:style="{ width: width + 'px', height: height + 'px' }"
></div>
</div>
</template>
<script>
import { enterprisesNum } from '@/api'
import { mapState } from 'vuex'
let zhejiang = require('@/assets/zhejiang.json')
let yiwu = require('@/assets/yiwu.json')
export default {
data() {
return {
mapname: '' // 保存当前点击的地区
}
},
props: {
width: {
type: Number,
default: 1200
},
height: {
type: Number,
default: 600
},
mapData: {
type: Array,
default() {
return [
{
name: '浙江省国有资本运营有限公司',
adress: '杭州市求是路'
}
]
}
}
},
watch: {
headerData(val) {},
mapname(val) {
// console.log(val)
}
},
computed: {
...mapState(['headerData']), // 获取最新的页面右上角公司名称
...mapState(['setheaderId']) // 获取最新的页面右上角公司id
},
created() {
// this.enterprisesNum()
this.$echarts5.registerMap('浙江', zhejiang)
this.$echarts5.registerMap('义乌', yiwu)
},
mounted() {
this.$nextTick(() => {
this.drawMap()
this.drawMap2()
})
},
methods: {
drawMap() {
// console.log(this.dataArr)
// 基于准备好的dom,初始化echarts实例
let myChart = this.$echarts5.init(document.getElementById('myChart'))
let myChart2 = this.$echarts5.init(document.getElementById('myChart2'))
// 监听地图点击事件获取当前点击地区名称
myChart.on('click', params => {
if (params.componentType === 'series') {
this.mapname = params.name
myChart2.dispatchAction({
type: 'unselect', // 取消默认选中////////////////////////////
name: '义乌市'
})
console.log(this.mapname)
}
})
// 绘制图表
let option = {
// backgroundColor: 'rgba(1, 20, 57, 1)',
grid: {
// top: '30%'
},
// 控制地图图例样式
visualMap: {
show: false,
type: 'piecewise',
right: '100',
top: 'bottom',
// orient: 'vertical',
orient: 'horizontal',
color: '#fff',
itemGap: 10,
align: 'left',
pieces: [
{ gt: 21, lte: 30, label: '1到10以内' },
{ gt: 0, lte: 20, label: '1以内' }
],
inRange: {
color: '#18cdfe',
symbol: 'rect'
},
textStyle: {
color: '#fff',
fontSize: '15'
}
},
// tooltip: {
// padding: 0,
// enterable: true,
// transitionDuration: 1,
// textStyle: {
// color: '#000',
// decoration: 'none'
// },
// position: 'top',
// className: 'tooltips',
// formatter: function(params) {
// var tipHtml = ''
// if (!params.data) {
// return tipHtml
// }
// tipHtml = `<div class="tooltip">
// <span class="name">${params.data.name}</span>
// <span class="value">${params.data.value}家</span>
// </div>`
// return tipHtml
// }
// },
series: [
{
name: '',
type: 'map',
mapType: '浙江',
// top: '25%',
center: [119.5, 29],
zoom: 1.1,
select: {
label: {
fontSize: 12,
color: '#ffffff' //设置地图点击后的文字颜色
},
itemStyle: {
borderColor: '#18cdfe',
borderWidth: '1',
areaColor: '#18cdfe' //设置地图点击后的颜色
}
},
label: {
// 控制常态默认情况下地图板块样式
normal: {
show: true,
color: '#ffffff', // 文字颜色
fontSize: 12
// 控制地区自定义文字
// formatter(params) {
// return `${params.data.name}\n${params.data.value}家`
// }
},
// 控制鼠标经过时地图板块样式
emphasis: {
show: true,
color: '#ffffff',
fontSize: 12
// 控制地区自定义文字
// formatter(params) {
// return `${params.data.name}\n${params.data.value}家`
// }
}
},
itemStyle: {
normal: {
label: {
show: false
},
areaColor: 'rgba(35, 95, 157, 1)',
borderColor: '#18cdfe',
borderWidth: 0.5,
shadowBlur: 0,
shadowColor: '#18cdfe',
shadowOffsetX: 0.5,
shadowOffsetY: 1
},
emphasis: {
label: {
show: true
},
areaColor: '#18cdfe',
color: '#fff'
}
}
// data: this.dataArr
}
]
}
myChart.setOption(option)
// myChart.dispatchAction({
// type: 'highlight',
// name: '杭州市'
// })
// function showTooltip() {
// myChart.dispatchAction({
// type: 'showTip',
// seriesIndex: 0,
// dataIndex: 0
// })
// }
// showTooltip()
},
drawMap2() {
// console.log(this.dataArr)
// 基于准备好的dom,初始化echarts实例
let myChart = this.$echarts5.init(document.getElementById('myChart2'))
let myChart2 = this.$echarts5.init(document.getElementById('myChart'))
// 绘制图表
let option = {
// backgroundColor: 'rgba(1, 20, 57, 1)',
grid: {
// top: '30%'
},
// 控制地图图例样式
visualMap: {
show: false,
type: 'piecewise',
right: '100',
top: 'bottom',
// orient: 'vertical',
orient: 'horizontal',
color: '#fff',
itemGap: 10,
align: 'left',
// pieces: [
// { gt: 21, lte: 30, label: '1到10以内' },
// { gt: 0, lte: 20, label: '1以内' }
// ],
inRange: {
color: '#0089ff',
symbol: 'rect'
},
textStyle: {
color: '#fff',
fontSize: '15'
}
},
series: [
{
name: '',
type: 'map',
mapType: '义乌',
// top: '25%',
center: [120, 29.3],
zoom: 1.1,
select: {
label: {
fontSize: 12,
color: '#ffffff' //设置地图点击后的文字颜色
},
itemStyle: {
borderColor: '#18cdfe',
borderWidth: '1',
areaColor: '#18cdfe' //设置地图点击后的颜色
}
},
label: {
// 控制常态默认情况下地图板块样式
normal: {
show: true,
color: '#ffffff', // 文字颜色
fontSize: 12
// 控制地区自定义文字
// formatter(params) {
// return `${params.data.name}\n${params.data.value}家`
// }
},
// 控制鼠标经过时地图板块样式
emphasis: {
show: true,
color: '#ffffff',
fontSize: 12
// 控制地区自定义文字
// formatter(params) {
// return `${params.data.name}\n${params.data.value}家`
// }
}
},
itemStyle: {
normal: {
label: {
show: false
},
areaColor: 'rgba(35, 95, 157, 1)',
borderColor: '#18cdfe',
borderWidth: 0.5,
shadowBlur: 0,
shadowColor: '#18cdfe',
shadowOffsetX: 0.5,
shadowOffsetY: 1
},
emphasis: {
label: {
show: true
},
areaColor: '#18cdfe',
color: '#fff'
}
}
// data: this.dataArr
}
]
}
myChart.setOption(option)
// 监听地图点击事件获取当前点击地区名称
myChart.on('click', params => {
if (params.componentType === 'series') {
// this.mapname = params.name
myChart2.dispatchAction({
type: 'unselect', // 取消选中效果////////////////////////////
dataIndex: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
})
console.log(params.name)
}
})
myChart.dispatchAction({
type: 'select', // 选中////////////////////////////////////////////////////////
name: '义乌市'
})
}
}
}
</script>
<style lang="less" scoped>
.map2 {
width: 70px;
height: 70px;
z-index: 2;
left: 439px;
top: 211px;
position: absolute;
// background-color: red;
}
/deep/ .tooltipbg {
background-color: rgba(250, 87, 87, 0) !important;
border: none !important;
padding: 0 !important;
box-shadow: none !important;
}
</style>
实现打点地图背景色
vue
<script>
echarts.registerMap('浙江', zhejiang)
let myChartMap = echarts.init(this.$refs.myEchart)
// 地图弹框数据(浙江)
// 地图弹框数据(浙江)
let data = [
{
name: '杭州市',
// itemStyle: {
// areaColor: '#56b1da'
// },
value: [
'16308.12',
'6082.47',
'6840.45',
'8349.82',
'473.8',
'422.38',
'364.34',
'950.0'
],
name2: [
'资产总额',
'国有资产',
'净资产',
'营业收入',
'利润总额',
'净利润',
'工业生产总值',
'企业数量'
],
unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
},
{
name: '宁波市',
// itemStyle: {
// areaColor: '#56b1da'
// },
value: [
'2764.58',
'1460.79',
'1535.75',
'2136.53',
'124.42',
'102.27',
'312.49',
'252.0'
],
name2: [
'资产总额',
'国有资产',
'净资产',
'营业收入',
'利润总额',
'净利润',
'工业生产总值',
'企业数量'
],
unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
},
{
name: '温州市',
// itemStyle: {
// areaColor: '#56b1da'
// },
value: [
'735.66',
'305.67',
'308.68',
'176.72',
'-2.56',
'-4.14',
'69.47',
'75.0'
],
name2: [
'资产总额',
'国有资产',
'净资产',
'营业收入',
'利润总额',
'净利润',
'工业生产总值',
'企业数量'
],
unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
},
{
name: '嘉兴市',
// itemStyle: {
// areaColor: '#56b1da'
// },
value: [
'453.94',
'231.15',
'241.87',
'170.85',
'19.25',
'15.12',
'31.62',
'83.0'
],
name2: [
'资产总额',
'国有资产',
'净资产',
'营业收入',
'利润总额',
'净利润',
'工业生产总值',
'企业数量'
],
unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
},
{
name: '湖州市',
// itemStyle: {
// areaColor: '#56b1da'
// },
value: [
'382.39',
'158.66',
'162.29',
'196.68',
'13.43',
'10.43',
'54.83',
'79.0'
],
name2: [
'资产总额',
'国有资产',
'净资产',
'营业收入',
'利润总额',
'净利润',
'工业生产总值',
'企业数量'
],
unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
},
{
name: '绍兴市',
// itemStyle: {
// areaColor: '#56b1da'
// },
value: [
'313.19',
'101.98',
'118.91',
'188.14',
'14.48',
'11.54',
'105.01',
'89.0'
],
name2: [
'资产总额',
'国有资产',
'净资产',
'营业收入',
'利润总额',
'净利润',
'工业生产总值',
'企业数量'
],
unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
},
{
name: '金华市',
// itemStyle: {
// areaColor: '#56b1da'
// },
value: [
'338.9',
'174.83',
'178.43',
'183.16',
'12.49',
'9.15',
'65.52',
'96.0'
],
name2: [
'资产总额',
'国有资产',
'净资产',
'营业收入',
'利润总额',
'净利润',
'工业生产总值',
'企业数量'
],
unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
},
{
name: '衢州市',
// itemStyle: {
// areaColor: '#56b1da'
// },
value: [
'940.43',
'374.97',
'440.13',
'429.0',
'5.99',
'4.49',
'295.17',
'123.0'
],
name2: [
'资产总额',
'国有资产',
'净资产',
'营业收入',
'利润总额',
'净利润',
'工业生产总值',
'企业数量'
],
unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
},
{
name: '舟山市',
// itemStyle: {
// areaColor: '#56b1da'
// },
value: [
'1444.14',
'909.83',
'928.27',
'345.35',
'26.74',
'24.22',
'33.35',
'97.0'
],
name2: [
'资产总额',
'国有资产',
'净资产',
'营业收入',
'利润总额',
'净利润',
'工业生产总值',
'企业数量'
],
unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
},
{
name: '台州市',
// itemStyle: {
// areaColor: '#56b1da'
// },
value: [
'684.87',
'232.04',
'243.89',
'148.56',
'2.97',
'1.05',
'46.51',
'87.0'
],
name2: [
'资产总额',
'国有资产',
'净资产',
'营业收入',
'利润总额',
'净利润',
'工业生产总值',
'企业数量'
],
unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
},
{
name: '丽水市',
// itemStyle: {
// areaColor: '#56b1da'
// },
value: [
'164.34',
'67.39',
'70.43',
'53.88',
'5.62',
'4.39',
'20.56',
'66.0'
],
name2: [
'资产总额',
'国有资产',
'净资产',
'营业收入',
'利润总额',
'净利润',
'工业生产总值',
'企业数量'
],
unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
}
]
// 浙江省打点位置数据
let markPoint = [
{
name: '杭州市',
value: '0',
coord: [119.39, 29.8]
},
{
name: '湖州市',
value: '0',
coord: [120, 30.8]
},
{
name: '嘉兴市',
value: '0',
coord: [121.05, 30.6]
},
{
name: '衢州市',
value: '0',
coord: [119, 28.75]
},
{
name: '绍兴市',
value: '0',
coord: [120.88, 29.65]
},
{
name: '宁波市',
value: '0',
coord: [121.86, 29.59]
},
{
name: '金华市',
value: '0',
coord: [120.28, 29]
},
{
name: '丽水市',
value: '0',
coord: [119.62, 27.95]
},
{
name: '温州市',
value: '0',
coord: [120.75, 27.77]
},
{
name: '台州市',
value: '0',
coord: [121.33, 28.78]
},
{
name: '舟山市',
value: '0',
coord: [122.55, 30.15]
}
]
const options = {
tooltip: {
backgroundColor: null,
formatter: function (params) {
let str2 = ''
let animaTime = 'animation-duration: 0s;'
if (params.data !== undefined && params.data.name2) {
params.data.name2.forEach((item, i) => {
str2 += `
<div class="IndustrialLayout22item">
<span>${item}</span>
<p>
<span style="color: #FFFFFF;">${params.data.value[i]}</span><span> ${params.data.unit[i]}</span>
</p>
</div>
`
})
if (params.data.name2.length > 5) {
str2 += str2
animaTime = `animation-duration: ${params.data.name2.length * 2}s;`
}
}
let str1 = `
<div class="IndustrialLayout22div">
<p class="IndustrialLayout22p">${params.name}</p>
<div class="IndustrialLayout22div1">
<div class="IndustrialLayout22div2" style="${animaTime}">
${str2}
</div>
</div>
</div>
`
return str1
}
},
geo: [
{
map: '浙江',
aspectScale: 1,
show: false,
roam: false, //是否允许缩放
layoutSize: `95%`,
layoutCenter: [`55%`, `57%`],
label: {
// 地图默认常态样式
show: false,
color: `#EEEEEE`,
// 鼠标划入样式
emphasis: {
show: false,
areaColor: `#fff`,
color: `#EEEEEE`
}
},
emphasis: {
label: {
show: false,
color: `#fff`
}
},
itemStyle: {
areaColor: `transparent`,
borderColor: `#d1e7f8`,
borderWidth: 1,
shadowBlur: 6,
shadowOffsetY: 0,
shadowOffsetX: 0,
shadowColor: `#d1e7f8`,
// 鼠标移入时板块样式
emphasis: {
areaColor: `rgba(103, 96, 158, 0.2)`,
label: {
color: `#fff`
}
}
},
z: 4
},
{
map: '浙江',
aspectScale: 1,
roam: false, //是否允许缩放
//zoom: 1.1, //默认显示级别
layoutSize: `95%`,
layoutCenter: [`55%`, `57%`],
itemStyle: {
// normal: {
areaColor: {
image: '', //配置图片
repeat: 'no-repeat' //可选值repeat、no-repeat、repeat-x、repeat-y
},
// color: {
// image: '', // 支持为 HTMLImageElement, HTMLCanvasElement,不支持路径字符串
// repeat: `repeat` // 是否平铺,可以是 'repeat-x', 'repeat-y', 'no-repeat'
// },
borderColor: `#37C1FD`,
borderWidth: 2
},
z: 3,
silent: true
},
{
map: '浙江',
aspectScale: 1,
roam: false, //是否允许缩放
//zoom: 1.1, //默认显示级别
layoutSize: `97%`,
layoutCenter: [`55.1%`, `59.8%`],
itemStyle: {
areaColor: `#233c83`,
borderColor: `#233c83`
},
z: 2,
silent: true
}
],
series: [
{
type: 'map',
// selectedMode: 'multiple',
mapType: '浙江',
aspectScale: 1,
roam: false, //是否允许缩放
layoutSize: `95%`,
layoutCenter: [`55%`, `57%`],
label: {
// 地图默认常态样式
show: true,
color: `#EEEEEE`,
// 鼠标划入样式
emphasis: {
show: false,
areaColor: `#fff`,
color: `#EEEEEE`
}
},
emphasis: {
label: {
show: false,
color: `#fff`
}
},
itemStyle: {
areaColor: `transparent`,
borderColor: `#d1e7f8`,
borderWidth: 0.5,
shadowBlur: 6,
shadowOffsetY: 0,
shadowOffsetX: 0,
shadowColor: `#d1e7f8`,
// 鼠标移入时板块样式
emphasis: {
areaColor: `rgba(103, 96, 158, 0.2)`,
label: {
color: `#fff`
}
}
},
data: data,
z: 10,
// 地图打点
markPoint: {
symbol: 'image://' + require('../../../static/images/c@2x.png'), // 自定义图片路径
//数据全是markPoint
symbolSize: [120, 52], // 标注大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2
itemStyle: {
normal: {
borderColor: '#FFFFFF',
borderWidth: 1, // 标注边线线宽,单位px,默认为1
label: {
show: true,
position: ['40%', '8%'],
color: '#fff'
}
},
emphasis: {
borderColor: 'red',
borderWidth: 5,
label: {
show: false
}
}
},
effect: {
show: true,
shadowBlur: 0
},
// 此数据源为定位点数据
data: markPoint
} //end markPoint
},
{
name: 'Top 5',
type: 'scatter',
coordinateSystem: 'geo',
// symbol: 'image://http://ssq168.shupf.cn/data/biaoji.png',
// symbolSize: [30,120],
// symbolOffset:[0, '-40%'] ,
label: {
normal: {
show: false
}
},
itemStyle: {
normal: {
color: '#D8BC37' //标志颜色
}
},
data: data,
showEffectOn: 'render',
rippleEffect: {
brushType: 'stroke'
},
hoverAnimation: true,
zlevel: 10
}
]
}
// 记录各省份打点对应数据位置(浙江)
let obj = {
杭州市: 0,
湖州市: 1,
嘉兴市: 2,
衢州市: 3,
绍兴市: 4,
宁波市: 5,
金华市: 6,
丽水市: 7,
温州市: 8,
台州市: 9,
舟山市: 10
}
// 引入地图背景图
let domImg = document.createElement('img')
domImg.src = './../../../static/images/zhejiangmap_1@2x.png'
options.geo[1].itemStyle.areaColor.image = domImg
// 引入地图背景图
// 产业布局 地图 浙江省
const { data: data2 } = await zjsMap({
statDate: this.chanyeyear,
indexName: this.panytype,
distName: '%'
})
if (!data2.success) return ''
data2.data.rows.forEach(item => {
if (obj[item.distName]) {
markPoint[obj[item.distName]].value = `${item.indexValue.split('.')[0]}${
item.indexUnit
}`
}
})
myChartMap.setOption(options, true)
</script>
按需加载
新建 src/utils/echarts.js
js
// 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口
import * as echarts from 'echarts/core'
// 引入各种图表,图表后缀都为 Chart
import { BarChart, PieChart } from 'echarts/charts'
// 引入提示框,标题,直角坐标系等组件,组件后缀都为 Component
import {
// TitleComponent,
TooltipComponent,
// ToolboxComponent,
GridComponent,
LegendComponent
// AxisPointerComponent,
// DatasetComponent,
// GraphicComponent
} from 'echarts/components'
// 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
import { SVGRenderer } from 'echarts/renderers'
// 注册必须的组件
echarts.use([
BarChart,
// LineChart,
PieChart,
// TitleComponent,
TooltipComponent,
// ToolboxComponent,
GridComponent,
LegendComponent,
// AxisPointerComponent,
// DatasetComponent,
// GraphicComponent,
SVGRenderer
])
export default echarts
在 main.js 中引入并挂载
在组件中使用
js
initCharts2(info) {
let charts = this.$echarts.init(document.getElementById('charts2'))
let option = {}
charts.resize()
charts.clear()
charts.setOption(option)
},
社区示例
http:www.ppchart.com/#/
js 实用写法
axios 全局捕获错误
js
import axios from 'axios'
axios.interceptors.response.use(
response => {
return response
},
error => {
// 这里可以提示用户,如:网络错误
console.log(error)
// 这种种写法可以在任何请求出错(如网络原因)时让该请求相关代码不再往下执行也可以捕获错误,简化代码省略 catch 或者 try、catch
return new Promise(() => {})
// return Promise.reject(error) 这种写法需要在对应请求代码中写入 catch 或者 try、catch
}
)
await 中简化 try catch
js
function getUserInfo() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('请求异常')
}, 1000)
})
}
// 不需要中断代码执行时可以这么写
async function logined() {
let userInfo = await getUserInfo().catch(e => console.warn(e))
// 执行没有中断,userInfo 为 undefined
if (!userInfo) return // 需要做非空校验
let pageInfo = await getPageInfo(userInfo?.userId)
}
// 需要中断代码执行时这么写
async function logined() {
let userInfo = await getUserInfo().catch(e => {
console.warn(e)
return Promise.reject(e) // 会导致控制台出现 uncaught (in promise) 报错信息
})
// 执行中断
let pageInfo = await getPageInfo(userInfo?.userId)
}
logined()
从 url 获取参数并转为对象
js
const getParameters = URL =>
JSON.parse(
`{"${decodeURI(URL.split('?')[1])
.replace(/"/g, '\\"')
.replace(/&/g, '","')
.replace(/=/g, '":"')}"}`
)
getParameters('https://www.google.com.hk/search?q=js+md&newwindow=1')
// {q: 'js+md', neww}
两日期之间相差的天数
js
const dayDiff = (date1, date2) =>
Math.ceil(Math.abs(date1.getTime() - date2.getTime()) / 86400000)
dayDiff(new Date('2021-10-21'), new Date('2022-02-12'))
// Result:144
高德地图使用
vue
<template>
<div class="GDwarp">
<div id="GDcontainer"></div>
<a-input
placeholder="如需修改位置请先搜索地址"
v-model="amap.searchAddress"
class="amap-search"
id="GDsearch"
:disabled="type === 2"
/>
<!-- 搜索结果 -->
<div id="amap-panel" v-show="amap.searchNearBy"></div>
<div ref="infoWindow" v-show="infoWindowShow" class="infoWindow">
<span>名称: {{ addressName }}</span>
<span>地址: {{ amap.formattedAddress }}</span>
<div class="triangle"></div>
</div>
</div>
</template>
<script>
import AMapLoader from '@amap/amap-jsapi-loader'
window._AMapSecurityConfig = {
securityJsCode: '9aab3b0492ae2e3a138d95f4259b85f8'
}
export default {
// 记录当前状态 1:新增 2:查看 3:编辑
props: ['type'],
data() {
return {
map: null,
// 保存自定义弹框
infoWindow: null,
infoWindowShow: false,
addressName: '',
amap: {
// 用户选择地址的经纬度
lonlat: '',
position: undefined,
// 用户选择的详细地址
formattedAddress: '',
searchNearBy: false,
placeSearch: null,
searchAddress: ''
}
}
},
methods: {
// 初始化
initMap() {
AMapLoader.load({
key: '81921971980445dc8138d38ea50b1fb9', // 申请好的Web端开发者Key,首次调用 load 时必填
plugins: ['AMap.PlaceSearch', 'AMap.Autocomplete', 'AMap.InfoWindow'],
AMapUI: {
plugins: ['misc/PositionPicker']
}
})
.then(AMap => {
this.amap.searchAddress = ''
this.map = new AMap.Map('GDcontainer', {
//设置地图容器id
zoom: 15, //初始化地图级别
center: [120.435702, 30.238782] //初始化地图中心点位置
})
// 地图点击事件
this.map.on('click', () => {
// 关闭信息弹框
this.map.clearInfoWindow()
this.infoWindowShow = false
})
// 初始化搜索框
this.addKeywordSearch()
})
.catch(e => {
console.log(e)
})
},
// 初始化搜索框
addKeywordSearch() {
const auto = new AMap.Autocomplete({
input: 'GDsearch'
})
this.amap.placeSearch = new AMap.PlaceSearch({
map: this.map,
panel: 'amap-panel', // 结果列表将在此容器中进行展示。
autoFitView: true, // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
extensions: 'base' //返回基本地址信息
})
if (this.type === 2) return
auto.on('select', this.select)
// 点击地图覆盖物
AMap.event.addListener(this.amap.placeSearch, 'markerClick', e => {
this.openInfo(e.data, e.event)
this.amap.position = e.data.location
this.amap.lonlat = e.data.location.lng + ',' + e.data.location.lat
this.fullLonlat = this.amap.lonlat
this.amap.formattedAddress =
e.data.pname +
e.data.cityname +
e.data.adname +
e.data.address +
e.data.name
this.$emit('getMapInfo', this.amap)
})
},
// 地图选择事件(点击搜索项)
select(e) {
this.amap.placeSearch.setCity(e.poi.adcode)
this.amap.placeSearch.search(e.poi.name) //关键字查询查询
this.amap.position = e.poi.location
if (e.poi.location) {
this.amap.lonlat = e.poi.location.lng + ',' + e.poi.location.lat
}
this.fullLonlat = this.amap.lonlat
this.amap.formattedAddress = e.poi.district + e.poi.address + e.poi.name
this.$emit('getMapInfo', this.amap)
},
// 自定义信息框
openInfo({ name }, { lnglat }) {
this.addressName = name
this.infoWindowShow = true
this.infoWindow = new AMap.InfoWindow({
isCustom: true,
content: this.$refs.infoWindow,
offset: new AMap.Pixel(0, -25)
})
this.infoWindow.open(this.map, lnglat)
}
}
}
</script>
<style lang="less" scoped>
#GDcontainer {
width: 100%;
height: 300px;
}
.GDwarp {
position: relative;
.amap-search {
position: absolute;
width: 50%;
top: 10px;
left: 10px;
}
#amap-panel {
position: absolute;
background-color: white;
max-height: 90%;
margin: 10px 0 10px 0;
overflow-y: auto;
top: 10px;
right: 10px;
width: 280px;
height: 300px;
border-bottom: solid 1px silver;
}
.infoWindow {
background-color: #fff;
box-shadow: 0px 4px 12px 0px rgba(0, 0, 0, 0.15);
border-radius: 2px;
line-height: 30px;
padding: 10px;
display: flex;
flex-direction: column;
position: relative;
.triangle {
position: absolute;
border-color: #fff transparent transparent transparent;
border-style: solid;
border-width: 15px 15px 15px 15px;
bottom: -30px;
left: 50%;
transform: translateX(-50%);
}
}
}
</style>
css 实现高度不固定过渡动画
css
/* 可以通过 max-height来实现 */
.div1 {
max-height: 0;
trabsition: 0.3s;
}
.div1:hover {
max-height: 800px;
}
还可以通过 grid 来实现,可参考 juejin.cn/post/7196843994030342200
html
<style>
.warp {
width: 200px;
}
.grid {
display: grid;
grid-template-columns: 0fr;
transition: 0.3s;
overflow: hidden;
background-color: aqua;
}
.grid > div {
min-height: 0;
}
.warp:hover .grid {
grid-template-columns: 1fr;
}
</style>
<div class="wrap">
<button class="trigger">鼠标移入</button>
<div class="grid">
<div>很多内容具体有多少不确定所以此 div 最终有多高不知道</div>
</div>
</div>
在 vue3 中使用 jsx
基本使用
由于 tsx 直接就是运行时了,无法在编译期做一些优化,导致性能比不过模板的写法
安装依赖
base
npm i @vitejs/plugin-vue-jsx -D
在 vite.config.js 文件中的 plugins 字段中添加 jsx 支持
js
import vueJsx from '@vitejs/plugin-vue-jsx'
export default defineConfig({
plugins: [vueJsx()]
})
新建 jsx 文件
jsx
import HelloWorld from './HelloWorld.vue'
export default {
setup() {
return () => <HelloWorld msg="11" />
}
}
也可以使用另一种写法
jsx
import { defineComponent, ref } from "vue";
export default defineComponent({
name: "TsxDemo",
props: {
msg: {
type: String,
required: true,
default: "hello wrold",
},
},
setup(props) {
const count = ref(0);
return () => (
<div>
<header>{props.msg}</header>
<main>{count.value}</main>
</div>
);
},
});
template 和 jsx 混用
vue
<template>
<el-tabs v-model="activeName" @tab-click="handleClick">
<!-- 使用 jsx 编写的组件 -->
<reuseP />
<el-tab-pane label="热门主题" name="hot">热门主题</el-tab-pane>
</el-tabs>
</template>
<script setup lang="tsx">
import { ref } from 'vue'
import type { TabsPaneContext } from 'element-plus'
const activeName = ref('new')
const arr = [1, 2, 3]
// 创建 jsx 编写的组件
const reuseP = () => arr.map((item: any) => <p key={item}>xxx</p>)
function handleClick(tab: TabsPaneContext) {
console.log(tab.paneName)
}
</script>
也可以使用这种写法
vue
<template>
<el-tabs v-model="activeName" @tab-click="handleClick">
<!-- 使用 jsx 编写的组件 -->
<Demo msg="hello world" />
<el-tab-pane label="热门主题" name="hot">热门主题</el-tab-pane>
</el-tabs>
</template>
<script setup lang="tsx">
import { ref,defineComponent } from 'vue'
import type { TabsPaneContext } from 'element-plus'
const activeName = ref('new')
// 创建 jsx 编写的组件
const Demo = defineComponent({
props: {
msg: String,
},
setup(props) {
return () => (
<div>
<div>msg is {props.msg}</div>
</div>
);
},
});
</script>
css 方案
.vue
文件中支持css module
和css scoped
方案
css module
vue
<template>
<div>
<Demo msg="hello world" />
</div>
</template>
<script lang="tsx" setup>
import { defineComponent, useCssModule } from "vue";
const styles = useCssModule();
const Demo = defineComponent({
props: {
msg: String,
},
setup(props) {
return () => (
<div class={styles.wrapper}>
<div class={styles.inner}>msg is {props.msg}</div>
</div>
);
},
});
</script>
<style lang="less" module>
.wrapper {
.inner {
color: red;
}
}
</style>
css scoped
vue
<template>
<div>
<Demo msg="hello world" />
</div>
</template>
<script lang="tsx" setup>
import { defineComponent } from "vue";
const Demo = defineComponent({
props: {
msg: String,
},
setup(props) {
return () => (
<div class="wrapper">
<div class="inner">msg is {props.msg}</div>
</div>
);
},
});
</script>
<style lang="less" scoped>
// 由于 Demo 是一个子组件,而 scoped 方案不会透传到子组件中dom中,所以这里我们得用:deep处理
:deep(.wrapper) {
.inner {
color: red;
}
}
</style>
如果想在混合且使用 scoped 的情况下,不写 deep 样式穿透可以使用如下写法
vue
<template>
<div>
<component :is="renderDemo('hello world')"></component>
</div>
</template>
<script lang="tsx" setup>
const renderDemo = (msg: string) => (
<div class="wrapper">
<div class="inner"> msg is {msg}</div>
</div>
);
</script>
<style lang="less" scoped>
.wrapper {
.inner {
color: red;
}
}
</style>