2019-05-21

image

前幾天遇到一個(gè)上傳頭像的需求 但是上傳的圖片可能會(huì)存在位置問(wèn)題,導(dǎo)致上傳的圖片不能正常的顯示出來(lái)于是就想著使用vue來(lái)寫一個(gè)圖片裁剪上傳的demo 我使用的是vue-cropper

vue-cropper

image

前幾天遇到一個(gè)上傳頭像的需求 但是上傳的圖片可能會(huì)存在位置問(wèn)題捏鱼,導(dǎo)致上傳的圖片不能正常的顯示出來(lái)于是就想著使用vue來(lái)寫一個(gè)圖片裁剪上傳的demo 我使用的是vue-cropper

vue-cropper

vue-cropper是一個(gè)能夠通過(guò)canva裁剪圖片的js工具庫(kù)。

安裝:

npm i vue-cropper

使用方法:


import VueCropper from 'vue-cropper'

Vue.use(VueCropper)

我們?cè)賛ain.js引用后就可以使用了


<template>

  <div >

    <label class="btn btn-orange" for="uploads" style="display:inline-block;width: 70px;padding: 0;text-align: center;line-height: 28px;">選擇圖片</label>

    <input type="file" id="uploads" :value="imgFile" style="position:absolute; clip:rect(0 0 0 0);" accept="image/png, image/jpeg, image/gif, image/jpg" @change="uploadImg($event, 1)">

    <input type="button" class="oper" style="height:30px;width:33px;font-size:20px;margin:3px 5px;" value="+" title="放大" @click="changeScale(1)">

    <input type="button" class="oper" style="height:30px;width:33px;font-size:20px;margin:3px 5px;" value="-" title="縮小" @click="changeScale(-1)">

    <input type="button" class="oper" style="height:30px;width:33px;font-size:20px;margin:3px 5px;" value="?" title="左旋轉(zhuǎn)" @click="rotateLeft">

    <input type="button" class="oper" style="height:30px;width:33px;font-size:20px;margin:3px 5px;" value="?" title="右旋轉(zhuǎn)" @click="rotateRight">

    <input type="button" class="oper" style="height:30px;width:33px;font-size:20px;margin:3px 5px;" value="↓" title="下載" @click="down('blob')">

    <input type="button" class="btn btn-blue" value="上傳頭像" @click="finish('blob')">

    <div class="info-item" style="flex:1;margin-left:-160px;margin-top:30px;">

      <div class="line" style="margin-top: 85px;">

        <div class="cropper-content" style="margin-top:-60px;width: 580px;">

          <div class="cropper">

            <vueCropper

              ref="cropper"

              :img="option.img"

              :outputSize="option.size"

              :outputType="option.outputType"

              :info="true"

              :full="option.full"

              :canMove="option.canMove"

              :canMoveBox="option.canMoveBox"

              :original="option.original"

              :autoCrop="option.autoCrop"

              :autoCropWidth="option.autoCropWidth"

              :autoCropHeight="option.autoCropHeight"

              :fixedBox="option.fixedBox"

              @realTime="realTime"

              @imgLoad="imgLoad"

            ></vueCropper>

          </div>

          <div>

            <div class="show-preview" :style="{'width': '150px', 'height':'155px',  'overflow': 'hidden', 'margin': '5px'}">

              <div :style="previews.div" class="preview">

                <img :src="previews.url" :style="previews.img">

              </div>

            </div>

          </div>

        </div>

      </div>

    </div>

  </div>

</template>

<script>

import { VueCropper } from 'vue-cropper'

