Mithril Animated

by Sam Fereday

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/mithril/1.1.3/mithril.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.0.2/anime.min.js"></script>

CSS

svg {
   height: 450px;
   width: 90%;
   border: 1px solid #DEDEDE;
 }
 
 svg path {
   fill: transparent;
 }
 
 svg text {
   cursor: inherit;
   -webkit-user-select: none;
   -moz-user-select: none;
   -ms-user-select: none;
   user-select: none;
 }
 
 path {
   fill: rgba(200, 200, 200, 1);
   stroke: black;
 }
 
 rect {
   stroke: black;
   fill: rgba(200, 200, 200, 1);
 }
 
 .app-hdr {
   background-color: #efefef;
   margin-bottom: 10px;
   padding: 5px;
   width: 90%;
 }
 
 .app-hdr > button {
   font-weight: bold;
   margin-right: 2px;
 }
 
 .note {
   color: grey;
   font-family: monospace;
   font-size: 0.9em;
 }
 
 .app-hdr > .note {
   display: none;
 }
 
 .line {
   border-bottom: inset;
   width: 90%;
 }
 
 .square {
   background-color: cyan;
   height: 25px;
   width: 25px;
 }
 
 .stretched {
   height: 2px;
   margin-bottom: 2px;
 }
 
 .circle {
   background-color: cyan;
   border-radius: 50%;
   height: 25px;
   width: 25px;
 }
 
 .triangle {
   border-color: transparent transparent cyan transparent;
   border-style: solid;
   border-width: 0 14px 24px 14px;
   height: 0;
   pointer-events: none;
   position: relative;
   width: 0;
 }
 
 .demos {
   display: flex;
   flex-wrap: wrap;
   width: 90%;
 }
 
 .demo {
   box-sizing: border-box;
   flex: 1 0 300px;
   margin-bottom: 20px;
 }
 
 .demo-hdr {
   font-family: monospace;
   margin-bottom: 5px;
 }
 
 .timeline-controls button {
   border-radius: 5px;
   width: 60px;
 }
 
 .timeline-controls input[type='range'] {
   position: relative;
   top: 5px;
   width: 100px;
 }
 
 .switch-widget {
   overflow-x: hidden;
 }
 
 .widget {
   border-radius: 3px;
   cursor: pointer;
   font-size: x-large;
   padding: 5px 10px;
   width: 175px
 }
 
 .widget > .note {
   font-size: x-small;
 }
 
 .widget1 {
   background-color: cyan;
 }
 
 .widget2 {
   border: 3px solid cyan;
 }
 
 .switch-route {
   align-items: center;
   border: 1px solid grey;
   border-radius: 5px;
   display: flex;
   height: 50px;
 ...

JavaScript

/* https://github.com/pakx/the-mithril-diaries/wiki/ui-animation/AnimeJS#gallery-main */

function main() {
  var settings = {
      paths: [{
        name: "A",
        route: "/A"
      }, {
        name: "B",
        route: "/B"
      }]
    },
    model = createModel(settings),
    actions = createActions(model),
    routeResolver = createRouteResolver(model, actions),
    defaultRoute = settings.paths[0].route
  m.route(document.body, defaultRoute, routeResolver)
}

function createModel(settings) {
  var elasticItems = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
    initialStates = [{
        translateX: 0
      }, {
        rotate: "0turn",
        scale: 1
      }, {
        rotate: 0,
        scale: 1,
        translateX: 0
      }, {
        elasticItems: elasticItems.map(function(itm) {
          return {
            translateX: 0
          }
        })
      }, {
        backgroundColor: "#00FFFF",
        translateX: 0
      }, {
        height: 25,
        translateX: 0,
        width: 25
      }, {
        square: {
          translateX: 0,
          translateY: 0
        },
        circle: {
          translateX: 0,
          translateY: 0
        },
        triangle: {
          translateX: 0,
          translateY: 0
        },
        progress: 0,
        callbacks: {} // populated in createActions()
      }, {
        points: "64 69.17821114346133 8.574" + " 99.96373240273172 62.94848110067368 67.35649303236691" + " 64 3.9637324027317162 65.05151889932631 67.35649303236691" + " 119.426 99.96373240273172"
      }
      // switch-widgets
      , {
        translateX: 0,
        widgetId: 0,
        isAnimating: false
      }
      // switch-route
      , {
        rotate: 0,
        scale: 1,
        translateX: 0,
        opacity: 1,
        isAnimating: false
      }
    ]

  return {
    paths: settings.paths.slice(),
    routeName: undefined,
    viewstate: {
      demos: initialStates.map(function(itm, idx) {
        return Object.assign(itm, {
         ...