Commit ecaddf9b by fanx

完成头像拍照裁剪功能

1 parent b80f05a7
...@@ -17,6 +17,10 @@ body { ...@@ -17,6 +17,10 @@ body {
padding: 0; padding: 0;
} }
img {
width: 100%;
}
@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) { @supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) {
.iPhone { .iPhone {
......
...@@ -25,12 +25,12 @@ ...@@ -25,12 +25,12 @@
.icon-logo { width: 224px; height: 224px; background-position: -1175px -737px; } .icon-logo { width: 224px; height: 224px; background-position: -1175px -737px; }
.icon-password { width: 36px; height: 36px; background-position: -2767px -1598px; } .icon-password { width: 36px; height: 36px; background-position: -2767px -1598px; }
.icon-photo-default { width: 124px; height: 124px; background-position: -1232px -526px; } .icon-photo-default { width: 124px; height: 124px; background-position: -1232px -526px; }
.icon-question-icon { width: 36px; height: 36px; background-position: -2823px -1598px; }
.icon-quit-member { width: 90px; height: 90px; background-position: -1734px -526px; } .icon-quit-member { width: 90px; height: 90px; background-position: -1734px -526px; }
.icon-shtyxydm { width: 54px; height: 54px; background-position: -2180px -1598px; } .icon-shtyxydm { width: 54px; height: 54px; background-position: -2180px -1598px; }
.icon-tel { width: 36px; height: 36px; background-position: -2823px -1598px; } .icon-tel { width: 36px; height: 36px; background-position: -1844px -526px; }
.icon-time-update { width: 45px; height: 45px; background-position: -2254px -1598px; } .icon-time-update { width: 45px; height: 45px; background-position: -2254px -1598px; }
.icon-user-question { width: 32px; height: 36px; background-position: -2012px -526px; } .icon-user-question { width: 32px; height: 36px; background-position: -2012px -526px; }
.icon-user { width: 36px; height: 36px; background-position: -1844px -526px; } .icon-user { width: 36px; height: 36px; background-position: -1900px -526px; }
.icon-verification { width: 36px; height: 36px; background-position: -1900px -526px; } .icon-verification { width: 36px; height: 36px; background-position: -1956px -526px; }
.icon-wechat { width: 80px; height: 78px; background-position: -2080px -1598px; } .icon-wechat { width: 80px; height: 78px; background-position: -2080px -1598px; }
\ No newline at end of file \ No newline at end of file
.icon-question-icon { width: 36px; height: 36px; background-position: -1956px -526px; }
\ No newline at end of file \ No newline at end of file

1.47 MB | W: | H:

1.47 MB | W: | H:

src/assets/images/sprite.png
src/assets/images/sprite.png
src/assets/images/sprite.png
src/assets/images/sprite.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -65,9 +65,6 @@ export default { ...@@ -65,9 +65,6 @@ export default {
type: Boolean, type: Boolean,
default: false default: false
}, },
onBack: {
type: Function,
}
}, },
computed: { computed: {
...mapGetters('common', ['GStatusBarHeight']), ...mapGetters('common', ['GStatusBarHeight']),
...@@ -99,7 +96,7 @@ export default { ...@@ -99,7 +96,7 @@ export default {
methods: { methods: {
handleBack () { handleBack () {
if (this.showBack) { if (this.showBack) {
this.onBack() this.$emit('onBack')
} else { } else {
this.$router.back() this.$router.back()
} }
......
...@@ -9,6 +9,7 @@ const buttonEn = { ...@@ -9,6 +9,7 @@ const buttonEn = {
okUnbinding: 'Ok', okUnbinding: 'Ok',
clear: 'Clear', clear: 'Clear',
finish: 'Finish', finish: 'Finish',
save: 'Save'
} }
} }
const buttonZn = { const buttonZn = {
...@@ -22,6 +23,7 @@ const buttonZn = { ...@@ -22,6 +23,7 @@ const buttonZn = {
okUnbinding: '确定解除', okUnbinding: '确定解除',
clear: '清空', clear: '清空',
finish: '完成', finish: '完成',
save: '保存'
} }
} }
export default { export default {
......
...@@ -13,6 +13,7 @@ const titleEn = { ...@@ -13,6 +13,7 @@ const titleEn = {
privacyPolicy: 'Privacy Policy', privacyPolicy: 'Privacy Policy',
serviceAgreement: 'Service Agreement', serviceAgreement: 'Service Agreement',
person: 'Personal', person: 'Personal',
photo: 'Edit Photo',
nickName: 'Edit NickName', nickName: 'Edit NickName',
name: 'Edit Name', name: 'Edit Name',
email: 'Edit Email', email: 'Edit Email',
...@@ -34,6 +35,7 @@ const titleZn = { ...@@ -34,6 +35,7 @@ const titleZn = {
privacyPolicy: '隐私政策', privacyPolicy: '隐私政策',
serviceAgreement: '服务协议', serviceAgreement: '服务协议',
person: '个人信息', person: '个人信息',
photo: '设置昵称',
nickName: '设置昵称', nickName: '设置昵称',
name: '设置姓名', name: '设置姓名',
email: '设置邮箱', email: '设置邮箱',
......
...@@ -25,7 +25,8 @@ import { ...@@ -25,7 +25,8 @@ import {
Uploader, Uploader,
List, List,
PullRefresh, PullRefresh,
SwipeCell SwipeCell,
DatetimePicker
} from 'vant' } from 'vant'
import NafmHeader from '@/components/NafmHeader' import NafmHeader from '@/components/NafmHeader'
...@@ -61,7 +62,8 @@ import FooterBottom from '@/components/FooterBottom' ...@@ -61,7 +62,8 @@ import FooterBottom from '@/components/FooterBottom'
Uploader, Uploader,
List, List,
PullRefresh, PullRefresh,
SwipeCell SwipeCell,
DatetimePicker
].forEach(item => Vue.use(item)) ].forEach(item => Vue.use(item))
// 先预制,后期做统一调整 // 先预制,后期做统一调整
......
<template>
<div class="updatePhoto_container">
<NafmHeader :title="$t('title.photo')" :showBack="true" navClass="nafmii-head-bg3" @onBack="$emit('close')">
<template slot="right">
<span class="finish" @click="handleSave">{{$t('button.save')}}</span>
</template>
</NafmHeader>
<img :src="image" ref="image">
</div>
</template>
<script>
import 'cropperjs/dist/cropper.css';
import Cropper from 'cropperjs';
export default {
name: 'UpdataPhoto',
props: {
file: {
required: true
}
},
data() {
return {
image: window.URL.createObjectURL(this.file),
cropper: null,
}
},
mounted() {
const image = this.$refs.image;
this.cropper = new Cropper(image, {
viewMode: 1,
dragMode: 'move',
aspectRatio: 1,
cropBoxMovable: false,
cropBoxResizable: false,
background: false,
movable: true
});
},
methods: {
async getCroppedCanvas() {
return new Promise(resolve => {
this.cropper.getCroppedCanvas().toBlob((file) => {
resolve(file)
})
})
},
async handleSave() {
// 图片上传 格式Content-Type: multipart/form-data,则一定要提交FormatData对象
const fd = new FormData()
// fd.append('photo', this.file)
const file = await this.getCroppedCanvas()
fd.append('photo', file)
// api 调用 todo
// 更新父组件
this.$emit('upDataPhoto', window.URL.createObjectURL(file))
// 关闭弹出层
this.$emit('close')
// 保存成功
Toast('保存成功')
}
}
}
</script>
<style lang="less" scoped>
.updatePhoto_container {
height: 100vh;
}
/deep/ .cropper-view-box {
border-radius: 50%;
}
</style>
\ No newline at end of file \ No newline at end of file
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
<div class="person_cantainer"> <div class="person_cantainer">
<NafmHeader :title="$t('title.person')" navClass="nafmii-head-bg3" /> <NafmHeader :title="$t('title.person')" navClass="nafmii-head-bg3" />
<div class="setting_list"> <div class="setting_list">
<van-cell :title="$t('person.photo')" center is-link value-class="right_content"> <input type="file" hidden ref="file" accept="image/*" @change="onFileChange">
<van-cell :title="$t('person.photo')" center is-link value-class="right_content" @click="openFile">
<template #default> <template #default>
<img :src="headerIcon" class="headerImg" alt=""> <img :src="headerIcon" class="headerImg" alt="">
</template> </template>
...@@ -30,7 +31,7 @@ ...@@ -30,7 +31,7 @@
<span v-else>{{$t('person.nationalityPlaceholder')}}</span> <span v-else>{{$t('person.nationalityPlaceholder')}}</span>
</template> </template>
</van-cell> </van-cell>
<van-cell :title="$t('person.birthday')" center is-link value-class="right_content"> <van-cell :title="$t('person.birthday')" center is-link value-class="right_content" @click="openBirthday(true)">
<template #default> <template #default>
<span v-if="birthday">{{birthday}}</span> <span v-if="birthday">{{birthday}}</span>
<span v-else>{{$t('person.birthdayPlaceholder')}}</span> <span v-else>{{$t('person.birthdayPlaceholder')}}</span>
...@@ -49,9 +50,16 @@ ...@@ -49,9 +50,16 @@
</template> </template>
</van-cell> </van-cell>
</div> </div>
<van-popup v-model="showPicker" position="bottom">
<van-datetime-picker v-model="currentDate" type="date" :min-date="minDate" :max-date="maxDate" @confirm="selectBirthday" @cancel="showPicker = false" />
</van-popup>
<van-popup v-model="showPhoto" position="bottom" style="height:100%">
<UpdatePhoto v-if="showPhoto" :file="previewImg" @close="showPhoto=false" @upDataPhoto="headerIcon=$event" />
</van-popup>
</div> </div>
</template> </template>
<script> <script>
import UpdatePhoto from './components/UpdatePhoto';
export default { export default {
name: 'Person', name: 'Person',
data() { data() {
...@@ -62,9 +70,18 @@ export default { ...@@ -62,9 +70,18 @@ export default {
nationality: '', nationality: '',
birthday: '', birthday: '',
email: '', email: '',
company: '' company: '',
showPicker: false,
minDate: new Date(1900, 0, 1),
maxDate: new Date(2220, 11, 1),
currentDate: new Date(),
showPhoto: false,
previewImg: null
} }
}, },
components: {
UpdatePhoto
},
methods: { methods: {
editCommon(title, value) { editCommon(title, value) {
this.$router.push({ this.$router.push({
...@@ -74,18 +91,40 @@ export default { ...@@ -74,18 +91,40 @@ export default {
value value
} }
}) })
},
openBirthday(value) {
this.showPicker = value
},
// 选择年月日
selectBirthday(value) {
console.log('date', value)
this.showPicker = false
},
// 打开图片预览和拍照
openFile() {
this.$refs.file.click()
},
// 选择图片操作
onFileChange() {
const file = this.$refs.file.files[0]
this.previewImg = file
this.showPhoto = true
// 为了解决相同图片 不触发 change事件 所以要清空file的value值
this.$refs.file.value = ''
} }
} }
} }
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.person_cantainer{ .person_cantainer {
background: #fafafa; background: #fafafa;
height: 100vh; height: 100vh;
} }
.headerImg { .headerImg {
width: 55px; width: 50px;
height: 55px; height: 50px;
border-radius: 50%; border-radius: 50%;
} }
.right_content { .right_content {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!