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) { return; // 避免显示太多,乱七八糟 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 aData = srcData.filter((item) => item.type == "组织活动次数"); let bData = srcData.filter((item) => item.type == "应参加活动次数"); let cData = srcData.filter((item) => item.type == "活动签到次数"); addFn(aData); addFn(bData); addFn(cData); }; const onInitChart = (F2, config) => { F2.Global.fontFamily = fontFamily; F2.Global.fontSize = fontSize; chart = new F2.Chart({ pixelRatio: radio, padding: [50, 20, 30, "auto"], ...config, }); const aColor = "#2F93EE"; const bColor = "#F56923"; const cColor = "#FAAA05"; chart.source(srcData, { date: { range: [0, 1], type: "timeCat", tickCount: 12, mask: "MM月", }, value: { // type: "linear", }, }); // 设置坐标轴 chart.axis("date", { line: { lineWidth: 1 * radio, stroke: "#E7EEEE", }, label: { rotate: -Math.PI / 6, fontWeight: 500, fontSize, fill: "#B5B7BF", textBaseline: "middle", }, labelOffset: 35 * 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(false); // 添加折线 chart .line() .position("date*value") .color("type", (type) => { if (type === "组织活动次数") { return aColor; } else if (type === "应参加活动次数") { return bColor; } else { return cColor; } }) .style("type", { lineWidth: 1, }) .animate(); chart .point() .position("date*value") .color("type", (type) => { if (type === "组织活动次数") { return aColor; } else if (type === "应参加活动次数") { return bColor; } else { return cColor; } }) .style({ lineWidth: 0.5, fillOpacity: 0.65, }); // 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(); }, }, });