export default {

  name: 'HelloWorld',

  data() {

      return {

        headImg:'',

        //剪切圖片上傳

        crap: false,

        previews: {},

        option: {

          img: '',

          outputSize:1, //剪切后的圖片質(zhì)量(0.1-1)

          full: false,//輸出原圖比例截圖 props名full

          outputType: 'png',

          canMove: true,

          original: false,

          canMoveBox: true,

          autoCrop: true,

          autoCropWidth: 150,

          autoCropHeight: 150,

          fixedBox: true

        },

        fileName:'',  //本機(jī)文件地址

        downImg: '#',

        imgFile:'',

        uploadImgRelaPath:'', //上傳后的圖片的地址(不帶服務(wù)器域名)

      }

    },

    components: {

      VueCropper

    },

    methods: {

      //放大/縮小

      changeScale(num) {

        console.log('changeScale')

        num = num || 1;

        this.$refs.cropper.changeScale(num);

      },

      //坐旋轉(zhuǎn)

      rotateLeft() {

        console.log('rotateLeft')

        this.$refs.cropper.rotateLeft();

      },

      //右旋轉(zhuǎn)

      rotateRight() {

        console.log('rotateRight')

        this.$refs.cropper.rotateRight();

      },

      //上傳圖片(點(diǎn)擊上傳按鈕)

      finish(type) {

        console.log('finish')

        let _this = this;

        let formData = new FormData();

        // 輸出

        if (type === 'blob') {

          this.$refs.cropper.getCropBlob((data) => {

            let img = window.URL.createObjectURL(data)

            this.model = true;

            this.modelSrc = img;

            formData.append("file", data, this.fileName);

            // 這里上傳post

          })

        } else {

          this.$refs.cropper.getCropData((data) => {

            this.model = true;

            this.modelSrc = data;

          })

        }

      },

      // 實(shí)時(shí)預(yù)覽函數(shù)

      realTime(data) {

        console.log('realTime')

        this.previews = data

      },

      //下載圖片

      down(type) {

        console.log('down')

        var aLink = document.createElement('a')

        aLink.download = 'author-img'

        if (type === 'blob') {

          this.$refs.cropper.getCropBlob((data) => {

            this.downImg = window.URL.createObjectURL(data)

            aLink.href = window.URL.createObjectURL(data)

            aLink.click()

          })

        } else {

          this.$refs.cropper.getCropData((data) => {

            this.downImg = data;

            aLink.href = data;

            aLink.click()

          })

        }

      },

      //選擇本地圖片

      uploadImg(e, num) {

        console.log('uploadImg');

        var _this = this;

        //上傳圖片

        var file = e.target.files[0]

        _this.fileName = file.name;

        if (!/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/.test(e.target.value)) {

          alert('圖片類型必須是.gif,jpeg,jpg,png,bmp中的一種')

          return false

        }

        var reader = new FileReader();

        reader.onload =(e) => {

          let data;

          if (typeof e.target.result === 'object') {

            // 把Array Buffer轉(zhuǎn)化為blob 如果是base64不需要

            data = window.URL.createObjectURL(new Blob([e.target.result]))

          }

          else {

            data = e.target.result

          }

          if (num === 1) {

            _this.option.img = data

          } else if (num === 2) {

            _this.example2.img = data

          }

        }

        // 轉(zhuǎn)化為base64

        // reader.readAsDataURL(file)

        // 轉(zhuǎn)化為blob

        reader.readAsArrayBuffer(file);

      },

      imgLoad (msg) {

        console.log('imgLoad')

        console.log(msg)

      }

    }

}

</script>

<style scoped lang="stylus">

.show-preview

  flex 1

  -webkit-flex 1

  display flex

  display -webkit-flex

  justify-content center

  -webkit-justify-content center

  background blue

  .preview

    overflow hidden

    border-radius 50%;

    border 1px solid #cccccc

    background #cccccc

.info

    width 720px

    margin 0 auto

    .oper-dv

      height:20px

      text-align:right

      margin-right:100px

      a

        font-weight 500

        &:last-child

          margin-left 30px

    .info-item

      margin-top 15px

      label

        display inline-block

        width 100px

        text-align right

      .sel-img-dv

        position relative

        .sel-file

          position absolute

          width 90px

          height 30px

          opacity 0

          cursor pointer

          z-index 2

        .sel-btn

          position absolute

          cursor pointer

          z-index 1

  .cropper-content

    display flex

    display -webkit-flex

    justify-content flex-end

    -webkit-justify-content flex-end

    .cropper

      width 260px

      height 260px

</style>

以上是具體的代碼實(shí)現(xiàn)

vue-cropper是一個(gè)能夠通過(guò)canva裁剪圖片的js工具庫(kù)卿樱。

安裝:

npm i vue-cropper

使用方法:


import VueCropper from 'vue-cropper'

Vue.use(VueCropper)

我們?cè)賛ain.js引用后就可以使用了


