Seamless animation between states, and some of animations break outside the container. Select the weather icons on the top to see each state.
A Pen by Steve Gardner on CodePen.
Seamless animation between states, and some of animations break outside the container. Select the weather icons on the top to see each state.
A Pen by Steve Gardner on CodePen.
<div class="background"> | |
<div class="container"> | |
<svg id="back"> | |
<radialGradient id="SVGID_1_" cx="0" cy="0" r="320.8304" gradientUnits="userSpaceOnUse"> | |
<stop offset="0" style="stop-color:#FFDE17;stop-opacity:0.7"/> | |
<stop offset="1" style="stop-color:#FFF200;stop-opacity:0"/> | |
</radialGradient> | |
<path id="sunburst" style="fill:url(#SVGID_1_);" d="M0,319.7c-18.6,0-37.3-1.6-55.5-4.8L-7.8,41.4c5.1,0.9,10.6,0.9,15.7,0L56,314.8C37.6,318,18.8,319.7,0,319.7z | |
M-160.8,276.6c-32.5-18.8-61.3-42.9-85.5-71.6L-34,26.2c3.4,4.1,7.4,7.4,12,10.1L-160.8,276.6z M161.3,276.4L22.1,36.2 | |
c4.5-2.6,8.6-6,12-10.1l212.6,178.5C222.5,233.4,193.8,257.6,161.3,276.4z M-302.5,108.3C-315.4,73-321.9,36-322-1.8l277.6-0.5 | |
c0,5.3,0.9,10.4,2.7,15.2L-302.5,108.3z M302.6,107.8L41.8,12.8c1.7-4.7,2.6-9.7,2.6-14.9c0-0.3,0-0.6,0-1H322l0-1.3l0,1.9 | |
C322,35.4,315.5,72.5,302.6,107.8z M-41.8-17.5l-261-94.5c12.8-35.4,31.6-68,55.8-96.9L-34.1-30.8C-37.5-26.8-40.1-22.3-41.8-17.5z | |
M41.7-17.7c-1.8-4.8-4.4-9.3-7.8-13.3l212-179.2c24.3,28.8,43.3,61.3,56.3,96.6L41.7-17.7z M-22.2-40.8l-139.6-240 | |
c32.7-19,68.1-32,105.2-38.6L-8-46.1C-13-45.2-17.8-43.4-22.2-40.8z M22-40.9c-4.4-2.6-9.2-4.3-14.2-5.1l47.1-273.6 | |
c37.2,6.4,72.7,19.2,105.4,38L22-40.9z"/> | |
</svg> | |
<nav> | |
<ul> | |
<li><a id="button-snow" class="active"><i class="wi wi-snow"></i></a></li> | |
<li><a id="button-wind"><i class="wi wi-strong-wind"></i></a></li> | |
<li><a id="button-rain"><i class="wi wi-rain"></i></a></li> | |
<li><a id="button-thunder"><i class="wi wi-lightning"></i></a></li> | |
<li><a id="button-sun"><i class="wi wi-day-sunny"></i></a></li> | |
</ul> | |
</nav> | |
<div id="card" class="weather"> | |
<svg id="inner"> | |
<defs> | |
<path id="leaf" d="M41.9,56.3l0.1-2.5c0,0,4.6-1.2,5.6-2.2c1-1,3.6-13,12-15.6c9.7-3.1,19.9-2,26.1-2.1c2.7,0-10,23.9-20.5,25 c-7.5,0.8-17.2-5.1-17.2-5.1L41.9,56.3z"/> | |
</defs> | |
<circle id="sun" style="fill: #F7ED47" cx="0" cy="0" r="50"/> | |
<g id="layer3"></g> | |
<g id="cloud3" class="cloud"></g> | |
<g id="layer2"></g> | |
<g id="cloud2" class="cloud"></g> | |
<g id="layer1"></g> | |
<g id="cloud1" class="cloud"></g> | |
</svg> | |
<div class="details"> | |
<div class="temp">20<span>c</span></div> | |
<div class="right"> | |
<div id="date">Monday 22 August</div> | |
<div id="summary"></div> | |
</div> | |
</div> | |
</div> | |
<svg id="outer"></svg> | |
</div> | |
</div> |
// 📝 Fetch all DOM nodes in jQuery and Snap SVG | |
var container = $('.container'); | |
var card = $('#card'); | |
var innerSVG = Snap('#inner'); | |
var outerSVG = Snap('#outer'); | |
var backSVG = Snap('#back'); | |
var summary = $('#summary'); | |
var date = $('#date'); | |
var weatherContainer1 = Snap.select('#layer1'); | |
var weatherContainer2 = Snap.select('#layer2'); | |
var weatherContainer3 = Snap.select('#layer3'); | |
var innerRainHolder1 = weatherContainer1.group(); | |
var innerRainHolder2 = weatherContainer2.group(); | |
var innerRainHolder3 = weatherContainer3.group(); | |
var innerLeafHolder = weatherContainer1.group(); | |
var innerSnowHolder = weatherContainer1.group(); | |
var innerLightningHolder = weatherContainer1.group(); | |
var leafMask = outerSVG.rect(); | |
var leaf = Snap.select('#leaf'); | |
var sun = Snap.select('#sun'); | |
var sunburst = Snap.select('#sunburst'); | |
var outerSplashHolder = outerSVG.group(); | |
var outerLeafHolder = outerSVG.group(); | |
var outerSnowHolder = outerSVG.group(); | |
var lightningTimeout; | |
// Set mask for leaf holder | |
outerLeafHolder.attr({ | |
'clip-path': leafMask | |
}); | |
// create sizes object, we update this later | |
var sizes = { | |
container: {width: 0, height: 0}, | |
card: {width: 0, height: 0} | |
} | |
// grab cloud groups | |
var clouds = [ | |
{group: Snap.select('#cloud1')}, | |
{group: Snap.select('#cloud2')}, | |
{group: Snap.select('#cloud3')} | |
] | |
// set weather types ☁️ 🌬 🌧 ⛈ ☀️ | |
var weather = [ | |
{ type: 'snow', name: 'Snow'}, | |
{ type: 'wind', name: 'Windy'}, | |
{ type: 'rain', name: 'Rain'}, | |
{ type: 'thunder', name: 'Storms'}, | |
{ type: 'sun', name: 'Sunny'} | |
]; | |
// 🛠 app settings | |
// in an object so the values can be animated in tweenmax | |
var settings = { | |
windSpeed: 2, | |
rainCount: 0, | |
leafCount: 0, | |
snowCount: 0, | |
cloudHeight: 100, | |
cloudSpace: 30, | |
cloudArch: 50, | |
renewCheck: 10, | |
splashBounce: 80 | |
}; | |
var tickCount = 0; | |
var rain = []; | |
var leafs = []; | |
var snow = []; | |
// ⚙ initialize app | |
init(); | |
// 👁 watch for window resize | |
$(window).resize(onResize); | |
// 🏃 start animations | |
requestAnimationFrame(tick); | |
function init() | |
{ | |
onResize(); | |
// 🖱 bind weather menu buttons | |
for(var i = 0; i < weather.length; i++) | |
{ | |
var w = weather[i]; | |
var b = $('#button-' + w.type); | |
w.button = b; | |
b.bind('click', w, changeWeather); | |
} | |
// ☁️ draw clouds | |
for(var i = 0; i < clouds.length; i++) | |
{ | |
clouds[i].offset = Math.random() * sizes.card.width; | |
drawCloud(clouds[i], i); | |
} | |
// ☀️ set initial weather | |
TweenMax.set(sunburst.node, {opacity: 0}) | |
changeWeather(weather[0]); | |
} | |
function onResize() | |
{ | |
// 📏 grab window and card sizes | |
sizes.container.width = container.width(); | |
sizes.container.height = container.height(); | |
sizes.card.width = card.width(); | |
sizes.card.height = card.height(); | |
sizes.card.offset = card.offset(); | |
// 📐 update svg sizes | |
innerSVG.attr({ | |
width: sizes.card.width, | |
height: sizes.card.height | |
}) | |
outerSVG.attr({ | |
width: sizes.container.width, | |
height: sizes.container.height | |
}) | |
backSVG.attr({ | |
width: sizes.container.width, | |
height: sizes.container.height | |
}) | |
TweenMax.set(sunburst.node, {transformOrigin:"50% 50%", x: sizes.container.width / 2, y: (sizes.card.height/2) + sizes.card.offset.top}); | |
TweenMax.fromTo(sunburst.node, 20, {rotation: 0}, {rotation: 360, repeat: -1, ease: Power0.easeInOut}) | |
// 🍃 The leaf mask is for the leafs that float out of the | |
// container, it is full window height and starts on the left | |
// inline with the card | |
leafMask.attr({x: sizes.card.offset.left, y: 0, width: sizes.container.width - sizes.card.offset.left, height: sizes.container.height}); | |
} | |
function drawCloud(cloud, i) | |
{ | |
/* | |
☁️ We want to create a shape thats loopable but that can also | |
be animated in and out. So we use Snap SVG to draw a shape | |
with 4 sections. The 2 ends and 2 arches the same width as | |
the card. So the final shape is about 4 x the width of the | |
card. | |
*/ | |
var space = settings.cloudSpace * i; | |
var height = space + settings.cloudHeight; | |
var arch = height + settings.cloudArch + (Math.random() * settings.cloudArch); | |
var width = sizes.card.width; | |
var points = []; | |
points.push('M' + [-(width), 0].join(',')); | |
points.push([width, 0].join(',')); | |
points.push('Q' + [width * 2, height / 2].join(',')); | |
points.push([width, height].join(',')); | |
points.push('Q' + [width * 0.5, arch].join(',')); | |
points.push([0, height].join(',')); | |
points.push('Q' + [width * -0.5, arch].join(',')); | |
points.push([-width, height].join(',')); | |
points.push('Q' + [- (width * 2), height/2].join(',')); | |
points.push([-(width), 0].join(',')); | |
var path = points.join(' '); | |
if(!cloud.path) cloud.path = cloud.group.path(); | |
cloud.path.animate({ | |
d: path | |
}, 0) | |
} | |
function makeRain() | |
{ | |
// 💧 This is where we draw one drop of rain | |
// first we set the line width of the line, we use this | |
// to dictate which svg group it'll be added to and | |
// whether it'll generate a splash | |
var lineWidth = Math.random() * 3; | |
// ⛈ line length is made longer for stormy weather | |
var lineLength = currentWeather.type == 'thunder' ? 35 : 14; | |
// Start the drop at a random point at the top but leaving | |
// a 20px margin | |
var x = Math.random() * (sizes.card.width - 40) + 20; | |
// Draw the line | |
var line = this['innerRainHolder' + (3 - Math.floor(lineWidth))].path('M0,0 0,' + lineLength).attr({ | |
fill: 'none', | |
stroke: currentWeather.type == 'thunder' ? '#777' : '#0000ff', | |
strokeWidth: lineWidth | |
}); | |
// add the line to an array to we can keep track of how | |
// many there are. | |
rain.push(line); | |
// Start the falling animation, calls onRainEnd when the | |
// animation finishes. | |
TweenMax.fromTo(line.node, 1, {x: x, y: 0- lineLength}, {delay: Math.random(), y: sizes.card.height, ease: Power2.easeIn, onComplete: onRainEnd, onCompleteParams: [line, lineWidth, x, currentWeather.type]}); | |
} | |
function onRainEnd(line, width, x, type) | |
{ | |
// first lets get rid of the drop of rain 💧 | |
line.remove(); | |
line = null; | |
// We also remove it from the array | |
for(var i in rain) | |
{ | |
if(!rain[i].paper) rain.splice(i, 1); | |
} | |
// If there is less rain than the rainCount we should | |
// make more. | |
if(rain.length < settings.rainCount) | |
{ | |
makeRain(); | |
// 💦 If the line width was more than 2 we also create a | |
// splash. This way it looks like the closer (bigger) | |
// drops hit the the edge of the card | |
if(width > 2) makeSplash(x, type); | |
} | |
} | |
function makeSplash(x, type) | |
{ | |
// 💦 The splash is a single line added to the outer svg. | |
// The splashLength is how long the animated line will be | |
var splashLength = type == 'thunder' ? 30 : 20; | |
// splashBounce is the max height the line will curve up | |
// before falling | |
var splashBounce = type == 'thunder' ? 120 : 100; | |
// this sets how far down the line can fall | |
var splashDistance = 80; | |
// because the storm rain is longer we want the animation | |
// to last slighly longer so the overall speed is roughly | |
// the same for both | |
var speed = type == 'thunder' ? 0.7 : 0.5; | |
// Set a random splash up amount based on the max splash bounce | |
var splashUp = 0 - (Math.random() * splashBounce); | |
// Sets the end x position, and in turn defines the splash direction | |
var randomX = ((Math.random() * splashDistance) - (splashDistance / 2)); | |
// Now we put the 3 line coordinates into an array. | |
var points = []; | |
points.push('M' + 0 + ',' + 0); | |
points.push('Q' + randomX + ',' + splashUp); | |
points.push((randomX * 2) + ',' + splashDistance); | |
// Draw the line with Snap SVG | |
var splash = outerSplashHolder.path(points.join(' ')).attr({ | |
fill: "none", | |
stroke: type == 'thunder' ? '#777' : '#0000ff', | |
strokeWidth: 1 | |
}); | |
// We animate the dasharray to have the line travel along the path | |
var pathLength = Snap.path.getTotalLength(splash); | |
var xOffset = sizes.card.offset.left;//(sizes.container.width - sizes.card.width) / 2 | |
var yOffset = sizes.card.offset.top + sizes.card.height; | |
splash.node.style.strokeDasharray = splashLength + ' ' + pathLength; | |
// Start the splash animation, calling onSplashComplete when finished | |
TweenMax.fromTo(splash.node, speed, {strokeWidth: 2, y: yOffset, x: xOffset + 20 + x, opacity: 1, strokeDashoffset: splashLength}, {strokeWidth: 0, strokeDashoffset: - pathLength, opacity: 1, onComplete: onSplashComplete, onCompleteParams: [splash], ease: SlowMo.ease.config(0.4, 0.1, false)}) | |
} | |
function onSplashComplete(splash) | |
{ | |
// 💦 The splash has finished animating, we need to get rid of it | |
splash.remove(); | |
splash = null; | |
} | |
function makeLeaf() | |
{ | |
var scale = 0.5 + (Math.random() * 0.5); | |
var newLeaf; | |
var areaY = sizes.card.height/2; | |
var y = areaY + (Math.random() * areaY); | |
var endY = y - ((Math.random() * (areaY * 2)) - areaY) | |
var x; | |
var endX; | |
var colors = ['#76993E', '#4A5E23', '#6D632F']; | |
var color = colors[Math.floor(Math.random() * colors.length)]; | |
var xBezier; | |
if(scale > 0.8) | |
{ | |
newLeaf = leaf.clone().appendTo(outerLeafHolder) | |
.attr({ | |
fill: color | |
}) | |
y = y + sizes.card.offset.top / 2; | |
endY = endY + sizes.card.offset.top / 2; | |
x = sizes.card.offset.left - 100; | |
xBezier = x + (sizes.container.width - sizes.card.offset.left) / 2; | |
endX = sizes.container.width + 50; | |
} | |
else | |
{ | |
newLeaf = leaf.clone().appendTo(innerLeafHolder) | |
.attr({ | |
fill: color | |
}) | |
x = -100; | |
xBezier = sizes.card.width / 2; | |
endX = sizes.card.width + 50; | |
} | |
leafs.push(newLeaf); | |
var bezier = [{x:x, y:y}, {x: xBezier, y:(Math.random() * endY) + (endY / 3)}, {x: endX, y:endY}] | |
TweenMax.fromTo(newLeaf.node, 2, {rotation: Math.random()* 180, x: x, y: y, scale:scale}, {rotation: Math.random()* 360, bezier: bezier, onComplete: onLeafEnd, onCompleteParams: [newLeaf], ease: Power0.easeIn}) | |
} | |
function onLeafEnd(leaf) | |
{ | |
leaf.remove(); | |
leaf = null; | |
for(var i in leafs) | |
{ | |
if(!leafs[i].paper) leafs.splice(i, 1); | |
} | |
if(leafs.length < settings.leafCount) | |
{ | |
makeLeaf(); | |
} | |
} | |
function makeSnow() | |
{ | |
var scale = 0.5 + (Math.random() * 0.5); | |
var newSnow; | |
var x = 20 + (Math.random() * (sizes.card.width - 40)); | |
var endX; // = x - ((Math.random() * (areaX * 2)) - areaX) | |
var y = -10; | |
var endY; | |
if(scale > 0.8) | |
{ | |
newSnow = outerSnowHolder.circle(0, 0, 5) | |
.attr({ | |
fill: 'white' | |
}) | |
endY = sizes.container.height + 10; | |
y = sizes.card.offset.top + settings.cloudHeight; | |
x = x + sizes.card.offset.left; | |
//xBezier = x + (sizes.container.width - sizes.card.offset.left) / 2; | |
//endX = sizes.container.width + 50; | |
} | |
else | |
{ | |
newSnow = innerSnowHolder.circle(0, 0 ,5) | |
.attr({ | |
fill: 'white' | |
}) | |
endY = sizes.card.height + 10; | |
//x = -100; | |
//xBezier = sizes.card.width / 2; | |
//endX = sizes.card.width + 50; | |
} | |
snow.push(newSnow); | |
TweenMax.fromTo(newSnow.node, 3 + (Math.random() * 5), {x: x, y: y}, {y: endY, onComplete: onSnowEnd, onCompleteParams: [newSnow], ease: Power0.easeIn}) | |
TweenMax.fromTo(newSnow.node, 1,{scale: 0}, {scale: scale, ease: Power1.easeInOut}) | |
TweenMax.to(newSnow.node, 3, {x: x+((Math.random() * 150)-75), repeat: -1, yoyo: true, ease: Power1.easeInOut}) | |
} | |
function onSnowEnd(flake) | |
{ | |
flake.remove(); | |
flake = null; | |
for(var i in snow) | |
{ | |
if(!snow[i].paper) snow.splice(i, 1); | |
} | |
if(snow.length < settings.snowCount) | |
{ | |
makeSnow(); | |
} | |
} | |
function tick() | |
{ | |
tickCount++; | |
var check = tickCount % settings.renewCheck; | |
if(check) | |
{ | |
if(rain.length < settings.rainCount) makeRain(); | |
if(leafs.length < settings.leafCount) makeLeaf(); | |
if(snow.length < settings.snowCount) makeSnow(); | |
} | |
for(var i = 0; i < clouds.length; i++) | |
{ | |
if(currentWeather.type == 'sun') | |
{ | |
if(clouds[i].offset > -(sizes.card.width * 1.5)) clouds[i].offset += settings.windSpeed / (i + 1); | |
if(clouds[i].offset > sizes.card.width * 2.5) clouds[i].offset = -(sizes.card.width * 1.5); | |
clouds[i].group.transform('t' + clouds[i].offset + ',' + 0); | |
} | |
else | |
{ | |
clouds[i].offset += settings.windSpeed / (i + 1); | |
if(clouds[i].offset > sizes.card.width) clouds[i].offset = 0 + (clouds[i].offset - sizes.card.width); | |
clouds[i].group.transform('t' + clouds[i].offset + ',' + 0); | |
} | |
} | |
requestAnimationFrame(tick); | |
} | |
function reset() | |
{ | |
for(var i = 0; i < weather.length; i++) | |
{ | |
container.removeClass(weather[i].type); | |
weather[i].button.removeClass('active'); | |
} | |
} | |
function updateSummaryText() | |
{ | |
summary.html(currentWeather.name); | |
TweenMax.fromTo(summary, 1.5, {x: 30}, {opacity: 1, x: 0, ease: Power4.easeOut}); | |
} | |
function startLightningTimer() | |
{ | |
if(lightningTimeout) clearTimeout(lightningTimeout); | |
if(currentWeather.type == 'thunder') | |
{ | |
lightningTimeout = setTimeout(lightning, Math.random()*6000); | |
} | |
} | |
function lightning() | |
{ | |
startLightningTimer(); | |
TweenMax.fromTo(card, 0.75, {y: -30}, {y:0, ease:Elastic.easeOut}); | |
var pathX = 30 + Math.random() * (sizes.card.width - 60); | |
var yOffset = 20; | |
var steps = 20; | |
var points = [pathX + ',0']; | |
for(var i = 0; i < steps; i++) | |
{ | |
var x = pathX + (Math.random() * yOffset - (yOffset / 2)); | |
var y = (sizes.card.height / steps) * (i + 1) | |
points.push(x + ',' + y); | |
} | |
var strike = weatherContainer1.path('M' + points.join(' ')) | |
.attr({ | |
fill: 'none', | |
stroke: 'white', | |
strokeWidth: 2 + Math.random() | |
}) | |
TweenMax.to(strike.node, 1, {opacity: 0, ease:Power4.easeOut, onComplete: function(){ strike.remove(); strike = null}}) | |
} | |
function changeWeather(weather) | |
{ | |
if(weather.data) weather = weather.data; | |
reset(); | |
currentWeather = weather; | |
TweenMax.killTweensOf(summary); | |
TweenMax.to(summary, 1, {opacity: 0, x: -30, onComplete: updateSummaryText, ease: Power4.easeIn}) | |
container.addClass(weather.type); | |
weather.button.addClass('active'); | |
// windSpeed | |
switch(weather.type) | |
{ | |
case 'wind': | |
TweenMax.to(settings, 3, {windSpeed: 3, ease: Power2.easeInOut}); | |
break; | |
case 'sun': | |
TweenMax.to(settings, 3, {windSpeed: 20, ease: Power2.easeInOut}); | |
break; | |
default: | |
TweenMax.to(settings, 3, {windSpeed: 0.5, ease: Power2.easeOut}); | |
break; | |
} | |
// rainCount | |
switch(weather.type) | |
{ | |
case 'rain': | |
TweenMax.to(settings, 3, {rainCount: 10, ease: Power2.easeInOut}); | |
break; | |
case 'thunder': | |
TweenMax.to(settings, 3, {rainCount: 60, ease: Power2.easeInOut}); | |
break; | |
default: | |
TweenMax.to(settings, 1, {rainCount: 0, ease: Power2.easeOut}); | |
break; | |
} | |
// leafCount | |
switch(weather.type) | |
{ | |
case 'wind': | |
TweenMax.to(settings, 3, {leafCount: 5, ease: Power2.easeInOut}); | |
break; | |
default: | |
TweenMax.to(settings, 1, {leafCount: 0, ease: Power2.easeOut}); | |
break; | |
} | |
// snowCount | |
switch(weather.type) | |
{ | |
case 'snow': | |
TweenMax.to(settings, 3, {snowCount: 40, ease: Power2.easeInOut}); | |
break; | |
default: | |
TweenMax.to(settings, 1, {snowCount: 0, ease: Power2.easeOut}); | |
break; | |
} | |
// sun position | |
switch(weather.type) | |
{ | |
case 'sun': | |
TweenMax.to(sun.node, 4, {x: sizes.card.width / 2, y: sizes.card.height / 2, ease: Power2.easeInOut}); | |
TweenMax.to(sunburst.node, 4, {scale: 1, opacity: 0.8, y: (sizes.card.height/2) + (sizes.card.offset.top), ease: Power2.easeInOut}); | |
break; | |
default: | |
TweenMax.to(sun.node, 2, {x: sizes.card.width / 2, y: -100, leafCount: 0, ease: Power2.easeInOut}); | |
TweenMax.to(sunburst.node, 2, {scale: 0.4, opacity: 0, y: (sizes.container.height/2)-50, ease: Power2.easeInOut}); | |
break; | |
} | |
// lightning | |
startLightningTimer(); | |
} |
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.4.1/snap.svg-min.js"></script> | |
<script src="https://codepen.io/steveg3003/pen/zBVakw.js"></script> |
@import 'https://fonts.googleapis.com/css?family=Lato:300'; | |
@import 'https://cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons.min.css'; | |
$speed: 2s; | |
html, body, .background | |
{ | |
width: 100%; | |
height: 100%; | |
margin: 0; | |
padding: 0; | |
font-family: 'Lato', sans-serif; | |
} | |
html | |
{ | |
background: #fff; | |
} | |
body | |
{ | |
background: #eee; | |
background: linear-gradient(0deg, rgba(0, 0, 200, 0.2) , rgba(0, 0, 200, 0) ); | |
} | |
.background | |
{ | |
background: #eee; | |
background: linear-gradient(120deg, rgba(50, 150, 100, 0.2) , rgba(0, 0, 100, 0) ); | |
} | |
.container | |
{ | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
justify-content: center; | |
margin: 0; | |
padding: 0; | |
height: 100%; | |
width: 100%; | |
overflow: auto; | |
position: relative; | |
background: #eee; | |
background: linear-gradient(240deg, rgba(150, 50, 50, 0.3) , rgba(0, 0, 200, 0) ); | |
&.cloud | |
{ | |
//background: linear-gradient(360deg, rgba(50, 50, 50, 0.5) , rgba(0, 0, 200, 0) ); | |
} | |
&.wind | |
{ | |
} | |
} | |
nav | |
{ | |
ul | |
{ | |
margin: 20px 20px 0 20px; | |
list-style-type: none; | |
padding: 0; | |
display: flex; | |
flex-direction: row; | |
} | |
li a | |
{ | |
display: block; | |
width: 50px; | |
text-align: center; | |
color: #aaa; | |
cursor: pointer; | |
&:hover | |
{ | |
color: #444; | |
} | |
&.active | |
{ | |
color: #4444ff; | |
} | |
} | |
} | |
#card | |
{ | |
//background: #fff; | |
box-shadow: 9px 7px 40px -6px rgba(0,0,0,0.25); | |
overflow: hidden; | |
width: 300px; | |
padding: 0; | |
height: 400px; | |
min-height: 300px; | |
margin: 20px; | |
border-radius: 5px; | |
//border: solid 0px #fff; | |
position: relative; | |
.details | |
{ | |
position: absolute; | |
top: 0; | |
left: 0; | |
right: 0; | |
padding: 16px 20px; | |
color: #888; | |
display: flex; | |
flex-direction: row; | |
justify-content: space-between; | |
transition: color $speed ease; | |
.thunder & | |
{ | |
color: #ddd; | |
} | |
.right | |
{ | |
text-align: right; | |
} | |
#date | |
{ | |
margin: 4px 0; | |
} | |
#summary | |
{ | |
font-weight: 600; | |
font-size: 22px; | |
} | |
.temp | |
{ | |
font-size: 60px; | |
line-height: 60px; | |
span | |
{ | |
font-size: 18px; | |
line-height: 30px; | |
vertical-align: top; | |
margin-left: 5px; | |
} | |
} | |
} | |
} | |
.weather | |
{ | |
background-color: #DAE3FD; | |
transition: background-color $speed ease; | |
.thunder & | |
{ | |
background-color: #9FA4AD; | |
} | |
.rain & | |
{ | |
background-color: #D8D8D8; | |
} | |
.sun & | |
{ | |
background-color: #ccccff; | |
} | |
#inner | |
{ | |
background-color: rgba(255,255,255,1); | |
background: linear-gradient(to bottom, rgba(255,255,255,0.5) 50%, rgba(255,255,255,0) 100%); | |
} | |
.cloud | |
{ | |
transition: fill $speed ease; | |
} | |
#cloud1 | |
{ | |
fill: #efefef; | |
.thunder & | |
{ | |
fill: #9FA4AD; | |
} | |
} | |
#cloud2 | |
{ | |
fill: #E6E6E6; | |
.thunder & | |
{ | |
fill: #8B8E98; | |
} | |
} | |
#cloud3 | |
{ | |
fill: #D5D5D5; | |
.thunder & | |
{ | |
fill: #7B7988; | |
} | |
} | |
} | |
#outer, #back | |
{ | |
position: fixed; | |
pointer-events: none; | |
} |