




DOCTYPE html>
<html>
<head>head>
<body>
<canvas id="canvas" width="800" height="800">canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d'); // 获取到 Canvas 对象
ctx.fillStyle = 'red'; // 修改填充色为红色
ctx.fillRect(0, 0, 50, 50); // 绘制矩形
ctx.beginPath();
ctx.lineWidth = 1; // 线条宽度
ctx.strokeStyle = 'blue'; // 线条填充色
ctx.moveTo(100, 100); // 起点坐标
ctx.lineTo(250, 75); // 中间点坐标
ctx.lineTo(300, 100); // 终点坐标
ctx.stroke(); // 绘制线段
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = 'green';
ctx.fillStyle = 'red';
ctx.arc(200, 200, 50, 0, 2 * Math.PI); // 绘制圆形
ctx.stroke();
ctx.fill();
ctx.beginPath();
ctx.lineWidth = 1; // 线条宽度
ctx.strokeStyle = 'red'; // 线条填充色
ctx.moveTo(300, 300); // 起点坐标
ctx.lineTo(301, 301); // 中间点坐标
ctx.stroke(); // 绘制线段
script>
body>
html>
DOCTYPE html>
<html>
<head>head>
<body>
<svg width="800" height="800">
<rect
width="50"
height="50"
style="fill:red;"
/>
<line
x1="100"
y1="100"
x2="250"
y2="75"
style="stroke:blue;stroke-width: 1;"
/>
<line
x1="250"
y1="75"
x2="300"
y2="100"
style="stroke:blue;stroke-width: 1;"
/>
<circle
cx="200"
cy="200"
r="50"
stroke="green"
stroke-width="2"
fill="red"
/>
<line
x1="300"
y1="300"
x2="301"
y2="301"
style="stroke:red;stroke-width: 1;"
/>
svg>
body>
html>
# 涉及到系统的3D绘图的知识,超纲了
# 有兴趣可自学
DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/zrender@4.3.0/dist/zrender.js">script>
head>
<body>
<div id="container" style="width: 800px;height: 800px;">div>
<script>
const zr = zrender.init(document.getElementById('container'));
const rect = new zrender.Rect({
shape: {
x: 0,
y: 0,
width: 50,
height: 50
},
style: {
fill: 'red',
lineWidth: 0
}
});
const line = new zrender.Polyline({
shape: {
points: [
[100, 100],
[250, 75],
[300, 100]
]
},
style: {
stroke: 'blue',
lineWidth: 1
}
});
const circle = new zrender.Circle({
shape: {
cx: 200,
cy: 200,
r: 50
},
style: {
fill: 'red',
stroke: 'green',
lineWidth: 2
}
});
const point = new zrender.Polyline({
shape: {
points: [
[300, 300],
[301, 301]
]
},
style: {
stroke: 'red',
lineWidth: 1
}
});
zr.add(rect)
zr.add(line)
zr.add(circle)
zr.add(point)
script>
body>
html>
DOCTYPE html>
<html>
<head>
<script src="https://d3js.org/d3.v5.js">script>
head>
<body>
<p>Vuep>
<p>Reactp>
<p>Agularp>
<button id="datum">datumbutton>
<button id="data">databutton>
<script>
const body = d3.select('body'); // 获取d3 dom
const p = body.selectAll('p');
function doDatum() {
const str = 'Framework';
p.datum(str);
p.text(function(d, i) {
return `${d}-${i}`;
});
}
function doData() {
const dataset = ['Vue', 'React', 'Agular'];
p.data(dataset)
.text(function(d, i) {
return `${d}-${i}`;
})
}
document.getElementById('datum').addEventListener('click', function(e) {
doDatum();
})
document.getElementById('data').addEventListener('click', function(e) {
doData();
})
script>
body>
html>
DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
head>
<body>
<input type="file" id="upload">
<script>
const ACCEPT = ['image/jpg', 'image/png', 'image/jpeg'];
const MAXSIZE = 3 * 1024 * 1024;
const MAXSIZE_STR = '3MB';
function convertImageToBase64(file, callback) {
let reader = new FileReader();
reader.addEventListener('load', function(e) {
const base64Image = e.target.result;
callback && callback(base64Image);
reader = null;
});
reader.readAsDataURL(file);
}
function compress(base64Image, callback) {
let maxW = 1024;
let maxH = 1024;
const image = new Image();
image.addEventListener('load', function(e) { // event load == onload, 表示一张页面或一幅图像完成加载时触发
let ratio; // 图片的压缩比
let needCompress = false; // 是否需要压缩
if (maxW < image.naturalWidth) {
needCompress = true;
ratio = image.naturalWidth / maxW;
maxH = image.naturalHeight / ratio;
} // 经过处理后,实际图片的尺寸为 1024 * 640
if (maxH < image.naturalHeight) {
needCompress = true;
ratio = image.naturalHeight / maxH;
maxW = image.naturalWidth / ratio;
}
if (!needCompress) {
maxW = image.naturalWidth;
maxH = image.naturalHeight;
} // 如果不需要压缩,需要获取图片的实际尺寸
const canvas = document.createElement('canvas');
canvas.setAttribute('id', '__compress__');
canvas.width = maxW;
canvas.height = maxH;
canvas.style.visibility = 'hidden';
document.body.appendChild(canvas);
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, maxW, maxH);
ctx.drawImage(image, 0, 0, maxW, maxH);
const compressImage = canvas.toDataURL('image/jpeg', 0.9);
callback && callback(compressImage);
canvas.remove();
});
image.src = base64Image;
}
function uploadToServer(compressImage) {
console.log('upload to server...', compressImage);
}
const upload = document.getElementById('upload');
upload.addEventListener('change', function(e) {
const [file] = e.target.files;
if (!file) {
return;
}
const { type: fileType, size: fileSize } = file;
if (!ACCEPT.includes(fileType)) {
alert(`不支持[${fileType}]文件类型!`);
upload.value = '';
return;
} // 图片类型检查
if (fileSize > MAXSIZE) {
alert(`文件超出${MAXSIZE_STR}!`);
upload.value = '';
return;
} // 图片容量检查
// 压缩图片
convertImageToBase64(file, (base64Image) => compress(base64Image));
})
script>
body>
html>





DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://unpkg.com/@antv/g2plot@latest/dist/g2plot.min.js">script>
head>
<body>
<div id="g2-chart">div>
<script>
const data = [
{ year: '1991', value: 3 },
{ year: '1992', value: 4 },
{ year: '1993', value: 3.5 },
{ year: '1994', value: 5 },
{ year: '1995', value: 4.9 },
{ year: '1996', value: 6 },
{ year: '1997', value: 7 },
{ year: '1998', value: 9 },
{ year: '1999', value: 13 },
];
const chartDom = document.getElementById('g2-chart');
const line = new G2Plot.Line(chartDom, {
title: {
visible: true,
text: 'g2折线图示例'
},
description: {
visible: true,
text: '折线图示例,这是一个副标题'
},
data,
xField: 'year',
yField: 'value',
point: {
visible: true,
size: 5,
color: '#fff',
style: {
stroke: '#fe740c',
lineWidth: 2,
fillOpacity: 0.6
}
},
label: {
visible: true
},
color: '#f2740c',
yAxis: {
formatter: (v) => {
return `${v}k`;
}
}
});
line.render();
script>
body>
html>
line.render();G6绘制矢量图DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-3.4.7/dist/g6.min.js">script>
head>
<body>
<div id="g6-chart">div>
<script>
const data = {
nodes: [{
id: 'node1',
x: 100,
y: 200,
label: '起始点',
size: 60,
labelCfg: {
position: 'center',
style: {
fontSize: 12,
fill: '#fff'
}
},
style: {
fill: '#ff0000',
stroke: '#888',
lineWidth: 1
}
}, {
id: 'node2',
x: 300,
y: 200,
label: '目标点1',
size: 80
}, {
id: 'node4',
x: 300,
y: 400,
label: '目标点4',
size: 80
}, {
id: 'node3',
x: 500,
y: 200,
label: '目标点2',
size: 100
}], // 点集
edges: [{
source: 'node1',
target: 'node2',
label: '连接线1'
}, {
source: 'node1',
target: 'node4',
label: '连接线3'
}, {
source: 'node2',
target: 'node3',
label: '连接线2'
}] // 边集
};
const graph = new G6.Graph({
container: 'g6-chart',
width: 800,
height: 500
}); // 完成 G6 图的初始化
graph.data(data); // 绑定数据源
graph.render(); // 绘制矢量图
script>
body>
html>
L7:地理空间数据可视分析引擎,官网案例:全球发电站气泡图DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://unpkg.com/@antv/l7">script>
<style>
html, body {
padding: 0;
margin: 0;
}
style>
head>
<body>
<div id="l7-map">div>
<script>
const scene = new L7.Scene({
id: 'l7-map',
map: new L7.GaodeMap({ // 加载高德地图
style: 'dark',
center: [120.19382669582967, 30.258134],
pitch: 0, // 地图显示的角度,默认为0,俯视
zoom: 12, // 粒度
token: 'e8653883477c1e38d190463340771816'
})
});
scene.on('loaded', function() {
// 全国发电站的数据
fetch(
'https://gw.alipayobjects.com/os/basement_prod/337ddbb7-aa3f-4679-ab60-d64359241955.json'
)
.then(res => res.json())
.then(data => {
console.log(data);
data.features = data.features.filter(item => item.properties.capacity > 1000); // 过滤器
const pointLayer = new L7.PointLayer({})
.source(data)
.shape('circle')
.size('capacity', [0, 16])
.color('capacity', [
'#34B6B7',
'#4AC5AF',
'#5FD3A6',
'#7BE39E',
'#A1EDB8',
'#CEF8D6'
])
.style({
strokeWidth: 0,
opacity: 0.5
})
.active(true);
scene.addLayer(pointLayer);
});
});
script>
body>
html>
基于zrender,有绚丽的特效;文档

画个柱状折线图
DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/echarts@4.7.0/dist/echarts.js">script>
<style>
#chart {
width: 800px;
height: 400px;
}
style>
head>
<body>
<div id="chart">div>
<script>
const chartDom = document.getElementById('chart');
const chart = echarts.init(chartDom);
chart.setOption({
dataset: {
source: [
['一季度', 100, 79, '分类1', 50],
['二季度', 112, 81, '分类2', 60],
['三季度', 96, 88, '分类3', 55],
['四季度', 123, 72, '分类4', 70]
]
},
title: {
text: 'ECharts 多系列案例',
subtext: '慕课网数据可视化课程'
},
xAxis: {
data: ['一季度', '二季度', '三季度', '四季度']
},
yAxis: {}, // 不设定,自己按照数据画
legend: {
data: [{
name: '分类',
icon: 'circle',
textStyle: {
color: 'red'
}
}, '折线图', '柱状图'],
left: 300
},
grid: {
top: 100,
left: '10%',
right: '10%',
bottom: 100
},
toolbox: {
feature: {
saveAsImage: {},
dataZoom: {
yAxisIndex: false
},
restore: {}
}
},
dataZoom: [
{
show: true,
start: 30,
end: 70
}
],
series: [{
name: '折线图',
type: 'line',
encode: { x: 0, y: 1 }
}, {
name: '柱状图',
type: 'bar',
encode: { x: 0, y: 2 }
}]
});
script>
body>
html>

