Skip to content

Commit

Permalink
refactor(circle-progress): move to script setup (jd-opensource#2969)
Browse files Browse the repository at this point in the history
  • Loading branch information
eiinu authored Mar 13, 2024
1 parent 88d1462 commit c043695
Show file tree
Hide file tree
Showing 13 changed files with 280 additions and 256 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<nut-space>
<nut-circle-progress :progress="50" color="red" />
<nut-circle-progress :progress="50" color="skyblue" />
<nut-circle-progress :progress="100" :color="gradientColor" />
</nut-space>
</template>
Expand Down
1 change: 1 addition & 0 deletions src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,7 @@
"name": "CircleProgress",
"cName": "环形进度条",
"desc": "用来展示进度",
"setup": true,
"author": "Drjingubo"
},
{
Expand Down
2 changes: 1 addition & 1 deletion src/packages/__VUE/circleprogress/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils';
import Circleprogress from '../index.vue';
import Circleprogress from '../';

test('CircleProgress: should change stoke when use width props', async () => {
const wrapper = mount(Circleprogress, {
Expand Down
111 changes: 111 additions & 0 deletions src/packages/__VUE/circleprogress/circle-progress.taro.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<template>
<view class="nut-circle-progress" :style="{ height: Number(radius) * 2 + 'px', width: Number(radius) * 2 + 'px' }">
<div :style="style"></div>
<div class="nut-circle-progress__text">
<slot>
<span>{{ progress }}%</span>
</slot>
</div>
</view>
</template>

<script setup lang="ts">
import Taro from '@tarojs/taro';
import { computed, ref, watch } from 'vue';
import type { CircleProgressStrokeLinecap } from './types';
interface Item {
key?: string;
value?: string;
}
defineOptions({
name: 'NutCircleProgress'
});
export type CircleProgressProps = Partial<{
progress: string | number;
strokeWidth: string | number;
radius: string | number;
strokeLinecap: CircleProgressStrokeLinecap;
color: any;
pathColor: string;
clockwise: boolean;
}>;
const props = withDefaults(defineProps<CircleProgressProps>(), {
progress: 0,
strokeWidth: 5,
radius: 50,
strokeLinecap: 'round',
color: '#fa2c19',
pathColor: '#d9d9d9',
clockwise: true
});
const isIos = Taro.getSystemInfoSync().platform === 'ios';
const currentRate = ref(props.progress);
const refRandomId = Math.random().toString(36).slice(-8);
const isObject = (val: unknown): val is Record<any, any> => val !== null && typeof val === 'object';
const transColor = (color: string | undefined) => {
return color && color.replace('#', '%23');
};
const stop = () => {
if (!isObject(props.color)) {
return [];
}
let color = props.color;
const colorArr = Object.keys(color).sort((a, b) => parseFloat(a) - parseFloat(b));
let stopArr: object[] = [];
colorArr.map((item) => {
let obj = {
key: '',
value: ''
};
obj.key = item;
obj.value = color[item];
stopArr.push(obj);
});
return stopArr;
};
const style = computed(() => {
let { strokeWidth } = props;
let stopArr: Array<object> = stop();
let stopDom: string[] = [];
if (stopArr) {
stopArr.map((item: Item) => {
let obj = '';
obj = `%3Cstop offset='${item.key}' stop-color='${transColor(item.value)}'/%3E`;
stopDom.push(obj);
});
}
let perimeter = 283;
let progress = +currentRate.value;
let offset = (perimeter * Number(format(parseFloat(progress.toFixed(1))))) / 100;
const isWise = props.clockwise ? 1 : 0;
const color = isObject(props.color) ? `url(%23${refRandomId})` : transColor(props.color);
let d = `M 50 50 m 0 -45 a 45 45 0 1 ${isWise} 0 90 a 45 45 0 1, ${isWise} 0 -90`;
const pa = `%3Cdefs%3E%3ClinearGradient id='${refRandomId}' x1='100%25' y1='0%25' x2='0%25' y2='0%25'%3E${stopDom}%3C/linearGradient%3E%3C/defs%3E`;
const path = `%3Cpath d='${d}' stroke-width='${strokeWidth}' stroke='${transColor(props.pathColor)}' fill='none'/%3E`;
const path1 = `%3Cpath d='${d}' stroke-width='${strokeWidth}' stroke-dasharray='${offset},${perimeter}' stroke-linecap='round' stroke='${color}' fill='none'/%3E`;
return {
background: `url("data:image/svg+xml,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E${pa}${path}${path1}%3C/svg%3E")`,
width: '100%',
height: '100%',
transition: `${isIos ? '' : 'background-image .3s ease 0s, '}stroke .3s ease 0s`
};
});
const format = (progress: string | number) => Math.min(Math.max(+progress, 0), 100);
watch(
() => props.progress,
(value) => {
currentRate.value = Math.min(Math.max(+value, 0), 100);
}
);
</script>
103 changes: 103 additions & 0 deletions src/packages/__VUE/circleprogress/circle-progress.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<template>
<div class="nut-circle-progress" :style="{ height: Number(radius) * 2 + 'px', width: Number(radius) * 2 + 'px' }">
<svg viewBox="0 0 100 100">
<defs>
<linearGradient :id="refRandomId" x1="100%" y1="0%" x2="0%" y2="0%">
<stop v-for="(item, index) in stop" :key="index" :offset="item.key" :stop-color="item.value"></stop>
</linearGradient>
</defs>
<path class="nut-circle-progress__path" :style="pathStyle" :d="path" fill="none" :stroke-width="strokeWidth">
>
</path>
<path
class="nut-circle-progress__hover"
:style="hoverStyle"
:d="path"
fill="none"
:stroke="hoverColor"
:stroke-linecap="strokeLinecap"
:stroke-width="strokeWidth"
></path>
</svg>
<div class="nut-circle-progress__text">
<slot>
<div>{{ progress }}%</div>
</slot>
</div>
</div>
</template>

<script setup lang="ts">
import { computed } from 'vue';
import { isObject } from '@/packages/utils/util';
import type { CircleProgressStrokeLinecap } from './types';
export interface stopArr {
key: string;
value: string;
}
defineOptions({
name: 'NutCircleProgress'
});
export type CircleProgressProps = Partial<{
progress: string | number;
strokeWidth: string | number;
radius: string | number;
strokeLinecap: CircleProgressStrokeLinecap;
color: any;
pathColor: string;
clockwise: boolean;
}>;
const props = withDefaults(defineProps<CircleProgressProps>(), {
progress: 0,
strokeWidth: 5,
radius: 50,
strokeLinecap: 'round',
color: '#fa2c19',
pathColor: '#d9d9d9',
clockwise: true
});
const refRandomId = Math.random().toString(36).slice(-8);
const path = computed(() => {
const isWise = props.clockwise ? 1 : 0;
return `M 50 50 m 0 -45 a 45 45 0 1 ${isWise} 0 90 a 45 45 0 1, ${isWise} 0 -90`;
});
const hoverColor = computed(() => {
return isObject(props.color) ? `url(#${refRandomId})` : props.color;
});
const hoverStyle = computed(() => {
let perimeter = 283;
let offset = (perimeter * Number(props.progress)) / 100;
return {
stroke: isObject(props.color) ? `url(#${refRandomId})` : props.color,
strokeDasharray: `${offset}px ${perimeter}px`
};
});
const pathStyle = computed(() => {
return {
stroke: props.pathColor
};
});
const stop = computed(() => {
if (!isObject(props.color)) {
return;
}
let color = props.color;
const colorArr = Object.keys(color).sort((a, b) => parseFloat(a) - parseFloat(b));
let stopArr: stopArr[] = [];
colorArr.map((item) => {
let obj = {
key: '',
value: ''
};
obj.key = item;
obj.value = color[item];
stopArr.push(obj);
});
return stopArr;
});
</script>
2 changes: 1 addition & 1 deletion src/packages/__VUE/circleprogress/demo/color.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<nut-space>
<nut-circle-progress :progress="50" color="red" />
<nut-circle-progress :progress="50" color="skyblue" />
<nut-circle-progress :progress="100" :color="gradientColor" />
</nut-space>
</template>
Expand Down
12 changes: 12 additions & 0 deletions src/packages/__VUE/circleprogress/doc.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ app.use(CircleProgress);
| --- | --- |
| default | Custom Content |

### Types version

The component exports the following type definitions:

```js
import type {
CircleProgressStrokeLinecap,
CircleProgressProps,
CircleProgressInstance
} from '@nutui/nutui';
```

## Theming

### CSS Variables
Expand Down
12 changes: 12 additions & 0 deletions src/packages/__VUE/circleprogress/doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ app.use(CircleProgress);
| --- | --- |
| default | 自定义文字内容 |

### 类型定义 version

组件导出以下类型定义:

```js
import type {
CircleProgressStrokeLinecap,
CircleProgressProps,
CircleProgressInstance
} from '@nutui/nutui';
```

## 主题定制

### 样式变量
Expand Down
12 changes: 12 additions & 0 deletions src/packages/__VUE/circleprogress/doc.taro.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ app.use(CircleProgress);
| --- | --- |
| default | 自定义文字内容 |

### 类型定义 version

组件导出以下类型定义:

```js
import type {
CircleProgressStrokeLinecap,
CircleProgressProps,
CircleProgressInstance
} from '@nutui/nutui-taro';
```

## 主题定制

### 样式变量
Expand Down
13 changes: 13 additions & 0 deletions src/packages/__VUE/circleprogress/index.taro.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import CircleProgress from './circle-progress.taro.vue';
import type { ComponentPublicInstance } from 'vue';
import { withInstall } from '@/packages/utils';

withInstall(CircleProgress);

export type { CircleProgressProps } from './circle-progress.taro.vue';

export type { CircleProgressStrokeLinecap } from './types';

export type CircleProgressInstance = ComponentPublicInstance & InstanceType<typeof CircleProgress>;

export { CircleProgress, CircleProgress as default };
Loading

0 comments on commit c043695

Please sign in to comment.