控件播放视频,播放暂停循环等功能,以及画布的scratch缓冲处理视频

本文探讨了Scratch缓冲画布的工作原理,它由video层、处理画布和展现画布三层组成,实现了视频的播放、暂停和循环功能。同时,详细解释了一帧视频如何通过像素的R、G、B、ALPHA四个值来呈现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.scratch缓冲画布是怎么工作的,由最下层的video,中间的处理画布,最上层的展现画布组成



2.视频的一帧 = 一个像素 = 4个值(R G B ALPHA)

var videos = {
video1: "video/demovideo1",
video2: "video/demovideo2"
};


var effectFunction = null;


window.onload = function() {


var video = document.getElementById("video");
video.src = videos["video1"] + getFormatExtension();
video.load();


// add click handlers to control anchors
var controlLinks = document.querySelectorAll("a.control");
for (var i = 0; i < controlLinks.length; i++) {
controlLinks[i].onclick = handleControl;
}


// add click handlers to effect anchors
var effectLinks = document.querySelectorAll("a.effect");
for (var i = 0; i < effectLinks.length; i++) {
effectLinks[i].onclick = setEffect;
}

// add click handlers to videoSelection anchors
var videoLinks = document.querySelectorAll("a.videoSelection");
for (var i = 0; i < videoLinks.length; i++) {
videoLinks[i].onclick = setVideo;
}


// add click handlers to video play
//video.onplay = processFrame;
//video.onended = endedHandler;
video.addEventListener("play", processFrame, false);
video.addEventListener("ended", endedHandler, false);


pushUnpushButtons("video1", []);
pushUnpushButtons("normal", []);
};


function setEffect(e) {
var id = e.target.getAttribute("id");
if (id == "normal") {
pushUnpushButtons("normal", ["western", "noir", "scifi"]);
effectFunction = null;
} else if (id == "western") {
pushUnpushButtons("western", ["normal", "noir", "scifi"]);
effectFunction = western;
} else if (id == "noir") {
pushUnpushButtons("noir", ["normal", "western", "scifi"]);
effectFunction = noir;
} else if (id == "scifi") {
pushUnpushButtons("scifi", ["normal", "western", "noir"]);
effectFunction = scifi;
}
}


function setVideo(e) {
var id = e.target.getAttribute("id");
var video = document.getElementById("video");
if (id == "video1") {
pushUnpushButtons("video1", ["video2"]);
} else if (id == "video2") {
pushUnpushButtons("video2", ["video1"]);
}
video.src = videos[id] + getFormatExtension();
video.load();
video.play();


pushUnpushButtons("play", ["pause"]);
}


function getFormatExtension() {
var video = document.getElementById("video");
if (video.canPlayType("video/mp4") != "") {
return ".mp4";
} 
else if (video.canPlayType("video/ogg") != "") {
return ".ogv";
}
else if (video.canPlayType("video/webm") != "") {
return ".webm";
} 
}


function handleControl(e) {
var id = e.target.getAttribute("id");
var video = document.getElementById("video");
if (id == "play") {
pushUnpushButtons("play", ["pause"]);
if (video.ended) {
video.load();
}
video.play();
} else if (id == "pause") {
pushUnpushButtons("pause", ["play"]);
video.pause();
} else if (id == "loop") {
if (isButtonPushed("loop")) {
pushUnpushButtons("", ["loop"]);
} else {
pushUnpushButtons("loop", []);
}
video.loop = !video.loop;
} else if (id == "mute") {
if (isButtonPushed("mute")) {
pushUnpushButtons("", ["mute"]);
} else {
pushUnpushButtons("mute", []);
}
video.muted = !video.muted;
}
}


//
// "ended" event handler
//
function endedHandler(e) {
pushUnpushButtons("", ["play"]);
}


