UNPKG

@datalayer/core

Version:
175 lines (174 loc) 6.69 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; /* * Copyright (c) 2023-2025 Datalayer, Inc. * Distributed under the terms of the Modified BSD License. */ import { Component } from 'react'; import html2canvas from 'html2canvas'; export class ScreenCapture extends Component { state = { on: false, startX: 0, startY: 0, endX: 0, endY: 0, crossHairsTop: 0, crossHairsLeft: 0, isMouseDown: false, windowWidth: 0, windowHeight: 0, borderWidth: 0, cropPositionTop: 0, cropPositionLeft: 0, cropWidth: 0, cropHeigth: 0, imageURL: '', }; handleWindowResize = () => { const windowWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; const windowHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; this.setState({ windowWidth, windowHeight, }); }; componentDidMount = () => { this.handleWindowResize(); window.addEventListener('resize', this.handleWindowResize); }; componentWillUnmount = () => { window.removeEventListener('resize', this.handleWindowResize); }; handStartCapture = () => this.setState({ on: true }); handleMouseMove = (e) => { const { isMouseDown, windowWidth, windowHeight, startX, startY, borderWidth } = this.state; let cropPositionTop = startY; let cropPositionLeft = startX; const endX = e.clientX; const endY = e.clientY; const isStartTop = endY >= startY; const isStartBottom = endY <= startY; const isStartLeft = endX >= startX; const isStartRight = endX <= startX; const isStartTopLeft = isStartTop && isStartLeft; const isStartTopRight = isStartTop && isStartRight; const isStartBottomLeft = isStartBottom && isStartLeft; const isStartBottomRight = isStartBottom && isStartRight; let newBorderWidth = borderWidth; let cropWidth = 0; let cropHeigth = 0; if (isMouseDown) { if (isStartTopLeft) { newBorderWidth = `${startY}px ${windowWidth - endX}px ${windowHeight - endY}px ${startX}px`; cropWidth = endX - startX; cropHeigth = endY - startY; } if (isStartTopRight) { newBorderWidth = `${startY}px ${windowWidth - startX}px ${windowHeight - endY}px ${endX}px`; cropWidth = startX - endX; cropHeigth = endY - startY; cropPositionLeft = endX; } if (isStartBottomLeft) { newBorderWidth = `${endY}px ${windowWidth - endX}px ${windowHeight - startY}px ${startX}px`; cropWidth = endX - startX; cropHeigth = startY - endY; cropPositionTop = endY; } if (isStartBottomRight) { newBorderWidth = `${endY}px ${windowWidth - startX}px ${windowHeight - startY}px ${endX}px`; cropWidth = startX - endX; cropHeigth = startY - endY; cropPositionLeft = endX; cropPositionTop = endY; } } cropWidth *= window.devicePixelRatio; cropHeigth *= window.devicePixelRatio; this.setState({ crossHairsTop: e.clientY, crossHairsLeft: e.clientX, borderWidth: newBorderWidth, cropWidth, cropHeigth, cropPositionTop: cropPositionTop, cropPositionLeft: cropPositionLeft, }); }; handleMouseDown = (e) => { const startX = e.clientX; const startY = e.clientY; this.setState(prevState => ({ startX, startY, cropPositionTop: startY, cropPositionLeft: startX, isMouseDown: true, borderWidth: `${prevState.windowWidth}px ${prevState.windowHeight}px`, })); }; handleMouseUp = () => { this.handleClickTakeScreenShot(); this.setState({ on: false, isMouseDown: false, borderWidth: 0, }); }; handleClickTakeScreenShot = () => { const { windowWidth, windowHeight, cropPositionTop, cropPositionLeft, cropWidth, cropHeigth, } = this.state; const body = document.querySelector('body'); if (body) { const scale = window.devicePixelRatio; html2canvas(body, { width: windowWidth, height: windowHeight, scale: scale }).then(canvas => { const croppedCanvas = document.createElement('canvas'); const croppedCanvasContext = croppedCanvas.getContext('2d'); croppedCanvas.width = cropWidth; croppedCanvas.height = cropHeigth; if (croppedCanvasContext) { croppedCanvasContext.drawImage(canvas, cropPositionLeft * scale, cropPositionTop * scale, cropWidth * scale, cropHeigth * scale, 0, 0, cropWidth * scale, cropHeigth * scale); } if (croppedCanvas) { const type = 'image/png'; const quality = 1; const outputshotData = croppedCanvas.toDataURL(type, quality); this.props.onEndCapture(outputshotData); } }); } this.setState({ crossHairsTop: 0, crossHairsLeft: 0, }); }; renderChild = () => { const { children } = this.props; const props = { onStartCapture: this.handStartCapture }; if (typeof children === 'function') { return children(props); } return children; }; render() { const { on, crossHairsTop, crossHairsLeft, borderWidth, isMouseDown, } = this.state; if (!on) { return this.renderChild(); } return (_jsxs("div", { onMouseMove: this.handleMouseMove, onMouseDown: this.handleMouseDown, onMouseUp: this.handleMouseUp, children: [this.renderChild(), _jsx("div", { className: `overlay ${isMouseDown && 'highlighting'}`, style: { borderWidth: `${borderWidth}` } }), _jsx("div", { className: 'crosshairs', style: { left: crossHairsLeft + 'px', top: crossHairsTop + 'px' } })] })); } } export default ScreenCapture;