I'm trying to adapt this Codepen loading animation, which has the triad [markup, style and logic] and use it as an exportable react component.
For that I try to import css from css
file, export javascript functions form js
file, and render html
in a <div>
within my component.
This is the code I have so far:
Loading.jsx
import React, { Component } from 'react';
import './css/clock.css';
import * from './js/clock.js';
class Loading extends Component {
render() {
return (
<div>
<div className="container">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600">
<title>clock coffee cup</title>
<defs>
<clipPath id="cupMask">
<path className="cupMask" d="M215.65,214.41c0,19.85,37.76,35.94,84.35,35.94s84.35-16.09,84.35-35.94H506V399H145V214.41h70.65Z" fill="#ff0d0d"/>
</clipPath>
<clipPath id="handleMask">
<path className="handleMask" fill="#4BFF00" d="M475,305c-23.7-2.4-104.6,3.9-104.6,3.9s12.1-11.9,13.9-46.2c0,0,2.3-39.9,0-48.3
c9.9,0,90.6,0,90.6,0V305z"/>
</clipPath>
</defs>
<g className="cupGroup">
<ellipse className="ripple" cx="300" cy="214.41" rx="84.35" ry="35.94" fill="rgba(0,0,0,0)" strokeLinecap="round" strokeMiterlimit="10" strokeWidth="6"/>
<ellipse className="ripple" cx="300" cy="214.41" rx="84.35" ry="35.94" fill="rgba(0,0,0,0)" strokeLinecap="round" strokeMiterlimit="10" strokeWidth="6"/>
<g clipPath="url(#cupMask)">
<path id="base" d="M216,214v48.7
c0,46.4,37.8,84.4,84.2,84.4h-0.3c46.4,0,84.1-38,84.1-84.4V214" fill="none" strokeLinecap="round" strokeMiterlimit="10" strokeWidth="14"/>
</g>
<g clipPath="url(#handleMask)">
<path opacity="1" id="handle" d="M384.5,228.7c15.9,0,27.8,13.6,27.8,31.5s-14.9,30.5-30.8,30.5" fill="none" strokeLinecap="round" strokeMiterlimit="10" strokeWidth="14"/>
</g>
<ellipse id="rim" cx="300" cy="214.41" rx="84.35" ry="35.94" fill="rgba(0,0,0,0)" strokeLinecap="round" strokeMiterlimit="10" strokeWidth="14"/>
</g>
<g className="clockGroup" opacity="1">
<line id="bighand" fill="none" strokeWidth="14" strokeLinecap="round" strokeMiterlimit="10" x1="300" y1="263" x2="300" y2="189"/>
<line id="littlehand" fill="none" strokeWidth="14" strokeLinecap="round" strokeMiterlimit="10" x1="300" y1="263" x2="300" y2="221"/>
</g>
<line id="table" x1="235" y1="376" x2="365" y2="376" fill="none" strokeLinecap="round" strokeMiterlimit="10" strokeWidth="14"/>
</svg>
</div>
</div>
);
}
}
export default Loading;
clock.css
body {
background-color:#FFF9ED;
overflow: hidden;
}
body,
html {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
.container{
position:absolute;
width:600px;
}
svg{
visibility:hidden;
}
line, ellipse, path{
stroke:#574227;
}
clock.js
var xmlns = "http://www.w3.org/2000/svg",
xlinkns = "http://www.w3.org/1999/xlink",
select = function(s) {
return document.querySelector(s);
},
selectAll = function(s) {
return document.querySelectorAll(s);
},
container = select('.container'),
cupGroup = select('.cupGroup'),
littlehand = select('#littlehand'),
bighand = select('#bighand'),
cupColour = '#574227',
clockColour = '#70A0A0',
rippleColour = '#AD834E'
//center the container cos it's pretty an' that
TweenMax.set(container, {
position: 'absolute',
top: '50%',
left: '50%',
xPercent: -50,
yPercent: -50
})
TweenMax.set('svg', {
visibility: 'visible'
})
TweenMax.set([littlehand, bighand],{
transformOrigin:'50% 100%'
})
export function makeAnimation(){
var tl = new TimelineMax({delay:2, onComplete:makeAnimation});
tl.to('#rim', 1, {
attr:{
ry:84.35
},
stroke:clockColour
})
.to('#base', 1, {
y:-47.5,
stroke:clockColour
},'-=1')
.to('#table', 0.8, {
drawSVG:'40% 60%',
alpha:0
},'-=1')
.to('#handle', 0.3, {
x:-50,
stroke:clockColour,
ease:Power1.easeIn
},'-=1')
.to(cupGroup, 1, {
y:36,
ease:Back.easeOut
},'-=1')
.fromTo([bighand,littlehand], 1, {
drawSVG:'-1% -1%',
y:20
},
{
y:0,
stroke:clockColour,
drawSVG:'0% 70%',
ease:Back.easeOut
},'-=0.6')
/* .to([littlehand, bighand], 0.1, {
rotation:0
}) */
.addCallback(setClock,'+=0.4')
.to([bighand], 2, {
rotation:0,
ease:Power1.easeInOut,
delay:5
})
.to([littlehand], 2, {
rotation:-360,
ease:Power1.easeInOut
},'-=2')
.to([bighand,littlehand], 0.6, {
drawSVG:'-1% -1%',
y:-40,
stroke:cupColour,
ease:Back.easeIn
})
.to('#rim', 1, {
attr:{
ry:35.94
},
stroke:cupColour,
},'-=0.6')
.to('#base', 1, {
y:0,
stroke:cupColour,
},'-=1')
.to(cupGroup, 1, {
y:0,
ease:Back.easeInOut
},'-=1')
.to('#handle', 0.6, {
x:0,
stroke:cupColour,
},'-=0.6')
.staggerFromTo('.ripple', 3, {
attr:{
rx:0,
ry:0
},
stroke:'#f7f7f7'
},{
attr:{
rx:84,
ry:36
},
alpha:1,
stroke:rippleColour
},0.4,'-=0.6')
.to('#table', 0.5, {
drawSVG:'0% 100%',
alpha:1
},'-=3.4')
tl.timeScale(1.8)
}
//ScrubGSAPTimeline(tl);
//tl.progress(1)
export function setClock(){
TweenMax.set([littlehand, bighand], {
rotation:0
})
//new date reference every minute
var myDate = new Date();
//hours minutes and seconds from Date object
var hours = myDate.getHours();
var minutes = myDate.getMinutes();
var seconds = myDate.getSeconds();
//minute position calculation
var minuteValue = minutes*6;
TweenMax.to(bighand,1.2, {
shortRotation:minuteValue,
ease:Back.easeOut.config(0.6)
});
//hour position calculation
var hourValue = hours*30 +(minutes/2);
TweenMax.to(littlehand,1.2, {
shortRotation:hourValue
});
}
makeAnimation();
at index.html
, I link javascript
settings required from codepen page, like so:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="theme-color" content="#000000" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link href="//cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css"rel="stylesheet">
<link href="//cdnjs.cloudflare.com/ajax/libs/gsap/1.19.1/TweenMax.min.js">
<link href="//s3-us-west-2.amazonaws.com/s.cdpn.io/35984/ScrubGSAPTimeline.js">
<link href="//s3-us-west-2.amazonaws.com/s.cdpn.io/16327/DrawSVGPlugin.js?r=12">
<link type="text/css" href="%PUBLIC_URL%/bootstrap.min.css" />
<!-- <script src="https://unpkg.com/react-media-player/dist/react-media-player.js"></script> -->
<title>App</title>
</head>
<body>
<!-- <style>
body {background-color: #C86428;
background-image: url("bg.png");
background-position: 0 5;
opacity: 1.0;
height: 120vh;}
</style> -->
<style>
@import url(https://fonts.googleapis.com/css?family=Josefin+Sans:100,400);
html, body {background:rgb(223,189,150);
font-family: 'Josefin Sans', sans-serif;
margin: 0px;
padding: 0px;
line-height:2.5em;}
h1 {
margin:0;
}
</style>
<div id="root">
</div>
</body>
</html>
in my App.jsx I import the component:
import Page from './components/Page';
and render it like so:
<Route exact path='/page' render={() => (
<Page
/>
)} />
and finally in Page.jsx I import Loading.jsx, like so:
import Loading from './Loading.jsx';
this is my project structure:
public/
index.html
js/
src/
App.jsx
index.js
components/
Page.jsx
Loading.jsx
css/
clock.css
js/
clock.js
Nothing is being rendered, though. What am I doing wrong?