In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly explains "how to achieve custom screenshots on Web". The content in the article is simple and clear, and it is easy to learn and understand. Please follow the editor's ideas to study and learn "how to achieve custom screenshots on Web".
Build a development environment
I want to use ts, scss, eslint, prettier to improve the maintainability of the plug-in, but I don't want to configure the webpack environment manually, so I decided to use Vue CLI to build the plug-in development environment.
This article will not go into detail about the process of building a plug-in development environment with Vue CLI. Developers who are interested in this should take a step forward: use CLI to develop a npm library for Vue3.
Remove vue related dependencies
After we have built the plug-in development environment, CLI will add Vue-related packages to package.json by default, and our plug-ins will not depend on vue, so we can delete it.
{- "vue": "^ 3.0.0-0",-"vue-class-component": "^ 8.0.0-0"}
Create DOM
To make it convenient for developers to use dom, here we choose to use js dynamic to create dom, and finally mount it to body. In the screenshot plug-in of vue3 version, we can use vue component to assist us. Here, we need to use js to create the corresponding dom based on the component and bind the corresponding events for it.
Part of the implementation code is as follows. The complete code should be moved to: 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 {/ / screenshot area canvas container private readonly screenShortController: HTMLCanvasElement / / Screenshot Toolbar Container private readonly toolController: HTMLDivElement; / / drawing options Top ico Container private readonly optionIcoController: HTMLDivElement; / / Brush drawing options Container private readonly optionController: HTMLDivElement; / / Type tool input Container private readonly textInputController: HTMLDivElement; / / Screenshot toolbar icon private readonly toolbar: Array; 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"); / / set id this.setAllControllerId () for all dom; / / set class this.setOptionIcoClassName () for brush painting option corner; this.toolbar = toolbar / / rendering toolbar this.setToolBarIco (); / / render brush related options this.setBrushSelectPanel (); / render text input this.setTextInputPanel (); / render page this.setDomToBody (); / / hide all dom this.hiddenAllDom ();} / * other code omitted * * /}
Plug-in entry file
We need to expose an install method when developing the vue plug-in, and since we don't need to rely on vue here, we don't need to expose the install method. My expectation is that when the user uses my plug-in, the plug-in can be instantiated directly.
Therefore, we expose a class by default, whether using script tags to introduce plug-ins, or using import in other js frameworks to introduce plug-ins, you only need to new when you use it.
Part of the code is as follows. The complete code should be moved to: main.ts
Import CreateDom from "@ / lib/main-entrance/CreateDom"; / / Import style 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 {/ / responsive data data private readonly data: InitData; / / video container for screen MediaStream flow private readonly videoController: HTMLVideoElement; / / screenshot area canvas container private readonly screenShortController: HTMLCanvasElement | null / / Screenshot toolbar dom private readonly toolController: HTMLDivElement | null; / / Screenshot image storage container private readonly screenShortImageController: HTMLCanvasElement; / / screenshot area canvas private screenShortCanvas: CanvasRenderingContext2D | undefined; / / text area dom private readonly textInputController: HTMLDivElement | null; / / Screenshot toolbar brush option dom private optionController: HTMLDivElement | null; private optionIcoController: HTMLDivElement | null / / drawing position parameters private drawGraphPosition: positionInfoType = {startX: 0, startY: 0, width: 0, height: 0}; / / temporary drawing position parameters private tempGraphPosition: positionInfoType = {startX: 0, startY: 0, width: 0, height: 0}; / / clipping frame node coordinate event private cutOutBoxBorderArr: Array = [] / / currently operated border node private borderOption: number | null = null; / / Mouse coordinates private movePosition: movePositionType = {moveStartX: 0, moveStartY: 0}; / / Mouse click status private clickFlag = false; private fontSize = 17; / / maximum number of revocable times private maxUndoNum = 15; / / mosaic smear area size private degreeOfBlur = 5 / / text input box location private textInputPosition: {mouseX: number; mouseY: number} = {mouseX: 0, mouseY: 0}; constructor () {/ / create dom new CreateDom (); this.videoController = document.createElement ("video"); this.videoController.autoplay = true; this.screenShortImageController = document.createElement ("canvas"); / / instantiated responsive data this.data = new InitData () / / obtain screenshot area canvas container 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 () } / * other codes are omitted * * /}
Expose default attributes to the public
After completing the above configuration, our plug-in development environment is set up. After I executed the build command to package the plug-in, I used import in the vue2 project to run normally, but I reported an error when using the script tag, so I printed out the exposed screenShotPlugin variable and found that he also had a default attribute, which is what our plug-in exposed.
With the help of my friend @ _ Dreams to find a solution, we need to configure the output.libraryExport attribute in webpack. Our plug-in is developed using Vue CLI, and the configuration of webpack needs to be configured in vue.config.js. The code is as follows:
Module.exports = {/ / Custom webpack configuration configureWebpack: {output: {/ / expose default attribute libraryExport: "default"}
The configuration of this section is also mentioned in the Vue CLI documentation. For interested developers, please move to: build-targets.html#vue-vs-js-ts-entry-files
Capture the entire screen using webrtc
At the beginning, the plug-in uses html2canvas to convert dom to canvas, because it has to traverse the dom in the entire body, and then convert it to canvas, and the picture cannot be cross-domain, so if there are more pictures on the page, it will become very slow.
In the comments section of the previous article, there was a developer whose @ name didn't matter. I suggested that I use webrtc instead of html2canvas, so I looked at the relevant webrtc documentation and finally realized the screenshot function, which intercepted things more accurately, had better performance, had no stutter problem or css problem, and it gave the user the choice to decide which part of the screen to share.
Realization idea
Next, I would like to share with you my ideas for implementation:
Use getDisplayMedia to capture the screen and get the MediaStream stream
Output the resulting MediaStream stream to the video tag
Use canvas to draw the contents of the video tag into the canvas container
For the specific use of getDisplayMedia, please move: use screen capture API
Implementation code
Next, let's take a look at the specific implementation code. The complete code can be moved to: main.ts.
/ / load screenshot component private load () {/ / set screenshot area canvas width and height this.data.setScreenShortInfo (window.innerWidth, window.innerHeight); / / set screenshot image storage container width and height this.screenShortImageController.width = window.innerWidth; this.screenShortImageController.height = window.innerHeight; / / display screenshot area container this.data.showScreenShortPanel () / / capture the entire screen this.screenShot ();} / / start capturing screen private startCapture = async () = > {let captureStream = null; try {/ / eslint-disable-next-line @ typescript-eslint/ban-ts-ignore / / @ ts-ignore / / capture screen captureStream = await navigator.mediaDevices.getDisplayMedia () / / output MediaStream to the video tag this.videoController.srcObject = captureStream;} catch (err) {throw "browser does not support webrtc" + err;} return captureStream;}; / / stop capturing the screen 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;}}; / / Screenshot private screenShot = () = > {/ / start capturing screen this.startCapture (). Then () = > {setTimeout () = > {/ / get screenshot area canvas container canvas const context = this.screenShortController?.getContext ("2d") If (context = = null | | this.screenShortController = = null) return; / / assigned screenshot area canvas canvas this.screenShortCanvas = context; / / draw mask drawMasking (context) / / draw the obtained screenshot to the image container this.screenShortImageController .getContext ("2d")? .drawImage (this.videoController, 0,0, this.screenShortImageController?.width, this.screenShortImageController?.height) / / add listening this.screenShortController?.addEventListener ("mousedown", this.mouseDownEvent); this.screenShortController?.addEventListener ("mousemove", this.mouseMoveEvent); this.screenShortController?.addEventListener ("mouseup", this.mouseUpEvent) / / stop capturing screen this.stopCapture ();}, 300);};}; thank you for reading. The above is the content of "how to achieve custom screenshot on Web". After the study of this article, I believe you have a deeper understanding of how to achieve custom screenshot on Web, and the specific usage needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.