11<template >
22 <view :class =" `wd-circle ${customClass}`" :style =" customStyle" >
3- <canvas :width =" canvasSize" :height =" canvasSize" :style =" style" :id =" canvasId" :canvas-id =" canvasId" ></canvas >
3+ <!-- #ifdef MP-WEIXIN -->
4+ <canvas :style =" canvasStyle" :id =" canvasId" :canvas-id =" canvasId" type =" 2d" ></canvas >
5+ <!-- #endif -->
6+ <!-- #ifndef MP-WEIXIN -->
7+ <canvas :width =" canvasSize" :height =" canvasSize" :style =" canvasStyle" :id =" canvasId" :canvas-id =" canvasId" ></canvas >
8+ <!-- #endif -->
9+
410 <view v-if =" !text" class =" wd-circle__text" >
511 <!-- 自定义提示内容 -->
612 <slot ></slot >
713 </view >
8- <!-- #ifdef MP-WEIXIN -->
9- <cover-view v-else class =" wd-circle__text" >
10- {{ text }}
11- </cover-view >
12- <!-- #endif -->
13- <!-- #ifndef MP-WEIXIN -->
14- <!-- eslint-disable-next-line vue/valid-v-else -->
14+
1515 <text v-else class =" wd-circle__text" >
1616 {{ text }}
1717 </text >
18- <!-- #endif -->
1918 </view >
2019</template >
2120<script lang="ts">
@@ -29,10 +28,10 @@ export default {
2928}
3029 </script >
3130<script lang="ts" setup>
32- // Circle 环形进度条
3331import { computed , getCurrentInstance , onBeforeMount , onMounted , onUnmounted , ref , watch } from ' vue'
3432import { addUnit , isObj , objToStyle , uuid } from ' ../common/util'
3533import { circleProps } from ' ./types'
34+ import { canvas2dAdapter } from ' ../common/canvasHelper'
3635
3736// 大于等于0且小于等于100
3837function format(rate : number ) {
@@ -47,23 +46,39 @@ const STEP = 1
4746const props = defineProps (circleProps )
4847
4948const progressColor = ref <string | CanvasGradient >(' ' ) // 进度条颜色
50- const pixel = ref < number >( 1 ) // 设备像素比
49+
5150const currentValue = ref <number >(0 ) // 当前值
5251const interval = ref <any >(null ) // 定时器
53- const canvasId = ref <string >(uuid ()) // canvasId
52+ const pixelRatio = ref <number >(1 ) // 像素比
53+ const canvasId = ref <string >(` wd-circle${uuid ()} ` ) // canvasId
5454let ctx: UniApp .CanvasContext | null = null
55+
5556// canvas渲染大小
5657const canvasSize = computed (() => {
57- return props .size * pixel .value
58+ let size = props .size
59+ // #ifdef MP-ALIPAY
60+ size = size * pixelRatio .value
61+ // #endif
62+
63+ return size
64+ })
65+
66+ // 进度条宽度
67+ const sWidth = computed (() => {
68+ let sWidth = props .strokeWidth
69+ // #ifdef MP-ALIPAY
70+ sWidth = sWidth * pixelRatio .value
71+ // #endif
72+ return sWidth
5873})
5974
6075// Circle 样式
61- const style = computed (() => {
76+ const canvasStyle = computed (() => {
6277 const style = {
6378 width: addUnit (props .size ),
6479 height: addUnit (props .size )
6580 }
66- return ` ${objToStyle (style )}; ${ props . customStyle } `
81+ return ` ${objToStyle (style )}; `
6782})
6883
6984// 监听目标数值变化
@@ -96,38 +111,9 @@ watch(
96111 { immediate: false , deep: true }
97112)
98113
99- // 监听轨道颜色变化
100- watch (
101- () => props .layerColor ,
102- () => {
103- drawCircle (currentValue .value )
104- },
105- { immediate: false }
106- )
107-
108- // 监听轨道宽度
109- watch (
110- () => props .strokeWidth ,
111- () => {
112- drawCircle (currentValue .value )
113- },
114- { immediate: false }
115- )
116-
117- // 监听轨道展示方向
118- watch (
119- () => props .clockwise ,
120- () => {
121- drawCircle (currentValue .value )
122- },
123- { immediate: false }
124- )
125-
126- // #ifdef MP-ALIPAY
127114onBeforeMount (() => {
128- pixel .value = uni .getSystemInfoSync ().pixelRatio
115+ pixelRatio .value = uni .getSystemInfoSync ().pixelRatio
129116})
130- // #endif
131117
132118onMounted (() => {
133119 currentValue .value = props .modelValue
@@ -143,32 +129,54 @@ const { proxy } = getCurrentInstance() as any
143129 * 获取canvas上下文
144130 */
145131function getContext() {
146- if (! ctx ) {
132+ return new Promise <UniApp .CanvasContext >((resolve ) => {
133+ if (ctx ) {
134+ return resolve (ctx )
135+ }
136+ // #ifndef MP-WEIXIN
147137 ctx = uni .createCanvasContext (canvasId .value , proxy )
148- }
149- return Promise .resolve (ctx )
138+ resolve (ctx )
139+ // #endif
140+ // #ifdef MP-WEIXIN
141+ uni
142+ .createSelectorQuery ()
143+ .in (proxy )
144+ .select (` #${canvasId .value } ` )
145+ .node ((res ) => {
146+ if (res && res .node ) {
147+ const canvas = res .node
148+ ctx = canvas2dAdapter (canvas .getContext (' 2d' ) as CanvasRenderingContext2D )
149+ canvas .width = props .size * pixelRatio .value
150+ canvas .height = props .size * pixelRatio .value
151+ ctx .scale (pixelRatio .value , pixelRatio .value )
152+ resolve (ctx )
153+ }
154+ })
155+ .exec ()
156+ // #endif
157+ })
150158}
151159
152160/**
153161 * 设置canvas
154162 */
155163function presetCanvas(context : any , strokeStyle : string | CanvasGradient , beginAngle : number , endAngle : number , fill ? : string ) {
156- const canvasSize = props .size * pixel .value
157- let strokeWidth = props .strokeWidth * pixel .value
158- const position = canvasSize / 2
164+ let width = sWidth .value
165+ const position = canvasSize .value / 2
159166 if (! fill ) {
160- strokeWidth = strokeWidth / 2
167+ width = width / 2
161168 }
162- const radius = position - strokeWidth / 2
169+ const radius = position - width / 2
163170 context .strokeStyle = strokeStyle
164- context .setLineWidth (strokeWidth )
171+ context .setStrokeStyle (strokeStyle )
172+ context .setLineWidth (width )
165173 context .setLineCap (props .strokeLinecap )
166174
167175 context .beginPath ()
168176 context .arc (position , position , radius , beginAngle , endAngle , ! props .clockwise )
169177 context .stroke ()
170178 if (fill ) {
171- context .setLineWidth (strokeWidth )
179+ context .setLineWidth (width )
172180 context .setFillStyle (fill )
173181 context .fill ()
174182 }
@@ -184,14 +192,13 @@ function renderLayerCircle(context: UniApp.CanvasContext) {
184192 * 渲染进度条
185193 */
186194function renderHoverCircle(context : UniApp .CanvasContext , formatValue : number ) {
187- const canvasSize = props .size * pixel .value
188195 // 结束角度
189196 const progress = PERIMETER * (formatValue / 100 )
190197 const endAngle = props .clockwise ? BEGIN_ANGLE + progress : 3 * Math .PI - (BEGIN_ANGLE + progress )
191198
192199 // 设置进度条颜色
193200 if (isObj (props .color )) {
194- const LinearColor = context .createLinearGradient (canvasSize , 0 , 0 , 0 )
201+ const LinearColor = context .createLinearGradient (canvasSize . value , 0 , 0 , 0 )
195202 Object .keys (props .color )
196203 .sort ((a , b ) => parseFloat (a ) - parseFloat (b ))
197204 .map ((key ) => LinearColor .addColorStop (parseFloat (key ) / 100 , (props .color as Record <string , any >)[key ]))
@@ -207,12 +214,11 @@ function renderHoverCircle(context: UniApp.CanvasContext, formatValue: number) {
207214 * 进度值为0时渲染一个圆点
208215 */
209216function renderDot(context : UniApp .CanvasContext ) {
210- const canvasSize = props .size * pixel .value
211- const strokeWidth = props .strokeWidth * pixel .value // 管道宽度=小圆点直径
212- const position = canvasSize / 2 // 坐标
217+ const strokeWidth = sWidth .value // 管道宽度=小圆点直径
218+ const position = canvasSize .value / 2 // 坐标
213219 // 设置进度条颜色
214220 if (isObj (props .color )) {
215- const LinearColor = context .createLinearGradient (canvasSize , 0 , 0 , 0 )
221+ const LinearColor = context .createLinearGradient (canvasSize . value , 0 , 0 , 0 )
216222 Object .keys (props .color )
217223 .sort ((a , b ) => parseFloat (a ) - parseFloat (b ))
218224 .map ((key ) => LinearColor .addColorStop (parseFloat (key ) / 100 , (props .color as Record <string , any >)[key ]))
@@ -230,9 +236,8 @@ function renderDot(context: UniApp.CanvasContext) {
230236 * 画圆
231237 */
232238function drawCircle(currentValue : number ) {
233- const canvasSize = props .size * pixel .value
234239 getContext ().then ((context ) => {
235- context .clearRect (0 , 0 , canvasSize , canvasSize )
240+ context .clearRect (0 , 0 , canvasSize . value , canvasSize . value )
236241 renderLayerCircle (context )
237242
238243 const formatValue = format (currentValue )
0 commit comments