<template>

  <div >

    <label class="btn btn-orange" for="uploads" style="display:inline-block;width: 70px;padding: 0;text-align: center;line-height: 28px;">選擇圖片</label>

    <input type="file" id="uploads" :value="imgFile" style="position:absolute; clip:rect(0 0 0 0);" accept="image/png, image/jpeg, image/gif, image/jpg" @change="uploadImg($event, 1)">

    <input type="button" class="oper" style="height:30px;width:33px;font-size:20px;margin:3px 5px;" value="+" title="放大" @click="changeScale(1)">

    <input type="button" class="oper" style="height:30px;width:33px;font-size:20px;margin:3px 5px;" value="-" title="縮小" @click="changeScale(-1)">

    <input type="button" class="oper" style="height:30px;width:33px;font-size:20px;margin:3px 5px;" value="?" title="左旋轉(zhuǎn)" @click="rotateLeft">

    <input type="button" class="oper" style="height:30px;width:33px;font-size:20px;margin:3px 5px;" value="?" title="右旋轉(zhuǎn)" @click="rotateRight">

    <input type="button" class="oper" style="height:30px;width:33px;font-size:20px;margin:3px 5px;" value="↓" title="下載" @click="down('blob')">

    <input type="button" class="btn btn-blue" value="上傳頭像" @click="finish('blob')">

    <div class="info-item" style="flex:1;margin-left:-160px;margin-top:30px;">

      <div class="line" style="margin-top: 85px;">

        <div class="cropper-content" style="margin-top:-60px;width: 580px;">

          <div class="cropper">

            <vueCropper

              ref="cropper"

              :img="option.img"

              :outputSize="option.size"

              :outputType="option.outputType"

              :info="true"

              :full="option.full"

              :canMove="option.canMove"

              :canMoveBox="option.canMoveBox"

              :original="option.original"

              :autoCrop="option.autoCrop"

              :autoCropWidth="option.autoCropWidth"

              :autoCropHeight="option.autoCropHeight"

              :fixedBox="option.fixedBox"

              @realTime="realTime"

              @imgLoad="imgLoad"

            ></vueCropper>

          </div>

          <div>

            <div class="show-preview" :style="{'width': '150px', 'height':'155px',  'overflow': 'hidden', 'margin': '5px'}">

              <div :style="previews.div" class="preview">

                <img :src="previews.url" :style="previews.img">

              </div>

            </div>

          </div>

        </div>

      </div>

    </div>

  </div>

</template>

<script>

import { VueCropper } from 'vue-cropper'

export default {

  name: 'HelloWorld',

  data() {

      return {

        headImg:'',

        //剪切圖片上傳

        crap: false,

        previews: {},

        option: {

          img: '',

          outputSize:1, //剪切后的圖片質(zhì)量(0.1-1)

          full: false,//輸出原圖比例截圖 props名full

          outputType: 'png',

          canMove: true,

          original: false,

          canMoveBox: true,

          autoCrop: true,

          autoCropWidth: 150,

          autoCropHeight: 150,

          fixedBox: true

        },

        fileName:'',  //本機(jī)文件地址

        downImg: '#',

        imgFile:'',

        uploadImgRelaPath:'', //上傳后的圖片的地址(不帶服務(wù)器域名)

      }

    },

    components: {

      VueCropper

    },

    methods: {

      //放大/縮小

      changeScale(num) {

        console.log('changeScale')

        num = num || 1;

        this.$refs.cropper.changeScale(num);

      },

      //坐旋轉(zhuǎn)

      rotateLeft() {

        console.log('rotateLeft')

        this.$refs.cropper.rotateLeft();

      },

      //右旋轉(zhuǎn)

      rotateRight() {

        console.log('rotateRight')

        this.$refs.cropper.rotateRight();

      },

      //上傳圖片(點(diǎn)擊上傳按鈕)

      finish(type) {

        console.log('finish')

        let _this = this;

        let formData = new FormData();

        // 輸出

        if (type === 'blob') {

          this.$refs.cropper.getCropBlob((data) => {

            let img = window.URL.createObjectURL(data)

            this.model = true;

            this.modelSrc = img;

            formData.append("file", data, this.fileName);

            // 這里上傳post

          })

        } else {

          this.$refs.cropper.getCropData((data) => {

            this.model = true;

            this.modelSrc = data;

          })

        }

      },

      // 實(shí)時(shí)預(yù)覽函數(shù)

      realTime(data) {

        console.log('realTime')

        this.previews = data

      },

      //下載圖片

      down(type) {

        console.log('down')

        var aLink = document.createElement('a')

        aLink.download = 'author-img'

        if (type === 'blob') {

          this.$refs.cropper.getCropBlob((data) => {

            this.downImg = window.URL.createObjectURL(data)

            aLink.href = window.URL.createObjectURL(data)

            aLink.click()

          })

        } else {

          this.$refs.cropper.getCropData((data) => {

            this.downImg = data;

            aLink.href = data;

            aLink.click()

          })

        }

      },

      //選擇本地圖片

      uploadImg(e, num) {

        console.log('uploadImg');

        var _this = this;

        //上傳圖片

        var file = e.target.files[0]

        _this.fileName = file.name;

        if (!/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/.test(e.target.value)) {

          alert('圖片類型必須是.gif,jpeg,jpg,png,bmp中的一種')

          return false

        }

        var reader = new FileReader();

        reader.onload =(e) => {

          let data;

          if (typeof e.target.result === 'object') {

            // 把Array Buffer轉(zhuǎn)化為blob 如果是base64不需要

            data = window.URL.createObjectURL(new Blob([e.target.result]))

          }

          else {

            data = e.target.result

          }

          if (num === 1) {

            _this.option.img = data

          } else if (num === 2) {

            _this.example2.img = data

          }

        }

        // 轉(zhuǎn)化為base64

        // reader.readAsDataURL(file)

        // 轉(zhuǎn)化為blob

        reader.readAsArrayBuffer(file);

      },

      imgLoad (msg) {

        console.log('imgLoad')

        console.log(msg)

      }

    }

}