function processFrame(e) {
var video = document.getElementById("video");


if (video.paused || video.ended) {   //如果不是播放直接返回
return;
}


var bufferCanvas = document.getElementById("buffer");  //缓冲区
var displayCanvas = document.getElementById("display");//展现区
var buffer = bufferCanvas.getContext("2d");
var display = displayCanvas.getContext("2d");


buffer.drawImage(video, 0, 0, bufferCanvas.width, displayCanvas.height);  //画布的drawImage方法
    var frame = buffer.getImageData(0, 0, bufferCanvas.width, displayCanvas.height);  //用context的getImageData获取每帧
    var length = frame.data.length / 4; //rgb alpha所以每个长度有4个值,要除以4


for (var i = 0; i < length; i++) {
var r = frame.data[i * 4 + 0]; //每个像素在数组中占4个位置,从第一个位置取r,第二个位置g。。。
var g = frame.data[i * 4 + 1];
var b = frame.data[i * 4 + 2];
if (effectFunction) {
effectFunction(i, r, g, b, frame.data);
}
}
display.putImageData(frame, 0, 0); //putImageData将数据放在画布上展现


setTimeout(processFrame, 0); //尽快再次运行processFrame


}




/*
 * bwcartoon is an extra filter for an exercise
 */
function bwcartoon(pos, r, g, b, outputData) {
var offset =  pos * 4;
if( outputData[offset] < 120 ) {
outputData[offset] = 80;
outputData[++offset] = 80;
outputData[++offset] = 80;
} else {
outputData[offset] = 255;
outputData[++offset] = 255;
outputData[++offset] = 255;
}
outputData[++offset] = 255;
++offset;
}


function noir(pos, r, g, b, data) {
var brightness = (3*r + 4*g + b) >>> 3;
if (brightness < 0) brightness = 0;
data[pos * 4 + 0] = brightness;
data[pos * 4 + 1] = brightness;
data[pos * 4 + 2] = brightness;
}


function western(pos, r, g, b, data) {
var brightness = (3*r + 4*g + b) >>> 3;
data[pos * 4 + 0] = brightness+40;
data[pos * 4 + 1] = brightness+20;
data[pos * 4 + 2] = brightness-20;
data[pos * 4 + 3] = 255; //220;
}


function scifi(pos, r, g, b, data) {
var offset = pos * 4;
data[offset] = Math.round(255 - r) ;
data[offset+1] = Math.round(255 - g) ;
data[offset+2] = Math.round(255 - b) ;
}




function pushUnpushButtons(idToPush, idArrayToUnpush) {
if (idToPush != "") {
var anchor = document.getElementById(idToPush);
var theClass = anchor.getAttribute("class");
if (!theClass.indexOf("selected") >= 0) {
theClass = theClass + " selected";
anchor.setAttribute("class", theClass);
var newImage = "url(images/" + idToPush + "pressed.png)";
anchor.style.backgroundImage = newImage;
}
}


for (var i = 0; i < idArrayToUnpush.length; i++) {
anchor = document.getElementById(idArrayToUnpush[i]);
theClass = anchor.getAttribute("class");
if (theClass.indexOf("selected") >= 0) {
theClass = theClass.replace("selected", "");
anchor.setAttribute("class", theClass);
anchor.style.backgroundImage = "";
}
}
}


function isButtonPushed(id) {
var anchor = document.getElementById(id);
var theClass = anchor.getAttribute("class");
return (theClass.indexOf("selected") >= 0);
}




<!doctype html>
<html lang="en">
<head>
<title>Starring YOU Video Booth</title>
<meta charset="utf-8">


    <script src="videobooth.js"></script>


    <link rel="stylesheet" href="videobooth.css">
</head>
<body>


<div id="booth">


<div id="console">


<div id="videoDiv">
<video id="video" width="720" height="480">
</video>
<canvas id="buffer" width="720" height="480"></canvas>
<canvas id="display" width="720" height="480"></canvas>
</div>


<div id="dashboard">


<div id="effects">
<a class="effect" id="normal"></a>
<a class="effect" id="western"></a>
<a class="effect" id="noir"></a>
<a class="effect" id="scifi"></a>
</div>


<div id="controls">
<a class="control" id="play"></a>
<a class="control" id="pause"></a>
<a class="control" id="loop"></a>
<a class="control" id="mute"></a>
</div>


<div id="videoSelection">
<a class="videoSelection" id="video1"></a>
<a class="videoSelection" id="video2"></a>
</div>


</div>


</div> <!-- booth -->


</body>
</html>


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值