From 427a5f816a4c3b45adbb5c0874eb1b22b7bbcc9e Mon Sep 17 00:00:00 2001 From: qiuchengw Date: Mon, 1 Dec 2025 18:29:49 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=80=82=E9=85=8Duniapp?= =?UTF-8?q?=E5=BC=80=E5=8F=91=EF=BC=88=E7=9B=B4=E6=8E=A5workspace=E5=B5=8C?= =?UTF-8?q?=E5=85=A5=E7=BC=96=E8=AF=91=E6=A8=A1=E5=BC=8F=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/GanttLinks.vue | 58 ++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 14 deletions(-) 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({