uni-app vue3 APP版本 在uni-popup组件中第二次弹出时canvas不生效

uni-app vue3 APP版本 在uni-popup组件中第二次弹出时canvas不生效

操作步骤:

如上

预期结果:

如上

实际结果:

如上

bug描述:

vue2的app版本和vue3的H5版本均正常。

复制官方曾经在github上面提供的代码也有概率会失败!!!

https://github.com/dcloudio/uni-ui/issues/232

信息类别 信息内容
产品分类 uniapp/App
PC开发环境 Windows
PC开发环境版本 win11
HBuilderX类型 正式
HBuilderX版本 3.4.7
手机系统 Android
手机系统版本 Android 11
手机厂商 小米
手机机型 多个
页面类型 vue
vue版本 vue3
打包方式 云端
项目创建方式 HBuilderX

bug.zip

14 回复

@DCloud_UNI_GSQ 好些天了,又看到吗?


亲,你的这个问题解决了吗?今天我也发现了这个问题,h5上测试没问题,app上有问题

<template> <view class=""> <button [@click](/user/click)="open">打开弹窗</button> <uni-popup ref="popup" type="bottom"> <canvas style="width: 300px; height: 200px;" canvas-id="firstCanvas" id="firstCanvas"></canvas> </uni-popup> </view> </template> <script> export default { data() { return { } }, onLoad() { }, methods: { open() { this.$refs.popup.open() setTimeout(() => { this.draw() }, 500) }, draw() { var context = uni.createCanvasContext('firstCanvas')
        context.setStrokeStyle("#00ff00")  
        context.setLineWidth(5)  
        context.rect(0, 0, 200, 200)  
        context.stroke()  
        context.setStrokeStyle("#ff0000")  
        context.setLineWidth(2)  
        context.moveTo(160, 100)  
        context.arc(100, 100, 60, 0, 2 * Math.PI, true)  
        context.moveTo(140, 100)  
        context.arc(100, 100, 40, 0, Math.PI, false)  
        context.moveTo(85, 80)  
        context.arc(80, 80, 5, 0, 2 * Math.PI, true)  
        context.moveTo(125, 80)  
        context.arc(120, 80, 5, 0, 2 * Math.PI, true)  
        context.stroke()  
        context.draw()  
    }  
}  

}
</script>

请上传一个能重现问题的测试工程

已经上传,但是其实就是直接复制的你们github上面提供的代码

@五块钱的果汁 已经上传工程

最近官方在忙什么吗?

测了一下,确实会存在。 临时解决方案:在打开和关闭的时候给canvas加vif控制一下 <canvas v-if="show" style="width: 300px; height: 200px;" canvas-id="firstCanvas" id="firstCanvas"></canvas>

这个临时方案亲测有效,看结果应该是关闭popup的时候canvas不可见了,再打开时并没有恢复canvas的可见状态

我也遇到了,目前的解决方案是每次打开弹窗,可以给canvas的id和canvas-id设置成随机字符串,不要使用固定值 template中的canvas组件和以下两个地方使用定义的随机id uni.createCanvasContext(‘随机字符id’,instance);
uni.canvasToTempFilePath({ canvasId: ‘随机字符id’ }

为什么会出现小程序不能显示,而在app端显示又是正常的情况

在使用 uni-popup 组件时,如果第二次弹出时 canvas 不生效,可能是由于 canvas 的上下文丢失或未正确初始化导致的。以下是一些可能的解决方案:

1. 确保 canvas 上下文正确初始化

在每次弹出 uni-popup 时,确保 canvas 的上下文被正确初始化。你可以在 uni-popupopen 事件中重新获取 canvas 的上下文。

<template>
  <uni-popup ref="popup" @open="onPopupOpen">
    <canvas ref="myCanvas"></canvas>
  </uni-popup>
</template>

<script setup>
import { ref, onMounted } from 'vue';

const popup = ref(null);
const myCanvas = ref(null);

const onPopupOpen = () => {
  const ctx = myCanvas.value.getContext('2d');
  // 重新绘制 canvas 内容
  ctx.clearRect(0, 0, myCanvas.value.width, myCanvas.value.height);
  ctx.fillStyle = 'red';
  ctx.fillRect(10, 10, 100, 100);
};

onMounted(() => {
  // 初始化 canvas
  const ctx = myCanvas.value.getContext('2d');
  ctx.fillStyle = 'blue';
  ctx.fillRect(10, 10, 100, 100);
});
</script>

2. 使用 v-if 控制 canvas 的显示

如果 canvasuni-popup 中不显示,可以尝试使用 v-if 来控制 canvas 的显示和销毁,确保每次弹出时 canvas 都是重新创建的。

<template>
  <uni-popup ref="popup" @open="onPopupOpen">
    <canvas v-if="showCanvas" ref="myCanvas"></canvas>
  </uni-popup>
</template>

<script setup>
import { ref } from 'vue';

const popup = ref(null);
const myCanvas = ref(null);
const showCanvas = ref(false);

const onPopupOpen = () => {
  showCanvas.value = true;
  nextTick(() => {
    const ctx = myCanvas.value.getContext('2d');
    // 重新绘制 canvas 内容
    ctx.clearRect(0, 0, myCanvas.value.width, myCanvas.value.height);
    ctx.fillStyle = 'red';
    ctx.fillRect(10, 10, 100, 100);
  });
};
</script>

3. 检查 canvas 的尺寸

确保 canvas 的尺寸在每次弹出时都正确设置。如果 canvas 的尺寸为 0,可能会导致绘制内容不可见。

<template>
  <uni-popup ref="popup" @open="onPopupOpen">
    <canvas ref="myCanvas" :width="canvasWidth" :height="canvasHeight"></canvas>
  </uni-popup>
</template>

<script setup>
import { ref } from 'vue';

const popup = ref(null);
const myCanvas = ref(null);
const canvasWidth = ref(300);
const canvasHeight = ref(150);

const onPopupOpen = () => {
  const ctx = myCanvas.value.getContext('2d');
  // 重新绘制 canvas 内容
  ctx.clearRect(0, 0, canvasWidth.value, canvasHeight.value);
  ctx.fillStyle = 'red';
  ctx.fillRect(10, 10, 100, 100);
};
</script>

4. 使用 uni-popupdestroyOnClose 属性

如果 uni-popup 提供了 destroyOnClose 属性,可以尝试将其设置为 true,这样在关闭 popup 时会销毁内部的内容,再次打开时会重新创建。

<template>
  <uni-popup ref="popup" destroyOnClose @open="onPopupOpen">
    <canvas ref="myCanvas"></canvas>
  </uni-popup>
</template>

5. 检查 canvas 的绘制逻辑

确保 canvas 的绘制逻辑没有问题,尤其是在多次绘制时,可能需要清除之前的绘制内容。

const ctx = myCanvas.value.getContext('2d');
ctx.clearRect(0, 0, myCanvas.value.width, myCanvas.value.height); // 清除画布
ctx.fillStyle = 'red';
ctx.fillRect(10, 10, 100, 100);
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!