国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

vue-avatar-tailor,vue頭像裁剪組件

imccl / 2161人閱讀

摘要:實現原理簡單,純技術處理圖片,幾乎不需要用到相關知識面向人群急于使用頭像裁剪組件的同學。裁剪框初始寬高上傳圖片后,裁剪區將預設為最大裁剪范圍。支持矩形裁剪目前九宮僅支持將圖片裁剪為正方形,不能裁剪為矩形,該功能將在后續優化。

項目簡介

本組件是vue下的頭像裁剪組件,可以直接拷貝代碼使用,無需安裝依賴

使用九宮格進行裁剪,自由選擇裁剪區域。

實時預覽裁剪后效果。

可以將裁剪好的圖片,導出為封裝好的file文件,直接上傳到服務器。

導出圖片鏈接,可以導出為圖片鏈接,直接使用裁剪后的效果。

實現原理簡單,純CSS技術處理圖片,幾乎不需要用到canvas相關知識

面向人群

急于使用vue頭像裁剪組件的同學。直接下載文件,拷貝代碼即可運行。

喜歡看源碼,希望了解組件背后原理的同學。
剛接觸前端的同學也可以通過本文章養成看源碼的習慣。打破對源碼的恐懼,相信自己,其實看源碼并沒有想象中的那么困難

技術難點

頭像裁剪效果需要解決這么幾個問題

【遮罩鏤空效果】進行裁剪時,是先將原圖添加一層透明的白色遮罩。并在遮罩中顯示一塊清晰的區塊,作為當前裁剪區。如何制作該裁剪區。

【裁剪框初始寬高】上傳圖片后,裁剪區將預設為最大裁剪范圍。當上傳的圖片非正方形時,如何設置裁剪區的最大范圍。

【實時預覽】如何將待裁剪區顯示在實時預覽區內。

【移動范圍約束】移動伸裁剪區時,如何約束裁剪區的位置,讓其一直位于原圖上。

【拖拽范圍擴展位置計算】當對裁剪區進行拉伸時,由于需要保持正方形,拉伸一邊,需要將其臨邊一并拉伸。如何保證拉伸后都不溢出。

實現思路

上傳圖片

通過臨時生成的img標簽獲取圖片的大小信息(getImgSize函數的具體實現請參考源碼)

比較原圖長和寬,以其長邊作為標準進行圖片的縮放顯示,讓整張圖顯示在待裁剪區域中

以圖片縮放后的短邊作為選擇框的寬,使裁剪框初始顯示為最大可選范圍

從而解決【裁剪框初始寬高】問題

// 選擇圖片
fileChange(event) {
  const fileObj = event.target.files[0]
  const reader = new FileReader()
  reader.onload = () => {
    const { selectData, containerBoxData } = this
    this.imgURL = reader.result
    this.getImgSize(this.imgURL).then((result) => { // 獲取圖片的大小
      if (result.width > result.height) { // 350為外盒子寬高,比較原圖長和寬,以其長邊作為標準進行圖片的縮放顯示
        this.scaleRate = 350 / result.width // 獲取并記錄圖片縮放比
        containerBoxData.width = 350
        containerBoxData.height = Math.floor(result.height * this.scaleRate)
        selectData.top = 0
        selectData.left = (350 - containerBoxData.height) / 2 // 裁剪選擇框居中顯示
        selectData.width = containerBoxData.height // 以圖片縮放后的短邊作為選擇框的寬,使其顯示為最大可選范圍
      } else {
        this.scaleRate = 350 / result.height
        containerBoxData.height = 350
        containerBoxData.width = Math.floor(result.width * this.scaleRate)
        selectData.left = 0
        selectData.top = (350 - containerBoxData.width) / 2
        selectData.width = containerBoxData.width
      }
      this.setPreview()
    })
  }
  reader.readAsDataURL(fileObj)
},

遮罩鏤空的效果實現思路如下

共通過三個元素重疊顯示,原圖img標簽放在最底下,遮罩層.img-mask放在中間,裁剪區域.select-box放在最外層

.img-mask是遮住了整個img標簽的,只是裁剪區域.select-box顯示的內容剛好與原圖上的一致。實現看起來遮罩被鏤空的效果

其實遮罩并沒有被鏤空,只是遮罩上又多了一層圖案,剛剛與原位置相同

裁剪區域.select-box,顯示的內容和位置,通過background相關屬性,background-position 和 background-size在實現

即選取圖片的特定區域作為裁剪區域.select-box的背景

  
  

渲染預覽效果

利用canvas的drawImage函數,將候選區域顯示在預覽區

drawImage函數可以設置圖形采取的范圍和位置

并設置采取獲得的圖形,顯示在canvas的那個地方,以多大的size顯示

從而實現采取區,于預覽區縮放的形式顯示

實現【實時預覽】效果

