以下是 HTML5 SVG每周天气预报特效代码 的示例演示效果:
部分效果截图:
HTML代码(index.html):
<!DOCTYPE html>
<html lang="en" class="no-js">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>HTML5 SVG每周天气预报特效</title>
<link rel="stylesheet" type="text/css" href="css/normalize.css" />
<link rel="stylesheet" type="text/css" href="css/select-css.css">
<link rel="stylesheet" type="text/css" href="css/demo.css" />
</head>
<body>
<svg class="hidden">
<defs>
<symbol id="icon-arrow" viewBox="0 0 24 24">
<title>arrow</title>
<polygon points="6.3,12.8 20.9,12.8 20.9,11.2 6.3,11.2 10.2,7.2 9,6 3.1,12 9,18 10.2,16.8 "/>
</symbol>
<symbol id="icon-drop" viewBox="0 0 24 24">
<title>drop</title>
<path d="M12,21c-3.6,0-6.6-3-6.6-6.6C5.4,11,10.8,4,11.4,3.2C11.6,3.1,11.8,3,12,3s0.4,0.1,0.6,0.3c0.6,0.8,6.1,7.8,6.1,11.2C18.6,18.1,15.6,21,12,21zM12,4.8c-1.8,2.4-5.2,7.4-5.2,9.6c0,2.9,2.3,5.2,5.2,5.2s5.2-2.3,5.2-5.2C17.2,12.2,13.8,7.3,12,4.8z"/><path d="M12,18.2c-0.4,0-0.7-0.3-0.7-0.7s0.3-0.7,0.7-0.7c1.3,0,2.4-1.1,2.4-2.4c0-0.4,0.3-0.7,0.7-0.7c0.4,0,0.7,0.3,0.7,0.7C15.8,16.5,14.1,18.2,12,18.2z"/>
</symbol>
<symbol id="icon-cam" viewBox="0 0 24 24">
<title>cam</title>
<path d="M1.7,10.4l1.1,0.5c-0.3,0.2-0.4,0.5-0.3,0.8l0.9,2.6c0.1,0.2,0.2,0.3,0.4,0.4c0.1,0,0.2,0.1,0.3,0.1c0.1,0,0.2,0,0.2,0L5,14.5c0.3,0.5,0.9,0.8,1.5,0.8c0.2,0,0.4,0,0.6-0.1L13,13c0.3,0.5,0.9,0.9,1.5,1l1.1,2.9c0.3,0.9,1.3,1.6,2.3,1.6h3.1v1c0,0.6,0.5,1,1,1h0.7c0.2,0,0.3-0.2,0.3-0.3v-5.5c0-0.2-0.2-0.3-0.3-0.3h-0.7c-0.6,0-1,0.5-1,1v1h-3.1c-0.1,0-0.3-0.1-0.3-0.2l-1.1-3c0.3-0.4,0.5-1,0.4-1.6l5-1.8c0.9-0.3,1.3-1.3,1-2.2l-1.1-2.9c0,0,0,0,0,0l-0.5-1.3c-0.3-0.9-1.3-1.3-2.2-1L1.8,8.7C1.2,8.9,1,9.3,1,9.5C1,9.7,1.1,10.1,1.7,10.4z M21.6,15.4c0-0.2,0.2-0.3,0.3-0.3h0.3v4.8h-0.3c-0.2,0-0.3-0.2-0.3-0.3V15.4z M15.2,14c0.1,0,0.2,0,0.3-0.1c0.1,0,0.2-0.1,0.4-0.2l1,2.7c0.1,0.4,0.5,0.7,1,0.7h3.1v0.7h-3.1c-0.7,0-1.4-0.5-1.6-1.1L15.2,14z M13.6,12.8l2.5-0.9c0,0.4-0.1,0.8-0.4,1c0,0,0,0,0,0c-0.1,0.1-0.3,0.2-0.5,0.3c-0.2,0.1-0.3,0.1-0.5,0.1c0,0,0,0,0,0C14.3,13.3,13.9,13.1,13.6,12.8z M3.7,11.3l0.2,0.1l0.9,2.4l-0.6,0.2l-0.9-2.6L3.7,11.3z M1.7,9.5c0,0,0.1-0.1,0.3-0.2l17.3-6.3c0.5-0.2,1.1,0.1,1.3,0.6l0.4,1c0,0,0,0,0,0L21.1,5c0.2,0.5-0.1,1.1-0.6,1.3l-0.3,0.1C20,6.5,19.9,6.7,20,6.8C20.1,7,20.3,7.1,20.4,7l0.3-0.1c0.4-0.1,0.7-0.4,0.8-0.7l0.6,1.6c0.2,0.5-0.1,1.1-0.6,1.3L6.8,14.5c-0.5,0.2-1.1-0.1-1.3-0.6l-0.8-2.1C5.1,11.9,5.6,12,6.1,12c0.4,0,0.9-0.1,1.2-0.2l9.9-3.6c0.2-0.1,0.3-0.3,0.2-0.4c-0.1-0.2-0.3-0.3-0.4-0.2l-9.9,3.6c-0.6,0.2-1.7,0.2-2.3-0.1l-0.5-0.2c0,0,0,0,0,0l-0.4-0.2c0,0,0,0,0,0L2,9.8C1.8,9.7,1.7,9.6,1.7,9.5z"/><path d="M18.1,7.5c0.1,0.1,0.2,0.2,0.3,0.2c0,0,0.1,0,0.1,0l0.6-0.2c0.2-0.1,0.3-0.3,0.2-0.4c-0.1-0.2-0.3-0.3-0.4-0.2l-0.6,0.2C18.1,7.2,18,7.4,18.1,7.5z"/>
</symbol>
<symbol id="icon-clock" viewBox="0 0 24 24">
<title>clock</title>
<path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/><path d="M12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z"/>
</symbol>
<symbol id="icon-wave" viewBox="0 0 24 24">
<title>wave</title>
<path d="M9.6,17.4c1,0.1,2,0.3,2.9,0.6c0,0,0,0,0,0l0,0c1.3,0.4,2.4,0.8,3.4,1.3c1.5,0.6,2.9,1.2,4.3,1.2c0.3,0,0.7,0,1-0.1c0,0,0,0,0,0l0,0c0.9-0.2,1.8-0.7,2.8-1.7l-1-1.1c-0.5,0.5-1,0.8-1.4,1c-1.1-1-2.6-2.9-2.1-4.4c0.6-2,2.8-3.2,2.8-3.2l1.8-1l-2-0.4c-0.1,0-7.3-1.4-9.8,5.7c-0.7-1.1-1-2.3-1-3.5c0-5.2,5.9-5.7,6.2-5.7l2.7-0.2l-2.5-1.2C17.4,4.5,10.5,1.3,5.5,6c-4,3.8-4,9.7-3.9,11.7C0.5,18.6,0,19.4,0,19.5l1.3,0.7C1.3,20.2,3.3,16.8,9.6,17.4z M19.8,11.1c-0.7,0.7-1.4,1.6-1.8,2.8c-0.6,1.9,0.6,3.8,1.7,5.1c-1-0.1-2-0.6-3.2-1.1c-0.9-0.4-1.9-0.8-3.1-1.2C14.6,12.2,17.7,11.2,19.8,11.1z M6.6,7.1c2.5-2.4,5.8-2.3,8-1.9c-2.4,0.9-4.8,2.9-4.8,6.6c0,1.5,0.4,3,1.2,4.2c-0.4-0.1-0.7-0.1-1.1-0.1c-3-0.3-5.1,0.2-6.7,0.9C3.1,14.6,3.4,10.1,6.6,7.1z" />
</symbol>
<symbol id="icon-thermometer" viewBox="0 0 24 24">
<title>thermometer</title>
<path d="M12.7,16.3V9.6h-1.5v6.7c-0.9,0.3-1.5,1.1-1.5,2.1c0,1.2,1,2.2,2.2,2.2c1.2,0,2.2-1,2.2-2.2 C14.2,17.4,13.6,16.6,12.7,16.3z M12,19.1c-0.4,0-0.7-0.3-0.7-0.7c0-0.4,0.3-0.7,0.7-0.7s0.7,0.3,0.7,0.7 C12.7,18.8,12.4,19.1,12,19.1z"/><path d="M15.2,15V4.2C15.2,2.4,13.8,1,12,1S8.8,2.4,8.8,4.2V15c-0.9,0.9-1.5,2.1-1.5,3.4c0,2.6,2.1,4.7,4.7,4.7s4.7-2.1,4.7-4.7C16.7,17.1,16.1,15.9,15.2,15z M12,21.5c-1.8,0-3.2-1.4-3.2-3.2c0-1,0.4-1.9,1.2-2.5l0.3-0.2V4.2c0-0.9,0.8-1.7,1.7-1.7c0.9,0,1.7,0.8,1.7,1.7v11.5l0.3,0.2c0.8,0.6,1.2,1.5,1.2,2.5C15.2,20.1,13.8,21.5,12,21.5z"/>
</symbol>
<symbol id="icon-direction" viewBox="0 0 100 100">
<title>direction</title>
<path d="M51.1,16c-0.5,0-1,0.3-1.2,0.8L25.6,82.3c-0.2,0.5,0,1.1,0.4,1.5c0.4,0.3,1.1,0.4,1.5,0L51.1,67l21.3,16.7c0.4,0.3,1.1,0.4,1.5,0c0.1,0,0.1-0.1,0.2-0.1c0.3-0.3,0.5-0.8,0.3-1.3L52.3,16.8C52.1,16.3,51.7,16,51.1,16z"/>
</symbol>
<symbol id="icon-cross" viewBox="0 0 24 24">
<title>cross</title>
<path d="M22.8,3.3l-2.2-2.2L12,9.8L3.3,1.2L1.2,3.3L9.8,12l-8.7,8.7l2.2,2.2l8.7-8.7l8.7,8.7l2.2-2.2L14.2,12L22.8,3.3z"/>
</symbol>
<symbol id="state-sunny" viewBox="0 0 80 80">
<title>sunny</title>
<path d="M25,20.31A13.12,13.12,0,1,1,11.88,33.44,13.13,13.13,0,0,1,25,20.31Z" fill="#FFEB3B"/>
</symbol>
<symbol id="state-clearnight" viewBox="0 0 80 80">
<title>clearnight</title>
<path d="M32.35,39.08A11,11,0,0,1,21.27,28.24a10.72,10.72,0,0,1,4-8.33,13.33,13.33,0,1,0,.26,26.65,13.62,13.62,0,0,0,13-9.33A11.23,11.23,0,0,1,32.35,39.08Z" fill="#435965"/>
</symbol>
<symbol id="state-cloudy" viewBox="0 0 80 80">
<title>cloudy</title>
<path d="M60.38,35.59a14.06,14.06,0,0,0-25.48-5.34,5.55,5.55,0,0,0-2.41-.56,5.62,5.62,0,0,0-5.63,5.63v0l-.94,0A10.31,10.31,0,0,0,15.63,45.62c0,.35,0,.69.05,1a6.55,6.55,0,0,0,.89,13H57.81a12.19,12.19,0,0,0,2.57-24.1Z" fill="#e1e1e1"/>
</symbol>
<symbol id="state-partlycloudy" viewBox="0 0 80 80">
<title>partly cloudy</title>
<path d="M25,20.31A13.12,13.12,0,1,1,11.88,33.44,13.13,13.13,0,0,1,25,20.31Z" fill="#FFEB3B"/><path d="M60.38,35.59a14.06,14.06,0,0,0-25.48-5.34,5.55,5.55,0,0,0-2.41-.56,5.62,5.62,0,0,0-5.63,5.63v0l-.94,0A10.31,10.31,0,0,0,15.63,45.62c0,.35,0,.69.05,1a6.55,6.55,0,0,0,.89,13H57.81a12.19,12.19,0,0,0,2.57-24.1Z" fill="#fff"/>
</symbol>
<symbol id="state-partlycloudynight" viewBox="0 0 80 80">
<title>partlycloudynight</title>
<path d="M32.35,39.08A11,11,0,0,1,21.27,28.24a10.72,10.72,0,0,1,4-8.33,13.33,13.33,0,1,0,.26,26.65,13.62,13.62,0,0,0,13-9.33A11.23,11.23,0,0,1,32.35,39.08Z" fill="#435965"/><path d="M60.38,35.59a14.06,14.06,0,0,0-25.48-5.34,5.55,5.55,0,0,0-2.41-.56,5.62,5.62,0,0,0-5.63,5.63v0l-.94,0A10.31,10.31,0,0,0,15.63,45.62c0,.35,0,.69.05,1a6.55,6.55,0,0,0,.89,13H57.81a12.19,12.19,0,0,0,2.57-24.1Z" fill="#e4e6e6"/>
</symbol>
<symbol id="state-rain" viewBox="0 0 80 80">
<title>rain</title>
<path d="M60.38,35.59a14.06,14.06,0,0,0-25.48-5.34,5.55,5.55,0,0,0-2.41-.56,5.62,5.62,0,0,0-5.63,5.63v0l-.94,0A10.31,10.31,0,0,0,15.63,45.62c0,.35,0,.69.05,1a6.55,6.55,0,0,0,.89,13H57.81a12.19,12.19,0,0,0,2.57-24.1Z" fill="#a0b0b0"/><path d="M35.36,54.71A1,1,0,0,0,34,55.1l-2.06,3.71a1,1,0,0,0,1.75,1l2.06-3.71A1,1,0,0,0,35.36,54.71Zm2.75-7-2.06,3.71a1,1,0,0,0,1.75,1l2.06-3.71a1,1,0,0,0-1.75-1Zm.69,15.41a1,1,0,0,0-1.36.39l-2.06,3.71a1,1,0,0,0,1.75,1l2.06-3.71A1,1,0,0,0,38.8,63.08Zm4.11-7.42a1,1,0,0,0-1.36.39L39.5,59.76a1,1,0,0,0,1.75,1L43.31,57A1,1,0,0,0,42.92,55.66ZM27.8,53.75a1,1,0,0,0-1.36.39l-2.06,3.71a1,1,0,0,0,1.75,1l2.06-3.71A1,1,0,0,0,27.8,53.75Zm-4.11,7.42a1,1,0,0,0-1.36.39l-2.06,3.71a1,1,0,0,0,1.75,1l2.06-3.71A1,1,0,0,0,23.69,61.17Zm7.56,1a1,1,0,0,0-1.36.39l-2.06,3.71a1,1,0,0,0,1.75,1l2.06-3.71A1,1,0,0,0,31.25,62.13Zm-4.12,7.42a1,1,0,0,0-1.36.39l-2.06,3.71a1,1,0,0,0,1.75,1l2.06-3.71A1,1,0,0,0,27.13,69.55Zm4.79-23.22a1,1,0,0,0-1.36.39L28.5,50.43a1,1,0,0,0,1.75,1l2.06-3.71A1,1,0,0,0,31.92,46.33Z" fill="#576a7e"/>
</symbol>
<symbol id="state-thunders" viewBox="0 0 80 80">
<title>thunders</title>
<path d="M60.38,35.59a14.06,14.06,0,0,0-25.48-5.34,5.55,5.55,0,0,0-2.41-.56,5.62,5.62,0,0,0-5.63,5.63v0l-.94,0A10.31,10.31,0,0,0,15.63,45.62c0,.35,0,.69.05,1a6.55,6.55,0,0,0,.89,13H57.81a12.19,12.19,0,0,0,2.57-24.1Z" fill="#7a90a5"/><path d="M45.67,56.26l-7.69,0L42.6,45.88H31.73L25.5,63h7.9L30.14,73.36Z" fill="#f0f0f0"/>
</symbol>
</defs>
</svg>
<main class="theme-1">
<header class="codrops-header">
<div class="custom-select"></div>
</header>
<div class="content content--cam">
<div data-type="youtube" data-video-id="lqmNApZXnGM"></div>
<button class="btn btn--close" aria-label="Close Live Cam"><svg class="icon icon--cross"><use xlink:href="#icon-cross"></use></svg></button>
</div>
<div class="content content--graph">
<svg class="graph" viewBox="0 0 1440 800" preserveAspectRatio="none">
<defs>
<linearGradient id="gradient1">
<stop offset="0%" stop-color="#1231bb" />
<stop offset="100%" stop-color="#238DE0" />
</linearGradient>
<linearGradient id="gradient2" x1="0" x2="0" y1="0" y2=".7" xlink:href="#gradient1"/>
</defs>
</svg>
</div>
<!-- Button for toggling the live cam content -->
<button class="btn btn--cam btn--hidden">
<svg class="icon icon--cam icon--btn"><use xlink:href="#icon-cam"></use></svg>
<span class="btn__text">Live Cam</span>
</button>
</main>
<script src="js/anime.min.js"></script>
<script src="js/enquire.min.js"></script>
<script src="js/catmullrom2bezier.js"></script>
<script src="js/plyr.js"></script>
<script src="js/main.js"></script>
</body>
</html>
JS代码(main.js):
/** * main.js * http://www.codrops.com * * Licensed under the MIT license. * http://www.opensource.org/licenses/mit-license.php * * Copyright 2016,Codrops * http://www.codrops.com */
;
(function(window){
'use strict';
// Helper vars and functions.function extend( a,b ){
for( var key in b ){
if( b.hasOwnProperty( key ) ){
a[key] = b[key];
}
}
return a;
}
function createDOMEl(type,className,content){
var el = document.createElement(type);
el.className = className || '';
el.innerHTML = content || '';
return el;
}
function createDOMElNS(type,className,content){
var el = document.createElementNS('http://www.w3.org/2000/svg',type);
el.setAttribute('class',className || '');
el.innerHTML = content || '';
return el;
}
// The SVG path element that represents the sea/wave.var wavePath,days = [],citiesCtrl,currentCity = 0,plyrReady,mainContainer = document.querySelector('main'),graphContainer = mainContainer.querySelector('.content--graph'),// The SVG/graph element.graph = graphContainer.querySelector('.graph'),// SVG viewbox values arr.viewbox = graph.getAttribute('viewBox').split(/\s+|,/),// Viewport size.winsize ={
width:window.innerWidth,height:window.innerHeight}
,oscilation = .4,timeIntervals = 6,/** * Weather data:* . day:the day of the week * . swellheight:let´s assume the swell goes from 0m - 30m. *The swell array represents the intervals of time (00h00m - 04h00m,04h00m - 08h00m,...,20h00m - 24h00m). *In this case we assume 6 intervals of time (timeIntervals = 6). *The swell interval represents the average value for the day (or whatever value we want to display when not seeing each individual swell value per time interval) * . swellperiod:same logic but showcasing the swell's period in seconds. * . water:same logic but showcasing the water's temperature. * . state (weather state / weather icon):*1-sunny *2-partly cloudy *3-cloudy *4-rain *5-thunderstorm *6-clearnight *7-partlycloudynight *. air:same logic but showcasing the air's temperature. *. windspeed:same logic but showcasing the wind´s speed. *. winddirection:same logic but showcasing the wind´s direction. */
data = [{
'name':'Nazaré','weather':[{
// today!'state':{
'display':1,'hourly':[6,6,2,1,1,7]}
,'day':'Today','date':'11/21','air':{
'display':28,'hourly':[20,17,25,28,27,25]}
,'windspeed':{
'display':3,'hourly':[1,2,3,2,1,1]}
,'winddirection':{
'display':135,'hourly':[1,178,111,114,210,220]}
,'swellheight':{
'display':2,'hourly':[4,2.5,2.5,3,4,6]}
,'swellperiod':{
'display':14,'hourly':[10,12,14,13,12,10]}
,'water':{
'display':22,'hourly':[18,19,21,22,21,19]}
}
,{
'state':{
'display':2,'hourly':[6,7,2,2,2,7]}
,'day':'Tuesday','date':'11/22','air':{
'display':31,'hourly':[22,18,25,31,30,26]}
,'windspeed':{
'display':22,'hourly':[6,6,11,16,22,11]}
,'winddirection':{
'display':189,'hourly':[100,178,180,186,190,198]}
,'swellheight':{
'display':4,'hourly':[3,4,4,5,4,2]}
,'swellperiod':{
'display':15,'hourly':[11,13,15,13,14,12]}
,'water':{
'display':21,'hourly':[17,18,20,21,20,18]}
}
,{
'state':{
'display':3,'hourly':[6,6,2,3,3,7]}
,'day':'Wednesday','date':'11/23','air':{
'display':25,'hourly':[19,16,23,25,24,21]}
,'windspeed':{
'display':18,'hourly':[9,11,13,18,18,13]}
,'winddirection':{
'display':200,'hourly':[190,187,210,215,220,100]}
,'swellheight':{
'display':9,'hourly':[3,4,5,8,8,9]}
,'swellperiod':{
'display':15,'hourly':[12,13,15,14,13,12]}
,'water':{
'display':20,'hourly':[17,19,19,20,20,18]}
}
,{
'state':{
'display':4,'hourly':[7,7,4,4,4,7]}
,'day':'Thursday','date':'11/24','air':{
'display':24,'hourly':[18,15,22,24,23,19]}
,'windspeed':{
'display':36,'hourly':[10,11,18,26,36,18]}
,'winddirection':{
'display':5,'hourly':[350,1,6,2,8,15]}
,'swellheight':{
'display':11,'hourly':[9,9,10,11,11,10]}
,'swellperiod':{
'display':16,'hourly':[13,16,16,15,15,14]}
,'water':{
'display':18,'hourly':[16,17,18,18,17,16]}
}
,{
'state':{
'display':5,'hourly':[7,7,5,5,5,6]}
,'day':'Friday','date':'11/25','air':{
'display':22,'hourly':[19,16,21,22,20,16]}
,'windspeed':{
'display':40,'hourly':[18,19,25,29,40,25]}
,'winddirection':{
'display':265,'hourly':[250,260,265,270,280,237]}
,'swellheight':{
'display':14,'hourly':[8,9,11,14,13,10]}
,'swellperiod':{
'display':19,'hourly':[17,18,19,18,17,16]}
,'water':{
'display':19,'hourly':[16,17,19,19,18,16]}
}
]}
,{
'name':'Arrifana','weather':[{
// today!'state':{
'display':2,'hourly':[6,7,2,2,2,7]}
,'day':'Today','date':'11/21','air':{
'display':29,'hourly':[20,17,25,29,27,22]}
,'windspeed':{
'display':36,'hourly':[35,36,28,25,18,13]}
,'winddirection':{
'display':135,'hourly':[1,178,111,114,210,220]}
,'swellheight':{
'display':9,'hourly':[6,8,9,9,8,7]}
,'swellperiod':{
'display':19,'hourly':[17,18,19,18,17,16]}
,'water':{
'display':23,'hourly':[18,19,21,23,22,19]}
}
,{
'state':{
'display':1,'hourly':[7,6,1,1,6,6]}
,'day':'Tuesday','date':'11/22','air':{
'display':27,'hourly':[18,15,22,27,26,19]}
,'windspeed':{
'display':26,'hourly':[10,11,18,26,25,18]}
,'winddirection':{
'display':5,'hourly':[350,1,6,2,8,15]}
,'swellheight':{
'display':8,'hourly':[6,8,7,8,8,7]}
,'swellperiod':{
'display':16,'hourly':[13,16,16,15,15,14]}
,'water':{
'display':20,'hourly':[16,19,20,20,19,17]}
}
,{
'state':{
'display':1,'hourly':[6,6,2,1,1,7]}
,'day':'Wednesday','date':'11/23','air':{
'display':33,'hourly':[22,18,25,33,31,26]}
,'windspeed':{
'display':22,'hourly':[6,6,11,16,22,11]}
,'winddirection':{
'display':189,'hourly':[100,178,180,186,190,198]}
,'swellheight':{
'display':5,'hourly':[6,5,4,4,3,2]}
,'swellperiod':{
'display':15,'hourly':[11,13,15,13,14,12]}
,'water':{
'display':21,'hourly':[17,18,20,21,21,18]}
}
,{
'state':{
'display':2,'hourly':[6,6,1,2,2,6]}
,'day':'Thursday','date':'11/24','air':{
'display':30,'hourly':[19,16,23,30,28,21]}
,'windspeed':{
'display':18,'hourly':[9,11,13,18,18,13]}
,'winddirection':{
'display':200,'hourly':[190,187,210,215,220,100]}
,'swellheight':{
'display':4,'hourly':[2,3,4,4,3,2]}
,'swellperiod':{
'display':15,'hourly':[12,13,15,14,13,12]}
,'water':{
'display':20,'hourly':[17,19,19,20,20,18]}
}
,{
'state':{
'display':3,'hourly':[6,6,2,3,2,6]}
,'day':'Friday','date':'11/25','air':{
'display':28,'hourly':[19,16,23,27,28,19]}
,'windspeed':{
'display':40,'hourly':[18,19,25,29,40,25]}
,'winddirection':{
'display':265,'hourly':[250,260,265,270,280,237]}
,'swellheight':{
'display':4,'hourly':[3,3,4,4,3,2]}
,'swellperiod':{
'display':14,'hourly':[10,12,14,13,12,10]}
,'water':{
'display':20,'hourly':[16,17,19,20,19,16]}
}
]}
,{
'name':'Matosinhos','weather':[{
// today!'state':{
'display':3,'hourly':[7,7,3,3,4,6]}
,'day':'Today','date':'11/21','air':{
'display':20,'hourly':[14,16,19,20,17,12]}
,'windspeed':{
'display':25,'hourly':[15,20,25,25,22,23]}
,'winddirection':{
'display':135,'hourly':[1,178,111,114,210,220]}
,'swellheight':{
'display':7,'hourly':[3,7,7,6,5,4]}
,'swellperiod':{
'display':19,'hourly':[17,18,19,18,17,16]}
,'water':{
'display':16,'hourly':[15,16,16,16,15,15]}
}
,{
'state':{
'display':4,'hourly':[7,6,3,4,4,7]}
,'day':'Tuesday','date':'11/22','air':{
'display':18,'hourly':[13,14,17,18,16,14]}
,'windspeed':{
'display':35,'hourly':[14,18,28,35,30,18]}
,'winddirection':{
'display':5,'hourly':[350,1,6,2,8,15]}
,'swellheight':{
'display':6,'hourly':[3,4,6,6,5,5]}
,'swellperiod':{
'display':16,'hourly':[13,16,16,15,15,14]}
,'water':{
'display':16,'hourly':[14,15,15,16,15,14]}
}
,{
'state':{
'display':4,'hourly':[7,7,3,4,3,6]}
,'day':'Wednesday','date':'11/23','air':{
'display':19,'hourly':[14,14,17,19,17,15]}
,'windspeed':{
'display':20,'hourly':[6,6,11,16,20,15]}
,'winddirection':{
'display':189,'hourly':[100,178,180,186,190,198]}
,'swellheight':{
'display':7,'hourly':[4,5,7,6,5,4]}
,'swellperiod':{
'display':15,'hourly':[11,13,15,13,14,12]}
,'water':{
'display':15,'hourly':[14,15,15,15,14,14]}
}
,{
'state':{
'display':5,'hourly':[7,7,4,5,5,7]}
,'day':'Thursday','date':'11/24','air':{
'display':17,'hourly':[13,15,16,17,16,11]}
,'windspeed':{
'display':18,'hourly':[9,11,13,18,18,13]}
,'winddirection':{
'display':200,'hourly':[190,187,210,215,220,100]}
,'swellheight':{
'display':6,'hourly':[3,5,6,6,6,5]}
,'swellperiod':{
'display':15,'hourly':[12,13,15,14,13,12]}
,'water':{
'display':15,'hourly':[14,15,15,15,15,15]}
}
,{
'state':{
'display':2,'hourly':[6,6,2,3,2,6]}
,'day':'Friday','date':'11/25','air':{
'display':19,'hourly':[14,16,17,19,18,14]}
,'windspeed':{
'display':40,'hourly':[18,19,25,29,40,25]}
,'winddirection':{
'display':265,'hourly':[250,260,265,270,280,237]}
,'swellheight':{
'display':3,'hourly':[4,3,3,3,2,1]}
,'swellperiod':{
'display':14,'hourly':[10,12,14,13,12,10]}
,'water':{
'display':16,'hourly':[14,15,16,16,15,15]}
}
]}
],citiesCtrlContainer = mainContainer.querySelector('.custom-select'),daysToShow = data[currentCity].weather.length,// Width of one day.slice = winsize.width/daysToShow,// Width of each time interval.subSliceWidth = slice/timeIntervals,// Show webcam ctrlwebcamCtrl = document.querySelector('.btn--cam'),webcamCloseCtrl = document.querySelector('.btn--close');
function DayForecast(weather,options){
this.weather = weather;
this.options = extend({
}
,this.options);
extend(this.options,options);
this.showhourly = true;
this._build();
this.setData();
}
DayForecast.prototype.options ={
units:{
temperature:'°C',speed:'km/h',length:'m',time:'s'}
}
;
DayForecast.prototype._build = function(){
this.DOM ={
}
;
// Contents:this.DOM.state = createDOMEl('div','wstate-wrap','<svg class="wstate wstate--sunny"><use xlink:href="#state-sunny"></use></svg><svg class="wstate wstate--cloudy"><use xlink:href="#state-cloudy"></use></svg><svg class="wstate wstate--partlycloudy"><use xlink:href="#state-partlycloudy"></use></svg><svg class="wstate wstate--rain"><use xlink:href="#state-rain"></use></svg><svg class="wstate wstate--thunders"><use xlink:href="#state-thunders"></use></svg><svg class="wstate wstate--clearnight"><use xlink:href="#state-clearnight"></use></svg><svg class="wstate wstate--partlycloudynight"><use xlink:href="#state-partlycloudynight"></use></svg>');
this.DOM.timeperiodWrapper = createDOMEl('span','slice__data slice__data--period slice__data--hidden');
this.DOM.timeperiodSVG = createDOMElNS('svg','icon icon--clock','<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-clock"></use>');
this.DOM.timeperiod = createDOMEl('span','slice__data slice__data--time');
this.DOM.timeperiodWrapper.appendChild(this.DOM.timeperiodSVG);
this.DOM.timeperiodWrapper.appendChild(this.DOM.timeperiod);
this.DOM.dayWrapper = createDOMEl('span','slice__data slice__data--dateday');
this.DOM.day = createDOMEl('span','slice__data slice__data--day');
this.DOM.date = createDOMEl('span','slice__data slice__data--date');
this.DOM.dayWrapper.appendChild(this.DOM.day);
this.DOM.dayWrapper.appendChild(this.DOM.date);
this.DOM.airWrapper = createDOMEl('span','slice__data slice__data--air')this.DOM.airSVG = createDOMElNS('svg','icon icon--thermometer','<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-thermometer"></use>');
this.DOM.air = createDOMEl('span','slice__data slice__data--temperature');
this.DOM.airWrapper.appendChild(this.DOM.airSVG);
this.DOM.airWrapper.appendChild(this.DOM.air);
this.DOM.wind = createDOMEl('span','slice__data slice__data--wind');
this.DOM.windspeed = createDOMEl('span','slice__data slice__data--wind-speed');
this.DOM.winddirectionWrapper = createDOMEl('span','slice__data slice__data--wind-direction');
this.DOM.winddirection = createDOMElNS('svg','icon icon--direction','<use xlink:href="#icon-direction"></use>');
this.DOM.winddirectionWrapper.appendChild(this.DOM.winddirection);
this.DOM.wind.appendChild(this.DOM.winddirection);
this.DOM.wind.appendChild(this.DOM.windspeed);
this.DOM.swell = createDOMEl('span','slice__data slice__data--swell');
this.DOM.swellSVG = createDOMElNS('svg','icon icon--wave','<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-wave"></use>');
this.DOM.swellheight = createDOMEl('span','slice__data slice__data--swell-height');
this.DOM.swellperiod = createDOMEl('span','slice__data slice__data--swell-period');
this.DOM.swell.appendChild(this.DOM.swellSVG);
this.DOM.swell.appendChild(this.DOM.swellheight);
this.DOM.swell.appendChild(this.DOM.swellperiod);
this.DOM.waterWrapper = createDOMEl('span','slice__data slice__data--water');
this.DOM.waterSVG = createDOMElNS('svg','icon icon--thermometer','<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-thermometer"></use>');
this.DOM.water = createDOMEl('span','slice__data slice__data--temperature');
this.DOM.waterWrapper.appendChild(this.DOM.waterSVG);
this.DOM.waterWrapper.appendChild(this.DOM.water);
this.DOM.slice = createDOMEl('div');
this.DOM.slice.appendChild(this.DOM.state);
this.DOM.slice.appendChild(this.DOM.timeperiodWrapper);
this.DOM.slice.appendChild(this.DOM.dayWrapper);
this.DOM.slice.appendChild(this.DOM.airWrapper);
this.DOM.slice.appendChild(this.DOM.wind);
this.DOM.slice.appendChild(this.DOM.swell);
this.DOM.slice.appendChild(this.DOM.waterWrapper);
this._buildHourlyLayout();
}
;
DayForecast.prototype._buildHourlyLayout = function(){
this.DOM.subslicesWrapper = createDOMEl('div','slice__hover');
var subslicesHTML = '';
for(var i = 0;
i <= timeIntervals-1;
++i){
subslicesHTML += '<div></div>';
}
this.DOM.subslicesWrapper.innerHTML = subslicesHTML;
this.DOM.slice.appendChild(this.DOM.subslicesWrapper);
var self = this;
this.mouseleaveFn = function(ev){
if( !self.showhourly ) return false;
self.DOM.timeperiodWrapper.classList.add('slice__data--hidden');
self.setData();
}
;
this.DOM.slice.addEventListener('mouseleave',self.mouseleaveFn);
this.mouseenterFn = function(ev){
if( !self.showhourly ) return false;
self._showTimePeriod(self.DOM.subslices.indexOf(ev.target));
}
;
this.DOM.subslices = [].slice.call(this.DOM.subslicesWrapper.querySelectorAll('div'));
this.DOM.subslices.forEach(function(subslice){
subslice.addEventListener('mouseenter',self.mouseenterFn);
}
);
}
;
DayForecast.prototype.setData = function(weather){
if( weather ){
this.weather = weather;
}
for(var w in this.weather){
this[w] = this.weather[w];
}
this._setState();
this._setTimePeriod();
this._setDay();
this._setDate();
this._setAir();
this._setWindSpeed();
this._setWindDirection();
this._setSwellHeight();
this._setSwellPeriod();
this._setWater();
}
;
DayForecast.prototype._setState = function(val,timeperiod){
var val = val !== undefined ? val:this.state.display;
if( timeperiod !== undefined ){
this.DOM.slice.className = 'slice ' + this._getStateClassname(val) + ' ' + this._getPeriodClassname(timeperiod);
}
else{
this.DOM.slice.className = 'slice ' + this._getStateClassname(val);
}
}
;
DayForecast.prototype._setTimePeriod = function(val){
var val = val !== undefined ? val:'
';
this.DOM.timeperiod.innerHTML = val;
}
;
DayForecast.prototype._setDay = function(val){
var val = val !== undefined ? val:this.day;
this.DOM.day.innerHTML = val;
}
;
DayForecast.prototype._setDate = function(val){
var val = val !== undefined ? val:this.date;
this.DOM.date.innerHTML = val;
}
;
DayForecast.prototype._setAir = function(val){
var val = val !== undefined ? val:this.air.display;
this.DOM.air.innerHTML = val + ' ' + this.options.units.temperature;
}
;
DayForecast.prototype._setWindSpeed = function(val){
var val = val !== undefined ? val:this.windspeed.display;
this.DOM.windspeed.innerHTML = val + ' ' + this.options.units.speed;
}
;
DayForecast.prototype._setWindDirection = function(val,windspeed){
var val = val !== undefined ? val:this.winddirection.display;
this.DOM.winddirection.style.WebkitTransform = this.DOM.winddirection.style.transform = 'rotate(' + val + 'deg)';
anime.remove(this.DOM.winddirection);
var windspeed = windspeed !== undefined ? windspeed:this.windspeed.display;
anime({
targets:this.DOM.winddirection,rotate:val + 40/100*windspeed,duration:200-windspeed,loop:true,direction:'alternate',easing:'easeInOutQuad'}
);
}
;
DayForecast.prototype._setSwellHeight = function(val){
var val = val !== undefined ? val:this.swellheight.display;
this.DOM.swellheight.innerHTML = val + ' ' + this.options.units.length;
}
;
DayForecast.prototype._setSwellPeriod = function(val){
var val = val !== undefined ? val:this.swellperiod.display;
this.DOM.swellperiod.innerHTML = val + ' ' + this.options.units.time;
}
;
DayForecast.prototype._setWater = function(val){
var val = val !== undefined ? val:this.water.display;
this.DOM.water.innerHTML = val + ' ' + this.options.units.temperature;
}
;
DayForecast.prototype._showTimePeriod = function(period){
this._setState(this.state.hourly[period],period);
this.DOM.timeperiodWrapper.classList.remove('slice__data--hidden');
this._setTimePeriod(this._getTimePeriod(period));
this._setAir(this.air.hourly[period]);
this._setWindSpeed(this.windspeed.hourly[period]);
this._setWindDirection(this.winddirection.hourly[period],this.windspeed.hourly[period]);
this._setSwellHeight(this.swellheight.hourly[period]);
this._setSwellPeriod(this.swellperiod.hourly[period]);
this._setWater(this.water.hourly[period]);
}
;
DayForecast.prototype._getTimePeriod = function(period){
var interval = 24/timeIntervals;
return period*interval+':00 - ' + (period+1)*interval + ':00';
}
;
DayForecast.prototype._getStateClassname = function(state){
var c = 'slice--state-';
switch(state){
case 1:c += 'sunny';
break;
case 2:c += 'partlycloudy';
break;
case 3:c += 'cloudy';
break;
case 4:c += 'rain';
break;
case 5:c += 'thunders';
break;
case 6:c += 'clearnight';
break;
case 7:c += 'partlycloudynight';
break;
}
;
return c;
}
;
DayForecast.prototype._getPeriodClassname = function(timeperiod){
return 'slice--period-' + (timeperiod + 1);
// todo:this depends on the [timeIntervals]}
;
DayForecast.prototype.getEl = function(){
return this.DOM.slice;
}
;
function init(){
layout();
createGraph();
initEvents();
}
function layout(){
citiesCtrl = createDOMEl('select');
citiesCtrl.innerHTML = '<select>';
for(var i = 0,len = data.length;
i <= len-1;
++i){
citiesCtrl.innerHTML += '<option value="' + i + '" ' + (i === 0 ? 'selected':'') + '>' + data[i].name + '</option>'}
citiesCtrl.innerHTML += '</select>';
citiesCtrlContainer.appendChild(citiesCtrl);
citiesCtrl.addEventListener('change',changeCityFn);
var slices = createDOMEl('div','slices');
// Create a "slice" per day.for(var i = 0;
i <= daysToShow-1;
++i){
var dayWeather = data[currentCity].weather[i];
var day = new DayForecast(dayWeather);
days.push(day);
slices.appendChild(day.getEl());
}
graphContainer.insertBefore(slices,graph);
}
function changeCityFn(ev){
currentCity = ev.target.value;
mainContainer.className = 'theme-' + parseInt(Number(currentCity)+1);
for(var i = 0;
i <= daysToShow-1;
++i){
days[i].setData(data[currentCity].weather[i]);
}
var points = setPoints(),newpath = calculatePath(points);
anime.remove(wavePath);
anime({
targets:wavePath,d:newpath,duration:1000,easing:'easeInOutQuad',complete:function(){
animateWave();
}
}
);
}
function createGraph(){
// Create the "wave" path.wavePath = createDOMElNS('path','graph__path');
graph.appendChild(wavePath);
// The path points needed to draw the curve. We will draw [daysToShow] points/days + 2 points to fill the path + 2 extra points to smooth the extremities.var points = setPoints();
anime.remove(wavePath);
wavePath.setAttribute('d',calculatePath(points));
setTimeout(animateWave,500);
}
function setPoints(shift){
var weather = data[currentCity].weather;
// the swell extremities (y-axis):var extremities ={
left:weather[0].swellheight.hourly[0],right:weather[daysToShow-1].swellheight.hourly[timeIntervals-1]}
,// the points arraypoints = [];
for(var i = 0;
i <= daysToShow+3;
++i){
var x,y;
if( i === 0 || i === daysToShow+3 ){
x = i === 0 ? -1*subSliceWidth*2:winsize.width+subSliceWidth*2;
y = 0;
points.push({
x:x,y:y}
);
}
else if( i === 1 || i === daysToShow+2 ){
x = i === 1 ? -1*subSliceWidth:winsize.width+subSliceWidth;
y = i === 1 ? extremities.left/2:extremities.right/2;
if( shift ){
y = i%2 === 0 ? y-oscilation:y+oscilation;
}
points.push({
x:x,y:y}
);
}
else{
var daySwell = weather[i-2].swellheight.hourly;
for(var j = 0,len = daySwell.length;
j <= len-1;
++j){
x = slice*(i-2) + subSliceWidth*j + subSliceWidth/2;
y = daySwell[j];
/*if( !shift ){
// Create the circles/points and add them to the graph.var point = createDOMElNS('circle','graph__point');
point.setAttribute('cx',viewbox[2]/winsize.width*x);
point.setAttribute('cy',(-1*Number(viewbox[3])/2)/30*y+Number(viewbox[3]));
point.setAttribute('r',2);
graph.appendChild(point);
}
else{
y = j%2 === 0 ? y-oscilation:y+oscilation;
}
*/
if( shift ){
y = j%2 === 0 ? y-oscilation:y+oscilation;
}
points.push({
x:x,y:y}
);
}
}
}
;
return points;
}
function animateWave(){
var shiftPoints = setPoints(true),shiftpath = calculatePath(shiftPoints);
anime({
targets:wavePath,d:shiftpath,duration:2000,loop:true,direction:'alternate',easing:'easeInOutQuad'}
);
}
function calculatePath(points){
var d = '',d2 = '';
for(var i = 0,len = points.length;
i < len;
++i){
var p = points[i];
var mapping ={
x:viewbox[2]/winsize.width*p.x,y:(-1*Number(viewbox[3])/2)/15*p.y+Number(viewbox[3])}
;
if( 0 == i ){
d = "M" + mapping.x + "," + mapping.y;
}
else if( 1 == i ){
d += " R" + mapping.x + "," + mapping.y;
}
else{
d += " " + mapping.x + "," + mapping.y;
}
d2 = parsePath(d);
}
return d2;
}
function initEvents(){
webcamCtrl.addEventListener('click',showLiveCam);
webcamCloseCtrl.addEventListener('click',hideLiveCam);
mainContainer.querySelector('.content--cam > div').addEventListener('canplay',function(){
webcamCtrl.classList.remove('btn--hidden');
player.setVolume(0);
plyrReady = true;
}
);
mainContainer.querySelector('.content--cam > div').addEventListener('ended',function(){
player.seek(0);
player.play();
}
);
// The hourly forecast per day is only active when the screen is bigger than X px..enquire.register("screen and (max-width:43.25em)",{
match:function(){
for(var i = 0;
i <= daysToShow-1;
++i){
days[i].showhourly = false;
}
}
,unmatch:function(){
for(var i = 0;
i <= daysToShow-1;
++i){
days[i].showhourly = true;
}
}
}
);
}
function showLiveCam(){
mainContainer.classList.add('switch-content');
if( plyrReady ){
player.setVolume(0);
player.play();
}
}
function hideLiveCam(){
mainContainer.classList.remove('switch-content');
player.pause();
}
// Video related.var players = plyr.setup({
controls:[],clickToPlay:false,//autoplay:true}
),player = players[0].plyr;
init();
}
)(window);
CSS代码(demo.css):
*,*::after,*::before{box-sizing:border-box;}
html{position:relative;height:100vh;overflow:hidden;}
body{font-family:'Roboto','Avenir Next',Avenir,'Helvetica Neue',Helvetica,'Segoe UI',Arial,sans-serif;color:#fff;background:#a0cfe4;position:relative;height:100vh;overflow:hidden;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;}
a{text-decoration:none;color:#435965;outline:none;}
a:hover,a:focus{color:#fff;}
.hidden{position:absolute;overflow:hidden;width:0;height:0;pointer-events:none;}
main{position:relative;width:100%;height:200vh;transition:-webkit-transform 0.5s;transition:transform 0.5s;}
.switch-content{-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0);}
/* Buttons */
.btn{margin:0;padding:0.25em;cursor:pointer;color:inherit;border:0;background:none;}
.btn:focus{outline:none;}
.btn--hidden{pointer-events:none;opacity:0;}
.btn__text{font-size:0.85em;}
.btn--cam{position:fixed;z-index:1001;right:1em;bottom:1em;}
.btn--close{position:absolute;z-index:10;top:1em;right:1em;color:#fff;}
/* Icons */
.icon{display:block;width:1.5em;height:1.5em;margin:0 auto;fill:currentColor;}
.icon--btn{font-size:1.5em;}
/* Header */
.codrops-header{position:relative;z-index:10000;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-align-items:center;-ms-flex-align:center;align-items:center;width:100%;padding:0.8em 1.5em 3em 0;}
.codrops-header__main{display:inherit;-webkit-align-items:center;-ms-flex-align:center;align-items:center;}
.codrops-header__title{font-size:1em;margin:0;padding:0;color:#435965;}
.codrops-header__tagline{margin:0 6em 0 0;padding:0 1em;}
/* Top Navigation Style */
.codrops-links{font-size:0.8em;position:relative;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;text-align:center;white-space:nowrap;color:#435965;}
.codrops-links::after{content:'';position:absolute;top:0;left:50%;width:1px;height:100%;opacity:0.7;background:currentColor;-webkit-transform:rotate3d(0,0,1,22.5deg);transform:rotate3d(0,0,1,22.5deg);}
.codrops-icon{display:inline-block;margin:0 0.5em;padding:0.5em;}
/* Graph content */
.content{position:absolute;top:0;left:0;overflow:hidden;width:100%;height:100vh;}
.anim-content .content__video{pointer-events:auto;}
.content--cam{top:100vh;display:-webkit-flex;display:-ms-flexbox;display:flex;z-index:1050;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;background:#000;}
/* Slices */
.slices{position:absolute;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;height:100vh;}
.slice{position:relative;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;overflow:hidden;width:calc(100vw / 5);height:100%;padding:5em 0 0 0;pointer-events:none;background:linear-gradient(200deg,#a0cfe4,#e8c37e);}
.slice--period-1,.slice--period-6{background:linear-gradient(200deg,#6a8a98,#e8c37e);}
.slice--period-2,.slice--period-5{background:linear-gradient(200deg,#8db7ca,#e8c37e);}
.slice--period-3,.slice--period-4{background:linear-gradient(200deg,#a0cfe4,#e8c37e);}
/* Theme 2 */
.theme-2 .slice{background:linear-gradient(200deg,#a0e4a8,#e8c37e);}
.theme-2 .slice--period-1,.theme-2 .slice--period-6{background:linear-gradient(200deg,#69946d,#e8c37e);}
.theme-2 .slice--period-2,.theme-2 .slice--period-5{background:linear-gradient(200deg,#8cc592,#e8c37e);}
.theme-2 .slice--period-3,.theme-2 .slice--period-4{background:linear-gradient(200deg,#a0e4a8,#e8c37e);}
/* Theme 3 */
.theme-3 .slice{background:linear-gradient(200deg,#e4a0a0,#e8cc7e);}
.theme-3 .slice--period-1,.theme-3 .slice--period-6{background:linear-gradient(200deg,#9c6e6e,#e8cc7e);}
.theme-3 .slice--period-2,.theme-3 .slice--period-5{background:linear-gradient(200deg,#ca8e8e,#e8cc7e);}
.theme-3 .slice--period-3,.theme-3 .slice--period-4{background:linear-gradient(200deg,#e4a0a0,#e8cc7e);}
.slice__data{font-size:1.25vw;line-height:1.5;position:relative;z-index:100;display:-webkit-flex;display:-ms-flexbox;display:flex;padding:1em;}
.slice__data .slice__data{display:inline-block;padding:0 0.5em 0 0;vertical-align:middle;white-space:nowrap;}
.slice__data--hidden{opacity:0;}
.slice__data--dateday{color:#4682a5;}
.slice__data--air,.slice__data--wind,.slice__data--water{color:#4682a5;}
.slice__data--period,.slice__data--swell{color:#fff;}
.slice__data--swell{font-size:1.5vw;margin-top:auto;}
.slice__data--water{margin-top:auto;}
.slice__data .icon{-webkit-flex:none;-ms-flex:none;flex:none;margin:0 0.5em 0 0;}
.wstate-wrap{font-size:2em;position:absolute;z-index:100;overflow:hidden;width:100%;height:100%;margin:0;}
.wstate{position:absolute;top:0;right:-40%;width:100%;max-height:100%;opacity:0;}
.slice--state-sunny .wstate--sunny,.slice--state-cloudy .wstate--cloudy,.slice--state-partlycloudy .wstate--partlycloudy,.slice--state-rain .wstate--rain,.slice--state-thunders .wstate--thunders,.slice--state-clearnight .wstate--clearnight,.slice--state-partlycloudynight .wstate--partlycloudynight{opacity:1;}
/* Hover areas */
.slice__hover{position:absolute;z-index:1000;top:0;left:0;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;height:100%;pointer-events:auto;}
.slice__hover div{width:calc(100% / 6);height:100%;}
.slice__hover div:hover{background:rgba(0,0,0,0.03);}
.plyr{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;width:100%;height:100%;text-align:center;}
.plyr__video-wrapper{width:100%;height:100%;}
/* video sizing (always full screen) 640 (video width) 360 (video height) */
.plyr iframe{position:absolute;top:50%;left:50%;width:calc(100vh * 640 / 360);height:100vh;pointer-events:none;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0);}
@media screen and (min-aspect-ratio:640/360){.plyr iframe{width:100vw;height:calc(100vw * 360 / 640);}
}
/* SVG graph and lines */
.graph,.lines{position:absolute;bottom:0;width:100%;height:100vh;pointer-events:none;}
.graph__path{opacity:0.6;fill:url(/#gradient2);stroke-linecap:round;}
.graph__point{fill:#fff;}
.line{stroke:#000;stroke-width:0px;}
@media screen and (max-width:43.25em){.codrops-header{font-size:0.85em;padding-bottom:1em;background:rgba(112,155,183,0.21);}
.custom-select select{font-size:14px;}
.slice{display:block;padding-top:3em;}
.slice:not(:last-child){border-right:1px solid rgba(0,0,0,0.1);}
.slice__data{font-size:2.25vw;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;width:100%;padding:0.85em 0.25em;text-align:center;color:#fff;}
.slice__data .slice__data{padding:0;}
.slice__data .icon{display:block;width:100%;margin:0 auto;color:rgba(0,0,0,0.5);}
.slice__data--swell,.slice__data--water{margin:0;}
.slice__data--period,.slice__hover,.slice__data .slice__data--day{display:none;}
.wstate-wrap{height:2em;}
.slice__data--dateday{padding:4em 0 0;}
}
@media screen and (max-width:35em){.slice__data{font-size:4vw;}
}