微信公众号开发

uniapp微信小程序端canvas做为自定义组件引入使用时不显示问题的解决方法

本文主要是介绍uniapp微信小程序端canvas做为自定义组件引入使用时不显示问题的解决方法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
环境
  • uniapp(vue3)
  • vite
问题描述
  • 把canvas放在自定义组件里,然后将其迎入到其他组件使用时在微信小程序端不显示
解决方法(可能造成的原因)
    1. 没有写canvas-id
    1. uni.createCanvasContext方法没有传入组件实例(单独作为组件引入时,vue2为this,vue3为getCurrentInstance())
    1. canvas标签上写了type="2d"(单独作为组件引入时)
  • 4.没有在onReady或者onMounted生命周期里实列话canvas

代码

自定义的canvas组件

summaryDialog.vue

<template>
  <Theme>
    <!-- default 必须加 -->
    <template #center>
      <view class="dialog-mask">
        <view class="content">
          <view class="summary-dialog">
            <view class="top-score">
              <canvas
                style="width: 84px; height: 84px"
                canvas-id="circlefCanvas"
              ></canvas>
              <text class="score-text">得分</text>
            </view>
            <view class="center-contain">
              <view class="num-item">
                <view class="num total-color">{{data.total}}题</view>
                <view class="sub-text">总题数</view>
              </view>
              <view class="num-item">
                <view class="num right-color">{{data.right}}题</view>
                <view class="sub-text">正确</view>
              </view>
              <view class="num-item">
                <view class="num error-color">{{data.total - data.right}}题</view>
                <view class="sub-text">错误</view>
              </view>
            </view>
            <view class="score-foot-btns">
              <view class="btn left" @click="close()">取消</view>
              <view class="btn right" @click="confirm()">确定</view>
            </view>
          </view>
        </view>
      </view>
    </template>
  </Theme>
</template>

<script setup lang="ts">
import { onReady } from "@dcloudio/uni-app";
import { onMounted, getCurrentInstance } from "vue";
interface Props {
  data: {
    [key: string]: number
  }
}
const props = withDefaults(defineProps<Props>(), {
  data: function() {
    return {
      right: 8,
      score: 80,
      total: 10
    }
  }
})
const emit = defineEmits(["close", "confirm"]);

const close = () => {
  emit("close", "close");
};

const confirm = () => {
  emit("confirm", "confirm");
};

/**
 * 环形进度条
 * arc(x, y, r, startAngle, endAngle, anticlockwise):
 * 以(x, y) 为圆心,以r 为半径,90°代表0.5 * PI
 * 从 startAngle 弧度开始到endAngle弧度结束。
 * anticlosewise 是布尔值,true 表示逆时针,false 表示顺时针(默认是顺时针
 */
const circleProgressbar = (score: number, value: number) => {
  const instance = getCurrentInstance() as any
  // 换整个圆环
  const ctx = uni.createCanvasContext("circlefCanvas", instance);
  ctx.beginPath();
  ctx.arc(42, 42, 30, 0, 2 * Math.PI);
  ctx.setStrokeStyle("#FAF7F7");
  ctx.setLineWidth(5);
  ctx.stroke();
  // 进度
  ctx.beginPath();
  ctx.arc(42, 42, 30, 0, value * Math.PI);
  ctx.setStrokeStyle("#E8736F");
  ctx.setLineWidth(5);
  ctx.stroke();

  // 中心字体
  ctx.setFillStyle("#E8736F");
  ctx.setFontSize(17);
  ctx.setTextAlign("center");
  ctx.fillText(`${score}分`, 42, 50);
  ctx.stroke();
  ctx.draw();
};

onMounted(() => {
  const percent = (props.data?.score / 100) * 2
  circleProgressbar(props.data?.score, percent);
});
</script>
<style lang="scss">
.dialog-mask {
  opacity: 1;
  position: fixed;
  inset: 0px;
  background-color: rgba(0, 0, 0, 0.4);
  transition: opacity 300ms ease 0ms, -webkit-transform 300ms ease 0ms,
    transform 300ms ease 0ms;
  transform-origin: 50% 50%;
  .content {
    transform: scale(1);
    opacity: 1;
    position: fixed;
    display: flex;
    flex-direction: column;
    inset: 0px;
    justify-content: center;
    align-items: center;
    transition: opacity 300ms ease 0ms, -webkit-transform 300ms ease 0ms,
      transform 300ms ease 0ms;
    transform-origin: 50% 50%;
  }
  .summary-dialog {
    width: 80%;
    height: 50%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    background: #ffffff;
    border-radius: 12rpx;
    padding: 30rpx;
    .top-score {
      display: flex;
      flex-direction: column;
      // justify-content: center;
      align-items: center;
      margin: 30rpx;
      .score-text {
        font-weight: bold;
        font-size: 34rpx;
        color: #000000;
      }
    }
    .center-contain {
      background: #faf7f7;
      border-radius: 8rpx;
      margin: 30rpx 0px;
      height: 136rpx;
      display: flex;
      .num-item {
        width: 33.33%;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        .num {
          font-size: 14px;
          font-weight: bold;
        }
        .sub-text {
          font-weight: 500;
          color: #8d8d8d;
          font-size: 13px;
        }
        .total-color {
          color: $uni-main-color;
        }
        .right-color {
          color: #F33A52;
        }
        .error-color {
          color: #07C180;
        }
      }
    }
    .score-foot-btns {
      display: flex;
      justify-content: space-between;
      .btn {
        width: 40%;
        display: flex;
        justify-content: center;
        align-items: center;
        height: 80rpx;
        font-size: 17px;
        font-weight: bold;
        border-radius: 12rpx;
      }
      .left {
        color: $uni-base-color;
        border: 2rpx solid $uni-base-color;
      }
      .right {
        color: white;
        background-color: $uni-primary;
      }
    }
  }
}
</style>

将自定义组件引入入其他组件使用

import SummaryDialog from './dialog/summaryDialog.vue'

.....
<view>
<SummaryDialog v-if="summaryDialogVisible" @close="close" @confirm="confirm"></SummaryDialog>
</view>

结果

我遇到的情况

  • 没加type="2d"时正常

正常显示canvas

  • 加了type="2d"时canvas不显示

不显示canvas

这篇关于uniapp微信小程序端canvas做为自定义组件引入使用时不显示问题的解决方法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!