自定义样式,这是ECharts里最实用的功能,官方只给出了两个主题
DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/echarts@4.7.0/dist/echarts.js">script>
<style>
#chart {
width: 800px;
height: 400px;
}
style>
<script>
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['exports', 'echarts'], factory);
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
// CommonJS
factory(exports, require('echarts'));
} else {
// Browser globals
factory({}, root.echarts);
}
}(this, function (exports, echarts) {
var log = function (msg) {
if (typeof console !== 'undefined') {
console && console.error && console.error(msg);
}
};
if (!echarts) {
log('ECharts is not Loaded');
return;
}
echarts.registerTheme('westeros', {
"color": [
"#516b91",
"#59c4e6",
"#edafda",
"#93b7e3",
"#a5e7f0",
"#cbb0e3"
],
"backgroundColor": "rgba(0,0,0,0)",
"textStyle": {},
"title": {
"textStyle": {
"color": "#516b91"
},
"subtextStyle": {
"color": "#93b7e3"
}
},
"line": {
"itemStyle": {
"normal": {
"borderWidth": "2"
}
},
"lineStyle": {
"normal": {
"width": "2"
}
},
"symbolSize": "6",
"symbol": "emptyCircle",
"smooth": true
},
"radar": {
"itemStyle": {
"normal": {
"borderWidth": "2"
}
},
"lineStyle": {
"normal": {
"width": "2"
}
},
"symbolSize": "6",
"symbol": "emptyCircle",
"smooth": true
},
"bar": {
"itemStyle": {
"normal": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
},
"emphasis": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
}
}
},
"pie": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"scatter": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"boxplot": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"parallel": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"sankey": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"funnel": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"gauge": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"candlestick": {
"itemStyle": {
"normal": {
"color": "#edafda",
"color0": "transparent",
"borderColor": "#d680bc",
"borderColor0": "#8fd3e8",
"borderWidth": "2"
}
}
},
"graph": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"lineStyle": {
"normal": {
"width": 1,
"color": "#aaaaaa"
}
},
"symbolSize": "6",
"symbol": "emptyCircle",
"smooth": true,
"color": [
"#516b91",
"#59c4e6",
"#edafda",
"#93b7e3",
"#a5e7f0",
"#cbb0e3"
],
"label": {
"normal": {
"textStyle": {
"color": "#eeeeee"
}
}
}
},
"map": {
"itemStyle": {
"normal": {
"areaColor": "#f3f3f3",
"borderColor": "#516b91",
"borderWidth": 0.5
},
"emphasis": {
"areaColor": "#a5e7f0",
"borderColor": "#516b91",
"borderWidth": 1
}
},
"label": {
"normal": {
"textStyle": {
"color": "#000"
}
},
"emphasis": {
"textStyle": {
"color": "#516b91"
}
}
}
},
"geo": {
"itemStyle": {
"normal": {
"areaColor": "#f3f3f3",
"borderColor": "#516b91",
"borderWidth": 0.5
},
"emphasis": {
"areaColor": "#a5e7f0",
"borderColor": "#516b91",
"borderWidth": 1
}
},
"label": {
"normal": {
"textStyle": {
"color": "#000"
}
},
"emphasis": {
"textStyle": {
"color": "#516b91"
}
}
}
},
"categoryAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"valueAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"logAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"timeAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"toolbox": {
"iconStyle": {
"normal": {
"borderColor": "#999999"
},
"emphasis": {
"borderColor": "#666666"
}
}
},
"legend": {
"textStyle": {
"color": "#999999"
}
},
"tooltip": {
"axisPointer": {
"lineStyle": {
"color": "#cccccc",
"width": 1
},
"crossStyle": {
"color": "#cccccc",
"width": 1
}
}
},
"timeline": {
"lineStyle": {
"color": "#8fd3e8",
"width": 1
},
"itemStyle": {
"normal": {
"color": "#8fd3e8",
"borderWidth": 1
},
"emphasis": {
"color": "#8fd3e8"
}
},
"controlStyle": {
"normal": {
"color": "#8fd3e8",
"borderColor": "#8fd3e8",
"borderWidth": 0.5
},
"emphasis": {
"color": "#8fd3e8",
"borderColor": "#8fd3e8",
"borderWidth": 0.5
}
},
"checkpointStyle": {
"color": "#8fd3e8",
"borderColor": "rgba(138,124,168,0.37)"
},
"label": {
"normal": {
"textStyle": {
"color": "#8fd3e8"
}
},
"emphasis": {
"textStyle": {
"color": "#8fd3e8"
}
}
}
},
"visualMap": {
"color": [
"#516b91",
"#59c4e6",
"#a5e7f0"
]
},
"dataZoom": {
"backgroundColor": "rgba(0,0,0,0)",
"dataBackgroundColor": "rgba(255,255,255,0.3)",
"fillerColor": "rgba(167,183,204,0.4)",
"handleColor": "#a7b7cc",
"handleSize": "100%",
"textStyle": {
"color": "#333333"
}
},
"markPoint": {
"label": {
"normal": {
"textStyle": {
"color": "#eeeeee"
}
},
"emphasis": {
"textStyle": {
"color": "#eeeeee"
}
}
}
}
});
}));
script>
head>
<body>
<div id="chart">div>
<script>
const chartDom = document.getElementById('chart');
// westeros是设置自定义主题
// svg是底层转化为svg画布,页面可选中了
const chart = echarts.init(chartDom, 'westeros', { renderer: 'svg' });
chart.setOption({
title: {
text: 'ECharts 入门案例'
},
xAxis: {
data: ['食品', '数码', '服饰', '箱包']
},
yAxis: {},
series: {
type: 'bar', // 柱状图
data: [100, 120, 90, 150]
}
});
script>
body>
html>
DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/echarts@4.7.0/dist/echarts.js">script>
<style>
#chart {
width: 800px;
height: 400px;
}
style>
head>
<body>
<div id="chart">div>
<script>
const chartDom = document.getElementById('chart');
const chart = echarts.init(chartDom);
chart.setOption({
dataset: {
source: [
['一季度', 100, 79, '分类1', 50],
['二季度', 112, 81, '分类2', 60],
['三季度', 96, 88, '分类3', 55],
['四季度', 123, 72, '分类4', 70]
]
},
title: {
text: 'ECharts 多系列案例',
subtext: '慕课网数据可视化课程'
},
xAxis: {
data: ['一季度', '二季度', '三季度', '四季度']
},
yAxis: {},
legend: {
data: [{
name: '分类',
icon: 'circle',
textStyle: {
color: 'red'
}
}, '折线图', '柱状图'],
left: 300
},
grid: {
top: 100,
left: '10%',
right: '10%',
bottom: 100
},
toolbox: {
feature: {
saveAsImage: {},
dataZoom: {
yAxisIndex: false
},
restore: {}
}
},
dataZoom: [
{
show: true,
start: 30,
end: 70
}
],
series: [{
name: '分类',
type: 'pie',
center: ['65%', 60],
radius: 35,
encode: { itemName: 3, value: 4 }
}, {
name: '折线图',
type: 'line',
encode: { x: 0, y: 1 }
}, {
name: '柱状图',
type: 'bar',
encode: { x: 0, y: 2 }
}]
});
script>
body>
html>



DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/echarts@4.7.0/dist/echarts.js">script>
<style>
#chart {
width: 800px;
height: 400px;
}
style>
head>
<body>
<div id="chart">div>
<script>
const chartDom = document.getElementById('chart');
const chart = echarts.init(chartDom);
chart.setOption({
xAxis: [{
type: 'category', // 必须指定为category
gridIndex: 0
}, {
type: 'category', // 第二个直角坐标系
gridIndex: 1
}],
yAxis: [{
min: 0, // 限定y轴范围,让画面更好看
max: 100,
gridIndex: 0 // x轴和y轴都要指定grid
}, {
splitLine: {
show: false // 不显示右边坐标轴的线,更好看
},
gridIndex: 0
}, {
min: 0, // 第二个坐标系的
max: 150,
gridIndex: 1
}],
grid: [{ // 两个grid,xAxis的gridIndex对应这里
bottom: '55%' // 分开两个坐标系
}, {
top: '55%' // 第二个坐标系举例顶部55%,两个就相距10%
}],
dataset: {
source: [
['product', '2012', '2013', '2014', '2015'],
['Matcha Latte', 41.1, 30.4, 65.1, 53.3],
['Milk Tea', 86.5, 92.1, 85.7, 83.1]
]
},
series: [{
type: 'bar',
seriesLayoutBy: 'row',
xAxisIndex: 0,
yAxisIndex: 0
}, {
type: 'line',
seriesLayoutBy: 'row', // 设置按行使用数据
xAxisIndex: 0, // 这两个都是0,表示共用第一个x轴
yAxisIndex: 1 // 使用第二行数据
}, {
type: 'bar',
seriesLayoutBy: 'row',
xAxisIndex: 1, // 使用第二个x轴
yAxisIndex: 2
}]
});
script>
body>
html>


NODE_PATH
cnpm i -g @vue/clivue create roy-datav-report-dev,按空格选中


E:\nodeJS\node_global,否则vue命令不能用npm run serve,如果有文件权限问题,可以在文件夹属性设置打开
vue add element,按需引入;启动前可将elint的检查关掉:'indent': 'off'
cnpm i -S echarts,-S表示将依赖加到dependency,方便每次使用,在main.jsimport ECharts from 'echarts' // 直接使用$echarts,不用每次import
Vue.prototype.$echarts = ECharts
"dependencies": {
"core-js": "^3.8.3",
"element-ui": "^2.4.5",
"echarts": "^5.3.3",
"vue": "^2.6.14",
"vue-router": "^3.5.1"
},
<template>
<div id="app">
<router-view/>
div>
template>
<script>
export default {
name: 'app'
}
script>
<style lang="scss">
html, body, #app {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
style>
index.vue<template>
<div class="home">
<top-view />
<sales-view />
<bottom-view />
<map-view />
div>
template>
<script>
import TopView from "../components/TopView"
import SalesView from "../components/SalesView"
import BottomView from "../components/BottomView"
import MapView from "../components/MapView"
export default {
name: 'Home',
components: {
TopView,
SalesView,
BottomView,
MapView
}
}
script>
<style>
.home {
width: 100%;
height: 100%;
padding: 20px;
background: #eee;
}
style>
Card,接下来逐个开发四个component

// element.js
import Vue from 'vue'
import { Card, Row, Col } from 'element-ui'
Vue.use(Card)
Vue.use(Row)
Vue.use(Col)
// index.vue
<template>
<div class="top-view">
<el-row :gutter="20">
<el-col :span="6">
<el-card shadow="hover">
鼠标悬浮显示
el-card>
el-col>
<el-col :span="6">
<el-card shadow="hover">
鼠标悬浮显示
el-card>
el-col>
<el-col :span="6">
<el-card shadow="hover">
鼠标悬浮显示
el-card>
el-col>
<el-col :span="6">
<el-card shadow="hover">
鼠标悬浮显示
el-card>
el-col>
el-row>
div>
template>
<script>
export default {
data () {
return {}
},
methods: {},
}
script>
<style scoped>
style>
// TotalUsers/index.vue,其他三部分同理
<template>
<common-card />
template>
<script>
import CommonCard from '../CommonCard'
export default {
components: {
CommonCard
}
}
script>
<style scoped>
style>
// CommonCard/index.vue
<template>
<div class="common-card">
<div class="title">{{title}}div>
<div class="value">{{value}}div>
<div class="chart">
<slot>slot>
div>
<div class="line" />
<div class="total">
<slot name="footer">slot>
div>
div>
template>
<script>
export default {
// 接收别的组件传过来的数据(在别的组件调用)
props: {
title: String,
value: [String, Number]
}
}
script>
<style lang="scss" scoped>
.title {
font-size: 12px;
color: #999;
}
.value {
font-size: 25px;
color: #000;
margin-top: 5px;
letter-spacing: 1px;
}
.chart {
height: 50px;
}
.line {
margin: 10px 0;
border-top: 1px solid #eee;
}
.total {
font-size: 12px;
color: #666;
}
style>
<style lang="scss">
.emphasis {
margin-left: 5px;
color: #333;
font-weight: 700;
}
.increase {
width: 0;
height: 0;
border-width: 3px;
border-color: transparent transparent red transparent;
border-style: solid;
margin: 0 0 3px 5px;
}
.decrease {
width: 0;
height: 0;
border-width: 3px;
border-color: green transparent transparent transparent;
border-style: solid;
margin: 7px 0 0 5px;
}
style>
// commonCardMixin.js
import CommonCard from '../components/CommonCard/index'
// 这些是TopView中各组件用到的公共代码
export default {
components: {
CommonCard
}
}
<script>
// 在各组件使用
import commonCardMixin from '@/mixins/commonCardMixin';
export default {
mixins: [commonCardMixin]
}
script>
// TopView <- TotalSales/TotalUsers... <- mixin <- CommonCard
props传递数据,使用插槽slot传递标签和数据,使用CSS绘制三角形箭头// TotalSales/index.vue
<template>
<common-card title='累积销售额' value="¥ 666666">
<template>
<div class="compare-wrapper">
<div class="compare">
<span>日同比span>
<span>7.33%span>
<div class="increase">div>
div>
<div class="compare">
<span>月同比span>
<span>7.33%span>
<div class="decrease">div>
div>
div>
template>
<template v-slot:footer>
<span>昨日销售额 span>
<span class="emphasis">¥ 30000span>
template>
common-card>
template>
<script>
import commonCardMixin from '@/mixins/commonCardMixin';
export default {
mixins: [commonCardMixin]
}
script>
<style lang="scss" scoped>
.compare-wrapper {
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
}
.compare {
display: flex;
align-items: center;
font-size: 12px;
margin-top: 3px;
color: #666;
// 下面这些公共样式也放在CommonCard
.increase {
width: 0;
height: 0;
border-width: 5px;
border-color: transparent transparent red transparent;
border-style: solid;
margin: 0 0 3px 5px;
}
.decrease {
width: 0;
height: 0;
border-width: 5px;
border-color: green transparent transparent transparent;
border-style: solid;
margin: 7px 0 0 5px; // 上右下左
}
}
style>

