首頁 > web前端 > Vue.js > Vue3中怎麼實現選取頭像並裁剪

Vue3中怎麼實現選取頭像並裁剪

WBOY
發布: 2023-05-29 10:22:49
轉載
1395 人瀏覽過

最終效果

Vue3中怎麼實現選取頭像並裁剪

安裝VueCropper元件

yarn add vue-cropper@next
登入後複製

上面的安裝值針對Vue3的,如果時Vue2或想使用其他的方式引用,請訪問它的npm官方地址:官方教程。

在元件中引用

使用時也很簡單,只需要引入對應的元件和它的樣式文件,我這裡沒有在全域引用,只在我的元件檔案中引入

<script>
import { userInfoByRequest } from &#39;../js/api&#39;
import { VueCropper } from &#39;vue-cropper&#39;
import &#39;vue-cropper/dist/index.css&#39;
export default {
    components: {
        VueCropper
    },
}
登入後複製

然後用<vue-cropper>標籤來進行使用,需要注意的是它需要有外層容器包裹,並且給外層容器設定指定的高度。

<el-dialog title="头像设置" v-model="showSetAvatarDialog">
            <div class="cropperBox">
                <vue-cropper ref="cropper" :canMoveBox="false" :img="avatarBase64" :fixedBox="true" :autoCrop="true"
                    autoCropWidth="200" autoCropHeight="200" outputType="png"></vue-cropper>
            </div>
            <div class="optionBtn">
                <el-button @click="rotateLeft"><i class="fa fa-rotate-left"></i>左旋转</el-button>
                <el-button @click="rotateRight"><i class="fa fa-rotate-right"></i>右旋转</el-button>
                <el-button @click="getPickAvatar" type="primary"><i class="fa fa-save"></i>保存</el-button>
            </div>
</el-dialog>
登入後複製

我這裡是將它放到一個Dialog彈框中,當選擇完圖片後會彈出這彈框。
關於它的一些屬性可以參考:官方教學中的詳細描述,上面用到的屬性意義:

  • canMoveBox:截圖框能否移動,預設是可以的,我設定為false,因為我想讓圖片移動,截圖框不動。

  • img:圖片來源,可以是圖片網址也可以是base64資料。

  • fixedBox:不允許改變截圖框的大小,預設是可以的,這裡我設定為了true,因為我想要一個固定長寬的方塊。

  • autoCrop:是否預設產生截圖框,這裡設定為了true

  • autoCropWidth:自動產生截圖框的預設寬度

  • autoCropHeight:自動產生截圖框的預設高度

  • #outputType:輸出圖片的格式,這裡我設定為了png格式

#取得圖片內容

透過下面這種方式,使用它內建的方法來取得截取圖片的內容

//获取base64格式的截图内容
this.$refs.cropper.getCropData(data => {
  // do something
  console.log(data)  
})
//获取blob格式的截图内容
this.$refs.cropper.getCropBlob(data => {
  // do something
  console.log(data)  
})
登入後複製

更多其他的內建方法請參考官方教學中的詳細描述。

自訂上傳圖片

截圖元件有了,下面需要我們選擇一個圖片,然後透過前端轉換為base64後彈出截圖的元件進行選擇,這裡用原生的input標籤,type為file,但是原生的樣式不是我們想要的,演示中我是點擊一個相機的小圖標後選擇圖片,這個實現過程如下:

  1. 首先將中加入hidden屬性,將它隱藏

  2. 然後當點擊相機圖示時透過js實作點擊input的事件

  3. 在input標籤中定義change事件,進行圖片轉base64的邏輯

  4. 然後將轉換的資料設定到全域變數中

## 完整的程式碼實作

##UserCenter .vue

