-
Notifications
You must be signed in to change notification settings - Fork 834
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: 头像裁剪组件 * docs: update config.json * feat: 增加bottom插槽,控制工具栏位置,抛出工具栏相关方法 * feat: 中间的文字提示可以通过props更改 * feat: 命名规范更改 * docs: update * feat: 头像裁剪组件-taro版本 * feat: 冲突 * feat: 优化文档结构 * feat: 针对web绘制使用设备像素比提升图像质量 * feat: 适配支付宝小程序canvas 2d,要求基础库版本2.7.0或更高 * feat: vue版本优化获取元素宽高的方式 * test: update test * test: update test avatarcropper toouch * Revert "test: update test avatarcropper toouch" This reverts commit 81f0843. * test: update test avatarcropper toouch * test: touch x * test: update touch * test: update test image * test: update input set value * Revert "test: update test image" This reverts commit ef51d8e.
- Loading branch information
Showing
17 changed files
with
1,953 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
packages/nutui-taro-demo/src/business/pages/avatarcropper/index.config.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export default { | ||
navigationBarTitleText: 'AvatarCropper' | ||
}; |
50 changes: 50 additions & 0 deletions
50
packages/nutui-taro-demo/src/business/pages/avatarcropper/index.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
<template> | ||
<div class="demo barrage-demo" :class="{ web: env === 'WEB' }"> | ||
<Header v-if="env === 'WEB'" /> | ||
<h2>基础用法</h2> | ||
<nut-cell> | ||
<nut-avatar-cropper @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"> | ||
<nut-avatar size="large"> | ||
<img :src="imageUrl" /> | ||
</nut-avatar> | ||
<template #toolbar> | ||
<div class="toolbar"> | ||
<nut-button type="primary" @click="avatarCropperRef.cancel()">取消</nut-button> | ||
<nut-button type="primary" @click="avatarCropperRef.reset()">重置</nut-button> | ||
<nut-button type="primary" @click="avatarCropperRef.rotate()">旋转</nut-button> | ||
<nut-button type="primary" @click="avatarCropperRef.confirm()">确认</nut-button> | ||
</div> | ||
</template> | ||
</nut-avatar-cropper> | ||
</nut-cell> | ||
</div> | ||
</template> | ||
|
||
<script lang="ts" setup> | ||
import { ref } from 'vue'; | ||
import Taro from '@tarojs/taro'; | ||
import Header from '../../../components/header.vue'; | ||
const env = Taro.getEnv(); | ||
const imageUrl = ref( | ||
'https://img12.360buyimg.com/imagetools/jfs/t1/196430/38/8105/14329/60c806a4Ed506298a/e6de9fb7b8490f38.png' | ||
); | ||
const avatarCropperRef = ref(); | ||
const cutImage = (url: string) => { | ||
imageUrl.value = url; | ||
}; | ||
</script> | ||
|
||
<style> | ||
.toolbar { | ||
display: flex; | ||
justify-content: space-between; | ||
} | ||
</style> |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
src/packages/__VUE/avatarcropper/__tests__/__snapshots__/avatarcropper.spec.ts.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html | ||
|
||
exports[`layout default slot 1`] = ` | ||
"<div class=\\"nut-avatar-cropper\\" data-edit-text=\\"编辑\\"><img src=\\"https://img12.360buyimg.com/imagetools/jfs/t1/196430/38/8105/14329/60c806a4Ed506298a/e6de9fb7b8490f38.png\\"><input type=\\"file\\" accept=\\"image/*\\" class=\\"nut-avatar-cropper__input\\"></div> | ||
<div class=\\"nut-cropper-popup\\" style=\\"display: none;\\"><canvas class=\\"nut-cropper-popup__canvas\\"></canvas> | ||
<div class=\\"nut-cropper-popup__highlight\\"> | ||
<div class=\\"highlight\\" style=\\"width: 0px; height: 0px;\\"></div> | ||
</div> | ||
<div class=\\"nut-cropper-popup__toolbar bottom\\"> | ||
<div class=\\"flex-sb\\"> | ||
<div class=\\"nut-cropper-popup__toolbar-item\\"> | ||
<view class=\\"nut-button nut-button--danger nut-button--normal nut-button--round\\"> | ||
<view class=\\"nut-button__wrap\\"> | ||
<!--v-if--> | ||
<!--v-if--> | ||
<view class=\\"\\">取消</view> | ||
</view> | ||
</view> | ||
</div> | ||
<div class=\\"nut-cropper-popup__toolbar-item\\"><svg class=\\"nut-icon nut-icon-refresh2\\" style=\\"color: rgb(255, 255, 255);\\" xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 1024 1024\\" role=\\"presentation\\"> | ||
<path d=\\"M771.938 315.077h199.55L958.358 469.99 758.81 364.964c-13.128-7.877-18.38-23.63-10.502-36.759 2.625-7.877 13.128-13.128 23.63-13.128zm-535.63 393.846H44.636L57.764 554.01l191.672 105.026c13.128 7.877 18.38 23.63 10.502 36.759-5.25 7.877-15.753 13.128-23.63 13.128zM509.374 1024C257.313 1024 44.636 845.456 5.251 596.02 0 575.016 15.754 556.637 36.76 551.386c21.005-2.626 42.01 10.502 44.636 31.507 34.133 210.052 215.302 362.339 427.98 362.339 191.671 0 362.338-128.657 417.476-312.452 5.252-21.005 28.882-34.133 49.887-26.256 21.006 5.251 34.134 28.882 26.257 49.887C937.354 871.713 735.179 1024 509.375 1024zm467.364-551.385c-18.379 0-36.759-13.128-39.384-34.133C903.22 231.056 722.05 78.77 509.374 78.77c-191.671 0-362.338 128.657-414.85 312.452-5.252 21.005-28.883 34.133-49.888 26.256-21.005-5.251-34.133-28.882-26.257-49.887C81.395 152.287 283.57 0 509.374 0c252.062 0 464.739 178.544 504.123 427.98 2.626 21.005-10.502 42.01-31.507 44.635h-5.252z\\" fill=\\"currentColor\\" fill-opacity=\\"0.9\\"></path> | ||
</svg></div> | ||
<div class=\\"nut-cropper-popup__toolbar-item\\"><svg class=\\"nut-icon nut-icon-retweet\\" style=\\"color: rgb(255, 255, 255);\\" xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 1024 1024\\" role=\\"presentation\\"> | ||
<path d=\\"M136 552h63.6c4.4 0 8-3.6 8-8V288.7h528.6v72.6c0 1.9.6 3.7 1.8 5.2 2.9 3.6 8.1 4.3 11.7 1.4L893 255.4c4.3-5 3.6-10.3 0-13.2L749.7 129.8c-1.5-1.2-3.3-1.8-5.2-1.8-4.6 0-8.4 3.8-8.4 8.4V209H199.7c-39.5 0-71.7 32.2-71.7 71.8V544c0 4.4 3.6 8 8 8zm752-80h-63.6c-4.4 0-8 3.6-8 8v255.3H287.8v-72.6c0-1.9-.6-3.7-1.8-5.2-2.9-3.6-8.1-4.3-11.7-1.4L131 768.6c-4.3 5-3.6 10.3 0 13.2l143.3 112.4c1.5 1.2 3.3 1.8 5.2 1.8 4.6 0 8.4-3.8 8.4-8.4V815h536.6c39.5 0 71.7-32.2 71.7-71.8V480c-.2-4.4-3.8-8-8.2-8z\\" fill=\\"currentColor\\" fill-opacity=\\"0.9\\"></path> | ||
</svg></div> | ||
<div class=\\"nut-cropper-popup__toolbar-item\\"> | ||
<view class=\\"nut-button nut-button--success nut-button--normal nut-button--round\\"> | ||
<view class=\\"nut-button__wrap\\"> | ||
<!--v-if--> | ||
<!--v-if--> | ||
<view class=\\"\\">确定</view> | ||
</view> | ||
</view> | ||
</div> | ||
</div> | ||
</div> | ||
</div>" | ||
`; |
83 changes: 83 additions & 0 deletions
83
src/packages/__VUE/avatarcropper/__tests__/avatarcropper.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import 'vitest-canvas-mock'; | ||
import { mount } from '@vue/test-utils'; | ||
import AvatarCropper from '../index.vue'; | ||
import { sleep, trigger, triggerDrag } from '@/packages/utils/unit'; | ||
import { h } from 'vue'; | ||
|
||
const mockFile = new File([new ArrayBuffer(10000)], 'test.jpg', { | ||
type: 'image/jpg' | ||
}); | ||
|
||
test('layout default slot', () => { | ||
const wrapper = mount(AvatarCropper, { | ||
slots: { | ||
default: h('img', { | ||
src: 'https://img12.360buyimg.com/imagetools/jfs/t1/196430/38/8105/14329/60c806a4Ed506298a/e6de9fb7b8490f38.png' | ||
}) | ||
} | ||
}); | ||
|
||
expect(wrapper.html()).toMatchSnapshot(); | ||
expect(wrapper.find('.nut-avatar-cropper').html()).toContain( | ||
'<img src="https://img12.360buyimg.com/imagetools/jfs/t1/196430/38/8105/14329/60c806a4Ed506298a/e6de9fb7b8490f38.png">' | ||
); | ||
}); | ||
|
||
test('should render base cutAvatar and type', async () => { | ||
const wrapper = mount(AvatarCropper); | ||
const up_load = wrapper.find('.nut-avatar-cropper'); | ||
expect(up_load.exists()).toBe(true); | ||
const up_load1 = wrapper.find('.nut-avatar-cropper__input'); | ||
expect(up_load1.attributes().type).toBe('file'); | ||
}); | ||
|
||
test('AvatarCropper: Select the image to open the crop window', async () => { | ||
const wrapper = mount(AvatarCropper); | ||
const input: any = wrapper.find<HTMLInputElement>('.nut-avatar-cropper__input'); | ||
expect(input.exists()).toBe(true); | ||
const smallFile = new File([new ArrayBuffer(100)], 'small.jpg'); | ||
Object.defineProperty(input.element, 'files', { | ||
get: vi.fn().mockReturnValue([mockFile, smallFile]) | ||
}); | ||
expect(wrapper.find('.nut-cropper-popup').attributes()).toHaveProperty('style', 'display: none;'); | ||
await input.trigger('change'); | ||
await sleep(); | ||
expect(wrapper.find('.nut-cropper-popup').attributes()).toHaveProperty('style', ''); | ||
const canvas = wrapper.find('.nut-cropper-popup__canvas'); | ||
expect(canvas.exists()).toBe(true); | ||
|
||
const track = wrapper.find('.nut-cropper-popup__highlight'); | ||
|
||
trigger(track, 'touchstart', 0, 0, { x: 0, y: 0 }); | ||
trigger(track, 'touchmove', 20, 20, { x: 40, y: 60 }); | ||
trigger(track, 'touchend', 20, 100, { x: 40, y: 60 }); | ||
|
||
triggerDrag(track, 50, 60); | ||
const toolbar = wrapper.findAll('.nut-cropper-popup__toolbar-item'); | ||
expect(toolbar.length).toBe(4); | ||
|
||
const cancel = toolbar[0]; | ||
cancel.trigger('click'); | ||
expect(wrapper.emitted('cancel')).toBeTruthy(); | ||
expect(input.element.value).toBe(''); | ||
await sleep(); | ||
expect(wrapper.find('.nut-cropper-popup').attributes()).toHaveProperty('style', 'display: none;'); | ||
|
||
const reset = toolbar[1]; | ||
reset.trigger('click'); | ||
expect(wrapper.vm.angle).toBe(0); | ||
|
||
const rotate = toolbar[2]; | ||
rotate.trigger('click'); | ||
expect(wrapper.vm.angle).toBe(90); | ||
triggerDrag(track, 1000, 2000); | ||
rotate.trigger('click'); | ||
expect(wrapper.vm.angle).toBe(180); | ||
rotate.trigger('click'); | ||
rotate.trigger('click'); | ||
expect(wrapper.vm.angle).toBe(0); | ||
|
||
const confirm = toolbar[3]; | ||
confirm.trigger('click'); | ||
expect(wrapper.emitted('confirm')).toBeTruthy(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<template> | ||
<div class="demo full"> | ||
<h2>基础用法</h2> | ||
<nut-cell> | ||
<nut-avatar-cropper @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"> | ||
<nut-avatar size="large"> | ||
<img :src="imageUrl" /> | ||
</nut-avatar> | ||
<template #toolbar> | ||
<div class="toolbar"> | ||
<nut-button type="primary" @click="avatarCropperRef.cancel()">取消</nut-button> | ||
<nut-button type="primary" @click="avatarCropperRef.reset()">重置</nut-button> | ||
<nut-button type="primary" @click="avatarCropperRef.rotate()">旋转</nut-button> | ||
<nut-button type="primary" @click="avatarCropperRef.confirm()">确认</nut-button> | ||
</div> | ||
</template> | ||
</nut-avatar-cropper> | ||
</nut-cell> | ||
</div> | ||
</template> | ||
|
||
<script lang="ts" setup> | ||
import { ref } from 'vue'; | ||
const imageUrl = ref( | ||
'https://img12.360buyimg.com/imagetools/jfs/t1/196430/38/8105/14329/60c806a4Ed506298a/e6de9fb7b8490f38.png' | ||
); | ||
const avatarCropperRef = ref(); | ||
const cutImage = (url: string) => { | ||
imageUrl.value = url; | ||
}; | ||
</script> | ||
|
||
<style> | ||
.toolbar { | ||
display: flex; | ||
justify-content: space-between; | ||
} | ||
</style> |
Oops, something went wrong.