import computedBehavior from "@npm/dai-mp/mixins/computed-component/index.js"; import { getNodeRect, nextTick } from "@utils/tools"; const app = getApp(); const systemInfo = wx.getSystemInfoSync(); const radio = systemInfo.windowWidth / 750; const isIos = systemInfo.platform === "ios"; // ios下字体渲染有bug const fontFamily = isIos ? "sans-serif" : "PingFang SC"; const fontSize = 20 * radio; let chart = null; let canvas = null; 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 * radio; const offsetY = 1 * radio; 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 onInitChart = (F2, config) => { F2.Global.fontFamily = fontFamily; F2.Global.fontSize = fontSize; chart = new F2.Chart({ pixelRatio: radio, ...config, }); const supColor = "#0C4A9D"; const oppColor = "#CB3B30"; chart.source(srcData, { date: { range: [0, 1], type: "timeCat", mask: "MM-DD", }, value: { // type: "linear", }, }); // 设置坐标轴 chart.axis("date", { line: { lineWidth: 1 * radio, stroke: "#E7EEEE", }, label: { fontWeight: 500, fontSize, fill: "#B5B7BF", textBaseline: "middle", }, labelOffset: 25 * radio, country: { range: [0.1, 0.9], // 配置 range 范围,使左右两边不留边距 }, grid: null, }); chart.axis("value", { line: { lineWidth: 1 * radio, stroke: "#E7EEEE", }, labelOffset: 20 * radio, label: { fontWeight: 500, fontSize, fill: "#B5B7BF", }, }); // 类别标识区 chart.legend({ position: "bottom", align: "center", offsetY: -30 * radio, custom: true, nameStyle: { fill: "#999", fontWeight: 500, fontSize, }, itemWidth: 150 * radio, wordSpace: 25 * radio, items: [ { name: "支持", marker(x, y, r, ctx) { ctx.lineWidth = 10 * radio; ctx.strokeStyle = supColor; ctx.moveTo(x - r - 15 * radio, y); ctx.lineTo(x + r + 15 * radio, y); ctx.stroke(); ctx.fill(); }, }, { name: "反对", marker(x, y, r, ctx) { ctx.lineWidth = 10 * radio; ctx.strokeStyle = oppColor; ctx.moveTo(x - r - 15 * radio, y); ctx.lineTo(x + r + 15 * radio, y); ctx.stroke(); ctx.fill(); }, }, ], }); // 添加折线 chart .line() .position("date*value") .color("type", (type) => { if (type === "支持") { return supColor; } return oppColor; }) .style("type", { lineWidth: 1, }) .animate(); // chart.interaction("pan"); chart.render(); addTextShape(); // 注意:需要把chart return 出来 return chart; }; Component({ behaviors: [computedBehavior], properties: { canvasId: { type: String, value: "canvas", }, srcData: { type: Array, value: [], }, }, data: { iniLoaded: false, opts: { width: 0, height: 0, }, onInitChart, }, computed: {}, watch: { srcData(arr) { if (Array.isArray(arr) && arr.length > 0) { this.updateData(arr); } }, }, lifetimes: { async ready() { await nextTick(100); this.init([ { value: 0, type: "支持", date: "0000-01-01" }, { value: 0, type: "反对", date: "0000-01-01" }, ]); }, detached() {}, }, pageLifetimes: { show() {}, hide() {}, }, methods: { async init(data = []) { const { width, height } = await getNodeRect("chart", this); const { opts } = this.data; opts.width = width; opts.height = height; this.setData({ opts, }); srcData = data; this.setData({ iniLoaded: true, }); console.log("折线图组件初始化完毕"); }, async updateData(data) { while (!this.data.iniLoaded || !chart) { await nextTick(100); } chart.changeData(data); srcData = data; addTextShape(); }, }, });