環境
- uniapp(vue3)
- vite
問題描述
- 把canvas放在自定義組件里,然后將其迎入到其他組件使用時在微信小程序端不顯示
解決方法(可能造成的原因)
-
- 沒有寫canvas-id
-
- uni.createCanvasContext方法沒有傳入組件實例(單獨作為組件引入時,vue2為this,vue3為getCurrentInstance())
-
- 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"時正常
- 加了type="2d"時canvas不顯示