Animated Timeline

by kelvinau

HTML

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<div id="main"></div>

SCSS

$arrow-size: 5px;
.timeline {
  margin: 0 30px;
  overflow: hidden;
  position: relative;
  height: 500px;
  .whole-line {
    position: absolute;
    display: flex;
    align-items: center;
    height: 500px;
    transition: transform ease-in-out 0.5s;
    .event {
      position: relative;
      .eventBubble {
        position: absolute;
        background-color: rgba(158, 158, 158, 0.1);
        width: 139px;
        height: 60px;
        border-radius: 5px;
        box-shadow: inset 0 0 5px rgba(158, 158, 158, 0.64);
        font-size: 12px;
        &:before,
        &:after {
          content: "";
          position: absolute;
          width: 0;
          height: 0;
          border-style: solid;
          border-color: transparent;
          border-bottom: 0;
        }
        .eventTime {
          display: flex;
          font-weight: bold;
          color: #4C4A4A;
          padding: 5px;
        }
        .eventTitle {
          color: #a71930;
          text-transform: uppercase;
          display: flex;
          flex: 1;
          align-items: center;
          padding: 0 5px;
          word-break: break-word;
          &:hover {
            cursor: pointer;
          }
        }
      }
      &.top {
        .eventBubble {
          top: -70px;
          &:before {
            bottom: -10px;
            left: 13px;
            border-top-color: rgba(222, 222, 222, 0.66);
            border-width: 12px;
          }
          &:after {
            bottom: -8px;
            left: 13px;
            border-top-color: #F6F6F6;
            border-width: 12px;
          }
          &.highlight {
            transform: translate(22px, -15px) scale(1.5);
            transition: ease-in-out 0.5s;
          }
        }
      }
      &.bottom {
        .eventBubble {
          top: 33px;
          &:before {
            bottom: 59px;
            left: 103px;
            border-top-color: rgba(222, 222, 222, 0.66);
            border-width: 12px;
           ...

JavaScript

var currentTranslateX = 0;
var translateValue = 100;
var minTranslateX = -400;
var maxTranslateX = 0;
var lineLength = 100;
var currentHightlightedItem = 0;
var timelineWidth;

var events = [{
    date: 'Feb 05, 2016',
    name: 'JS/NEMUCOD.DSQ!TR.DLDR'
  },
  {
    date: 'Mar 10, 2016',
    name: 'W32/LOCKY.M!TR.RANSOM'
  },
  {
    date: 'Mar 12, 2016',
    name: 'JS/NEMUCOD.DSQ!TR.DLDR'
  },
  {
    date: 'April 10, 2016',
    name: 'W32/LOCKY.M!TR.RANSOM'
  },
  {
    date: 'April 15, 2016',
    name: 'W32/Generic.AC.3F52C2!tr.ransom'
  },
  {
    date: 'Jun 19, 2016',
    name: 'W32/LOCKY.M!TR.RANSOM'
  },
  {
    date: 'Jun 22, 2016',
    name: 'JS/NEMUCOD.DSQ!TR.DLDR'
  },
  {
    date: 'Jul 28, 2016',
    name: 'W32/Locky.AZKQ!tr.ransom'
  },
  {
    date: 'Sep 01, 2016',
    name: 'W32/Filecoder_P'
  },
  {
    date: 'Sep 03, 2016',
    name: 'W32/LOCKY.M!TR.RANSOM'
  },
  {
    date: 'Sep 03, 2016',
    name: 'W32/LOCKY.M!TR.RANSOM'
  },
  {
    date: 'Sep 03, 2016',
    name: 'W32/LOCKY.M!TR.RANSOM'
  },
  {
    date: 'Jan 15, 2017',
    name: 'W32/Generic.AC.3F52C2!tr.ransom'
  },
  {
    date: 'Feb 19, 2017',
    name: 'W32/LOCKY.M!TR.RANSOM'
  },
  {
    date: 'Jun 19, 2017',
    name: 'JS/NEMUCOD.DSQ!TR.DLDR'
  },
  {
    date: 'Jul 28, 2018',
    name: 'W32/Locky.AZKQ!tr.ransom'
  },
  {
    date: 'Sep 01, 2018',
    name: 'W32/Filecoder_P'
  },
  {
    date: 'Sep 03, 2018',
    name: 'W32/LOCKY.M!TR.RANSOM'
  },
  {
    date: 'Sep 03, 2018',
    name: 'W32/LOCKY.M!TR.RANSOM'
  },
  {
    date: 'Sep 03, 2018',
    name: 'W32/LOCKY.M!TR.RANSOM'
  },
]

var timelineDom = $(`
<i class="left"></i>
<div class="timeline">
	<div class="whole-line"></div>
</div>
  <i class="right"></i>'
`);
var wholeLineDom = timelineDom.find('.whole-line');
wholeLineDom.append(getLineHtml(true));
events.forEach(function(event, i) {
  wholeLineDom.append(createHtml(event, i));
});
//wholeLineDom.append(getLineHtml(true));
//timelineDom.append(`<div...