papayaui 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/components/circle/circle.scss +19 -0
- package/components/circle/circle.vue +163 -0
- package/components/circle/demo.vue +21 -0
- package/components/circle/index.ts +4 -0
- package/components/circle/props.ts +59 -0
- package/components/index.ts +1 -0
- package/demos/circle/demo-1.vue +3 -0
- package/demos/circle/demo-2.vue +35 -0
- package/global.d.ts +1 -0
- package/package.json +2 -2
- package/styles/layout_border.scss +7 -1
- package/styles/layout_font.scss +3 -3
- package/styles/layout_grid.scss +3 -3
- package/styles/layout_margin.scss +12 -12
- package/styles/vars.scss +2 -1
- package/.DS_Store +0 -0
package/README.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
- 💪 Vue 3 Composition API
|
|
6
6
|
- 🔥 Written in TypeScript
|
|
7
|
+
- 🧀 [Document](https://jiangwei58.github.io/papayaui)
|
|
7
8
|
|
|
8
9
|
## 准备工作
|
|
9
10
|
|
|
@@ -83,8 +84,6 @@ pnpm install async-validator dayjs
|
|
|
83
84
|
// ...
|
|
84
85
|
"types": ["papayaui/global"]
|
|
85
86
|
},
|
|
86
|
-
// 防止组件props类型识别错误
|
|
87
|
-
"include": ["node_modules/papayaui/components/*/*.vue"]
|
|
88
87
|
}
|
|
89
88
|
```
|
|
90
89
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
@import '../../styles/vars.scss';
|
|
2
|
+
|
|
3
|
+
.#{$prefix}-circle {
|
|
4
|
+
position: relative;
|
|
5
|
+
display: inline-block;
|
|
6
|
+
text-align: center;
|
|
7
|
+
|
|
8
|
+
&__text {
|
|
9
|
+
position: absolute;
|
|
10
|
+
top: 50%;
|
|
11
|
+
left: 0;
|
|
12
|
+
width: 100%;
|
|
13
|
+
color: _var(circle-text-color, _var(color-black));
|
|
14
|
+
font-weight: _var(circle-font-weight, 500);
|
|
15
|
+
font-size: _var(circle-font-size, 14px);
|
|
16
|
+
line-height: _var(circle-text-line-height, 20px);
|
|
17
|
+
transform: translateY(-50%);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view :class="ns.b()">
|
|
3
|
+
<canvas
|
|
4
|
+
:id="id"
|
|
5
|
+
:canvas-id="id"
|
|
6
|
+
type="2d"
|
|
7
|
+
:style="{
|
|
8
|
+
width: getUnitValue(size, 'px'),
|
|
9
|
+
height: getUnitValue(size, 'px'),
|
|
10
|
+
}"
|
|
11
|
+
/>
|
|
12
|
+
<view v-if="!text" :class="ns.e('text')">
|
|
13
|
+
<slot></slot>
|
|
14
|
+
</view>
|
|
15
|
+
<cover-view v-else :class="ns.e('text')">{{ text }}</cover-view>
|
|
16
|
+
</view>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script setup lang="ts">
|
|
20
|
+
import { getCurrentInstance, onMounted, watch } from 'vue'
|
|
21
|
+
import { useNamespace } from '../../core'
|
|
22
|
+
import { getUnitValue } from '../../utils'
|
|
23
|
+
import { circleProps } from './props'
|
|
24
|
+
|
|
25
|
+
const ns = useNamespace('circle')
|
|
26
|
+
|
|
27
|
+
const props = defineProps(circleProps)
|
|
28
|
+
|
|
29
|
+
const instance = getCurrentInstance()
|
|
30
|
+
const id = ns.e('canvas') + Date.now()
|
|
31
|
+
|
|
32
|
+
const BEGIN_ANGLE = -Math.PI / 2
|
|
33
|
+
const PERIMETER = 2 * Math.PI
|
|
34
|
+
const STEP = 1
|
|
35
|
+
|
|
36
|
+
let context: CanvasRenderingContext2D | null = null
|
|
37
|
+
let currentValue = 0
|
|
38
|
+
|
|
39
|
+
onMounted(() => {
|
|
40
|
+
// #ifdef H5
|
|
41
|
+
initH5()
|
|
42
|
+
// #endif
|
|
43
|
+
// #ifndef H5
|
|
44
|
+
initMP()
|
|
45
|
+
// #endif
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
watch(
|
|
49
|
+
() => props.modelValue,
|
|
50
|
+
() => {
|
|
51
|
+
if (context) {
|
|
52
|
+
renderCircle(context)
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
const initMP = () => {
|
|
58
|
+
const ratio = uni.getSystemInfoSync().pixelRatio
|
|
59
|
+
const query = uni.createSelectorQuery()
|
|
60
|
+
query
|
|
61
|
+
.in(instance)
|
|
62
|
+
.select('#' + id)
|
|
63
|
+
.node(() => {})
|
|
64
|
+
.exec((res) => {
|
|
65
|
+
const canvas = res[0].node as HTMLCanvasElement
|
|
66
|
+
const canvasSize = props.size * ratio
|
|
67
|
+
canvas.width = canvasSize
|
|
68
|
+
canvas.height = canvasSize
|
|
69
|
+
context = canvas.getContext('2d')
|
|
70
|
+
if (!context) return
|
|
71
|
+
|
|
72
|
+
context.scale(ratio, ratio)
|
|
73
|
+
renderCircle(context)
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const initH5 = () => {
|
|
78
|
+
const ratio = window.devicePixelRatio
|
|
79
|
+
const canvasSize = props.size * ratio
|
|
80
|
+
const canvas = document.querySelector(`#${id} canvas`) as HTMLCanvasElement
|
|
81
|
+
canvas.width = canvasSize
|
|
82
|
+
canvas.height = canvasSize
|
|
83
|
+
context = canvas.getContext('2d')
|
|
84
|
+
if (!context) return
|
|
85
|
+
|
|
86
|
+
context.scale(ratio, ratio)
|
|
87
|
+
renderCircle(context)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const renderCircle = (ctx: CanvasRenderingContext2D) => {
|
|
91
|
+
if (props.speed <= 0 || props.speed > 1000) {
|
|
92
|
+
drawCircle(ctx, props.modelValue)
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let interval: number | null
|
|
97
|
+
currentValue = currentValue ?? 0
|
|
98
|
+
const run = () => {
|
|
99
|
+
interval = setTimeout(() => {
|
|
100
|
+
if (currentValue === props.modelValue) {
|
|
101
|
+
stop()
|
|
102
|
+
return
|
|
103
|
+
}
|
|
104
|
+
if (Math.abs(currentValue - props.modelValue) < STEP) {
|
|
105
|
+
currentValue = props.modelValue
|
|
106
|
+
} else if (currentValue < props.modelValue) {
|
|
107
|
+
currentValue += STEP
|
|
108
|
+
} else {
|
|
109
|
+
currentValue -= STEP
|
|
110
|
+
}
|
|
111
|
+
drawCircle(ctx, currentValue)
|
|
112
|
+
run()
|
|
113
|
+
}, 1000 / props.speed) as unknown as number | null
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const stop = () => {
|
|
117
|
+
if (interval) {
|
|
118
|
+
clearTimeout(interval)
|
|
119
|
+
interval = null
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
stop()
|
|
124
|
+
run()
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const drawLayerCircle = (ctx: CanvasRenderingContext2D) => {
|
|
128
|
+
drawCanvas(ctx, BEGIN_ANGLE, PERIMETER, props.layerColor)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const drawCircle = (ctx: CanvasRenderingContext2D, value: number) => {
|
|
132
|
+
const progress = PERIMETER * (value / 100)
|
|
133
|
+
const endAngle = props.clockwise ? BEGIN_ANGLE + progress : 3 * Math.PI - (BEGIN_ANGLE + progress)
|
|
134
|
+
ctx.clearRect(0, 0, props.size, props.size)
|
|
135
|
+
drawLayerCircle(ctx)
|
|
136
|
+
if (value !== 0) {
|
|
137
|
+
drawCanvas(ctx, BEGIN_ANGLE, endAngle, props.color, props.clockwise)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const drawCanvas = (
|
|
142
|
+
ctx: CanvasRenderingContext2D,
|
|
143
|
+
sRadian: number,
|
|
144
|
+
eRadian: number,
|
|
145
|
+
color: string,
|
|
146
|
+
clockwise = true,
|
|
147
|
+
) => {
|
|
148
|
+
const position = props.size / 2
|
|
149
|
+
const lineWidth = Number(props.strokeWidth)
|
|
150
|
+
const radius = position - lineWidth / 2
|
|
151
|
+
|
|
152
|
+
ctx.beginPath()
|
|
153
|
+
ctx.lineCap = 'round'
|
|
154
|
+
ctx.strokeStyle = color
|
|
155
|
+
ctx.lineWidth = lineWidth
|
|
156
|
+
ctx.arc(position, position, radius, sRadian, eRadian, !clockwise)
|
|
157
|
+
ctx.stroke()
|
|
158
|
+
}
|
|
159
|
+
</script>
|
|
160
|
+
|
|
161
|
+
<style lang="scss" scoped>
|
|
162
|
+
@import './circle.scss';
|
|
163
|
+
</style>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<DocDemoBlock title="基础用法" card>
|
|
3
|
+
<Demo1 />
|
|
4
|
+
</DocDemoBlock>
|
|
5
|
+
<DocDemoBlock title="样式定制" card>
|
|
6
|
+
<Demo2 />
|
|
7
|
+
</DocDemoBlock>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script setup lang="ts">
|
|
11
|
+
import DocDemoBlock from '../../doc/doc-demo-block.vue'
|
|
12
|
+
import Demo1 from '../../demos/circle/demo-1.vue'
|
|
13
|
+
import Demo2 from '../../demos/circle/demo-2.vue'
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<style lang="scss" scoped></style>
|
|
17
|
+
<style lang="scss">
|
|
18
|
+
page {
|
|
19
|
+
background-color: var(--pa-color-gray);
|
|
20
|
+
}
|
|
21
|
+
</style>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ExtractPropTypes } from 'vue'
|
|
2
|
+
|
|
3
|
+
export const circleProps = {
|
|
4
|
+
/**
|
|
5
|
+
* 目标进度
|
|
6
|
+
*/
|
|
7
|
+
modelValue: {
|
|
8
|
+
type: Number,
|
|
9
|
+
default: 0,
|
|
10
|
+
},
|
|
11
|
+
/**
|
|
12
|
+
* 圆环直径,单位px
|
|
13
|
+
*/
|
|
14
|
+
size: {
|
|
15
|
+
type: Number,
|
|
16
|
+
default: 100,
|
|
17
|
+
},
|
|
18
|
+
/**
|
|
19
|
+
* 进度条颜色
|
|
20
|
+
*/
|
|
21
|
+
color: {
|
|
22
|
+
type: String,
|
|
23
|
+
default: '#009c5d',
|
|
24
|
+
},
|
|
25
|
+
/**
|
|
26
|
+
* 轨道颜色
|
|
27
|
+
*/
|
|
28
|
+
layerColor: {
|
|
29
|
+
type: String,
|
|
30
|
+
default: '#fff',
|
|
31
|
+
},
|
|
32
|
+
/**
|
|
33
|
+
* 文字
|
|
34
|
+
*/
|
|
35
|
+
text: String,
|
|
36
|
+
/**
|
|
37
|
+
* 进度条宽度,单位px
|
|
38
|
+
*/
|
|
39
|
+
strokeWidth: {
|
|
40
|
+
type: [Number, String],
|
|
41
|
+
default: 4,
|
|
42
|
+
},
|
|
43
|
+
/**
|
|
44
|
+
* 是否顺时针
|
|
45
|
+
*/
|
|
46
|
+
clockwise: {
|
|
47
|
+
type: Boolean,
|
|
48
|
+
default: true,
|
|
49
|
+
},
|
|
50
|
+
/**
|
|
51
|
+
* 动画速度(单位为 value/s)
|
|
52
|
+
*/
|
|
53
|
+
speed: {
|
|
54
|
+
type: Number,
|
|
55
|
+
default: 50,
|
|
56
|
+
},
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export type CircleProps = ExtractPropTypes<typeof circleProps>
|
package/components/index.ts
CHANGED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view>
|
|
3
|
+
<pa-circle :model-value="progress" stroke-width="8" text="设置宽度" />
|
|
4
|
+
<pa-circle :model-value="progress" color="#ff2b2b" text="设置颜色" />
|
|
5
|
+
<pa-circle :model-value="progress" :clockwise="false" text="逆时针" />
|
|
6
|
+
<pa-circle :model-value="progress" :size="150" text="设置大小" />
|
|
7
|
+
</view>
|
|
8
|
+
<view class="mt-15">
|
|
9
|
+
<pa-button type="primary" @click="add">增加</pa-button>
|
|
10
|
+
<pa-button type="danger" class="ml-15" @click="subtract">减少</pa-button>
|
|
11
|
+
</view>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
import { ref } from 'vue'
|
|
16
|
+
|
|
17
|
+
const STEP = 10
|
|
18
|
+
const progress = ref(80)
|
|
19
|
+
|
|
20
|
+
const add = () => {
|
|
21
|
+
if (progress.value >= 100) return
|
|
22
|
+
progress.value += STEP
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const subtract = () => {
|
|
26
|
+
if (progress.value <= 0) return
|
|
27
|
+
progress.value -= STEP
|
|
28
|
+
}
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<style lang="scss" scoped>
|
|
32
|
+
:deep(.pa-circle) {
|
|
33
|
+
margin-right: 15px;
|
|
34
|
+
}
|
|
35
|
+
</style>
|
package/global.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ declare module '@vue/runtime-core' {
|
|
|
10
10
|
PaCheckbox: typeof import('papayaui/components/checkbox/checkbox.vue')['default']
|
|
11
11
|
PaCheckboxBtns: typeof import('papayaui/components/checkbox-btns/checkbox-btns.vue')['default']
|
|
12
12
|
PaCheckboxGroup: typeof import('papayaui/components/checkbox-group/checkbox-group.vue')['default']
|
|
13
|
+
PaCircle: typeof import('papayaui/components/circle/circle.vue')['default']
|
|
13
14
|
PaCollapse: typeof import('papayaui/components/collapse/collapse.vue')['default']
|
|
14
15
|
PaCollapseItem: typeof import('papayaui/components/collapse-item/collapse-item.vue')['default']
|
|
15
16
|
PaContainer: typeof import('papayaui/components/container/container.vue')['default']
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "papayaui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "适用于uniapp的ui扩展库",
|
|
5
5
|
"packageManager": "pnpm@8.6.0",
|
|
6
6
|
"dependencies": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"bugs": {
|
|
19
19
|
"url": "https://github.com/jiangwei58/papayaui/issues"
|
|
20
20
|
},
|
|
21
|
-
"homepage": "https://github.
|
|
21
|
+
"homepage": "https://jiangwei58.github.io/papayaui",
|
|
22
22
|
"author": "jiangw",
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"main": "index.ts",
|
|
@@ -60,9 +60,15 @@
|
|
|
60
60
|
// 定义圆角
|
|
61
61
|
@for $i from 3 through 35 {
|
|
62
62
|
.rounded-#{$i} {
|
|
63
|
-
border-radius:
|
|
63
|
+
border-radius: $i + $pixelUnit;
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
+
.rounded-none {
|
|
67
|
+
border-radius: 0;
|
|
68
|
+
}
|
|
69
|
+
.rounded-full {
|
|
70
|
+
border-radius: 9999px;
|
|
71
|
+
}
|
|
66
72
|
|
|
67
73
|
// 盒子模型
|
|
68
74
|
.box-border {
|
package/styles/layout_font.scss
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
//
|
|
1
|
+
// 定义字体大小
|
|
2
2
|
@for $i from 20 through 65 {
|
|
3
3
|
.text-#{$i} {
|
|
4
|
-
font-size:
|
|
4
|
+
font-size: $i + $pixelUnit;
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
// 定义字体行高
|
|
9
9
|
@for $i from 10 through 65 {
|
|
10
10
|
.leading-#{$i} {
|
|
11
|
-
line-height:
|
|
11
|
+
line-height: $i + $pixelUnit;
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
package/styles/layout_grid.scss
CHANGED
|
@@ -62,13 +62,13 @@
|
|
|
62
62
|
// 只要双数和能被5除尽的数
|
|
63
63
|
@if $i % 2 == 0 or $i % 5 == 0 {
|
|
64
64
|
.gap-#{$i} {
|
|
65
|
-
gap: $i +
|
|
65
|
+
gap: $i + $pixelUnit;
|
|
66
66
|
}
|
|
67
67
|
.gap-x-#{$i} {
|
|
68
|
-
column-gap: $i +
|
|
68
|
+
column-gap: $i + $pixelUnit;
|
|
69
69
|
}
|
|
70
70
|
.gap-y-#{$i} {
|
|
71
|
-
row-gap: $i +
|
|
71
|
+
row-gap: $i + $pixelUnit;
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
}
|
|
@@ -3,37 +3,37 @@
|
|
|
3
3
|
// 只要双数和能被5除尽的数
|
|
4
4
|
@if $i % 2 == 0 or $i % 5 == 0 {
|
|
5
5
|
.m-#{$i} {
|
|
6
|
-
margin: $i +
|
|
6
|
+
margin: $i + $pixelUnit !important;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
.p-#{$i} {
|
|
10
|
-
padding: $i +
|
|
10
|
+
padding: $i + $pixelUnit !important;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
.mx-#{$i} {
|
|
14
|
-
margin-left: $i +
|
|
15
|
-
margin-right: $i +
|
|
14
|
+
margin-left: $i + $pixelUnit;
|
|
15
|
+
margin-right: $i + $pixelUnit;
|
|
16
16
|
}
|
|
17
17
|
.my-#{$i} {
|
|
18
|
-
margin-top: $i +
|
|
19
|
-
margin-bottom: $i +
|
|
18
|
+
margin-top: $i + $pixelUnit;
|
|
19
|
+
margin-bottom: $i + $pixelUnit;
|
|
20
20
|
}
|
|
21
21
|
.px-#{$i} {
|
|
22
|
-
padding-left: $i +
|
|
23
|
-
padding-right: $i +
|
|
22
|
+
padding-left: $i + $pixelUnit;
|
|
23
|
+
padding-right: $i + $pixelUnit;
|
|
24
24
|
}
|
|
25
25
|
.py-#{$i} {
|
|
26
|
-
padding-top: $i +
|
|
27
|
-
padding-bottom: $i +
|
|
26
|
+
padding-top: $i + $pixelUnit;
|
|
27
|
+
padding-bottom: $i + $pixelUnit;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
@each $short, $long in l left, t top, r right, b bottom {
|
|
31
31
|
.m#{$short}-#{$i} {
|
|
32
|
-
margin-#{$long}: $i +
|
|
32
|
+
margin-#{$long}: $i + $pixelUnit !important;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
.p#{$short}-#{$i} {
|
|
36
|
-
padding-#{$long}: $i +
|
|
36
|
+
padding-#{$long}: $i + $pixelUnit !important;
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
}
|
package/styles/vars.scss
CHANGED
package/.DS_Store
DELETED
|
Binary file
|