diff --git a/src/components/GanttLinks.vue b/src/components/GanttLinks.vue index a5523cc..e796395 100644 --- a/src/components/GanttLinks.vue +++ b/src/components/GanttLinks.vue @@ -3,6 +3,15 @@ import { ref, watch, nextTick, onMounted, onUnmounted } from 'vue' import type { Task } from '../models/classes/Task' import { getPredecessorIds } from '../utils/predecessorUtils' +// uni-app 类型声明 +declare global { + interface Window { + uni?: { + createCanvasContext: (canvasId: string) => CanvasRenderingContext2D & { draw?: () => void } + } + } +} + // 定义 TaskBar 位置信息类型 interface TaskBarPosition { left: number @@ -65,25 +74,39 @@ const drawLinks = () => { const canvas = canvasRef.value if (!canvas) return - const ctx = canvas.getContext('2d', { alpha: true }) + // 判断是否在 uni-app 环境中 + const isUniApp = typeof window !== 'undefined' && window.uni + let ctx: (CanvasRenderingContext2D & { draw?: () => void }) | null = null + + if (isUniApp && window.uni) { + // uni-app 环境:使用 uni.createCanvasContext + // https://uniapp.dcloud.net.cn/component/canvas.html + // 这儿存在一个问题:如果一个应用多个gantt视图会存在id冲突问题,所以后期可以加上一个配置,外部传入canvas-id + ctx = window.uni.createCanvasContext('gantt-link-canvas') + } else { + // Web 环境:使用标准 Canvas API + ctx = canvas.getContext('2d', { alpha: true }) + } + if (!ctx) { // eslint-disable-next-line no-console console.error('❌ Canvas context 获取失败,可能是尺寸超限') return } - // 适配高清屏(Retina) - const dpr = window.devicePixelRatio || 1 const displayWidth = props.width const displayHeight = props.height - // 只在尺寸变化时更新 canvas 尺寸 - const pixelWidth = displayWidth * dpr - const pixelHeight = displayHeight * dpr - if (canvas.width !== pixelWidth || canvas.height !== pixelHeight) { - canvas.width = pixelWidth - canvas.height = pixelHeight - ctx.scale(dpr, dpr) + // Web 环境才需要手动处理 DPR(uni-app 通过 hidpi 属性自动处理) + if (!isUniApp) { + const dpr = window.devicePixelRatio || 1 + const pixelWidth = displayWidth * dpr + const pixelHeight = displayHeight * dpr + if (canvas.width !== pixelWidth || canvas.height !== pixelHeight) { + canvas.width = pixelWidth + canvas.height = pixelHeight + ctx.scale(dpr, dpr) + } } // 清空画布(透明) @@ -311,6 +334,11 @@ const drawLinks = () => { // 恢复透明度 ctx.globalAlpha = 1 } + + // uni-app 环境需要调用 draw() 方法将绘制内容渲染到画布 + if (isUniApp && ctx?.draw) { + ctx.draw() + } } /** @@ -390,7 +418,7 @@ watch( // 组件挂载后初始化绘制 onMounted(() => { // 监听主题变化 - themeObserver = new MutationObserver((mutations) => { + themeObserver = new MutationObserver(mutations => { for (const mutation of mutations) { if (mutation.attributeName === 'data-theme') { updateTheme() @@ -433,14 +461,16 @@ defineExpose({