這篇文章主要講解了“怎么實現(xiàn)Web端自定義截屏”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“怎么實現(xiàn)Web端自定義截屏”吧!

十年的峨山縣網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。全網(wǎng)整合營銷推廣的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整峨山縣建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。創(chuàng)新互聯(lián)從事“峨山縣網(wǎng)站設(shè)計”,“峨山縣網(wǎng)站推廣”以來,每個客戶項目都認真落實執(zhí)行。
搭建開發(fā)環(huán)境
我想使用ts、scss、eslint、prettier來提升插件的可維護性,又嫌麻煩,不想手動配置webpack環(huán)境,于是我決定使用Vue CLI來搭建插件開發(fā)環(huán)境。
本文不細講Vue CLI搭建插件開發(fā)環(huán)境的過程,對此感興趣的開發(fā)者請移步:使用CLI開發(fā)一個Vue3的npm庫。
移除vue相關(guān)依賴
我們搭建好插件的開發(fā)環(huán)境后,CLI默認會在package.json中添加Vue的相關(guān)包,我們的插件不會依賴于vue,因此我們把它刪除即可。
{ - "vue": "^3.0.0-0", - "vue-class-component": "^8.0.0-0" }創(chuàng)建DOM
為了方便開發(fā)者使用dom,這里選擇使用js動態(tài)來創(chuàng)建dom,最后將其掛載到body中,在vue3版本的截圖插件中,我們可以使用vue組件來輔助我們,這里我們就要基于組件來使用js來創(chuàng)建對應(yīng)的dom,為其綁定對應(yīng)的事件。
部分實現(xiàn)代碼如下,完整代碼請移步:CreateDom.ts
import toolbar from "@/lib/config/Toolbar"; import { toolbarType } from "@/lib/type/ComponentType"; import { toolClickEvent } from "@/lib/split-methods/ToolClickEvent"; import { setBrushSize } from "@/lib/common-methords/SetBrushSize"; import { selectColor } from "@/lib/common-methords/SelectColor"; import { getColor } from "@/lib/common-methords/GetColor"; export default class CreateDom { // 截圖區(qū)域canvas容器 private readonly screenShortController: HTMLCanvasElement; // 截圖工具欄容器 private readonly toolController: HTMLDivElement; // 繪制選項頂部ico容器 private readonly optionIcoController: HTMLDivElement; // 畫筆繪制選項容器 private readonly optionController: HTMLDivElement; // 文字工具輸入容器 private readonly textInputController: HTMLDivElement; // 截圖工具欄圖標 private readonly toolbar: Array<toolbarType>; constructor() { this.screenShortController = document.createElement("canvas"); this.toolController = document.createElement("div"); this.optionIcoController = document.createElement("div"); this.optionController = document.createElement("div"); this.textInputController = document.createElement("div"); // 為所有dom設(shè)置id this.setAllControllerId(); // 為畫筆繪制選項角標設(shè)置class this.setOptionIcoClassName(); this.toolbar = toolbar; // 渲染工具欄 this.setToolBarIco(); // 渲染畫筆相關(guān)選項 this.setBrushSelectPanel(); // 渲染文本輸入 this.setTextInputPanel(); // 渲染頁面 this.setDomToBody(); // 隱藏所有dom this.hiddenAllDom(); } /** 其他代碼省略 **/ }插件入口文件
在開發(fā)vue插件時我們需要暴露一個install方法,由于此處我們不需要依賴vue,我們就無需暴露install方法,我的預想效果是:用戶在使用我插件時,直接實例化插件就能正常運行。
因此,我們默認暴露出一個class,無論是使用script標簽引入插件,還是在其他js框架里使用import來引入插件,都只需要在使用時new一下即可。
部分代碼如下,完整代碼請移步:main.ts
import CreateDom from "@/lib/main-entrance/CreateDom"; // 導入截圖所需樣式 import "@/assets/scss/screen-short.scss"; import InitData from "@/lib/main-entrance/InitData"; import { cutOutBoxBorder, drawCutOutBoxReturnType, movePositionType, positionInfoType, zoomCutOutBoxReturnType } from "@/lib/type/ComponentType"; import { drawMasking } from "@/lib/split-methods/DrawMasking"; import { fixedData, nonNegativeData } from "@/lib/common-methords/FixedData"; import { drawPencil, initPencil } from "@/lib/split-methods/DrawPencil"; import { drawText } from "@/lib/split-methods/DrawText"; import { drawRectangle } from "@/lib/split-methods/DrawRectangle"; import { drawCircle } from "@/lib/split-methods/DrawCircle"; import { drawLineArrow } from "@/lib/split-methods/DrawLineArrow"; import { drawMosaic } from "@/lib/split-methods/DrawMosaic"; import { drawCutOutBox } from "@/lib/split-methods/DrawCutOutBox"; import { zoomCutOutBoxPosition } from "@/lib/common-methords/ZoomCutOutBoxPosition"; import { saveBorderArrInfo } from "@/lib/common-methords/SaveBorderArrInfo"; import { calculateToolLocation } from "@/lib/split-methods/CalculateToolLocation"; export default class ScreenShort { // 當前實例的響應(yīng)式data數(shù)據(jù) private readonly data: InitData; // video容器用于存放屏幕MediaStream流 private readonly videoController: HTMLVideoElement; // 截圖區(qū)域canvas容器 private readonly screenShortController: HTMLCanvasElement | null; // 截圖工具欄dom private readonly toolController: HTMLDivElement | null; // 截圖圖片存放容器 private readonly screenShortImageController: HTMLCanvasElement; // 截圖區(qū)域畫布 private screenShortCanvas: CanvasRenderingContext2D | undefined; // 文本區(qū)域dom private readonly textInputController: HTMLDivElement | null; // 截圖工具欄畫筆選項dom private optionController: HTMLDivElement | null; private optionIcoController: HTMLDivElement | null; // 圖形位置參數(shù) private drawGraphPosition: positionInfoType = { startX: 0, startY: 0, width: 0, height: 0 }; // 臨時圖形位置參數(shù) private tempGraphPosition: positionInfoType = { startX: 0, startY: 0, width: 0, height: 0 }; // 裁剪框邊框節(jié)點坐標事件 private cutOutBoxBorderArr: Array<cutOutBoxBorder> = []; // 當前操作的邊框節(jié)點 private borderOption: number | null = null; // 點擊裁剪框時的鼠標坐標 private movePosition: movePositionType = { moveStartX: 0, moveStartY: 0 }; // 鼠標點擊狀態(tài) private clickFlag = false; private fontSize = 17; // 最大可撤銷次數(shù) private maxUndoNum = 15; // 馬賽克涂抹區(qū)域大小 private degreeOfBlur = 5; // 文本輸入框位置 private textInputPosition: { mouseX: number; mouseY: number } = { mouseX: 0, mouseY: 0 }; constructor() { // 創(chuàng)建dom new CreateDom(); this.videoController = document.createElement("video"); this.videoController.autoplay = true; this.screenShortImageController = document.createElement("canvas"); // 實例化響應(yīng)式data this.data = new InitData(); // 獲取截圖區(qū)域canvas容器 this.screenShortController = this.data.getScreenShortController() as HTMLCanvasElement | null; this.toolController = this.data.getToolController() as HTMLDivElement | null; this.textInputController = this.data.getTextInputController() as HTMLDivElement | null; this.optionController = this.data.getOptionController() as HTMLDivElement | null; this.optionIcoController = this.data.getOptionIcoController() as HTMLDivElement | null; this.load(); } /** 其他代碼省略 **/ }對外暴露default屬性
做完上述配置后我們的插件開發(fā)環(huán)境就搭建好了,我執(zhí)行build命令打包插件后,在vue2項目中使用import形式正常運行,在使用script標簽時引入時卻報錯了,于是我將暴露出來的screenShotPlugin變量打印出來后發(fā)現(xiàn)他還有個default屬性,default屬性才是我們插件暴露出來的東西。
求助了下我朋友@_Dreams找到了解決方案,需要配置下webpack中的output.libraryExport屬性,我們的插件是使用Vue CLI開發(fā)的,有關(guān)webpack的配置需要在需要在vue.config.js中進行配置,代碼如下:
module.exports = { // 自定義webpack配置 configureWebpack: { output: { // 對外暴露default屬性 libraryExport: "default" } } }這一塊的配置在Vue CLI文檔中也有被提到,感興趣的開發(fā)者請移步:build-targets.html#vue-vs-js-ts-entry-files
使用webrtc截取整個屏幕
插件一開始使用的是html2canvas來將dom轉(zhuǎn)換為canvas的,因為他要遍歷整個body中的dom,然后再轉(zhuǎn)換成canvas,而且圖片還不能跨域,如果頁面中圖片一多,它會變得非常慢。
在上一篇文章的評論區(qū)中有位開發(fā)者 @名字什么的都不重要 建議我使用webrtc來替代html2canvas,于是我就看了下webrtc的相關(guān)文檔,最終實現(xiàn)了截屏功能,它截取出來的東西更精確、性能更好,不存在卡頓問題也不存在css問題,而且它把選擇權(quán)交給了用戶,讓用戶決定來共享屏幕的那一部分內(nèi)容。
實現(xiàn)思路
接下來就跟大家分享下我的實現(xiàn)思路:
使用getDisplayMedia來捕獲屏幕,得到MediaStream流
將得到的MediaStream流輸出到video標簽中
使用canvas將video標簽中的內(nèi)容繪制到canvas容器中
有關(guān)getDisplayMedia的具體用法,請移步:使用屏幕捕獲API
實現(xiàn)代碼
接下來,我們來看下具體的實現(xiàn)代碼,完整代碼請移步:main.ts
// 加載截圖組件 private load() { // 設(shè)置截圖區(qū)域canvas寬高 this.data.setScreenShortInfo(window.innerWidth, window.innerHeight); // 設(shè)置截圖圖片存放容器寬高 this.screenShortImageController.width = window.innerWidth; this.screenShortImageController.height = window.innerHeight; // 顯示截圖區(qū)域容器 this.data.showScreenShortPanel(); // 截取整個屏幕 this.screenShot(); } // 開始捕捉屏幕 private startCapture = async () => { let captureStream = null; try { // eslint-disable-next-line @typescript-eslint/ban-ts-ignore // @ts-ignore // 捕獲屏幕 captureStream = await navigator.mediaDevices.getDisplayMedia(); // 將MediaStream輸出至video標簽 this.videoController.srcObject = captureStream; } catch (err) { throw "瀏覽器不支持webrtc" + err; } return captureStream; }; // 停止捕捉屏幕 private stopCapture = () => { const srcObject = this.videoController.srcObject; if (srcObject && "getTracks" in srcObject) { const tracks = srcObject.getTracks(); tracks.forEach(track => track.stop()); this.videoController.srcObject = null; } }; // 截屏 private screenShot = () => { // 開始捕捉屏幕 this.startCapture().then(() => { setTimeout(() => { // 獲取截圖區(qū)域canvas容器畫布 const context = this.screenShortController?.getContext("2d"); if (context == null || this.screenShortController == null) return; // 賦值截圖區(qū)域canvas畫布 this.screenShortCanvas = context; // 繪制蒙層 drawMasking(context); // 將獲取到的屏幕截圖繪制到圖片容器里 this.screenShortImageController .getContext("2d") ?.drawImage( this.videoController, 0, 0, this.screenShortImageController?.width, this.screenShortImageController?.height ); // 添加監(jiān)聽 this.screenShortController?.addEventListener( "mousedown", this.mouseDownEvent ); this.screenShortController?.addEventListener( "mousemove", this.mouseMoveEvent ); this.screenShortController?.addEventListener( "mouseup", this.mouseUpEvent ); // 停止捕捉屏幕 this.stopCapture(); }, 300); }); };感謝各位的閱讀,以上就是“怎么實現(xiàn)Web端自定義截屏”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對怎么實現(xiàn)Web端自定義截屏這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!
網(wǎng)站標題:怎么實現(xiàn)Web端自定義截屏
瀏覽路徑:http://chinadenli.net/article12/pgjpdc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、面包屑導航、外貿(mào)建站、品牌網(wǎng)站設(shè)計、建站公司、全網(wǎng)營銷推廣
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)