mirror of
https://gitee.com/wot-design-uni/wot-design-uni.git
synced 2025-12-07 01:28:30 +08:00
feat: ✨ 新增 Circle 环形进度条组件,支持进度渐变动画
This commit is contained in:
parent
51425b107a
commit
7c38a6f03e
@ -272,6 +272,9 @@ export default defineConfig({
|
|||||||
}, {
|
}, {
|
||||||
link: "/component/progress",
|
link: "/component/progress",
|
||||||
text: "Progress 进度条"
|
text: "Progress 进度条"
|
||||||
|
}, {
|
||||||
|
link: "/component/circle",
|
||||||
|
text: "Circle 环形进度条"
|
||||||
}, {
|
}, {
|
||||||
link: "/component/sort-button",
|
link: "/component/sort-button",
|
||||||
text: "SortButton 排序按钮"
|
text: "SortButton 排序按钮"
|
||||||
|
|||||||
91
docs/component/circle.md
Normal file
91
docs/component/circle.md
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<frame/>
|
||||||
|
|
||||||
|
# Circle 环形进度条 <el-tag text style="vertical-align: middle;margin-left:8px;" effect="plain">0.1.19</el-tag>
|
||||||
|
|
||||||
|
圆环形的进度条组件,支持进度渐变动画。
|
||||||
|
|
||||||
|
## 基础用法
|
||||||
|
|
||||||
|
通过`v-model`表示进度条的当前进度,`text`属性控制进度条中间文字内容。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<wd-circle v-model="current" :text="`进度:${current}%`"></wd-circle>
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const current = ref<number>(10)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 宽度控制
|
||||||
|
|
||||||
|
通过`strokeWidth`属性来控制进度条宽度,默认`10px`。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<wd-circle v-model="current" :strokeWidth="15"></wd-circle>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 颜色定制
|
||||||
|
|
||||||
|
通过`color`属性控制进度条颜色,默认`#1C64FD`,通过`layerColor`属性控制进度条轨道颜色,默认`#EBEEF5`。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<wd-circle v-model="current" color="#1C64FD" layer-color="#EBEEF5"></wd-circle>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 渐变色
|
||||||
|
|
||||||
|
`color`属性支持传入对象格式来定义渐变色。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<wd-circle v-model="current" :color="gradientColor"></wd-circle>
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const gradientColor = {
|
||||||
|
'0%': '#ffd01e',
|
||||||
|
'100%': '#ee0a24'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 进度条展开方向
|
||||||
|
|
||||||
|
通过`clockwise`属性控制进度条展开方向,`clockwise`为`false`时,进度会从逆时针方向开始。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<wd-circle v-model="current" :clockwise="false"></wd-circle>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 大小定制
|
||||||
|
|
||||||
|
通过`size`属性控制进度条圆环直径,默认`100px`。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<wd-circle v-model="current" :size="300"></wd-circle>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Attributes
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 最低版本 |
|
||||||
|
| ----------------- | ---------------------------- | --------------------------- | ------------------------------------------ | --------------- | -------- |
|
||||||
|
| `v-model` \|`modelValue` | 当前进度 | number | - | `0` | 0.1.19 |
|
||||||
|
| `customClass` | 自定义class | string | - | - | 0.1.19 |
|
||||||
|
| `customStyle` | 自定义style | string | - | - | 0.1.19 |
|
||||||
|
| `rate` | 目标进度 | number \| string | - | `100` | 0.1.19 |
|
||||||
|
| `size` | 圆环直径,默认单位为 px | number | - | `100` | 0.1.19 |
|
||||||
|
| `color` | 进度条颜色 | string \| Record<string, string> | - | `#4d80f0` | 0.1.19 |
|
||||||
|
| `layerColor` | 轨道颜色 | string | - | `#EBEEF5` | 0.1.19 |
|
||||||
|
| `fill` | 填充颜色 | string | - | `#ffffff` | 0.1.19 |
|
||||||
|
| `speed` | 动画速度(单位为 rate/s) | number | - | `50` | 0.1.19 |
|
||||||
|
| `text` | 文字 | string | - | - | 0.1.19 |
|
||||||
|
| `strokeWidth` | 进度条宽度,单位px | number | - | `10` | 0.1.19 |
|
||||||
|
| `strokeLinecap` | 进度条端点的形状 | string | `butt` \| `round` \| `square` | `round` | 0.1.19 |
|
||||||
|
| `clockwise` | 是否顺时针增加 | boolean | - | `true` | 0.1.19 |
|
||||||
|
|
||||||
|
|
||||||
|
## Circle 外部样式类
|
||||||
|
|
||||||
|
| 类名 | 说明 | 最低版本 |
|
||||||
|
|-----|------|--------|
|
||||||
|
| custom-class | 根结点样式 | - |
|
||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
# Watermark 水印 <el-tag text style="vertical-align: middle;margin-left:8px;" effect="plain">0.1.16</el-tag>
|
# Watermark 水印 <el-tag text style="vertical-align: middle;margin-left:8px;" effect="plain">0.1.16</el-tag>
|
||||||
|
|
||||||
|
在页面或组件上添加指定的图片或文字,可用于版权保护、品牌宣传等场景。
|
||||||
|
|
||||||
## 基础用法
|
## 基础用法
|
||||||
|
|
||||||
|
|||||||
@ -561,6 +561,16 @@
|
|||||||
},
|
},
|
||||||
"navigationBarTitleText": "Watermark 水印"
|
"navigationBarTitleText": "Watermark 水印"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/circle/Index",
|
||||||
|
"name": "circle",
|
||||||
|
"style": {
|
||||||
|
"mp-alipay": {
|
||||||
|
"allowsBounceVertical": "NO"
|
||||||
|
},
|
||||||
|
"navigationBarTitleText": "Circle 环形进度条"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
// "tabBar": {
|
// "tabBar": {
|
||||||
|
|||||||
49
src/pages/circle/index.vue
Normal file
49
src/pages/circle/index.vue
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<template>
|
||||||
|
<view class="circle">
|
||||||
|
<page-wraper>
|
||||||
|
<demo-block title="基础用法">
|
||||||
|
<wd-circle custom-class="custom-circle" v-model="current" :text="current + '%'" />
|
||||||
|
</demo-block>
|
||||||
|
<demo-block title="样式定制">
|
||||||
|
<wd-circle custom-class="custom-circle" v-model="current" :stroke-width="6" text="宽度定制" />
|
||||||
|
<wd-circle custom-class="custom-circle" v-model="current" layer-color="#eee" color="#ee0a24" text="颜色定制" />
|
||||||
|
<wd-circle custom-class="custom-circle" v-model="current" :color="gradientColor" text="渐变色" />
|
||||||
|
<wd-circle custom-class="custom-circle" v-model="current" color="#07c160" :clockwise="false" text="逆时针" />
|
||||||
|
<wd-circle custom-class="custom-circle" v-model="current" :size="120" text="大小定制" />
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block>
|
||||||
|
<wd-button custom-style="margin-right:24rpx" type="primary" size="small" @click="doAdd">增加</wd-button>
|
||||||
|
<wd-button type="error" size="small" @click="doDecre">减少</wd-button>
|
||||||
|
</demo-block>
|
||||||
|
</page-wraper>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const current = ref<number>(20)
|
||||||
|
const gradientColor: Record<string, string> = {
|
||||||
|
'0': 'red',
|
||||||
|
'100': 'white'
|
||||||
|
} // 进度条颜色渐变色
|
||||||
|
|
||||||
|
function doAdd() {
|
||||||
|
if (current.value < 100) {
|
||||||
|
current.value += 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function doDecre() {
|
||||||
|
if (current.value > 0) {
|
||||||
|
current.value -= 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.circle {
|
||||||
|
:deep(.custom-circle) {
|
||||||
|
margin-left: 24rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -207,6 +207,10 @@ const list = ref([
|
|||||||
id: 'progress',
|
id: 'progress',
|
||||||
name: 'Progress 进度条'
|
name: 'Progress 进度条'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'circle',
|
||||||
|
name: 'Circle 环形进度条'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'sortButton',
|
id: 'sortButton',
|
||||||
name: 'SortButton 排序按钮'
|
name: 'SortButton 排序按钮'
|
||||||
|
|||||||
@ -704,23 +704,26 @@ $-curtain-content-close-color: var(--wot-curtain-content-close-color, $-color-wh
|
|||||||
$-curtain-content-close-fs: var(--wot-curtain-content-close-fs, $-fs-big) !default; // 关闭按钮大小
|
$-curtain-content-close-fs: var(--wot-curtain-content-close-fs, $-fs-big) !default; // 关闭按钮大小
|
||||||
|
|
||||||
// Notify
|
// Notify
|
||||||
$notify-text-color: var(--wot-notify-text-color, $-color-white) !default;
|
$-notify-text-color: var(--wot-notify-text-color, $-color-white) !default;
|
||||||
$notify-padding: var(--wot-notify-padding, 8px 16px) !default;
|
$-notify-padding: var(--wot-notify-padding, 8px 16px) !default;
|
||||||
$notify-font-size: var(--wot-notify-font-size, $-fs-content) !default;
|
$-notify-font-size: var(--wot-notify-font-size, $-fs-content) !default;
|
||||||
$notify-line-height: var(--wot-notify-line-height, 20px) !default;
|
$-notify-line-height: var(--wot-notify-line-height, 20px) !default;
|
||||||
$notify-primary-background: var(--wot-notify-primary-background, $-color-theme) !default;
|
$-notify-primary-background: var(--wot-notify-primary-background, $-color-theme) !default;
|
||||||
$notify-success-background: var(--wot-notify-success-background, $-color-success) !default;
|
$-notify-success-background: var(--wot-notify-success-background, $-color-success) !default;
|
||||||
$notify-danger-background: var(--wot-notify-danger-background, $-color-danger) !default;
|
$-notify-danger-background: var(--wot-notify-danger-background, $-color-danger) !default;
|
||||||
$notify-warning-background: var(--wot-notify-warning-background, $-color-warning) !default;
|
$-notify-warning-background: var(--wot-notify-warning-background, $-color-warning) !default;
|
||||||
|
|
||||||
// Skeleton
|
// Skeleton
|
||||||
$skeleton-background-color: var(--wot-skeleton-background-color, #eee) !default;
|
$-skeleton-background-color: var(--wot-skeleton-background-color, #eee) !default;
|
||||||
$skeleton-animation-gradient: var(--wot-skeleton-animation-gradient, rgba(0, 0, 0, 0.04)) !default;
|
$-skeleton-animation-gradient: var(--wot-skeleton-animation-gradient, rgba(0, 0, 0, 0.04)) !default;
|
||||||
$skeleton-animation-flashed: var(--wot-skeleton-animation-flashed, rgba(230, 230, 230, 0.3)) !default;
|
$-skeleton-animation-flashed: var(--wot-skeleton-animation-flashed, rgba(230, 230, 230, 0.3)) !default;
|
||||||
$skeleton-text-height-default: var(--wot-skeleton-text-height-default, 16px) !default;
|
$-skeleton-text-height-default: var(--wot-skeleton-text-height-default, 16px) !default;
|
||||||
$skeleton-rect-height-default: var(--wot-skeleton-rect-height-default, 16px) !default;
|
$-skeleton-rect-height-default: var(--wot-skeleton-rect-height-default, 16px) !default;
|
||||||
$skeleton-circle-height-default: var(--wot-skeleton-circle-height-default, 48px) !default;
|
$-skeleton-circle-height-default: var(--wot-skeleton-circle-height-default, 48px) !default;
|
||||||
$skeleton-row-margin-bottom: var(--wot-skeleton-row-margin-bottom, 16px) !default;
|
$-skeleton-row-margin-bottom: var(--wot-skeleton-row-margin-bottom, 16px) !default;
|
||||||
$skeleton-border-radius-text: var(--wot-skeleton-border-radius-text, 2px) !default;
|
$-skeleton-border-radius-text: var(--wot-skeleton-border-radius-text, 2px) !default;
|
||||||
$skeleton-border-radius-rect: var(--wot-skeleton-border-radius-rect, 4px) !default;
|
$-skeleton-border-radius-rect: var(--wot-skeleton-border-radius-rect, 4px) !default;
|
||||||
$skeleton-border-radius-circle: var(--wot-skeleton-border-radius-circle, 50%) !default;
|
$-skeleton-border-radius-circle: var(--wot-skeleton-border-radius-circle, 50%) !default;
|
||||||
|
|
||||||
|
// circle
|
||||||
|
$-circle-text-color: var(--wot-circle-text-color, $-color-content) !default; // circle文字颜色
|
||||||
|
|||||||
@ -26,11 +26,11 @@ export function addUnit(num: number) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 判断target是否对象
|
* @description 判断target是否对象
|
||||||
* @param obj
|
* @param value
|
||||||
* @return {boolean}
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
export function isObj(obj: any): boolean {
|
export function isObj(value: any): value is object {
|
||||||
return Object.prototype.toString.call(obj) === '[object Object]' || typeof obj === 'object'
|
return Object.prototype.toString.call(value) === '[object Object]' || typeof value === 'object'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -0,0 +1,18 @@
|
|||||||
|
@import "../common/abstracts/variable.scss";
|
||||||
|
@import "../common/abstracts/_mixin.scss";
|
||||||
|
|
||||||
|
@include b(circle) {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
@include e(text) {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
color: $-circle-text-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,341 @@
|
|||||||
|
<template>
|
||||||
|
<view :class="`wd-circle ${customClass}`">
|
||||||
|
<canvas :width="canvasSize" :height="canvasSize" :style="style" :id="canvasId" :canvas-id="canvasId"></canvas>
|
||||||
|
<view v-if="!text" class="wd-circle__text">
|
||||||
|
<!-- 自定义提示内容 -->
|
||||||
|
<slot></slot>
|
||||||
|
</view>
|
||||||
|
<!-- #ifdef MP-WEIXIN -->
|
||||||
|
<cover-view v-else class="wd-circle__text">
|
||||||
|
{{ text }}
|
||||||
|
</cover-view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef MP-WEIXIN -->
|
||||||
|
<!-- eslint-disable-next-line vue/valid-v-else -->
|
||||||
|
<text v-else class="wd-circle__text">
|
||||||
|
{{ text }}
|
||||||
|
</text>
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'wd-circle',
|
||||||
|
options: {
|
||||||
|
addGlobalClass: true,
|
||||||
|
virtualHost: true,
|
||||||
|
styleIsolation: 'shared'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
// Circle 环形进度条
|
||||||
|
import { computed, getCurrentInstance, onBeforeMount, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
|
import { addUnit, isObj, objToStyle, uuid } from '../common/util'
|
||||||
|
|
||||||
|
// 大于等于0且小于等于100
|
||||||
|
function format(rate: number) {
|
||||||
|
return Math.min(Math.max(rate, 0), 100)
|
||||||
|
}
|
||||||
|
// 结束角度
|
||||||
|
const PERIMETER = 2 * Math.PI
|
||||||
|
// 开始角度
|
||||||
|
const BEGIN_ANGLE = -Math.PI / 2
|
||||||
|
const STEP = 1
|
||||||
|
// 进度条端点的形状,可选值为 "butt" | "round" | "square"
|
||||||
|
type StrokeLinecapType = 'butt' | 'round' | 'square'
|
||||||
|
interface Props {
|
||||||
|
// 当前进度
|
||||||
|
modelValue: number
|
||||||
|
// 自定义class
|
||||||
|
customClass?: string
|
||||||
|
// 自定义style
|
||||||
|
customStyle?: string
|
||||||
|
// 目标进度
|
||||||
|
rate?: number | string
|
||||||
|
// 圆环直径,默认单位为 px
|
||||||
|
size?: number
|
||||||
|
// 进度条颜色,传入对象格式可以定义渐变色
|
||||||
|
color?: string | Record<string, string>
|
||||||
|
// 轨道颜色
|
||||||
|
layerColor?: string
|
||||||
|
// 填充颜色
|
||||||
|
fill?: string
|
||||||
|
// 动画速度(单位为 rate/s)
|
||||||
|
speed?: number
|
||||||
|
// 文字
|
||||||
|
text?: string
|
||||||
|
// 进度条宽度 单位px
|
||||||
|
strokeWidth?: number
|
||||||
|
// 进度条端点的形状,可选值为 "butt" | "round" | "square"
|
||||||
|
strokeLinecap?: StrokeLinecapType
|
||||||
|
// 是否顺时针增加
|
||||||
|
clockwise?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
// 当前进度
|
||||||
|
modelValue: 0,
|
||||||
|
// 自定义class
|
||||||
|
customClass: '',
|
||||||
|
// 自定义style
|
||||||
|
customStyle: '',
|
||||||
|
// 目标进度
|
||||||
|
rate: 100,
|
||||||
|
// 圆环直径,默认单位为 px
|
||||||
|
size: 100,
|
||||||
|
// 进度条颜色,传入对象格式可以定义渐变色
|
||||||
|
color: '#4d80f0',
|
||||||
|
// 轨道颜色
|
||||||
|
layerColor: '#EBEEF5',
|
||||||
|
// 填充颜色
|
||||||
|
fill: '#ffffff',
|
||||||
|
// 动画速度(单位为 rate/s)
|
||||||
|
speed: 50,
|
||||||
|
// 进度条宽度 默认单位px
|
||||||
|
strokeWidth: 10,
|
||||||
|
// 进度条端点的形状
|
||||||
|
strokeLinecap: 'round',
|
||||||
|
// 是否顺时针增加
|
||||||
|
clockwise: true
|
||||||
|
})
|
||||||
|
|
||||||
|
const progressColor = ref<string | CanvasGradient>('') // 进度条颜色
|
||||||
|
const pixel = ref<number>(1) // 设备像素比
|
||||||
|
const currentValue = ref<number>(0) // 当前值
|
||||||
|
const interval = ref<any>(null) // 定时器
|
||||||
|
const canvasId = ref<string>(uuid()) // canvasId
|
||||||
|
|
||||||
|
// canvas渲染大小
|
||||||
|
const canvasSize = computed(() => {
|
||||||
|
return props.size * pixel.value
|
||||||
|
})
|
||||||
|
|
||||||
|
// Circle 样式
|
||||||
|
const style = computed(() => {
|
||||||
|
const style = {
|
||||||
|
width: addUnit(props.size),
|
||||||
|
height: addUnit(props.size)
|
||||||
|
}
|
||||||
|
return `${objToStyle(style)}; ${props.customStyle}`
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听目标数值变化
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
() => {
|
||||||
|
reRender()
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
// 监听Circle大小变化
|
||||||
|
watch(
|
||||||
|
() => props.size,
|
||||||
|
() => {
|
||||||
|
let timer = setTimeout(() => {
|
||||||
|
drawCircle(currentValue.value)
|
||||||
|
clearTimeout(timer)
|
||||||
|
}, 50)
|
||||||
|
},
|
||||||
|
{ immediate: false }
|
||||||
|
)
|
||||||
|
|
||||||
|
// 监听进度条颜色变化
|
||||||
|
watch(
|
||||||
|
() => props.color,
|
||||||
|
() => {
|
||||||
|
drawCircle(currentValue.value)
|
||||||
|
},
|
||||||
|
{ immediate: false, deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
// 监听轨道颜色变化
|
||||||
|
watch(
|
||||||
|
() => props.layerColor,
|
||||||
|
() => {
|
||||||
|
drawCircle(currentValue.value)
|
||||||
|
},
|
||||||
|
{ immediate: false }
|
||||||
|
)
|
||||||
|
|
||||||
|
// 监听轨道宽度
|
||||||
|
watch(
|
||||||
|
() => props.strokeWidth,
|
||||||
|
() => {
|
||||||
|
drawCircle(currentValue.value)
|
||||||
|
},
|
||||||
|
{ immediate: false }
|
||||||
|
)
|
||||||
|
|
||||||
|
// 监听轨道展示方向
|
||||||
|
watch(
|
||||||
|
() => props.clockwise,
|
||||||
|
() => {
|
||||||
|
drawCircle(currentValue.value)
|
||||||
|
},
|
||||||
|
{ immediate: false }
|
||||||
|
)
|
||||||
|
|
||||||
|
// #ifdef MP-ALIPAY
|
||||||
|
onBeforeMount(() => {
|
||||||
|
pixel.value = uni.getSystemInfoSync().pixelRatio
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
currentValue.value = props.modelValue
|
||||||
|
drawCircle(currentValue.value)
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
clearTimeInterval()
|
||||||
|
})
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as any
|
||||||
|
/**
|
||||||
|
* 获取canvas上下文
|
||||||
|
*/
|
||||||
|
function getContext() {
|
||||||
|
const ctx = uni.createCanvasContext(canvasId.value, proxy)
|
||||||
|
return Promise.resolve(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置canvas
|
||||||
|
*/
|
||||||
|
function presetCanvas(context: any, strokeStyle: string | CanvasGradient, beginAngle: number, endAngle: number, fill?: string) {
|
||||||
|
const canvasSize = props.size * pixel.value
|
||||||
|
let strokeWidth = props.strokeWidth * pixel.value
|
||||||
|
const position = canvasSize / 2
|
||||||
|
if (!fill) {
|
||||||
|
strokeWidth = strokeWidth / 2
|
||||||
|
}
|
||||||
|
const radius = position - strokeWidth / 2
|
||||||
|
context.strokeStyle = strokeStyle
|
||||||
|
context.setLineWidth(strokeWidth)
|
||||||
|
context.setLineCap(props.strokeLinecap)
|
||||||
|
|
||||||
|
context.beginPath()
|
||||||
|
context.arc(position, position, radius, beginAngle, endAngle, !props.clockwise)
|
||||||
|
context.stroke()
|
||||||
|
if (fill) {
|
||||||
|
context.setLineWidth(strokeWidth)
|
||||||
|
context.setFillStyle(fill)
|
||||||
|
context.fill()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 渲染管道
|
||||||
|
*/
|
||||||
|
function renderLayerCircle(context: UniApp.CanvasContext) {
|
||||||
|
presetCanvas(context, props.layerColor, 0, PERIMETER, props.fill)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染进度条
|
||||||
|
*/
|
||||||
|
function renderHoverCircle(context: UniApp.CanvasContext, formatValue: number) {
|
||||||
|
const canvasSize = props.size * pixel.value
|
||||||
|
// 结束角度
|
||||||
|
const progress = PERIMETER * (formatValue / 100)
|
||||||
|
const endAngle = props.clockwise ? BEGIN_ANGLE + progress : 3 * Math.PI - (BEGIN_ANGLE + progress)
|
||||||
|
|
||||||
|
// 设置进度条颜色
|
||||||
|
if (isObj(props.color)) {
|
||||||
|
const LinearColor = context.createLinearGradient(canvasSize, 0, 0, 0)
|
||||||
|
Object.keys(props.color)
|
||||||
|
.sort((a, b) => parseFloat(a) - parseFloat(b))
|
||||||
|
.map((key) => LinearColor.addColorStop(parseFloat(key) / 100, props.color[key]))
|
||||||
|
progressColor.value = LinearColor
|
||||||
|
} else {
|
||||||
|
progressColor.value = props.color
|
||||||
|
}
|
||||||
|
presetCanvas(context, progressColor.value, BEGIN_ANGLE, endAngle)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染圆点
|
||||||
|
* 进度值为0时渲染一个圆点
|
||||||
|
*/
|
||||||
|
function renderDot(context: UniApp.CanvasContext) {
|
||||||
|
const canvasSize = props.size * pixel.value
|
||||||
|
const strokeWidth = props.strokeWidth * pixel.value // 管道宽度=小圆点直径
|
||||||
|
const position = canvasSize / 2 // 坐标
|
||||||
|
// 设置进度条颜色
|
||||||
|
if (isObj(props.color)) {
|
||||||
|
const LinearColor = context.createLinearGradient(canvasSize, 0, 0, 0)
|
||||||
|
Object.keys(props.color)
|
||||||
|
.sort((a, b) => parseFloat(a) - parseFloat(b))
|
||||||
|
.map((key) => LinearColor.addColorStop(parseFloat(key) / 100, props.color[key]))
|
||||||
|
progressColor.value = LinearColor
|
||||||
|
} else {
|
||||||
|
progressColor.value = props.color
|
||||||
|
}
|
||||||
|
context.beginPath()
|
||||||
|
context.arc(position, strokeWidth / 4, strokeWidth / 4, 0, PERIMETER)
|
||||||
|
context.setFillStyle(progressColor.value)
|
||||||
|
context.fill()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 画圆
|
||||||
|
*/
|
||||||
|
function drawCircle(currentValue: number) {
|
||||||
|
const canvasSize = props.size * pixel.value
|
||||||
|
getContext().then((context) => {
|
||||||
|
context.clearRect(0, 0, canvasSize, canvasSize)
|
||||||
|
renderLayerCircle(context)
|
||||||
|
|
||||||
|
const formatValue = format(currentValue)
|
||||||
|
if (formatValue !== 0) {
|
||||||
|
renderHoverCircle(context, formatValue)
|
||||||
|
} else {
|
||||||
|
renderDot(context)
|
||||||
|
}
|
||||||
|
context.draw()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Circle组件渲染
|
||||||
|
* 当前进度值变化时重新渲染Circle组件
|
||||||
|
*/
|
||||||
|
function reRender() {
|
||||||
|
// 动画通过定时器渲染
|
||||||
|
if (props.speed <= 0 || props.speed > 1000) {
|
||||||
|
drawCircle(props.modelValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
clearTimeInterval()
|
||||||
|
currentValue.value = currentValue.value || 0
|
||||||
|
const run = () => {
|
||||||
|
interval.value = setTimeout(() => {
|
||||||
|
if (currentValue.value !== props.modelValue) {
|
||||||
|
if (Math.abs(currentValue.value - props.modelValue) < STEP) {
|
||||||
|
currentValue.value = props.modelValue
|
||||||
|
} else if (currentValue.value < props.modelValue) {
|
||||||
|
currentValue.value += STEP
|
||||||
|
} else {
|
||||||
|
currentValue.value -= STEP
|
||||||
|
}
|
||||||
|
drawCircle(currentValue.value)
|
||||||
|
run()
|
||||||
|
} else {
|
||||||
|
clearTimeInterval()
|
||||||
|
}
|
||||||
|
}, 1000 / props.speed)
|
||||||
|
}
|
||||||
|
run()
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 清除定时器
|
||||||
|
*/
|
||||||
|
function clearTimeInterval() {
|
||||||
|
interval.value && clearTimeout(interval.value)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import './index.scss';
|
||||||
|
</style>
|
||||||
@ -6,10 +6,10 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: $notify-padding;
|
padding: $-notify-padding;
|
||||||
font-size: $notify-font-size;
|
font-size: $-notify-font-size;
|
||||||
line-height: $notify-line-height;
|
line-height: $-notify-line-height;
|
||||||
color: $notify-text-color;
|
color: $-notify-text-color;
|
||||||
|
|
||||||
// allow newline character
|
// allow newline character
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
@ -17,18 +17,18 @@
|
|||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
|
||||||
@include m(primary) {
|
@include m(primary) {
|
||||||
background: $notify-primary-background;
|
background: $-notify-primary-background;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include m(success) {
|
@include m(success) {
|
||||||
background: $notify-success-background;
|
background: $-notify-success-background;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include m(danger) {
|
@include m(danger) {
|
||||||
background: $notify-danger-background;
|
background: $-notify-danger-background;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include m(warning) {
|
@include m(warning) {
|
||||||
background: $notify-warning-background;
|
background: $-notify-warning-background;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
@include e(row) {
|
@include e(row) {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: $skeleton-row-margin-bottom;
|
margin-bottom: $-skeleton-row-margin-bottom;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
@ -23,8 +23,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@include e(col) {
|
@include e(col) {
|
||||||
border-radius: $skeleton-border-radius-text;
|
border-radius: $-skeleton-border-radius-text;
|
||||||
background-color: $skeleton-background-color;
|
background-color: $-skeleton-background-color;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -37,21 +37,21 @@
|
|||||||
@include m(type) {
|
@include m(type) {
|
||||||
&-text {
|
&-text {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: $skeleton-text-height-default;
|
height: $-skeleton-text-height-default;
|
||||||
border-radius: $skeleton-border-radius-text;
|
border-radius: $-skeleton-border-radius-text;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-rect {
|
&-rect {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: $skeleton-rect-height-default;
|
height: $-skeleton-rect-height-default;
|
||||||
border-radius: $skeleton-border-radius-rect;
|
border-radius: $-skeleton-border-radius-rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-circle {
|
&-circle {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
width: $skeleton-circle-height-default;
|
width: $-skeleton-circle-height-default;
|
||||||
height: $skeleton-circle-height-default;
|
height: $-skeleton-circle-height-default;
|
||||||
border-radius: $skeleton-border-radius-circle;
|
border-radius: $-skeleton-border-radius-circle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@include m(animation) {
|
@include m(animation) {
|
||||||
@ -63,7 +63,7 @@
|
|||||||
content: ' ';
|
content: ' ';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
animation: wd-skeleton-gradient 1.5s linear 2s infinite;
|
animation: wd-skeleton-gradient 1.5s linear 2s infinite;
|
||||||
background: linear-gradient(90deg, rgba(255, 255, 255, 0), $skeleton-animation-gradient, rgba(255, 255, 255, 0));
|
background: linear-gradient(90deg, rgba(255, 255, 255, 0), $-skeleton-animation-gradient, rgba(255, 255, 255, 0));
|
||||||
inset: 0;
|
inset: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@
|
|||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
background-color: $skeleton-animation-flashed;
|
background-color: $-skeleton-animation-flashed;
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|||||||
2
src/uni_modules/wot-design-uni/global.d.ts
vendored
2
src/uni_modules/wot-design-uni/global.d.ts
vendored
@ -67,6 +67,8 @@ declare module '@vue/runtime-core' {
|
|||||||
WdTransition: typeof import('./components/wd-transition/wd-transition.vue')['default']
|
WdTransition: typeof import('./components/wd-transition/wd-transition.vue')['default']
|
||||||
WdUpload: typeof import('./components/wd-upload/wd-upload.vue')['default']
|
WdUpload: typeof import('./components/wd-upload/wd-upload.vue')['default']
|
||||||
WdNotify: typeof import('./components/wd-notify/wd-notify.vue')['default']
|
WdNotify: typeof import('./components/wd-notify/wd-notify.vue')['default']
|
||||||
|
WdWatermark: typeof import('./components/wd-watermark/wd-watermark.vue')['default']
|
||||||
|
WdCircle: typeof import('./components/wd-circle/wd-circle.vue')['default']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user