|
|
@ -1,13 +1,12 @@ |
|
|
|
<template> |
|
|
|
<div class="m-chart"> |
|
|
|
<canvas :id="id" :width="width" :height="height" /> |
|
|
|
<div :id="id" style="width: 400px; height: 200px"></div> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
<script> |
|
|
|
import nextTick from "dai-js/tools/nextTick"; |
|
|
|
import F2 from "@antv/f2/lib/index-all"; |
|
|
|
|
|
|
|
import * as echarts from "echarts"; |
|
|
|
// ios下字体渲染有bug |
|
|
|
const fontFamily = "PingFang SC"; |
|
|
|
const fontSize = 14; |
|
|
@ -16,195 +15,6 @@ let id = "myChart" + new Date().getDate(); |
|
|
|
let chart; |
|
|
|
let srcData = []; |
|
|
|
|
|
|
|
let textShapeList = []; |
|
|
|
const addTextShape = () => { |
|
|
|
if (textShapeList.length > 0) { |
|
|
|
textShapeList.forEach((item) => { |
|
|
|
item.remove(true); |
|
|
|
}); |
|
|
|
textShapeList = []; |
|
|
|
} |
|
|
|
// 添加折线上文本 |
|
|
|
const canvas = chart.get("canvas"); |
|
|
|
const group = canvas.addGroup(); |
|
|
|
const shapes = {}; |
|
|
|
|
|
|
|
function addFn(list) { |
|
|
|
const listLength = list.length; |
|
|
|
list.forEach(function (obj, index) { |
|
|
|
// 避免显示太多,乱七八糟 |
|
|
|
if (listLength > 7 && index > 0 && index < listLength - 1) { |
|
|
|
if (index % Math.ceil(listLength / 5) != 0) { |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const offsetX = 6; |
|
|
|
const offsetY = 1; |
|
|
|
const point = chart.getPosition(obj); |
|
|
|
const text = group.addShape("text", { |
|
|
|
attrs: { |
|
|
|
x: obj.type === "支持" ? point.x + 2 * offsetX : point.x - offsetX, |
|
|
|
y: point.y + offsetY, |
|
|
|
text: obj.value, |
|
|
|
textAlign: "center", |
|
|
|
textBaseline: "bottom", |
|
|
|
fill: "#333", |
|
|
|
fontWeight: 500, |
|
|
|
fontFamily, |
|
|
|
fontSize, |
|
|
|
}, |
|
|
|
}); |
|
|
|
|
|
|
|
textShapeList.push(text); // 缓存该 shape, 便于后续查找 |
|
|
|
}); |
|
|
|
} |
|
|
|
srcData.sort((a, b) => { |
|
|
|
return new Date(a.date).getTime() - new Date(b.date).getTime(); |
|
|
|
}); |
|
|
|
let supData = srcData.filter((item) => item.type == "支持"); |
|
|
|
let oppData = srcData.filter((item) => item.type == "反对"); |
|
|
|
addFn(supData); |
|
|
|
addFn(oppData); |
|
|
|
}; |
|
|
|
|
|
|
|
const iniChart = function (config, srcData) { |
|
|
|
chart = new F2.Chart({ |
|
|
|
id, |
|
|
|
...config, |
|
|
|
}); |
|
|
|
|
|
|
|
const supColor = "#FFDA0E"; |
|
|
|
const oppColor = "#00E5ED"; |
|
|
|
|
|
|
|
chart.source(srcData, { |
|
|
|
date: { |
|
|
|
range: [0, 1], |
|
|
|
type: "timeCat", |
|
|
|
mask: "MM-DD", |
|
|
|
}, |
|
|
|
value: { |
|
|
|
// type: "linear", |
|
|
|
}, |
|
|
|
}); |
|
|
|
|
|
|
|
// 设置坐标轴 |
|
|
|
chart.axis("date", { |
|
|
|
line: { |
|
|
|
lineWidth: 1, |
|
|
|
stroke: "#E7EEEE", |
|
|
|
}, |
|
|
|
label: { |
|
|
|
fontWeight: 500, |
|
|
|
fontSize, |
|
|
|
fill: "#B5B7BF", |
|
|
|
textBaseline: "middle", |
|
|
|
}, |
|
|
|
labelOffset: 25, |
|
|
|
country: { |
|
|
|
range: [0.1, 0.9], // 配置 range 范围,使左右两边不留边距 |
|
|
|
}, |
|
|
|
grid: null, |
|
|
|
}); |
|
|
|
chart.axis("value", { |
|
|
|
line: { |
|
|
|
lineWidth: 1, |
|
|
|
stroke: "#E7EEEE", |
|
|
|
}, |
|
|
|
labelOffset: 20, |
|
|
|
label: { |
|
|
|
fontWeight: 500, |
|
|
|
fontSize, |
|
|
|
fill: "#B5B7BF", |
|
|
|
}, |
|
|
|
}); |
|
|
|
chart.tooltip({ |
|
|
|
custom: true, // 是否自定义 tooltip 提示框 |
|
|
|
showXTip: true, // 是否展示 X 轴的辅助信息 |
|
|
|
showYTip: true, // 是否展示 Y 轴的辅助信息 |
|
|
|
snap: true, // 是否将辅助线准确定位至数据点 |
|
|
|
crosshairsType: "xy", // 辅助线的种类 |
|
|
|
crosshairsStyle: { |
|
|
|
// 配置辅助线的样式 |
|
|
|
lineDash: [2], // 点线的密度 |
|
|
|
stroke: "rgba(255, 0, 0, 0.25)", |
|
|
|
lineWidth: 20, |
|
|
|
}, |
|
|
|
}); |
|
|
|
// 类别标识区 |
|
|
|
chart.legend({ |
|
|
|
position: "bottom", |
|
|
|
align: "center", |
|
|
|
offsetY: -30, |
|
|
|
custom: true, |
|
|
|
nameStyle: { |
|
|
|
fill: "#999", |
|
|
|
fontWeight: 500, |
|
|
|
fontSize, |
|
|
|
}, |
|
|
|
itemWidth: 150, |
|
|
|
wordSpace: 25, |
|
|
|
items: [ |
|
|
|
{ |
|
|
|
name: "支持", |
|
|
|
marker(x, y, r, ctx) { |
|
|
|
ctx.lineWidth = 10; |
|
|
|
ctx.strokeStyle = supColor; |
|
|
|
ctx.moveTo(x - r - 15, y); |
|
|
|
ctx.lineTo(x + r + 15, y); |
|
|
|
ctx.stroke(); |
|
|
|
ctx.fill(); |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "反对", |
|
|
|
marker(x, y, r, ctx) { |
|
|
|
ctx.lineWidth = 10; |
|
|
|
ctx.strokeStyle = oppColor; |
|
|
|
ctx.moveTo(x - r - 15, y); |
|
|
|
ctx.lineTo(x + r + 15, y); |
|
|
|
ctx.stroke(); |
|
|
|
ctx.fill(); |
|
|
|
}, |
|
|
|
}, |
|
|
|
], |
|
|
|
}); |
|
|
|
// 添加折线 |
|
|
|
// chart.tooltip({ |
|
|
|
// showCrosshairs: true, // 展示 Tooltip 辅助线 |
|
|
|
// shared: true, |
|
|
|
// }); |
|
|
|
// // new Add -- 监听 tooltip:change 事件 |
|
|
|
// chart.on('tooltip:change', ev => { |
|
|
|
// // 自己可以在控制台打印一下ev,看下里面的结构,找到自己所需要的信息 |
|
|
|
// hoverData = ev.data.items[0].data; |
|
|
|
// }) |
|
|
|
// // new Add -- 监听绘图区plot的点击事件 |
|
|
|
// chart.on('plot:click', ev => { |
|
|
|
// // 当用户在画布上点击时,这个时候用户看到tooltip上的数据其实已经被存在了hoverData里。拿到hoverData,相当于你拿到了折线上相关点的数据,之后再有什么需求都可以实现啦! |
|
|
|
// console.log(JSON.stringify(hoverData)); |
|
|
|
// }) |
|
|
|
|
|
|
|
chart |
|
|
|
.line() |
|
|
|
.position("date*value") |
|
|
|
.color("type", (type) => { |
|
|
|
if (type === "支持") { |
|
|
|
return supColor; |
|
|
|
} |
|
|
|
return oppColor; |
|
|
|
}) |
|
|
|
.style("type", { |
|
|
|
lineWidth: 1, |
|
|
|
}) |
|
|
|
.animate(); |
|
|
|
chart.render(); |
|
|
|
addTextShape(); |
|
|
|
|
|
|
|
// 注意:需要把chart return 出来 |
|
|
|
return chart; |
|
|
|
}; |
|
|
|
|
|
|
|
export default { |
|
|
|
name: "chart", |
|
|
|
props: { |
|
|
@ -237,25 +47,121 @@ export default { |
|
|
|
}, |
|
|
|
watch: { |
|
|
|
list(data) { |
|
|
|
chart.changeData(data); |
|
|
|
this.initCharts(); |
|
|
|
srcData = data; |
|
|
|
addTextShape(); |
|
|
|
}, |
|
|
|
}, |
|
|
|
async created() { |
|
|
|
await nextTick(200); |
|
|
|
console.log(this.config, "config"); |
|
|
|
console.log(this.list, "list"); |
|
|
|
iniChart(this.config, this.list); |
|
|
|
|
|
|
|
//在这里调用初始化图表的方法 |
|
|
|
await nextTick(200); |
|
|
|
this.iniLoading = true; |
|
|
|
}, |
|
|
|
|
|
|
|
mounted() { |
|
|
|
console.log(this.config, "config"); |
|
|
|
console.log(this.list, "list"); |
|
|
|
let date = this.list |
|
|
|
.filter((item) => item.type == "支持") |
|
|
|
.map((item) => item.date); |
|
|
|
let data = this.list |
|
|
|
.filter((item) => item.type == "支持") |
|
|
|
.map((item) => item.value); |
|
|
|
let data1 = this.list |
|
|
|
.filter((item) => item.type == "反对") |
|
|
|
.map((item) => item.value); |
|
|
|
console.log(data); |
|
|
|
nextTick(1000); |
|
|
|
this.initCharts(date, data, data1); |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
setList(data) { |
|
|
|
chart.changeData(data); |
|
|
|
srcData = data; |
|
|
|
addTextShape(); |
|
|
|
// date x轴时间 data支持人数 data1 反对人数 |
|
|
|
initCharts(date, data, data1) { |
|
|
|
console.log(this.id); |
|
|
|
let div = document.getElementById(this.id); |
|
|
|
let myChart = echarts.init(div); |
|
|
|
var option = { |
|
|
|
tooltip: { |
|
|
|
trigger: "axis", |
|
|
|
}, |
|
|
|
legend: { |
|
|
|
data: ["支持", "反对"], |
|
|
|
}, |
|
|
|
grid: { |
|
|
|
left: "3%", |
|
|
|
right: "4%", |
|
|
|
bottom: "3%", |
|
|
|
containLabel: true, |
|
|
|
}, |
|
|
|
toolbox: { |
|
|
|
feature: { |
|
|
|
saveAsImage: {}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
dataZoom: [ |
|
|
|
{ |
|
|
|
type: 'slider', |
|
|
|
realtime: true, |
|
|
|
start: 0, |
|
|
|
// end: 20, // 数据窗口范围的结束百分比。范围是:0 ~ 100。 |
|
|
|
height: 5, //组件高度 |
|
|
|
left: '25%', //左边的距离 |
|
|
|
right: '25%', //右边的距离 |
|
|
|
bottom: '12%', //下边的距离 |
|
|
|
show: true, // 是否展示 |
|
|
|
fillerColor: "rgba(2,110,252,1)", // 滚动条颜色 |
|
|
|
borderColor: "rgba(17, 100, 210, 0.12)", |
|
|
|
backgroundColor: 'rgba(232,244,255,0.51)',//两边未选中的滑动条区域的颜色 |
|
|
|
handleSize: 0, //两边手柄尺寸 |
|
|
|
showDetail: false, //拖拽时是否展示滚动条两侧的文字 |
|
|
|
zoomLock: true, //是否只平移不缩放 |
|
|
|
moveOnMouseMove: false, //鼠标移动能触发数据窗口平移 |
|
|
|
//zoomOnMouseWheel: false, //鼠标移动能触发数据窗口缩放 |
|
|
|
|
|
|
|
//下面是自己发现的一个问题,当点击滚动条横向拖拽拉长滚动条时,会出现文字重叠,导致效果很不好,以此用下面四个属性进行设置,当拖拽时,始终保持显示六个柱状图,可结合自己情况进行设置。添加这个属性前后的对比见**图二** |
|
|
|
startValue: 0, // 从头开始。 |
|
|
|
endValue: 3, // 最多5个 |
|
|
|
// minValueSpan: 5, // 放大到最少几个 |
|
|
|
// maxValueSpan: 5, // 缩小到最多几个 |
|
|
|
}, |
|
|
|
{ |
|
|
|
type: "inside", // 支持内部鼠标滚动平移 |
|
|
|
start: 0, |
|
|
|
// end: 20, |
|
|
|
startValue: 0, // 从头开始。 |
|
|
|
endValue: 5, // 最多5个 |
|
|
|
zoomOnMouseWheel: false, // 关闭滚轮缩放 |
|
|
|
moveOnMouseWheel: true, // 开启滚轮平移 |
|
|
|
moveOnMouseMove: true // 鼠标移动能触发数据窗口平移 |
|
|
|
} |
|
|
|
], |
|
|
|
xAxis: { |
|
|
|
type: "category", |
|
|
|
boundaryGap: false, |
|
|
|
data: date, |
|
|
|
}, |
|
|
|
yAxis: { |
|
|
|
type: "value", |
|
|
|
minInterval: "1", |
|
|
|
}, |
|
|
|
series: [ |
|
|
|
{ |
|
|
|
name: "支持", |
|
|
|
type: "line", |
|
|
|
|
|
|
|
data: data, |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "反对", |
|
|
|
type: "line", |
|
|
|
|
|
|
|
data: data1, |
|
|
|
}, |
|
|
|
], |
|
|
|
}; |
|
|
|
myChart.setOption(option); |
|
|
|
window.addEventListener("resize", () => myChartPieLeft.resize(), false); |
|
|
|
}, |
|
|
|
}, |
|
|
|
}; |
|
|
|