<template>
    <div class="userCenter">
        <input id="avatarFile" type="file" hidden @change="selectFile" />
        <header>
            <div class="avatar">
                <div class="back">
                    <el-tooltip content="返回">
                        <i @click="back" class="fa fa-arrow-left"></i>
                    </el-tooltip>
                </div>
                <div class="topInfo">
                    <el-avatar :size="120" :src="avatarBlob==null?(userInfo.avatar==null?defaultAvatar:userInfo.avatar):avatarBlob"></el-avatar>
                    <div class="setAvatar">
                        <el-tooltip content="修改头像">
                            <i @click="getFile" class="fa fa-camera"></i>
                        </el-tooltip>
                    </div>
                    <div class="username">{{userInfo.nickName}}</div>
                </div>
            </div>
        </header>
        <el-row justify="center">
            <el-col :lg="12" :xl="12" :md="18" :sm="20" :xs="20">
                <div class="userInfoBox">
                    <div class="headerOption">
                        <el-tooltip content="修改用户基本信息,涉及账号的修改请点击底栏的操作按钮">
                            <el-link @click="editUserInfo"><i class="fa fa-edit"></i></el-link>
                        </el-tooltip>
                    </div>
                    <ul>
                        <li>
                            <div class="userInfoTitle">用户名:</div>
                            <div class="userInfoValue">{{userInfo.username}}</div>
                        </li>
                        <li>
                            <div class="userInfoTitle">邮箱:</div>
                            <div class="userInfoValue">{{userInfo.email}}</div>
                        </li>
                        <li>
                            <div class="userInfoTitle">昵称:</div>
                            <div class="userInfoValue">{{userInfo.nickName}}</div>
                        </li>
                        <li>
                            <div class="userInfoTitle">性别:</div>
                            <div class="userInfoValue">{{userInfo.gender==3?&#39;保密&#39;:(userInfo.gender==0?&#39;男&#39;:&#39;女&#39;)}}</div>
                        </li>
                        <li>
                            <div class="userInfoTitle">年龄:</div>
                            <div class="userInfoValue">{{userInfo.age}}</div>
                        </li>
                        <li>
                            <div class="userInfoTitle">生日:</div>
                            <div class="userInfoValue">{{userInfo.birthday}}</div>
                        </li>
                    </ul>
                </div>
            </el-col>
        </el-row>
        <div class="option">
            <el-button class="optionBtn" size="large" round><i class="fa fa-user"></i>用户名修改</el-button>
            <el-button class="optionBtn" size="large" round><i class="fa fa-lock"></i>修改密码</el-button>
            <el-button class="optionBtn" size="large" round><i class="fa fa-envelope"></i>修改邮箱</el-button>
            <el-button class="optionBtn" size="large" round><i class="fa fa-toggle-on"></i>激活邮箱</el-button>
            <el-button class="optionBtn" size="large" round><i class="fa fa-power-off"></i>注销账号</el-button>
        </div>
        <el-dialog title="基本信息" v-model="showUserInfoDialog">
            <el-form :model="userInfoForm">
                <el-form-item label="昵称">
                    <el-input placeholder="请输入昵称" v-model="userInfoForm.nickName"></el-input>
                </el-form-item>
                <el-form-item label="性别">
                    <el-select v-model="userInfoForm.gender">
                        <el-option v-for="item in genders" :key="item.id" :label="item.genderName"
                            :value="item.genderCode"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="生日">
                    <el-date-picker v-model="userInfoForm.birthday" :locale="locale" placeholder="选择出生日期"
                        value-format="yyyy-MM-dd"></el-date-picker>
                </el-form-item>
                <div class="submitBtn" >
                    <el-button @click="showUserInfoDialog=false" type="info">取消</el-button>
                    <el-button type="primary">确定</el-button>
                </div>
            </el-form>
        </el-dialog>
        <el-dialog title="头像设置" v-model="showSetAvatarDialog">
            <div class="cropperBox">
                <vue-cropper ref="cropper" :canMoveBox="false" :img="avatarBase64" :fixedBox="true" :autoCrop="true"
                    autoCropWidth="200" autoCropHeight="200" outputType="png"></vue-cropper>
            </div>
            <div class="optionBtn">
                <el-button @click="rotateLeft"><i class="fa fa-rotate-left"></i>左旋转</el-button>
                <el-button @click="rotateRight"><i class="fa fa-rotate-right"></i>右旋转</el-button>
                <el-button @click="getPickAvatar" type="primary"><i class="fa fa-save"></i>保存</el-button>
            </div>
        </el-dialog>
    </div>
</template>
<script>
import { userInfoByRequest } from &#39;../js/api&#39;
import { VueCropper } from &#39;vue-cropper&#39;
import &#39;vue-cropper/dist/index.css&#39;
export default {
    components: {
        VueCropper
    },
    data() {
        return {
            userInfo: {},
            defaultAvatar: &#39;https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png&#39;,
            userInfoForm: {},
            genders: [
                {
                    id: 1,
                    genderName: &#39;男性&#39;,
                    genderCode: 0,
                },
                {
                    id: 2,
                    genderName: &#39;女性&#39;,
                    genderCode: 1,
                },
                {
                    id: 3,
                    genderName: &#39;保密&#39;,
                    genderCode: 3,
                }
            ],
            showUserInfoDialog: false,
            showSetAvatarDialog: false,
            avatarBase64:&#39;&#39;,
            avatarBlob: null
        }
    },
    methods: {
        back() {
            this.$router.go(-1)
        },
        getUserInfo() {
            userInfoByRequest().then(res => {
                this.userInfo = res.data;
            })
        },
        editUserInfo() {
            this.userInfoForm.nickName = this.userInfo.nickName;
            this.userInfoForm.gender = this.userInfo.gender;
            this.userInfoForm.birthday = this.userInfo.birthday;
            this.showUserInfoDialog = true;
        },
        getPickAvatar() {
            this.$refs.cropper.getCropData(data => {
                this.avatarBlob = data
            })
            this.showSetAvatarDialog = false;
        },
        rotateLeft() {
            this.$refs.cropper.rotateLeft();
        },
        rotateRight() {
            this.$refs.cropper.rotateRight();
        },
        getFile() {
            let fileEle = document.getElementById(&#39;avatarFile&#39;)
            fileEle.click()
        },
        selectFile(e) {
            var file = e.target.files[0];
            var filesize = file.size;
            var filename = file.name;
            var reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onload = (e) => {
                var imgcode = e.target.result;
                this.avatarBase64 = imgcode
                this.showSetAvatarDialog = true;
            }
        }
    },
    mounted() {
        this.getUserInfo();
    }
}
</script>
<style scoped>
.userCenter {
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.username {
    color: #fff;
    font-weight: bold;
    font-size: 19px;
    padding: 0 10px;
}

header {
    text-align: center;
    padding: 10px;
    background-color: #333;

}

.topInfo {
    animation: userInfoCard 2s;
    -webkit-animation: userInfoCard 2s;
    /* Safari and Chrome */
}

.back {
    text-align: left;
    color: #fff;
    position: relative;
    left: 10px;
}

.back>i {
    cursor: pointer;
}

.userInfoBox {
    box-shadow: 2px 3px 10px #D3d7d4;
    margin-top: 20px;
    padding: 20px;
    background-color: #fff;
    font-size: 16px;
    text-align: center;
    border-radius: 4px;
    animation: userInfoCard 3s;
    -webkit-animation: userInfoCard 3s;
    /* Safari and Chrome */
}

.setAvatar {
    position: relative;
    top: -20px;
    font-size: 14px;
    color: #000;
    margin: -10px;
}

.setAvatar>i {
    cursor: pointer;
}

ul>li {
    display: flex;
    padding: 5px;
}

.userInfoTitle {
    font-weight: bold;
    width: 100px;
    text-align: right;
    padding-right: 10px;
}

.option {
    width: 100%;
    text-align: center;
    position: fixed;
    bottom: 20px;
    border: 1px solid gainsboro;
    padding: 10px;
}

.optionBtn {
    font-weight: bold;
    text-align: center;
    margin-top: 10px;
}

.headerOption {
    text-align: right;
}

@keyframes userInfoCard {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

@-webkit-keyframes userInfoCard

/* Safari and Chrome */
    {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

.cropperBox {
    width: 100%;
    height: 300px;
}
</style>
登入後複製

以上是Vue3中怎麼實現選取頭像並裁剪的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:yisu.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板