Adding Animations to Your Stream

Adding Animations to Your Stream

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)

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>
Author
Jaxel
First release
Last update
Rating
5.00 star(s) 1 ratings

More resources from Jaxel

Top