我的截圖外掛被Gitee使用了

神奇的程式設計師發表於2021-12-01

前言

上週六有個群友@我說Gitee的反饋模組新增了截圖功能,我就去體驗了下,發現他們用的就是我的外掛?,本文就跟大家分享下這個外掛,歡迎各位感興趣的開發者閱讀本文。

外掛地址與實現原理

本外掛採用原生js實現,可以整合在任意一個web專案中,外掛npm地址與GitHub地址請移步:

外掛的實現原理請移步:

線上體驗本外掛,可移步我的開源專案chat-system進行體驗,外掛的執行效果視訊請移步實現web端自定義截圖功能-效果視訊

Gitee產品經理的青睞

月初的時候,Gitee的產品經理在掘金看到我的截圖外掛js-screen-shot覺得還不錯,他們最近在做這方面的功能,就打算將我的外掛直接整合進去,跟我溝通了下版權相關的事情。

image-20211129225953184

溝通完成後,他問我要不要把外掛在Gitee也放一份,可以幫我推薦下,我毫不猶豫的抱住了大腿,就把外掛搬過去了,得到一波首頁推薦?

image-20211129230823603

bf89cb2cce8d4d8383983ebad4e86f28

Gitee的反饋模組需要登入後,點頁面右側的傳送反饋圖示。

gitee反饋

影響體驗的一些小問題

上週二,從GitHub來了個網友,加了我微信,給我的外掛提了兩個issues,因為周內沒時間處理這些問題,就計劃週末統一處理下外掛的issues。

image-20211129231616134

整理有效的issues

時間回到上週六早上,我開啟GitHub瞅了一眼issues,許久不看居然已經有19條了。

image-20211129232250926

經過一番整理,去掉一些無用的和已經修改好了的,最終確定了4條:

  • 呼叫者可以在框選區域外繪製問題
  • 截圖區域工具欄首次點選時刪除裁剪框的8個可操作點
  • 修復框選完成後,滑鼠點選其他位置截圖工具欄跟著移動問題
  • 新增可選引數支援單擊截全屏功能

解決issues

問題整理完成,接下來就是解決問題環節了。

選區外繪製問題

正常情況下,截圖區域確立後,使用者都會在裁剪框區域內進行繪製,所以我就沒考慮這個邊界情況?,外掛用的人多了後,自然就有人發現了這個問題,我們拿gitee的反饋模組舉例(gitee目前用的還是我的舊版外掛,肯定存在這個問題),如下所示,我們繪製的4個紅色方框都超出裁剪框了:

image-20211129234154073

實現思路

這個問題解決起來比較簡單,裁剪框已經繪製好了,知道它的座標資訊,我們在進行繪製時,只需要判斷當前滑鼠位置是否超出裁剪框的座標點區域即可。部分實現程式碼如下所示:

// 獲取裁剪框位置資訊
const cutBoxPosition = this.data.getCutOutBoxPosition();
// 繪製中工具的起始x、y座標不能小於裁剪框的起始座標
// 繪製中工具的起始x、y座標不能大於裁剪框的結束座標
// 當前滑鼠的x座標不能小於裁剪框起始x座標,不能大於裁剪框的結束座標
// 當前滑鼠的y座標不能小於裁剪框起始y座標,不能大於裁剪框的結束座標
if (
      !getDrawBoundaryStatus(startX, startY, cutBoxPosition) ||
      !getDrawBoundaryStatus(currentX, currentY, cutBoxPosition)
   )
      return;

getDrawBoundaryStatus函式實現如下所示:

/**
 * 獲取工具欄工具邊界繪製狀態
 * @param startX x軸繪製起點
 * @param startY y軸繪製起點
 * @param cutBoxPosition 裁剪框位置資訊
 */
export function getDrawBoundaryStatus(
  startX: number,
  startY: number,
  cutBoxPosition: positionInfoType
): boolean {
  if (
    startX < cutBoxPosition.startX ||
    startY < cutBoxPosition.startY ||
    startX > cutBoxPosition.startX + cutBoxPosition.width ||
    startY > cutBoxPosition.startY + cutBoxPosition.height
  ) {
    // 無法繪製
    return false;
  }
  // 可以繪製
  return true;
}
具體程式碼請移步提交記錄: fix: 修復外掛呼叫者可以在框選區域外繪製問題
實現效果

實現後的效果如下所示:

01

工具欄跟隨滑鼠移動問題

這個問題可以描述為:裁剪框確定後,工具欄尚未點選,此時滑鼠點其他位置,截圖工具欄就跟著滑鼠重新計算了位置,我們繼續用Gitee來舉例,如下所示:

10011

實現思路

當滑鼠左鍵抬起時,如果工具欄尚未被點選,則會根據當前滑鼠的位置結合裁剪框的大小確立截圖工具欄的位置。使用者只是單純的點選了裁剪框區域的任意位置,工具欄就跟著移動了。