</script>

<style scoped lang="stylus">

.show-preview

  flex 1

  -webkit-flex 1

  display flex

  display -webkit-flex

  justify-content center

  -webkit-justify-content center

  background blue

  .preview

    overflow hidden

    border-radius 50%;

    border 1px solid #cccccc

    background #cccccc

.info

    width 720px

    margin 0 auto

    .oper-dv

      height:20px

      text-align:right

      margin-right:100px

      a

        font-weight 500

        &:last-child

          margin-left 30px

    .info-item

      margin-top 15px

      label

        display inline-block

        width 100px

        text-align right

      .sel-img-dv

        position relative

        .sel-file

          position absolute

          width 90px

          height 30px

          opacity 0

          cursor pointer

          z-index 2

        .sel-btn

          position absolute

          cursor pointer

          z-index 1

  .cropper-content

    display flex

    display -webkit-flex

    justify-content flex-end

    -webkit-justify-content flex-end

    .cropper

      width 260px

      height 260px

</style>

以上是具體的代碼實(shí)現(xiàn)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末署隘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子淆院,更是在濱河造成了極大的恐慌此再,老刑警劉巖昔搂,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異输拇,居然都是意外死亡摘符,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門策吠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)逛裤,“玉大人,你說(shuō)我怎么就攤上這事猴抹〈澹” “怎么了?”我有些...
    開封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵蟀给,是天一觀的道長(zhǎng)蝙砌。 經(jīng)常有香客問(wèn)我,道長(zhǎng)跋理,這世上最難降的妖魔是什么择克? 我笑而不...
    開封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮前普,結(jié)果婚禮上肚邢,老公的妹妹穿的比我還像新娘。我一直安慰自己汁政,他們只是感情好道偷,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著记劈,像睡著了一般勺鸦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上目木,一...
    開封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天换途,我揣著相機(jī)與錄音,去河邊找鬼刽射。 笑死军拟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的誓禁。 我是一名探鬼主播懈息,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼摹恰!你這毒婦竟也來(lái)了辫继?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤俗慈,失蹤者是張志新(化名)和其女友劉穎姑宽,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體闺阱,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡炮车,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了酣溃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘦穆。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖赊豌,靈堂內(nèi)的尸體忽然破棺而出难审,到底是詐尸還是另有隱情,我是刑警寧澤亿絮,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布告喊,位于F島的核電站,受9級(jí)特大地震影響派昧,放射性物質(zhì)發(fā)生泄漏黔姜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一蒂萎、第九天 我趴在偏房一處隱蔽的房頂上張望秆吵。 院中可真熱鬧,春花似錦五慈、人聲如沸纳寂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)毙芜。三九已至忽媒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間腋粥,已是汗流浹背晦雨。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留隘冲,地道東北人闹瞧。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像展辞,于是被迫代替她去往敵國(guó)和親奥邮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • HTML HTML(HyperText Markup Language)就是超文本標(biāo)記語(yǔ)言罗珍∧眨”超文本”就是表示頁(yè)面...
    1fa38a6a3bcf閱讀 227評(píng)論 0 0
  • “關(guān)琦通殃,需要換多少歐元呢度液?”納納是很細(xì)心的人,第一次去瑞士蘇黎世画舌,臨行前問(wèn)我堕担。 “我不打算換~去年帶楚楚參加過(guò)一次...
    琦琦小野閱讀 1,334評(píng)論 1 4
  • CSS3-@media總結(jié) 設(shè)置Meta標(biāo)簽 首先我們?cè)谑褂肕edia的時(shí)候需要先設(shè)置下面這段代碼,來(lái)兼容移動(dòng)設(shè)備...
    動(dòng)弦閱讀 220評(píng)論 0 1
  • copy from https://cran.rproject.org/web/packages/ggsci/vi...
    zwz110閱讀 1,255評(píng)論 0 2
  • 今天是2019年5月19號(hào)曲聂,五點(diǎn)醒來(lái)霹购。剛巧這時(shí)我家先生也醒了,他說(shuō):“你“走火入魔”了朋腋,每天這么早醒來(lái)齐疙,干嘛呀?”...
    幸福感1314閱讀 253評(píng)論 0 5