// 設置預覽圖
setPreview() {
  const { selectData, scaleRate } = this
  const $canvas = this.$refs.$canvas.getContext("2d")
  $canvas.clearRect(0, 0, 190, 190) // 清除canvas中的內容
  $canvas.drawImage( // 將原圖中,選定區域的圖案通過canvas渲染出來
    this.$refs.$img, // 圖形元素
    Math.floor(selectData.left / scaleRate), // 截取原圖中的那個位置作為起始點,X軸方向上
    Math.floor(selectData.top / scaleRate), // 截取原圖中的那個位置作為起始點,Y軸方向上
    selectData.width / scaleRate, // 截取原圖中多大的范圍,寬度
    selectData.width / scaleRate, // 截取原圖中多大的范圍,高度
    0, // 顯示在canvas中的X坐標
    0, // 顯示在canvas中的Y坐標
    190, // 將內容伸縮為多大的寬度顯示
    190, // 將內容伸縮為多大的高度顯示
  )
},

拉伸操作的監聽

在裁剪區域中,使用ul,li標簽充當各個操作點,及形成九宮格中的虛線功能

在每個操作點中,監聽mousedown事件,記錄即將移動的方向,表示接下來的mousemove事件中,是進行那個方向上的拉伸

在created鉤子中,監聽全局 mouseup 和 mousemove 事件。因為鼠標的離開和利用不一樣在裁剪區域中,在其他地方觸發也應該同樣執行相關操作

在 mousemove 事件中區裁剪區移動操作「move」,裁剪區拉伸操作「stretch」。執行不同的函數

數據設置完成后,重新渲染預覽區

實現【拖拽范圍擴展位置計算】及【拖拽范圍擴展約束】功能

onMouseMove(event) {
  const { selectData, containerBoxData } = this
  const { x, y } = selectData.originPoint
  const moveX = event.clientX - x // X軸移動的距離
  const moveY = event.clientY - y // Y軸移動的距離
  if (selectData.action === "move") { // 移動選擇框
    this.doMove(selectData, containerBoxData, moveX, moveY)
  } else if (selectData.action === "stretch") { // 拉伸選擇框
    this.doStretch(selectData, containerBoxData, moveX, moveY)
  } else {
    return
  }

  selectData.originPoint = {
    x: event.clientX > 0 ? event.clientX : 0,
    y: event.clientY > 0 ? event.clientY : 0,
  }

  this.setPreview()
},

裁剪區移動

比較移動后上下左右各個邊與原圖可裁剪區域的位置關系

若超出范圍,則設置為邊界值

實現【移動范圍約束】功能

// 鼠標移動
doMove(selectData, containerBoxData, moveX, moveY) {
  selectData.top += moveY
  selectData.left += moveX
  if (selectData.top < 0) {
    selectData.top = 0
  }
  if (selectData.left < 0) {
    selectData.left = 0
  }
  if (selectData.top + selectData.width > containerBoxData.height) {
    selectData.top = containerBoxData.height - selectData.width
  }
  if (selectData.left + selectData.width > containerBoxData.width) {
    selectData.left = containerBoxData.width - selectData.width
  }
},

裁剪區拉伸

設置各個方位具體的拉伸操作

調用對應函數,先進行一次拉伸操作

拉伸完成后,比較上下左右,寬高的溢出情況,獲得最大的溢出值

以最大溢出值進行反向操作,確保裁剪區一直在可選范圍內

 // 選擇框拉伸
