Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 头像裁剪 AvatarCropper 支持裁剪圆形 #2818

Merged
merged 3 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/packages/__VUE/avatarcropper/demo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@
</nut-avatar>
</nut-avatar-cropper>
</nut-cell>
<h2>裁剪圆形形状</h2>
<nut-cell>
<nut-avatar-cropper cut-shape="round" @confirm="cutImage">
<nut-avatar size="large">
<img :src="imageUrl" />
</nut-avatar>
</nut-avatar-cropper>
</nut-cell>
<h2>裁剪区域toolbar插槽</h2>
<nut-cell>
<nut-avatar-cropper ref="avatarCropperRef" toolbar-position="top" edit-text="修改" @confirm="cutImage">
Expand Down
26 changes: 26 additions & 0 deletions src/packages/__VUE/avatarcropper/doc.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,31 @@ const cutImage = (url) => {

:::

### Cut round shape

:::demo

```vue
<template>
<nut-avatar-cropper cut-shape="round" @confirm="cutImage">
<nut-avatar size="large">
<img :src="imageUrl" />
</nut-avatar>
</nut-avatar-cropper>
</template>
<script setup>
import { ref } from 'vue';
const imageUrl = ref(
'https://img12.360buyimg.com/imagetools/jfs/t1/196430/38/8105/14329/60c806a4Ed506298a/e6de9fb7b8490f38.png'
);
const cutImage = (url) => {
imageUrl.value = url;
};
</script>
```

:::

### Clipping region toolbar slots

Customize the clipping area toolbar, and toolbar-position controls the toolbar position
Expand Down Expand Up @@ -97,6 +122,7 @@ const cutImage = (url) => {
| edit-text | The text content in the middle | string | 编辑 |
| cancel-text | Cancel button text | string | 取消 |
| cancel-confirm | Confirm button text | string | 确认 |
| cut-shape | Cut round shape The optional value is:`square` `round` | string | square |

### AvatarCropper Slots

Expand Down
26 changes: 26 additions & 0 deletions src/packages/__VUE/avatarcropper/doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,31 @@ const cutImage = (url) => {

:::

### 裁剪圆形形状

:::demo

```vue
<template>
<nut-avatar-cropper cut-shape="round" @confirm="cutImage">
<nut-avatar size="large">
<img :src="imageUrl" />
</nut-avatar>
</nut-avatar-cropper>
</template>
<script setup>
import { ref } from 'vue';
const imageUrl = ref(
'https://img12.360buyimg.com/imagetools/jfs/t1/196430/38/8105/14329/60c806a4Ed506298a/e6de9fb7b8490f38.png'
);
const cutImage = (url) => {
imageUrl.value = url;
};
</script>
```

:::

### 裁剪区域toolbar插槽

自定义裁剪区域工具栏,toolbar-position控制工具栏位置
Expand Down Expand Up @@ -97,6 +122,7 @@ const cutImage = (url) => {
| edit-text | 中间的文字内容 | string | 编辑 |
| cancel-text | 取消按钮的文字 | string | 取消 |
| cancel-confirm | 确认按钮的文字 | string | 确认 |
| cut-shape | 裁剪形状,可选值为:`square` `round` | string | square |

### AvatarCropper Slots

Expand Down
3 changes: 3 additions & 0 deletions src/packages/__VUE/avatarcropper/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@
z-index: 1;
background-color: transparent;
box-shadow: 0 0 1000px 1000px rgba(0, 0, 0, 0.6);
&-round {
border-radius: 50%;
}
}
}
}
20 changes: 18 additions & 2 deletions src/packages/__VUE/avatarcropper/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
@touchend="onTouchEnd"
@touchcancel="onTouchEnd"
>
<div class="highlight" :style="highlightStyle"></div>
<div class="highlight" :class="{ 'highlight-round': cutShape === 'round' }" :style="highlightStyle"></div>
</div>
<div class="nut-cropper-popup__toolbar" :class="[toolbarPosition]">
<slot v-if="$slots.toolbar" name="toolbar"></slot>
Expand All @@ -44,7 +44,7 @@
import { watch, ref, reactive, toRefs, computed, Ref, PropType } from 'vue';
import NutButton from '../button/index.vue';
import { createComponent } from '@/packages/utils/create';
import type { AvatarCropperToolbarPosition } from './types';
import type { AvatarCropperToolbarPosition, CutShapeType } from './types';
const { create } = createComponent('avatar-cropper');
import { Refresh2, Retweet } from '@nutui/icons-vue';
import { useTouch } from '@/packages/utils/useTouch';
Expand Down Expand Up @@ -80,6 +80,10 @@
confirmText: {
type: String,
default: '确定'
},
cutShape: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

新增属性名称改为 shape 即可,它的类型名称为 组件名+属性名,即 AvatarCropperShape.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

有这样一个问题:nut-avatar-cropper 样式上有一个灰色遮盖层,是 after 伪元素,无法动态修改为圆形

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

你可参考react版本更改,我在react里面更改了一版,jdf2e/nutui-react#1842

type: String as PropType<CutShapeType>,
default: 'square'
}
},
emits: ['confirm', 'cancel'],
Expand Down Expand Up @@ -380,6 +384,18 @@
// 设置新canvas的大小与裁剪区域相同
croppedCanvas.width = width;
croppedCanvas.height = height;

// 裁剪形状为圆形
if (props.cutShape === 'round') {
const circle = {
x: width / 2,
y: height / 2,
r: width / 2
};
croppedCtx.arc(circle.x, circle.y, circle.r, 0, Math.PI * 2, false);
croppedCtx.clip();
}

Check warning on line 397 in src/packages/__VUE/avatarcropper/index.vue

View check run for this annotation

Codecov / codecov/patch

src/packages/__VUE/avatarcropper/index.vue#L390-L397

Added lines #L390 - L397 were not covered by tests

// 使用drawImage方法将原canvas中指定区域的内容绘制到新canvas上
canvas && croppedCtx.drawImage(canvas, sx, sy, width, height, 0, 0, width, height);

Expand Down
1 change: 1 addition & 0 deletions src/packages/__VUE/avatarcropper/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export type AvatarCropperToolbarPosition = 'top' | 'bottom';
export type AvatarCropperSizeType = 'original' | 'compressed';
export type AvatarCropperSourceType = 'album' | 'camera';
export type CutShapeType = 'square' | 'round';