This guide has been replaced with this:
https://obsproject.com/forum/resources/animating-streams-with-scoreboard-assistant.373/
Adding animations to your stream is actually very easy. The problem however is that animations are resource intensive; so unless you have a strong computer, your animations may stutter or appear sluggish. I have created several videos which show off animations.
The first demo starts at 5:55 in this video:
What I show in this video is how to do a very simple image slide-in. In the video, I show it using jQuery. Since then I have converted the animation to pure CSS3 animations; which will help improve performance and won't require the use of such a large Javascript package such as jQuery. You can see the new version live here:
http://8wayrun.tv/scripts/versus.html
(I added an animated video for the background)
The second demo I have for your guys is a lot more complicated. Its not just about loading up images and sliding them in a single time. In this demo, I show a working example of a periodic polling, which updates text fields and animates a scoreboard based on the input.
This one couldn't be done with simple CSS3. Since we are polling an XML file once a second, we need to use Javascript. In addition to this, the animations are run through Javascript as well, since there isn't a reliable way to reset CSS3 animations. Instead of jQuery, in this one, I am using MinifiedJS; its much smaller and lightweight than jQuery.
http://8wayrun.tv/scripts/sboard.html
(I commented out the periodic polling)
https://obsproject.com/forum/resources/animating-streams-with-scoreboard-assistant.373/
Adding animations to your stream is actually very easy. The problem however is that animations are resource intensive; so unless you have a strong computer, your animations may stutter or appear sluggish. I have created several videos which show off animations.
The first demo starts at 5:55 in this video:
What I show in this video is how to do a very simple image slide-in. In the video, I show it using jQuery. Since then I have converted the animation to pure CSS3 animations; which will help improve performance and won't require the use of such a large Javascript package such as jQuery. You can see the new version live here:
http://8wayrun.tv/scripts/versus.html
(I added an animated video for the background)
HTML:
<html>
<head>
<title>CSS3 Animation Text</title>
<style>
body { margin: 0; }
main { margin: 50 auto; position: relative; width: 1280px; height: 720px; overflow: hidden; }
p1 { -webkit-animation: p1Intro 2.5s ease; position: absolute; top: 0; left: 0; }
p2 { -webkit-animation: p2Intro 2.5s ease; position: absolute; top: 0; right: 0; transform: scaleX(-1); }
vs { -webkit-animation: vsIntro 2.5s ease-in; position: absolute; top: 160px; left: 440px; }
bg { position: absolute: top: 0; left: 0; }
@-webkit-keyframes p1Intro {
0%, 40% { transform: translateX(-100%) }
100% { transform: translateX(0) }
}
@-webkit-keyframes p2Intro {
0%, 40% { transform: translateX(+100%) scaleX(-1); }
100% { transform: translateX(0) scaleX(-1); }
}
@-webkit-keyframes vsIntro {
0%, 80% { transform: scale(4); opacity: 0; }
100% { transform: scale(1); opacity: 1; }
}
</style>
</head>
<body>
<main>
<p1><img src="versus/file1.png"/></p1>
<p2><img src="versus/file2.png"/></p2>
<vs><img src="versus/vs.png"/></vs>
<bg><video width="1280" height="720" autoplay loop><source src="versus/bg.mp4" type="video/mp4"></video></bg>
</main>
</body>
</html>
The second demo I have for your guys is a lot more complicated. Its not just about loading up images and sliding them in a single time. In this demo, I show a working example of a periodic polling, which updates text fields and animates a scoreboard based on the input.
This one couldn't be done with simple CSS3. Since we are polling an XML file once a second, we need to use Javascript. In addition to this, the animations are run through Javascript as well, since there isn't a reliable way to reset CSS3 animations. Instead of jQuery, in this one, I am using MinifiedJS; its much smaller and lightweight than jQuery.
http://8wayrun.tv/scripts/sboard.html
(I commented out the periodic polling)
HTML:
<html>
<head>
<title>Minified Animation Test</title>
<script src="minified.js"></script>
<script type="text/javascript">
var MINI = require('minified');
var _=MINI._, $=MINI.$, $$=MINI.$$, EE=MINI.EE, HTML=MINI.HTML;
var p1, p2, s1, s2, mm, gg, timeOld, timeNew, updating;
var xmlRequest = new XMLHttpRequest();
$(function() {
xmlRequest.overrideMimeType('text/xml');
checkUpdate();
// setInterval(function() { checkUpdate(); }, 1000);
});
function checkUpdate() {
if (updating) return;
getRequest();
}
function getRequest() {
xmlRequest.open("GET","sboard/sboard.xml");
xmlRequest.onreadystatechange = function() {
if(xmlRequest.status == 200 && xmlRequest.readyState == 4){
xmlResponse = xmlRequest.responseXML;
p1 = xmlResponse.getElementsByTagName("player1")[0].childNodes[0].nodeValue;
p2 = xmlResponse.getElementsByTagName("player2")[0].childNodes[0].nodeValue;
s1 = xmlResponse.getElementsByTagName("score1")[0].childNodes[0].nodeValue;
s2 = xmlResponse.getElementsByTagName("score2")[0].childNodes[0].nodeValue;
mm = xmlResponse.getElementsByTagName("matchB")[0].childNodes[0].nodeValue;
gg = xmlResponse.getElementsByTagName("gameB")[0].childNodes[0].nodeValue;
timeOld = timeNew;
timeNew = xmlResponse.getElementsByTagName("time")[0].childNodes[0].nodeValue;
runUpdate();
}
};
xmlRequest.send();
}
function runUpdate()
{
if (timeOld == timeNew) return;
if ($('#mm').text() != mm)
{
updating = true;
$('.top').animate({$top: '-40px'}, 500).then(function()
{
$('#mm').fill(mm);
$('.top').animate({$top: '0'}, 1500).then(function() { updating = false; });
});
}
if ($('#p1').text() != p1 || $('#p2').text() != p2)
{
updating = true;
$('.pl').animate({$top: '-40px'}, 500).then(function()
{
$('#p1').fill(p1);
$('#p2').fill(p2);
$('.pl').animate({$top: '0'}, 1500).then(function() { updating = false; });
});
}
if ($('#s1').text() != s1 || $('#s2').text() != s2)
{
updating = true;
$('.sc').animate({$top: '-40px'}, 500).then(function()
{
$('#s1').fill(s1);
$('#s2').fill(s2);
$('.sc').animate({$top: '0'}, 1500).then(function() { updating = false; });
});
}
if ($('#gg').text() != gg)
{
updating = true;
$('.btm').animate({$bottom: '-40px'}, 500).then(function()
{
$('#gg').fill(gg);
$('.btm').animate({$bottom: '0'}, 1500).then(function() { updating = false; });
});
}
}
</script>
<style>
body {
position: relative; width: 1280px; height: 720px; margin: 50 auto; overflow: hidden;
color: #FFF; font: bolder 16px 'Century Gothic'; line-height: 30px; text-align: center;
text-shadow: 1px 1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, -1px -1px 0 #000;
}
.top { position: absolute; width: 1280px; height: 40px; }
.top .mm { position: absolute; width: 1280px; height: 40px; background: url('sboard/versus2-top.png'); }
.top .pl { position: absolute; width: 460px; height: 40px; }
.top .sc { position: absolute; width: 95px; height: 40px; font-size: 24px; }
.top .pl.p1 { background: url('sboard/versus2-top-p1.png'); left: 100px; }
.top .pl.p2 { background: url('sboard/versus2-top-p2.png'); right: 100px; }
.top .pl>div { margin: 6px 40px 0; }
.top .pl.p1 #p1 { text-align: left; }
.top .pl.p2 #p2 { text-align: right; }
.top .sc.s1 { background: url('sboard/versus2-top-s1.png'); left: 465px; }
.top .sc.s2 { background: url('sboard/versus2-top-s2.png'); right: 465px; }
.top .sc>div { margin: 6px 0 0; }
.btm { position: absolute; bottom: 0; width: 1280px; height: 40px; background: url('sboard/event-btm.png') center bottom; }
.btm .gg { position: absolute; width: 1280px; height: 40px; background: url('sboard/versus2-btm.png'); }
.btm .gg>div { margin: 4px 0 0; }
.btm .tx { position: absolute; width: 420px; height: 40px; }
.btm .tx.t1 { left: 100px; }
.btm .tx.t2 { right: 100px; }
.btm .tx>div { margin: 10px 20px 0; }
.top { top: -40px; }
.btm { bottom: -40px; }
.bg { position: absolute; background: url('sboard/bg.jpg'); width: 1280px; height: 720px; }
</style>
</head>
<body>
<div class="bg"></div>
<div class="top">
<div class="pl p1"><div id="p1">Player One</div></div>
<div class="pl p2"><div id="p2">Player Two</div></div>
<div class="sc s1"><div id="s1">0</div></div>
<div class="sc s2"><div id="s2">0</div></div>
<div class="mm"><div id="mm">Match</div></div>
</div>
<div class="btm">
<div class="gg"><div id="gg">Game</div></div>
</div>
<div class="btm">
<div class="tx t1"><div id="t1">Event One</div></div>
<div class="tx t2"><div id="t2">Event Two</div></div>
</div>
</body>
</html>