<template>
<common-card title='累积订单量' value="¥ 777777">
<template>
<div id="total-order-chart" :style="{width:'100%', height:'100%'}">div>
template>
<template v-slot:footer>
<span>昨日订单量 span>
<span class="emphasis">¥ 777777span>
template>
common-card>
template>
<script>
import commonCardMixin from '@/mixins/commonCardMixin'
// import commonDataMixin from '@/mixins/commonDataMixin'
export default {
mixins: [commonCardMixin],
mounted() {
const chartDom = document.getElementById('total-order-chart')
const chart = this.$echarts.init(chartDom) // 全局的实例都可以用这个变量
chart.setOption({
xAxis: {
type: 'category', // 分类(不同的柱子)
show: false,
boundaryGap: false // 让chart完全伸展开,占满
},
yAxis: {
show: false // 不显示
},
series: [{
type: 'line', // 折线图
data: [234, 456, 567, 345, 678, 123, 345, 478, 627],
areaStyle: { // 显示面积(填充)
color: 'purple'
},
lineStyle: {
width: 0 // 不显示线
},
itemStyle: {
opacity: 0 // 不显示圈
},
smooth: true // 平滑显示
}],
grid: {
// 顶格显示
top: 0,
bottom: 0,
left: 0,
right: 0
}
})
}
}
script>
<style scoped>
style>
series;这里用到stack合并图<template>
<common-card title='累积用户数' value="¥ 18877">
<template>
<div id="total-users-chart" :style="{width:'100%', height:'100%'}">div>
template>
<template v-slot:footer>
<div class="total-users">
<span>日同比 span>
<span class="emphasis">8.77%span>
<div class="increase">div>
<span>月同比 span>
<span class="emphasis">8.77%span>
<div class="decrease">div>
div>
template>
common-card>
template>
<script>
import commonCardMixin from '@/mixins/commonCardMixin';
export default {
mixins: [commonCardMixin],
mounted() {
const chartDom = document.getElementById('total-users-chart')
const chart = this.$echarts.init(chartDom)
chart.setOption({
color: ['#3398DB'],
// 让x轴放值,y轴作为类别,相当于放倒的柱状图
xAxis: {
type: 'value',
show: false,
},
yAxis: {
type: 'category',
show: false,
},
series: [{
type: 'bar', // 柱状图
data: [207],
stack: '总量', // stack一样的系列可以放在一个柱子上
barWidth: 10, // 柱子的宽度
itemStyle: {
color: '#45c946'
}
},{
type: 'bar',
data: [107],
stack: '总量',
// barWidth: 10 写一个就行
itemStyle: {
color: '#eee'
}
},{
// 绘制那两个三角形
type: 'custom',
data: [207],
stack: '总量',
itemStyle: {
color: '#45c946'
},
renderItem: (param, api) => {
// 查看功能
// console.log(param, api)
// 找到绘制点
const value = api.value(0)
const endPoint = api.coord([value], 0)
// 绘制
return {
type: 'group', // 绘制多个
position: endPoint,
children: [{
type: 'path',
shape: {
// 在矢量图库找到这个参数
d: 'M957.056 338.624C951.84 327.296 940.512 320 928 320L96 320c-12.512 0-23.84 7.296-29.088 18.624-5.216 11.36-3.328 24.704 4.768 34.208l416 485.344c6.08 7.104 14.944 11.2 24.288 11.2s18.208-4.096 24.288-11.2l416-485.344C960.448 363.328 962.272 349.984 957.056 338.624z', // 指定svg图片
x: -5, // 在绘制点的基础上微调
y: -15,
width: 10,
height: 10,
layout: 'cover' // 拉伸填充
},
style: {
fill: 'red'
}
},{
type: 'path',
shape: {
d: 'M952.32 715.2l-416-485.376c-12.16-14.176-36.448-14.176-48.608 0l-416 485.376c-8.128 9.472-9.984 22.848-4.768 34.176C72.16 760.704 83.488 768 96 768l832 0c12.512 0 23.84-7.296 29.056-18.624S960.448 724.672 952.32 715.2z',
x: -5, // 在绘制点的基础上微调
y: 5,
width: 10,
height: 10,
layout: 'center' // 保持原来svg比例
},
style: {
fill: 'red'
}
}
]
}
}
}],
grid: {
// 顶格显示
top: 0,
bottom: 0,
left: 0,
right: 0
}
})
}
}
script>
<style scoped>
.total-users {
display: flex;
/* 垂直居中 */
align-items: center;
}
style>
npm install echarts vue-echarts --force,和之前的依赖有些冲突main.js全局注册import VueEcharts from 'vue-echarts'
// 和prototype有啥区别
Vue.component('v-chart', VueEcharts) // import + export to global
<template>
<div id="app">
<!-- 默认都是100%,用div限制一下 -->
<v-chart :options="data" />
</div>
</template>
<script>
export default {
data() {
return {
data: {
xAxis: {
type: 'category',
},
yAxis: {
},
series: [{
type: 'line', // 折线图
data: [234, 678, 123, 345, 478, 627],
}]
}
}
}
}
</script>
<style scoped>
#app {
height: 300px;
}
</style>
cnpm i -S v-charts,还是依赖ECharts的import Vue from 'vue'
import { VeLine } from "v-charts/lib/line.common";
Vue.component('ve-line', VeLine) // 直接提供组件
<template>
<ve-line
:data="datas"
/>
</template>
<script>
export default {
data () {
return {
datas: {
columns: ['日期', '销售额'],
rows: [
{ '日期': '1月1日', '销售额': 123 },
{ '日期': '1月2日', '销售额': 1223 },
{ '日期': '1月3日', '销售额': 2123 },
{ '日期': '1月4日', '销售额': 4123 },
{ '日期': '1月5日', '销售额': 3123 },
{ '日期': '1月6日', '销售额': 7123 }
]
}
}
}
}
</script>
<style scoped>
</style>
methods,因为后面数据时动态传递的,需要调用方法更新<template>
<common-card title='累积订单量' value="¥ 777777">
<template v-slot:middle>
<v-chart :option="getOptions()">v-chart>
template>
<template v-slot:footer>
<span>昨日订单量 span>
<span class="emphasis">¥ 777777span>
template>
common-card>
template>
<script>
import commonCardMixin from '@/mixins/commonCardMixin'
// import commonDataMixin from '@/mixins/commonDataMixin'
export default {
mixins: [commonCardMixin],
methods: {
getOptions() {
return {
xAxis: {
type: 'category', // 区分data的每个数据
show: false,
boundaryGap: false // 让chart完全伸展开,占满
},
yAxis: {
show: false // 不显示
},
series: [{
type: 'line', // 折线图
data: [234, 456, 567, 345, 678, 123, 345, 478, 627],
areaStyle: { // 显示面积(填充)
color: 'purple'
},
lineStyle: {
width: 0 // 不显示线
},
itemStyle: {
opacity: 0 // 不显示圈
},
smooth: true // 平滑显示
}],
grid: {
// 顶格显示
top: 0,
bottom: 0,
left: 0,
right: 0
}
}
}
}
}
script>
<style scoped>
style>

