Commit ecaddf9b by fanx

完成头像拍照裁剪功能

1 parent b80f05a7
......@@ -17,6 +17,10 @@ body {
padding: 0;
}
img {
width: 100%;
}
@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) {
.iPhone {
......
......@@ -25,12 +25,12 @@
.icon-logo { width: 224px; height: 224px; background-position: -1175px -737px; }
.icon-password { width: 36px; height: 36px; background-position: -2767px -1598px; }
.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-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-user-question { width: 32px; height: 36px; background-position: -2012px -526px; }
.icon-user { width: 36px; height: 36px; background-position: -1844px -526px; }
.icon-verification { width: 36px; height: 36px; background-position: -1900px -526px; }
.icon-user { 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; }
\ No newline at end of file
.icon-question-icon { width: 36px; height: 36px; background-position: -1956px -526px; }
\ 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 {
type: Boolean,
default: false
},
onBack: {
type: Function,
}
},
computed: {
...mapGetters('common', ['GStatusBarHeight']),
......@@ -99,7 +96,7 @@ export default {
methods: {
handleBack () {
if (this.showBack) {
this.onBack()
this.$emit('onBack')
} else {
this.$router.back()
}
......
......@@ -9,6 +9,7 @@ const buttonEn = {
okUnbinding: 'Ok',
clear: 'Clear',
finish: 'Finish',
save: 'Save'
}
}
const buttonZn = {
......@@ -22,6 +23,7 @@ const buttonZn = {
okUnbinding: '确定解除',
clear: '清空',
finish: '完成',
save: '保存'
}
}
export default {
......
......@@ -13,6 +13,7 @@ const titleEn = {
privacyPolicy: 'Privacy Policy',
serviceAgreement: 'Service Agreement',
person: 'Personal',
photo: 'Edit Photo',
nickName: 'Edit NickName',
name: 'Edit Name',
email: 'Edit Email',
......@@ -34,6 +35,7 @@ const titleZn = {
privacyPolicy: '隐私政策',
serviceAgreement: '服务协议',
person: '个人信息',
photo: '设置昵称',
nickName: '设置昵称',
name: '设置姓名',
email: '设置邮箱',
......
......@@ -25,7 +25,8 @@ import {
Uploader,
List,
PullRefresh,
SwipeCell
SwipeCell,
DatetimePicker
} from 'vant'
import NafmHeader from '@/components/NafmHeader'
......@@ -61,7 +62,8 @@ import FooterBottom from '@/components/FooterBottom'
Uploader,
List,
PullRefresh,
SwipeCell
SwipeCell,
DatetimePicker
].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
......@@ -2,7 +2,8 @@
<div class="person_cantainer">
<NafmHeader :title="$t('title.person')" navClass="nafmii-head-bg3" />
<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>
<img :src="headerIcon" class="headerImg" alt="">
</template>
......@@ -30,7 +31,7 @@
<span v-else>{{$t('person.nationalityPlaceholder')}}</span>
</template>
</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>
<span v-if="birthday">{{birthday}}</span>
<span v-else>{{$t('person.birthdayPlaceholder')}}</span>
......@@ -49,9 +50,16 @@
</template>
</van-cell>
</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>
</template>
<script>
import UpdatePhoto from './components/UpdatePhoto';
export default {
name: 'Person',
data() {
......@@ -62,9 +70,18 @@ export default {
nationality: '',
birthday: '',
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: {
editCommon(title, value) {
this.$router.push({
......@@ -74,18 +91,40 @@ export default {
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>
<style lang="less" scoped>
.person_cantainer{
.person_cantainer {
background: #fafafa;
height: 100vh;
}
.headerImg {
width: 55px;
height: 55px;
width: 50px;
height: 50px;
border-radius: 50%;
}
.right_content {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!