在 Javascript 中将图形运动与视频同步
Sync motion of graphics with video in Javascript
我想在浏览器上构建一个小应用程序 运行(使用 Chrome),将嵌入的视频与一些图形同步。我从这里得到灵感https://www.youtube.com/watch?v=_AD2ciZ-0UI做了个小测试
我在这里尝试播放视频并相应地以同步方式“移动”矩形的位置:
<!DOCTYPE html>
<html>
<body>
<video id="myvideo" width="400" controls>
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4"></source>
</video>
<svg id="myrect" viewBox="0 0 200 200" > <rect x=10 y=8 width=5 height=20
fill-opacity=0.0
style="stroke-width:0.5;stroke:rgb(0,0,0)"/> </svg>
<script>
var m = 10 ;
var myvideo = document.getElementById('myvideo')
var rect = document.getElementById('myrect');
myvideo.addEventListener('play', function() {
timerID=window.setInterval(function (){
m=parseInt(myvideo.currentTime);
console.log(m);
rect.setAttribute('x',m);
},100)
})
</script>
</body>
</html>
不幸的是,当 运行 时,我看到变量“m”正确递增(查看控制台中的值),但矩形没有移动。我做错了什么?
@VC.ONE 回答后更新。
这是来自@vc.one 的工作版本,略有修改。细微的修改是矩形现在以与进度条同步的方式移动到视频下方。这种方法似乎有效,但看起来矩形跟随进度条有一些延迟,特别是当它被快速拖动时。如何提高这段代码的响应能力? (我也愿意使用其他 platforms/programs )
<!DOCTYPE html>
<html>
<head>
<style>
body {
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
background-color: #f1f1f1;
}
</style>
</head>
<body>
<div>
<video id="myvideo" width="720" controls>
<source src="mov_bbb.mp4" type="video/mp4"></source>
</video>
<svg id="mysvgrect" viewBox="0 0 200 200" > <rect id="myrect" x=4 y=0 width=5 height=15
fill-opacity=0.0
style="stroke-width:0.5;stroke:rgb(0,0,0)"/> </svg>
</div>
<script>
var timerID;
var m = 10;
var speed = 0;
const rect = document.getElementById('myrect');
const myvideo = document.getElementById('myvideo');
myvideo.addEventListener('timeupdate', function() { moveShape() } );
myvideo.addEventListener('play', function() { handle_Play() } );
function moveShape()
{
speed = 188/myvideo.duration ;
m = 4 + ( speed * (myvideo.currentTime) );
rect.style.x = m; //# direct access to "x" Style
//rect.setAttribute('x', m); //# alt way to access same "x" Style
}
function handle_Play()
{
//# if needed (may clog the console with constant messages every 100 ms)
//timerID = window.setInterval( doTimer(), 100);
}
function doTimer()
{
m = parseInt( myvideo.currentTime );
console.log("video secs : " + m);
}
</script>
</body>
</html>
使用 setInterval 更新工作版本:
经过一些尝试,我再次尝试使用 setInterval,就同步速度而言,我认为效果更好:
<!DOCTYPE html>
<html>
<head>
<style>
body {
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
background-color: #f1f1f1;
}
</style>
</head>
<body>
<div>
<video id="myvideo" width="720" controls>
<source src="video.mp4" type="video/mp4"></source>
</video>
<svg id="mysvgrect" viewBox="0 0 200 200" > <rect id="myrect" x=4 y=0 width=5 height=15
fill-opacity=0.0
style="stroke-width:0.5;stroke:rgb(0,0,0)"/> </svg>
</div>
<script>
var timerID;
var m = 10;
var speed = 0;
const rect = document.getElementById('myrect');
const myvideo = document.getElementById('myvideo');
setInterval(function () {
speed = 188/myvideo.duration ;
m = 4 + ( speed * (myvideo.currentTime) );
rect.style.x = m; // will get you a lot more updates.
}, 30);
</script>
</body>
</html>
我认为的主要区别在于,使用 setInterval 可以更好地控制函数调用的频率(例如,这里我设置了 30 毫秒),而使用 timeupdate 我没有发现这种可能性。但我不确定缺点。请就您对此解决方案的看法发表任何评论...(对于那些感兴趣的人,setInterval 也对更新频率有限制,https://www.w3schools.com/jsref/met_win_setinterval.asp,即 10 毫秒)
- 考虑为
<rect>
元素提供自己的唯一 ID 以直接访问它。
- 使用视频 API 的
timeupdate
事件根据视频时间移动形状。
尝试这样的事情(ps:注意 rect id="myrect"
与 svg id="mysvgrect"
):
<!DOCTYPE html>
<html>
<body>
<video id="myvideo" width="400" controls>
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4"></source>
</video>
<svg id="mysvgrect" viewBox="0 0 200 200" > <rect id="myrect" x=10 y=8 width=5 height=20
fill-opacity=0.0
style="stroke-width:0.5;stroke:rgb(0,0,0)"/> </svg>
<script>
var timerID;
var m = 10;
var speed = 0;
const rect = document.getElementById('myrect');
const myvideo = document.getElementById('myvideo');
myvideo.addEventListener('timeupdate', function() { moveShape() } );
myvideo.addEventListener('play', function() { handle_Play() } );
function moveShape()
{
speed = 9.8;
m = 10 + ( speed * (myvideo.currentTime) );
rect.style.x = m; //# direct access to "x" Style
//rect.setAttribute('x', m); //# alt way to access same "x" Style
}
function handle_Play()
{
//# if needed (may clog the console with constant messages every 100 ms)
//timerID = window.setInterval( doTimer(), 100);
}
function doTimer()
{
m = parseInt( myvideo.currentTime );
console.log("video secs : " + m);
}
</script>
</body>
</html>
我想在浏览器上构建一个小应用程序 运行(使用 Chrome),将嵌入的视频与一些图形同步。我从这里得到灵感https://www.youtube.com/watch?v=_AD2ciZ-0UI做了个小测试
我在这里尝试播放视频并相应地以同步方式“移动”矩形的位置:
<!DOCTYPE html>
<html>
<body>
<video id="myvideo" width="400" controls>
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4"></source>
</video>
<svg id="myrect" viewBox="0 0 200 200" > <rect x=10 y=8 width=5 height=20
fill-opacity=0.0
style="stroke-width:0.5;stroke:rgb(0,0,0)"/> </svg>
<script>
var m = 10 ;
var myvideo = document.getElementById('myvideo')
var rect = document.getElementById('myrect');
myvideo.addEventListener('play', function() {
timerID=window.setInterval(function (){
m=parseInt(myvideo.currentTime);
console.log(m);
rect.setAttribute('x',m);
},100)
})
</script>
</body>
</html>
不幸的是,当 运行 时,我看到变量“m”正确递增(查看控制台中的值),但矩形没有移动。我做错了什么?
@VC.ONE 回答后更新。
这是来自@vc.one 的工作版本,略有修改。细微的修改是矩形现在以与进度条同步的方式移动到视频下方。这种方法似乎有效,但看起来矩形跟随进度条有一些延迟,特别是当它被快速拖动时。如何提高这段代码的响应能力? (我也愿意使用其他 platforms/programs )
<!DOCTYPE html>
<html>
<head>
<style>
body {
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
background-color: #f1f1f1;
}
</style>
</head>
<body>
<div>
<video id="myvideo" width="720" controls>
<source src="mov_bbb.mp4" type="video/mp4"></source>
</video>
<svg id="mysvgrect" viewBox="0 0 200 200" > <rect id="myrect" x=4 y=0 width=5 height=15
fill-opacity=0.0
style="stroke-width:0.5;stroke:rgb(0,0,0)"/> </svg>
</div>
<script>
var timerID;
var m = 10;
var speed = 0;
const rect = document.getElementById('myrect');
const myvideo = document.getElementById('myvideo');
myvideo.addEventListener('timeupdate', function() { moveShape() } );
myvideo.addEventListener('play', function() { handle_Play() } );
function moveShape()
{
speed = 188/myvideo.duration ;
m = 4 + ( speed * (myvideo.currentTime) );
rect.style.x = m; //# direct access to "x" Style
//rect.setAttribute('x', m); //# alt way to access same "x" Style
}
function handle_Play()
{
//# if needed (may clog the console with constant messages every 100 ms)
//timerID = window.setInterval( doTimer(), 100);
}
function doTimer()
{
m = parseInt( myvideo.currentTime );
console.log("video secs : " + m);
}
</script>
</body>
</html>
使用 setInterval 更新工作版本:
经过一些尝试,我再次尝试使用 setInterval,就同步速度而言,我认为效果更好:
<!DOCTYPE html>
<html>
<head>
<style>
body {
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
background-color: #f1f1f1;
}
</style>
</head>
<body>
<div>
<video id="myvideo" width="720" controls>
<source src="video.mp4" type="video/mp4"></source>
</video>
<svg id="mysvgrect" viewBox="0 0 200 200" > <rect id="myrect" x=4 y=0 width=5 height=15
fill-opacity=0.0
style="stroke-width:0.5;stroke:rgb(0,0,0)"/> </svg>
</div>
<script>
var timerID;
var m = 10;
var speed = 0;
const rect = document.getElementById('myrect');
const myvideo = document.getElementById('myvideo');
setInterval(function () {
speed = 188/myvideo.duration ;
m = 4 + ( speed * (myvideo.currentTime) );
rect.style.x = m; // will get you a lot more updates.
}, 30);
</script>
</body>
</html>
我认为的主要区别在于,使用 setInterval 可以更好地控制函数调用的频率(例如,这里我设置了 30 毫秒),而使用 timeupdate 我没有发现这种可能性。但我不确定缺点。请就您对此解决方案的看法发表任何评论...(对于那些感兴趣的人,setInterval 也对更新频率有限制,https://www.w3schools.com/jsref/met_win_setinterval.asp,即 10 毫秒)
- 考虑为
<rect>
元素提供自己的唯一 ID 以直接访问它。 - 使用视频 API 的
timeupdate
事件根据视频时间移动形状。
尝试这样的事情(ps:注意 rect id="myrect"
与 svg id="mysvgrect"
):
<!DOCTYPE html>
<html>
<body>
<video id="myvideo" width="400" controls>
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4"></source>
</video>
<svg id="mysvgrect" viewBox="0 0 200 200" > <rect id="myrect" x=10 y=8 width=5 height=20
fill-opacity=0.0
style="stroke-width:0.5;stroke:rgb(0,0,0)"/> </svg>
<script>
var timerID;
var m = 10;
var speed = 0;
const rect = document.getElementById('myrect');
const myvideo = document.getElementById('myvideo');
myvideo.addEventListener('timeupdate', function() { moveShape() } );
myvideo.addEventListener('play', function() { handle_Play() } );
function moveShape()
{
speed = 9.8;
m = 10 + ( speed * (myvideo.currentTime) );
rect.style.x = m; //# direct access to "x" Style
//rect.setAttribute('x', m); //# alt way to access same "x" Style
}
function handle_Play()
{
//# if needed (may clog the console with constant messages every 100 ms)
//timerID = window.setInterval( doTimer(), 100);
}
function doTimer()
{
m = parseInt( myvideo.currentTime );
console.log("video secs : " + m);
}
</script>
</body>
</html>