Graphics 画布中的文本将被下面的视频画布擦除
注:最小工作示例。点击Graphics 画布中的文本将被下面的视频画布擦除,graphics,html5-canvas,html5-video,Graphics,Html5 Canvas,Html5 Video,注:最小工作示例。点击更改文本按钮,您可以看到文本将出现一帧,然后消失 我想给我的视频添加一个覆盖层,所以我把两张画布堆叠起来,并在透明的顶部画布上填充文本 但是,文本不会粘住。它消失了 为了测试我是否正确填充了文本,我尝试在下面使用黑色画布(没有视频) 我只需要填写一次文本,文本就保留了下来 但是,在下面的视频画布上,除非我在requestAnimationFrame中绘制文本,否则文本不会粘住,我相信它会在每个帧中绘制相同的文本,这是不必要的 文本画布应该与视频画布分开。为什么在没有requ
更改文本
按钮,您可以看到文本将出现一帧,然后消失
我想给我的视频添加一个覆盖层,所以我把两张画布堆叠起来,并在透明的顶部画布上填充文本
但是,文本不会粘住。它消失了
为了测试我是否正确填充了文本,我尝试在下面使用黑色画布(没有视频)
我只需要填写一次文本,文本就保留了下来
但是,在下面的视频画布上,除非我在requestAnimationFrame中绘制文本,否则文本不会粘住,我相信它会在每个帧中绘制相同的文本,这是不必要的
文本画布应该与视频画布分开。为什么在没有requestAnimationFrame的情况下这会被删除
我怎样才能修好它
最小的工作示例,但代码也显示在下面
import "./styles.css";
import { useEffect, useRef, useState } from "react";
export default function App() {
const inputStreamRef = useRef();
const videoRef = useRef();
const canvasRef = useRef();
const overlayCanvasRef = useRef();
const [text, setText] = useState("Hello");
function drawTextWithBackground() {
const ctx = overlayCanvasRef.current.getContext("2d");
ctx.clearRect(
0,
0,
overlayCanvasRef.current.width,
overlayCanvasRef.current.height
);
/// lets save current state as we make a lot of changes
ctx.save();
/// set font
const font = "50px monospace";
ctx.font = font;
/// draw text from top - makes life easier at the moment
ctx.textBaseline = "top";
/// color for background
ctx.fillStyle = "#FFFFFF";
/// get width of text
const textWidth = ctx.measureText(text).width;
// Just note that this way of "measuring" height is not accurate.
// You can measure height of a font by using a temporary div / span element and
// get the calculated style from that when font and text is set for it.
const textHeight = parseInt(font, 10);
const textXPosition = canvasRef.current.width / 2 - textWidth / 2;
const textYPosition = canvasRef.current.height - textHeight * 3;
ctx.save();
ctx.globalAlpha = 0.4;
/// draw background rect assuming height of font
ctx.fillRect(textXPosition, textYPosition, textWidth, textHeight);
ctx.restore(); // this applies globalAlpha to just this?
/// text color
ctx.fillStyle = "#000";
ctx.fillText(text, textXPosition, textYPosition);
/// restore original state
ctx.restore();
}
function updateCanvas() {
const ctx = canvasRef.current.getContext("2d");
ctx.drawImage(
videoRef.current,
0,
0,
videoRef.current.videoWidth,
videoRef.current.videoHeight
);
// QUESTION: Now the text won't stick unless I uncomment this below,
// which runs drawTextWithBackground in requestAnimationFrame.
// Previosuly, with just a black canvas underneath, I just needed to fillText once
// and the text stayed.
// The text canvas is supposed to be separate. Why is this getting wiped out without requestAnimationFrame?
// drawTextWithBackground();
requestAnimationFrame(updateCanvas);
}
const CAMERA_CONSTRAINTS = {
audio: true,
video: {
// the best (4k) resolution from camera
width: 4096,
height: 2160
}
};
const enableCamera = async () => {
inputStreamRef.current = await navigator.mediaDevices.getUserMedia(
CAMERA_CONSTRAINTS
);
videoRef.current.srcObject = inputStreamRef.current;
await videoRef.current.play();
// We need to set the canvas height/width to match the video element.
canvasRef.current.height = videoRef.current.videoHeight;
canvasRef.current.width = videoRef.current.videoWidth;
overlayCanvasRef.current.height = videoRef.current.videoHeight;
overlayCanvasRef.current.width = videoRef.current.videoWidth;
requestAnimationFrame(updateCanvas);
};
useEffect(() => {
enableCamera();
});
return (
<div className="App">
<video
ref={videoRef}
style={{ visibility: "hidden", position: "absolute" }}
/>
<div style={{ position: "relative", width: "90vw" }}>
<canvas
style={{ width: "100%", top: 0, left: 0, position: "static" }}
ref={canvasRef}
width="500"
height="400"
/>
<canvas
style={{
width: "100%",
top: 0,
left: 0,
position: "absolute"
}}
ref={overlayCanvasRef}
width="500"
height="400"
/>
</div>
<button
onClick={() => {
setText(text + "c");
drawTextWithBackground();
}}
>
change text
</button>
</div>
);
}
导入“/styles.css”;
从“react”导入{useffect,useRef,useState};
导出默认函数App(){
const inputStreamRef=useRef();
const videoRef=useRef();
const canvasRef=useRef();
const overlayCanvasRef=useRef();
const[text,setText]=useState(“Hello”);
函数drawTextWithBackground(){
const ctx=overlycanvasref.current.getContext(“2d”);
ctx.clearRect(
0,
0,
覆盖canvasref.current.width,
覆盖CanvasRef.current.height
);
///让我们在进行大量更改时保存当前状态
ctx.save();
///设置字体
const font=“50px monospace”;
ctx.font=font;
///从顶部绘制文本-使当前的生活更轻松
ctx.textb基线=“顶部”;
///背景颜色
ctx.fillStyle=“#FFFFFF”;
///获取文本的宽度
const textWidth=ctx.measureText(text).width;
//请注意,这种“测量”高度的方法并不准确。
//您可以使用临时div/span元素和
//设置字体和文字时,从中获取计算的样式。
const textHeight=parseInt(字体,10);
const textXPosition=canvasRef.current.width/2-textWidth/2;
const textYPosition=canvasRef.current.height-textHeight*3;
ctx.save();
ctx.globalAlpha=0.4;
///假设字体高度绘制背景矩形
ctx.fillRect(textXPosition、textYPosition、textWidth、textHeight);
ctx.restore();//这将globalAlpha应用于此?
///文本颜色
ctx.fillStyle=“#000”;
ctx.fillText(text,textXPosition,textYPosition);
///恢复原始状态
ctx.restore();
}
函数updateCanvas(){
const ctx=canvasRef.current.getContext(“2d”);
ctx.drawImage(
videoRef.current,
0,
0,
videoRef.current.videoWidth,
videoRef.current.videoHeight
);
//问题:除非我在下面取消注释,否则文本不会保持不变,
//它在requestAnimationFrame中运行drawTextWithBackground。
//以前,只有一块黑色的画布在下面,我只需要填充一次文本
//文本保持不变。
//文本画布应该是分开的。为什么在没有requestAnimationFrame的情况下会被删除?
//drawTextWithBackground();
requestAnimationFrame(updateCanvas);
}
常量摄影机约束={
音频:是的,
视频:{
//摄像机的最佳(4k)分辨率
宽度:4096,
身高:2160
}
};
const enableCamera=async()=>{
inputStreamRef.current=等待navigator.mediaDevices.getUserMedia(
摄像机约束
);
videoRef.current.srcObject=inputStreamRef.current;
等待videoRef.current.play();
//我们需要设置画布的高度/宽度以匹配视频元素。
canvasRef.current.height=videoRef.current.videoHeight;
canvasRef.current.width=videoRef.current.videoWidth;
OverlyCanvasref.current.height=videoRef.current.videoHeight;
OverlyCanvasref.current.width=videoRef.current.videoWidth;
requestAnimationFrame(updateCanvas);
};
useffect(()=>{
启用摄像头();
});
返回(
{
setText(文本+c);
drawTextWithBackground();
}}
>
更改文本
);
}
从视频中更新画布时,画布中的所有像素都将使用视频中的像素进行更新。把它想象成一堵墙: 你在墙上画了“这是我的文字” 然后你把整面墙漆成蓝色。(你的文字不见了,墙上只有蓝色) 如果你把整面墙涂成蓝色,然后重新涂上“这是我的文字”,你仍然可以在蓝色的墙上看到你的文字 重新绘制画布时,必须重新绘制要显示在画布上的所有内容。如果视频“覆盖”了你的文本,你必须重新绘制文本
在画布的每一帧上绘制chyron(新闻故事底部的条形图)的工作示例。当您从视频更新画布时,画布中的所有像素都会用视频中的像素更新。把它想象成一堵墙: 你在墙上画了“这是我的文字” 然后你把整面墙漆成蓝色。(你的文字不见了,墙上只有蓝色) 如果你把整面墙涂成蓝色,然后重新涂上“这是我的文字”,你仍然可以在蓝色的墙上看到你的文字 重新绘制画布时,必须重新绘制要显示在画布上的所有内容。如果视频“覆盖”了你的文本,你必须重新绘制文本 在画布的每一帧上绘制一个chyron(新闻故事底部的条形图)的工作示例。非常简单的修复 由于如何反应更新状态,画布正在被清除 修复 最简单的修复方法是只使用一个画布,并将文本绘制到用于显示视频的画布上 从工作示例更改两个函数
updateCanvas
和dra
function drawTextWithBackground(ctx) {
const can = ctx.canvas;
const textH = 50;
ctx.font = textH + "px monospace";
ctx.textBaseline = "top";
ctx.textAlign = "center";
ctx.fillStyle = "#FFFFFF66"; // alpha 0.4 as part of fillstyle
ctx.fillStyle = "#000";
const [W, X, Y] = [ctx.measureText(text).width, can.width, can.height - textH * 3];
ctx.fillRect(X - W / 2, Y, W, textH);
ctx.fillText(text, X, Y);
}
function updateCanvas() {
const vid = videoRef.current;
const ctx = canvasRef.current.getContext("2d");
ctx.drawImage(vid, 0, 0, vid.videoWidth, vid.videoHeight);
drawTextWithBackground(ctx);
requestAnimationFrame(updateCanvas);
}