解決這個問題也很簡單,我們只需要在滑鼠移動時新增一個標識,滑鼠抬起時判斷這個標識是否為true即可。部分程式碼如下所示:

  // 滑鼠拖動狀態
  private dragFlag = false;

  // 滑鼠移動事件
  private mouseMoveEvent = (event: MouseEvent) => {
     // 工具欄未選擇且滑鼠處於按下狀態時
    if (!this.data.getToolClickStatus() && this.data.getDragging()) {
      // 修改拖動狀態為true;
      this.dragFlag = true;
    }
  }
  
  // 滑鼠抬起事件
  private mouseUpEvent = () => {
    // 滑鼠尚未拖動且工具欄未選擇則不修改工具欄位置
    if (!this.dragFlag && !this.data.getToolClickStatus()) {
      // 復原裁剪框的座標
      this.drawGraphPosition.startX = this.drawGraphPrevX;
      this.drawGraphPosition.startY = this.drawGraphPrevY;
      // 顯示截圖工具欄
      this.data.setToolStatus(true);
      return;
    }
  }
具體程式碼請移步提交記錄:fix: 修復框選完成後,滑鼠點選其他位置截圖工具欄跟著移動問題
實現結果

修復後的效果如下所示:

工具欄跟著滑鼠移動-修復後的.2021-11-30 21_08_28

刪除8個可操作點

去年截圖外掛剛寫好時,我就發現這個問題了,當截圖工具欄點選後裁剪框就不允許更改了,如果8個可操作點依然存在的話,看起來很奇怪,當時想到的思路是直接刪除邊框的8點,但是這8個點都是繪製上去的,折騰了挺久沒找到方案就擱置了,這個問題如下圖所示:

刪除8個可操作點

實現思路

一年後的今天,我知道刪除那8個點的思路肯定行不通,我就一遍又一遍的體驗QQ的截圖,觀察他是怎麼做的,突然,我靈感驚現?,我既然有裁剪框的座標和大小資訊,我重新繪製一下這個裁剪框不就好了?,裁剪框四周的8個可操作點刪除後,我就可以刪掉生成圖片時優化那8個點的計算邏輯,導致範圍不精確問題,從而實現完美截圖。部分實現程式碼如下所示:

  // 工具欄尚未點選,當前屬於首次點選,重新繪製一個無畫素點的裁剪框
  if (!data.getToolClickStatus()) {
    // 獲取裁剪框位置資訊
    const cutBoxPosition = data.getCutOutBoxPosition();
    // 開始繪製無畫素點裁剪框
    drawCutOutBox(
      cutBoxPosition.startX,
      cutBoxPosition.startY,
      cutBoxPosition.width,
      cutBoxPosition.height,
      screenShortCanvas,
      data.getBorderSize(),
      screenShortController as HTMLCanvasElement,
      ScreenShortImageController,
      false
    );
  }
具體程式碼請移步提交記錄:fix: 截圖區域工具欄首次點選時刪除裁剪框的8個可操作點
實現效果

刪除8個可操作點-修復

實現單擊截全屏功能

給我提issues的那個網友希望截圖外掛載入完畢後,使用者不拖拽生成選框,直接滑鼠左鍵單擊就能擷取整個螢幕,我覺得這個需求需要的人不多,就將其做成了可選引數。

實現思路

這個也很簡單,滑鼠抬起時,如果開啟了單擊截全屏,則從座標(0,0)位置繪製一個與畫布同等大小的裁剪框即可,部分程式碼如下所示:

  // 滑鼠抬起事件
  private mouseUpEvent = () => {
    if (
      cutBoxPosition.width === 0 &&
      cutBoxPosition.height === 0 &&
      cutBoxPosition.startX === 0 &&
      cutBoxPosition.startY === 0 &&
      !this.dragFlag &&
      this.clickCutFullScreen
    ) {
      // 設定裁剪框位置為全屏
      this.tempGraphPosition = drawCutOutBox(
        0,
        0,
        this.screenShortImageController.width,
        this.screenShortImageController.height,
        this.screenShortCanvas,
        this.data.getBorderSize(),
        this.screenShortController,
        this.screenShortImageController
      ) as drawCutOutBoxReturnType;
    }
  }
具體程式碼請移步提交記錄:feat: 新增可選引數支援單擊截全屏功能

寫在最後

至此,文章就分享完畢了。

我是神奇的程式設計師,一位前端開發工程師。

如果你對我感興趣,請移步我的個人網站,進一步瞭解。

  • 文中如有錯誤,歡迎在評論區指正,如果這篇文章幫到了你,歡迎點贊和關注?
  • 本文首發於神奇的程式設計師公眾號,未經許可禁止轉載?

相關文章