JSFiddle - React, Tailwind, and code Playground

Fairylights

by amcharts

HTML

<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="http://www.amcharts.com/lib/3/amcharts.js"></script>
<script type="text/javascript" src="http://www.amcharts.com/lib/3/serial.js"></script>
<script type="text/javascript" src="http://extra.amcharts.com/support/christmas/injection.js"></script>
<div class="container">
    <div class="row">
        <div class="col-xs-12">
                <div id="chartdiv" style="height: 400px; margin: 70px 0 30px 0;"></div>
            <p>
                <button class="btn btn-default btn-add">Add Fairylight</button>
                <button class="btn btn-default btn-remove">Remove Fairylight</button>
            </p>
        </div>
    </div>
</div>

CSS

@import url(http://fonts.googleapis.com/css?family=Amatic+SC);
body {
    background-image: url(http://www.amcharts.com/wp-content/themes/amcharts/static/img/special/christmas_bg.jpg);
}
.amcharts_graph_smoothedLine_fairyLight_0,
.amcharts_graph_smoothedLine_fairyLight_2,
.amcharts_graph_smoothedLine_fairyLight_4,
.amcharts_graph_smoothedLine_fairyLight_6,
.amcharts_graph_smoothedLine_fairyLight_8,
.amcharts_graph_smoothedLine_fairyLight_10 {
    stroke-dasharray: 5px 10px;
    stroke-width: 5px;
    stroke-linecap: round;
    -webkit-animation: amcharts-pulsate 1s linear infinite;
    animation: amcharts-pulsate 1s linear infinite;
}
.amcharts_graph_smoothedLine_fairyLight_2 {
    -webkit-animation: amcharts-pulsate 1s .3s linear infinite;
    animation: amcharts-pulsate 1s .3s linear infinite;
}
.amcharts_graph_smoothedLine_fairyLight_4,
.amcharts_graph_smoothedLine_fairyLight_6,
.amcharts_graph_smoothedLine_fairyLight_8,
.amcharts_graph_smoothedLine_fairyLight_10 {
    -webkit-animation: amcharts-move 3s linear infinite;
    animation: amcharts-move 3s linear infinite;
}
/* PULSATE */
@-webkit-keyframes amcharts-pulsate {
    0% {
        stroke-opacity: .5;
        stroke-width: 4px;
    }
    50% {
        stroke-opacity: .8;
        stroke-width: 6px;
    }
    100% {
        stroke-opacity: .5;
        stroke-width: 4px;
    }
}
@keyframes amcharts-pulsate {
    0% {
        stroke-opacity: .5;
        stroke-width: 4px;
    }
    50% {
        stroke-opacity: .8;
        stroke-width: 6px;
    }
    100% {
        stroke-opacity: .5;
        stroke-width: 4px;
    }
}
/* MOVE */
@-webkit-keyframes amcharts-move {
    100% {
        stroke-dashoffset: -15px;
    }
}
@keyframes amcharts-move {
    100% {
        stroke-dashoffset: -15px;
    }
}

JavaScript

var chartData = [];

            function generateData(chart, color, update) {
                var maxDate = new Date(2015, 0, 1, 0, 0, 0);
                var gID = chart.graphs.length;
                var vID = "value_" + gID;
                var tmp = {};

                function addPoint(data) {
                    var valid = true;

                    for (i in chartData) {
                        if (chartData[i].date == data.date) {
                            valid = false;
                            AmCharts.extend(chartData[i], data);
                            break;
                        }
                    }

                    if (valid) {
                        chartData.push(data);
                    }
                }

                tmp = {};
                tmp['date'] = new Date(2014, 11, 1, 0, 0, 0);
                tmp[vID] = 0;
                addPoint(tmp);
                tmp = {};
                tmp['date'] = new Date(2014, 11, 1, 0, 0, 2);
                tmp[vID] = Math.random() * 200;
                addPoint(tmp);
                tmp = {};
                tmp['date'] = new Date(2014, 11, 1, 0, 0, 3);
                tmp[vID] = 0;
                addPoint(tmp);

                function generateAnother() {
                    var tmp = {};
                    var prev = chartData.pop();
                    var newDate = new Date(prev.date);
                    var io = 23 + Math.random() * 120;
                    var value = Math.random() * 200;

                    newDate.setHours(io);
                    addPoint(prev);

                    if (Number(newDate) > Number(maxDate)) {
                        newDate = maxDate;
                    }

                    tmpDate = new Date(newDate);
                    tmpDate.setSeconds(-1);
                    tmp = {};
                    tmp['date'] = tmpDate;
                    tmp[vID] = 0;
                    addPoint(tmp);

                    tmp = {};
          ...