<template>
<div class="sales-view">
<el-card shadow="hover">
<template v-slot:header>
<div class="menu-wrapper">
<el-menu class="sales-menu" mode="horizontal" :default-active="activeIndex" @select="onMenuSelect">
<el-menu-item index="1">销售额el-menu-item>
<el-menu-item index="2">访问量el-menu-item>
el-menu>
<div class="menu-right">
<el-radio-group v-model="radioSelect">
<el-radio-button label="今日">el-radio-button>
<el-radio-button label="本周">el-radio-button>
<el-radio-button label="本月">el-radio-button>
<el-radio-button label="本年">el-radio-button>
el-radio-group>
<el-date-picker
type="daterange"
v-model="date"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="开始日期"
size="small"
:picker-options="pickerOptions"
unlink-panels
class="sales-picker"
/>
div>
div>
template>
el-card>
div>
template>
<script>
export default {
// data()是默认的方法
data() {
return {
activeIndex: '1',
radioSelect: '今日',
date: null,
pickerOptions: {
// 配置左侧快捷键
shortcuts: [{
text: "最近一周",
onClick(picker) {
const start = new Date()
const end = new Date()
start.setTime(start.getTime() - 3600 * 24 * 1000 * 7) // 毫秒运算
// debugger 开启调试,方便追踪代码,F12继续执行
picker.$emit('pick', [start, end], true) // visiable=true 即选中日期后不关闭框
}
},{
text: "最近一月",
onClick(picker) {
const start = new Date()
const end = new Date()
start.setTime(start.getTime() - 3600 * 24 * 1000 * 30) // 毫秒运算
picker.$emit('pick', [start, end])
}
},{
text: "最近三月",
onClick(picker) {
const start = new Date()
const end = new Date()
start.setTime(start.getTime() - 3600 * 24 * 1000 * 90) // 毫秒运算
picker.$emit('pick', [start, end])
}
}]
}
};
},
methods: {
onMenuSelect(index) {
this.activeIndex = index
console.log(this.activeIndex)
}
}
};
script>
<style lang="scss" scoped>
.sales-view {
margin-top: 20px;
.menu-wrapper {
position: relative;
display: flex;
.sales-menu {
width: 100%;
padding-left: 20px;
.el-menu-item {
height: 50px;
line-height: 50px;
margin: 0 20px;
}
}
.menu-right {
position: absolute;
top: 0;
right: 20px;
height: 50px;
display: flex;
align-items: center;
// 水平方向
justify-content: flex-end;
.sales-picker {
margin-left: 20px;
}
}
}
}
style>
<template>
<div class="sales-view">
<el-card shadow="hover" :body-style="{padding: '0 0 20px 0'}">
<template v-slot:header>
<div class="menu-wrapper">
<el-menu class="sales-menu" mode="horizontal" :default-active="activeIndex" @select="onMenuSelect">
<el-menu-item index="1">销售额el-menu-item>
<el-menu-item index="2">访问量el-menu-item>
el-menu>
<div class="menu-right">
<el-radio-group v-model="radioSelect">
<el-radio-button label="今日">el-radio-button>
<el-radio-button label="本周">el-radio-button>
<el-radio-button label="本月">el-radio-button>
<el-radio-button label="本年">el-radio-button>
el-radio-group>
<el-date-picker
type="daterange"
v-model="date"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="开始日期"
size="small"
:picker-options="pickerOptions"
unlink-panels
class="sales-picker"
/>
div>
div>
template>
<tempate>
<div class="sales-chart-wrapper">
<v-chart :option="chartOption">v-chart>
<div class="sales-list">
<div class="sales-list-title">排行榜div>
<div class="list-item-wrapper">
<div class="list-item" v-for="item in rankData" :key="item.no">
<div class="list-item-no" :class="+item.no <= 3 ? 'top-no' : ''">{{item.no}}div>
<div class="list-item-name">{{item.name}}div>
<div class="list-item-money">{{item.money}}div>
div>
div>
div>
div>
tempate>
el-card>
div>
template>
<script>
export default {
// data()是默认的方法
data() {
return {
activeIndex: '1',
radioSelect: '今日',
date: null,
// element-ui的日期组件参数定义
pickerOptions: {
// 配置左侧快捷键
shortcuts: [{
text: "最近一周",
onClick(picker) {
const start = new Date()
const end = new Date()
start.setTime(start.getTime() - 3600 * 24 * 1000 * 7) // 毫秒运算
// debugger 开启调试,方便追踪代码,F12继续执行
picker.$emit('pick', [start, end], true) // visiable=true 即选中日期后不关闭框
}
},{
text: "最近一月",
onClick(picker) {
const start = new Date()
const end = new Date()
start.setTime(start.getTime() - 3600 * 24 * 1000 * 30) // 毫秒运算
picker.$emit('pick', [start, end])
}
},{
text: "最近三月",
onClick(picker) {
const start = new Date()
const end = new Date()
start.setTime(start.getTime() - 3600 * 24 * 1000 * 90) // 毫秒运算
picker.$emit('pick', [start, end])
}
}]
},
// 右侧数据
rankData: [
{
no: 1,
name: '麦当劳',
money: '666666'
},
{
no: 2,
name: '肯德基',
money: '666666'
},
{
no: 3,
name: '德克士',
money: '666666'
},
{
no: 4,
name: '华莱士',
money: '666666'
},
{
no: 5,
name: '汉堡王',
money: '666666'
},
{
no: 6,
name: '马格格',
money: '666666'
}
],
// 左侧柱状图
chartOption: {
title: {
text: '年度销售额',
textStyle: {
fontSize: 12,
color: '#666',
},
left: 25,
top: 20
},
xAxis: {
type: 'category',
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
axisTick: {
// show: false
alignWithLabel: true, // 坐标轴上的短线放在柱子正下方
lineStyle: {
color: '#999'
}
},
axisLine: {
lineStyle: {
color: '#999'
}
}
},
yAxis: {
axisLine: {
show: false // 坐标轴
},
axisTick: {
show: false // 坐标轴上的小短线
},
splitLine: {
lineStyle: {
type: 'dotted', // 网格线,用点画,浅色
color: '#eee'
}
}
},
series: [{
type: 'bar',
data: [307, 200, 400, 390, 800, 122, 307, 200, 400, 390, 800, 122],
barWidth: '35%',
itemStyle: {
color: '#45c946'
}
}],
grid: {
// 顶格显示
top: 70,
bottom: 50,
left: 60,
right: 60
},
color: ['#3398DB']
}
};
},
methods: {
onMenuSelect(index) {
this.activeIndex = index
console.log(this.activeIndex)
}
}
};
script>
<style lang="scss" scoped>
.sales-view {
margin-top: 20px;
.menu-wrapper {
position: relative;
display: flex;
.sales-menu {
width: 100%;
padding-left: 20px;
.el-menu-item {
height: 50px;
line-height: 50px;
margin: 0 20px;
}
}
.menu-right {
position: absolute;
top: 0;
right: 20px;
height: 50px;
display: flex;
align-items: center;
// 水平方向
justify-content: flex-end;
.sales-picker {
margin-left: 20px;
}
}
}
.sales-chart-wrapper {
display: flex;
height: 270px;
// 左侧的vue-echarts
.echarts {
flex: 0 0 70%;
width: 70%;
height: 100%;
}
// 占据剩余部分
.sales-list {
flex: 1;
width: 100%;
height: 100%;
overflow: hidden; // ?
.sales-list-title {
margin-top: 20px;
font-size: 12px;
color: #666;
font-weight: 500;
}
.list-item-wrapper {
margin-top: 15px;
.list-item {
display: flex; // 序号 内容
align-items: center;
font-size: 12px;
height: 20px;
padding: 6px 20px 6px 0;
.list-item-no {
display: flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
color: #333;
&.top-no {
background: #000;
border-radius: 50%;
color: #fff;
font-weight: 500;
}
}
.list-item-name {
margin-left: 10px;
color: #333;
}
.list-item-money {
flex: 1; // 把剩下的占满
text-align: right;
}
}
}
}
}
}
style>
<template>
<div class="bottom-view">
<div class="view">
<el-card shadow="hover">
<template v-slot:header>
<div class="title-wrapper">
<div class="title">关键词搜索div>
div>
template>
<div class="chart-wrapper">
<div class="chart-inner">
<div class="chart">
<div class="chart-title">搜索用户数div>
<div class="chart-data">93634div>
<v-chart :option="searchUserOption">v-chart>
div>
<div class="chart">
<div class="chart-title">搜索量div>
<div class="chart-data">12345div>
<v-chart :option="searchUserOption">v-chart>
div>
div>
<div class="table-wrapper">
<el-table :data="tableData">
<el-table-column prop="rank" label="排名" width="180">el-table-column>
<el-table-column prop="keyword" label="地区" width="180">el-table-column>
<el-table-column prop="count" label="数量" width="180">el-table-column>
<el-table-column prop="users" label="用户" width="180">el-table-column>
el-table>
<el-pagination layout="prev, pager, next" :total="100" :page-size=4 background @current-change="onPageChange">el-pagination>
div>
div>
el-card>
div>
<div class="view">
<el-card shadow="hover">
<template v-slot:header>
<div class="title-wrapper">
<div class="title">分类销售排行div>
<div class="radio-wrapper">
<el-radio-group v-model="radioSelect" size="small">
<el-radio-button label="品类">el-radio-button>
<el-radio-button label="商品">el-radio-button>
el-radio-group>
div>
div>
template>
<template>
<div class="chart-wrapper">
<v-chart :option="categoryOption">v-chart>
div>
template>
el-card>
div>
div>
template>
<script>
export default {
data () {
return {
radioSelect: '品类',
searchUserOption: {
xAxis: {
type: 'category',
boundaryGap: false
},
yAxis: {
show: false,
min: 0,
max: 800 // 设计一个算法找到最大值
},
series: [{
type: 'line',
areaStyle: {
color: 'rgba(95, 187, 255, .5)'
},
data: [307, 200, 400, 390, 800, 122, 307, 200, 400, 390, 800, 122],
lineStyle: {
color: 'rgba(95, 187, 255, .5)'
},
}],
grid: {
// 顶格显示
top: 0,
bottom: 0,
left: 0,
right: 0
},
color: ['#3398DB']
},
// searchNumOption: {
// },
tableData: [
{id:1, rank:1, keyword:'北京', count:100, users:90, range:'90%'},
{id:1, rank:2, keyword:'宁夏', count:100, users:90, range:'90%'},
{id:1, rank:3, keyword:'北京', count:100, users:90, range:'90%'},
{id:1, rank:4, keyword:'北京', count:100, users:90, range:'90%'},
{id:1, rank:5, keyword:'北京', count:100, users:90, range:'90%'},
],
categoryOption: {
// 这里不定义,放在renderPieChart,在mounted调用
// 新的方式吧
},
}
},
methods: {
onPageChange(page) {
},
// 右侧饼图定制
// 因为有数据和图,在这里统一封装
renderPieChart() {
const mockData = [
{
// 这些字段名是定义好的,series-data会来取,不能随便定义
legendname: '粥和鸡蛋',
value: 20,
percent: '20%',
itemStyle: {
color: '#8d7fec'
},
name: '粥和鸡蛋 | 20%', // 单独在右边的图例
},
{
legendname: '简餐便当',
value: 20,
percent: '20%',
name: '简餐便当 | 20%',
},
{
legendname: '面条米饭',
value: 20,
percent: '20%',
name: '面条米饭 | 20%',
},
{
legendname: '牛奶面包',
value: 20,
percent: '20%',
name: '牛奶面包 | 20%',
},
{
legendname: '酱牛肉',
value: 20,
percent: '20%',
name: '酱牛肉 | 20%',
},
]
this.categoryOption = {
title: [
{
text: '品类分布',
textStyle: {
fontSize: 14,
color: '#666',
},
left: 20,
top: 20
},
{
// 展示在圆环中
text: '累积订单量',
subtext: '320', // 副标题
x: '29%',
y: '45%',
textAlign: 'center',
textStyle: {
fontSize: 12,
color: '#666',
},
subtextStyle: {
fontSize: 24,
color: '#666',
},
}
],
series: [{
name: '品类分布', // 多个图标可以通过name区分
type: 'pie',
data: mockData,
label: {
normal: {
show: true,
poaition: 'outter', // 让介绍文字在外侧
formatter: function(params) {
return `${params.data.legendname} | ${params.data.percent}`
}
}
},
center: ['30%', '50%'], // 放到原图宽度的30%处,即左移;或者canvas的某个位置,传数字
// 环形饼图
radius: ['45%', '60%'], // 内半径,外半径(用canvas宽/高的较小值来算)
labelLine: {
// 靠近环的是线段1
normal: {
length: 5,
length2: 3,
smooth: true
}
},
clockwise: false, // 逆时针展示数据
itemStyle: {
borderWidth: 3,
borderColor: '#fff'
}
}],
legend: {
type: 'scroll',
orient: 'vertical',
height: 250, // 大概能显示5行legend,多出去了会出现箭头
left: '70%', // canvas的70%
top: 'middle',
textStyle: {
fontSize: 12,
color: '#8c8c8c',
},
},
// 弹层(鼠标放在饼图上弹出来的信息)
tooltip: {
trigger: 'item',
// 格式定制
formatter: function(params) {
// console.log(params)
const str = params.seriesName + '
' + params.marker + params.data.legendname + '
' + '数量' +
params.data.value + '
' + '占比' + params.data.percent
return str
},
}
}
}
},
mounted() {
this.renderPieChart()
}
}
script>
<style lang="scss" scoped>
.bottom-view {
display: flex;
margin-top: 20px;
background-color: #eee;
.view {
/* 占满 */
flex: 1;
width: 50%;
&:first-child {
padding: 0 10px 0 0 ;
}
&:last-child {
padding: 0 0 0 10px;
}
.title-wrapper {
display: flex;
align-items: center;
height: 60px;
box-sizing: border-box;
border-bottom: 1px solid #eee;
font-size: 14px;
font-weight: 500;
padding: 0 0 0 20px;
.radio-wrapper {
flex: 1;
display: flex;
justify-content: flex-end;
padding-right: 20px;
}
}
// 避免混乱,可以先在这里写嵌套关系
.chart-wrapper {
display: flex;
flex-direction: column;
height: 452px;
.chart-inner {
display: flex;
// 上下 左右
padding: 0 10px;
margin-top: 10px;
.chart {
flex:1;
padding: 0 10px;
.chart-title {
color: #999;
font-size: 14px;
}
.chart-data {
font-size: 20px;
color: #333;
font-weight: 500;
letter-spacing: 2px;
}
.echarts {
height: 50px;
}
}
}
.table-wrapper {
flex:1;
margin-top: 20px;
padding: 0 10px 10px;
.el-pagination {
display: flex;
justify-content: center;
margin-top: 10px;
}
}
}
}
}
style>