Appearance
使用 SVG 在 Taro 小程序中简单作图

如图,就这么简单个东西。要在 Taro 的小程序上画个曲线。
一开始研究的方向是给小程序里内置 ECharts,问了 AI,搜了 Github,最后找到了 echarts4taro3。鼓捣半天,死活都报错。
后来换了研究方向,我干嘛不直接生成 svg,当成图片画上去呢。
js
import Taro from '@tarojs/taro'
export const generateSvgCurve = (dataList) => {
// 1. 定义画布基础尺寸
const width = 300;
const height = 120;
const padding = 15;
// 2. 映射 X 轴和 Y 轴的坐标
const xStep = (width - padding * 2) / 6;
const amounts = dataList.map(item => item.amount || 0);
const maxAmount = Math.max(...amounts, 1);
const minAmount = Math.min(...amounts, 0);
const range = maxAmount - minAmount;
const points = dataList.map((item, index) => {
const x = padding + index * xStep;
const ratio = range === 0 ? 0.5 : (item.amount - minAmount) / range;
const y = height - padding - ratio * (height - padding * 2);
return { x, y };
});
// 3. 使用贝塞尔控制点让折线变弯
let pathData = `M ${points[0].x} ${points[0].y}`;
for (let i = 0; i < points.length - 1; i++) {
const p0 = points[i];
const p1 = points[i + 1];
const cpX1 = p0.x + xStep / 2;
const cpY1 = p0.y;
const cpX2 = p1.x - xStep / 2;
const cpY2 = p1.y;
pathData += ` C ${cpX1} ${cpY1}, ${cpX2} ${cpY2}, ${p1.x} ${p1.y}`;
}
const lastPoint = points[points.length - 1];
// 4. 🌟 核心修改:把里面的 %23 全部恢复成标准的 # 号
// 在 Base64 方案下,标准的 # 号才是对的,并且不需要任何正则压缩处理
const svgHtml = `<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 ${width} ${height}' width='100%' height='100%'><path d='${pathData}' fill='none' stroke='#9bc88d' stroke-width='3' stroke-linecap='round' /><circle cx='${lastPoint.x}' cy='${lastPoint.y}' r='5' fill='#ff9244' /></svg>`;
// 5. 传入 Taro 原生转换
const uint8Array = new TextEncoder().encode(svgHtml);
const base64Data = Taro.arrayBufferToBase64(uint8Array.buffer);
return `data:image/svg+xml;base64,${base64Data}`;
};vue
<script setup>
const svgSrc = ref('')
const initChart = (originData = [{ amount: 0 }, { amount: 0 }, { amount: 0 }, { amount: 0 }, { amount: 0 }, { amount: 0 }, { amount: 0 }]) => {
const isAllZero = originData.every(item => item.amount === 0);
let renderData = [...originData];
if (isAllZero) {
const mockWaves = [10, 11, 13, 12, 11, 12, 10];
renderData = originData.map((item, index) => ({
...item,
amount: mockWaves[index]
}));
}
// 生成 SVG 链接
svgSrc.value = generateSvgCurve(renderData);
};
</script>
<template>
<image class="recently7-graph" :src="svgSrc" mode="contain"></image>
</template>完事。