doStretch(selectData, containerBoxData, moveX, moveY) {
  const { minWidth } = this

  // 比較上下左右,寬高的溢出情況,返回最大的溢出值
  function getOverflowLength() {
    const overflowLeft = selectData.left < 0 ? -selectData.left : 0
    const overflowTop = selectData.top < 0 ? -selectData.top : 0
    const overflowRight = selectData.left + selectData.width > containerBoxData.width ? selectData.left + selectData.width - containerBoxData.width : 0
    const overflowBottom = selectData.top + selectData.width > containerBoxData.height ? selectData.top + selectData.width - containerBoxData.height : 0
    const overflowWidth = selectData.width < minWidth ? minWidth - selectData.width : 0
    return Math.max(overflowLeft, overflowTop, overflowRight, overflowBottom, overflowWidth)
  }

  // 向左拉伸
  function doStretchLeft(action) {
    let space = moveX
    space = action === "preDo" ? space : -space
    selectData.top += space / 2
    selectData.left += space
    selectData.width -= space
  }

  function doStretchRight(action) {
    let space = moveX
    space = action === "preDo" ? space : -space
    selectData.top -= space / 2
    selectData.width += space
  }

  function doStretchTop(action) {
    let space = moveY
    space = action === "preDo" ? space : -space
    selectData.top += space
    selectData.left += space / 2
    selectData.width -= space
  }

  function doStretchBottom(action) {
    let space = moveY
    space = action === "preDo" ? space : -space
    selectData.left -= space / 2
    selectData.width += space
  }

  function doStretchTopLeft(action) {
    let space = Math.abs(moveX) > Math.abs(moveY) ? moveX : moveY
    space = action === "preDo" ? space : -space
    selectData.top += space
    selectData.left += space
    selectData.width -= space
  }

  function doStretchTopRight(action) {
    let space = Math.abs(moveX) > Math.abs(moveY) ? moveX : -moveY
    space = action === "preDo" ? space : -space
    selectData.top -= space
    selectData.width += space
  }

  function doStretchBottomLeft(action) {
    let space = Math.abs(moveX) > Math.abs(moveY) ? moveX : -moveY
    space = action === "preDo" ? space : -space
    selectData.left += space
    selectData.width -= space
  }

  function doStretchBottomRight(action) {
    let space = Math.abs(moveX) > Math.abs(moveY) ? moveX : moveY
    space = action === "preDo" ? space : -space
    selectData.width += space
  }

  const doStretchFun = {
    doStretchLeft,
    doStretchRight,
    doStretchTop,
    doStretchBottom,
    doStretchTopLeft,
    doStretchTopRight,
    doStretchBottomLeft,
    doStretchBottomRight,
  }[`doStretch${this.getWord(this.getCamelCase(selectData.direction))}`]

  // 進行拉伸操作
  doStretchFun("preDo")
  let overflowLength = getOverflowLength() // 拉伸完成后,獲取最大溢出值
  if (overflowLength > 0) { // 以最大溢出值進行反向操作,確保裁剪區一直在可選范圍內
    doStretchFun("reset")
  }
},

后續優化

【代碼優化】可以看到上面的代碼,有部分冗余,略顯繁瑣。后續將簡化實現邏輯。

【支持矩形裁剪】目前九宮僅支持將圖片裁剪為正方形,不能裁剪為矩形,該功能將在后續優化。

【原圖的縮放】目前上傳的裁剪目標圖并不支持縮放,上傳大圖時,裁剪顯得不那么靈活,這也將在后續優化

項目源碼及示例 最后送上一張示例中使用的喬巴表情圖

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/98137.html

相關文章

  • 編寫一個頭像裁剪組件(一)

    摘要:需求是編寫一個頭像剪裁工具再封裝成為一個組件,然后根據功能開始逐步編寫代碼先是上傳圖片預覽圖片編輯圖片。 需求是編寫一個頭像剪裁工具再封裝成為一個組件,然后根據功能開始逐步編寫代碼:先是上傳圖片 => 預覽圖片 => 編輯圖片。 剛開始沒有去考慮兼容性的問題,直接編寫upload部分的代碼,參考了很多代碼還有HTML5 FILE API之后,發現很少有React編寫的這樣的代碼,因為想...

    whatsns 評論0 收藏0
  • 騰訊 AlloyTeam 移動 Web 裁剪組件 AlloyCrop 正式開源

    摘要:兼容性如何支持以及的設備的瀏覽器便可運行不一一列舉一共不到行為什么體積這么小騰訊手內大量的都會去不斷地從各個維度進行性能優化。騰訊內部有哪些項目在用目前主要是興趣部落群等業務在用,剛剛開源出來,只要有裁剪圖片的地方都會用到。 傳送門 Github地址:https://github.com/AlloyTeam/AlloyFinger/tree/master/alloy_crop 在線De...

    yexiaobai 評論0 收藏0
  • vue自定義指令clickoutside擴展--多個元素的并集作為inside

    摘要:指令中自定義的指令之一,顧名思義,就是當鼠標點擊了指令所綁定元素的外部時,就會觸發綁定方法。在鼠標放開觸發事件處理時,通過獲取到他們的對象。使用示例原來的使用方式不受影響,只是添加了多個元素并集作為的功能。指令中的參數學習 都是個人理解,如果發現錯誤,懇請大家批評指正,謝謝。還有我說的會比較啰嗦,因為是以自身菜雞水平的視角來記錄學習理解的過程,見諒。 1.前言 產品使用vue+elem...

    ivan_qhz 評論0 收藏0
  • vue2+element 管理后臺 集成解決方案 沒有沒做的,只要想不到的!

    摘要:目前的技術棧主要的采用由于是個人項目,所以數據請求都是用了代替。后續會出一系列的教程配套文章,如如何從零構建后臺項目框架,如何做完整的用戶系統如權限驗證,二次登錄等,如何二次開發組件如富文本,如何整合七牛等等文章,各種后臺開發經驗等等。 完整項目地址:vue-element-admin系類文章一:手摸手,帶你用vue擼后臺 系列一(基礎篇)系類文章二:手摸手,帶你用vue擼后臺 系列二...

    sanyang 評論0 收藏0

發表評論

0條評論

imccl

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<