Skip to content

Commit

Permalink
Merge pull request #42 from Im-Rises/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
Im-Rises authored May 15, 2023
2 parents f3b85a8 + 629390e commit 5a2694a
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 37 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ You can also pass a pre tag reference to the component, so it can be used to get
fontColor={'white'}
backgroundColor={'black'}
flipY={true}
frameRate={frameRate}
preTagRef={preTagRef}
/>
```
Expand All @@ -101,7 +100,6 @@ To use the component, you need to pass the following props:
- `fontColor` - The color of the font.
- `backgroundColor` - The color of the background.
- `flipY` - Flip the ascii art vertically.
- `frameRate` - The frame rate of the video stream.
- `preTagRef` - The reference of the pre tag, to get the ascii art text.

The `parentRef` is used to fit the ascii art in the parent element, so you need to pass the reference of the parent
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "video-stream-ascii",
"version": "1.5.0",
"version": "1.6.0",
"description": "Convert video stream to ascii art",
"homepage": "https://im-rises.github.io/video-stream-ascii-webcam",
"repository": "https://github.com/Im-Rises/video-stream-ascii",
Expand Down
1 change: 0 additions & 1 deletion src/components/CameraAsciiPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ const CameraAsciiPanel = () => {
fontColor={'white'}
backgroundColor={'black'}
flipY={true}
frameRate={30}
preTagRef={preTagRef}
/>
) : (
Expand Down
63 changes: 30 additions & 33 deletions src/components/VideoAscii.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useRef, useEffect, useState} from 'react';
import React, {useRef, useEffect, useState, createRef} from 'react';
import {asciiChars} from '../constants/pixel-ascii';
import {
calculateAndSetFontSize, canvasImgToUrl,
Expand All @@ -23,25 +23,29 @@ type Props = {
artType: ArtTypeEnum;
flipY?: boolean;
preTagRef?: React.RefObject<HTMLPreElement>;
frameRate?: number;
};

const defaultProps = {
flipY: false,
preTagRef: createRef<HTMLPreElement>(),
};

export const VideoAscii = (props: Props) => {
const canvasVideoBufferRef = useRef<HTMLCanvasElement>(null);
const preTagRef = props.preTagRef ?? useRef<HTMLPreElement>(null);
const flipY = props.flipY ?? false;
const frameRate = props.frameRate ?? 30;
// Merge the props with the default props
const mergedProps = {...defaultProps, ...props};

// Set the local variables
const canvasVideoBufferRef = useRef<HTMLCanvasElement>(null);
const [asciiText, setAsciiText] = useState('');

// UseEffect to calculate the font size and set the resize observer (to resize the canvas and the font size, when the parent element is resized)
useEffect(() => {
calculateAndSetFontSize(preTagRef.current!, props.charsPerLine, props.charsPerColumn, props.parentRef.current!.clientWidth, props.parentRef.current!.clientHeight);
calculateAndSetFontSize(mergedProps.preTagRef.current!, props.charsPerLine, props.charsPerColumn, props.parentRef.current!.clientWidth, props.parentRef.current!.clientHeight);

// Set a resize observer to the parent element to resize the canvas and the font size
const resizeObserver = new ResizeObserver(entries => {
const {width, height} = entries[0].contentRect;
calculateAndSetFontSize(preTagRef.current!, props.charsPerLine, props.charsPerColumn, width, height);
calculateAndSetFontSize(mergedProps.preTagRef.current!, props.charsPerLine, props.charsPerColumn, width, height);
});
if (props.parentRef.current) {
resizeObserver.observe(props.parentRef.current);
Expand All @@ -58,8 +62,8 @@ export const VideoAscii = (props: Props) => {
const canvas = canvasVideoBufferRef.current!;
const context = canvas.getContext('2d', {willReadFrequently: true})!;

// // Animation frame id
// let animationFrameId: number;
// Animation frame id
let animationFrameId: number;

// Refresh the ascii art text every frame
const updateAscii = () => {
Expand All @@ -78,31 +82,25 @@ export const VideoAscii = (props: Props) => {
break;
case ArtTypeEnum.ASCII_COLOR_BG_IMAGE:
setAsciiText(getAsciiFromImage(imageData, asciiChars));
preTagRef.current!.style.backgroundImage = `url(${canvasImgToUrl(canvas).src})`;// Use the resized canvas as background image
// preTagRef.current!.style.backgroundImage = `url(${videoImgToUrl(props.videoStreaming).src})`;// Use the original image as background image
// Set the background image of the pre tag to the resized canvas
mergedProps.preTagRef.current!.style.backgroundImage = `url(${canvasImgToUrl(canvas).src})`;
// // Set the background image of the pre tag to the original dimensions video
// mergedProps.preTagRef.current!.style.backgroundImage = `url(${videoImgToUrl(props.videoStreaming).src})`;
break;
default:
break;
}

// // Schedule the next frame
// animationFrameId = requestAnimationFrame(updateAscii);
// Schedule the next frame
animationFrameId = requestAnimationFrame(updateAscii);
};

const intervalId = setInterval(() => {
updateAscii();
}, 1000 / frameRate);

// // Start the animation loop when the component mounts
// updateAscii();
//
// // Stop the animation loop when the component unmounts
// return () => {
// cancelAnimationFrame(animationFrameId);
// };
// Start the animation loop when the component mounts
updateAscii();

// Stop the animation loop when the component unmounts
return () => {
clearInterval(intervalId);
cancelAnimationFrame(animationFrameId);
};
}, [props.videoStreaming, props.artType]);

Expand All @@ -119,30 +117,30 @@ export const VideoAscii = (props: Props) => {
switch (props.artType) {
case ArtTypeEnum.ASCII:
return (
<pre ref={preTagRef} style={{
<pre ref={mergedProps.preTagRef} style={{
backgroundColor: props.backgroundColor,
color: props.fontColor,
padding: 0,
margin: 0,
letterSpacing: `${lineSpacing}em`,
lineHeight: `${lineHeight}em`,
transform: `scaleX(${flipY ? -1 : 1})`,
transform: `scaleX(${mergedProps.flipY ? -1 : 1})`,
overflow: 'hidden',
}}>
{asciiText}
</pre>
);
case ArtTypeEnum.ASCII_COLOR:
return (
<pre ref={preTagRef} dangerouslySetInnerHTML={{__html: asciiText}}
<pre ref={mergedProps.preTagRef} dangerouslySetInnerHTML={{__html: asciiText}}
style={{
backgroundColor: props.backgroundColor,
color: props.fontColor,
padding: 0,
margin: 0,
letterSpacing: `${lineSpacing}em`,
lineHeight: `${lineHeight}em`,
transform: `scaleX(${flipY ? -1 : 1})`,
transform: `scaleX(${mergedProps.flipY ? -1 : 1})`,
overflow: 'hidden',
}}
></pre>
Expand All @@ -158,7 +156,7 @@ export const VideoAscii = (props: Props) => {
might think that the change of pre tag is an update not a replace
*/
}
<pre ref={preTagRef} style={{
<pre ref={mergedProps.preTagRef} style={{
padding: 0,
margin: 0,
letterSpacing: `${lineSpacing}em`,
Expand All @@ -167,9 +165,8 @@ export const VideoAscii = (props: Props) => {
backgroundClip: 'text',
WebkitBackgroundClip: 'text',
color: 'transparent',
transform: `scaleX(${flipY ? -1 : 1})`,
transform: `scaleX(${mergedProps.flipY ? -1 : 1})`,
overflow: 'hidden',
// backgroundImage: `url(${props.videoStreaming.src})`,
}}>
{asciiText}
</pre>
Expand Down

0 comments on commit 5a2694a

Please sign in to comment.