├── LICENSE
├── index.html
├── README.md
├── cloudy.svg
├── animatedshape.svg
├── styles.css
├── script.js
├── snow.svg
└── worldmap.svg
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Rishi
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Weather
7 |
8 |
9 |
10 |
11 |
12 |
13 |
Weather
14 |
15 |
16 | Search
17 |
18 |
19 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Weather app
2 |
3 | A Basic Weather searching website made with
4 | * HTML5
5 | * CSS3
6 | * JavaScript (jQuery) Ajax
7 | * SVG backgrounds
8 | * Data from https://open-meteo.com/ (API)
9 | * Deployment in vercel.
10 | [The Deployed site, check it out.](bit.ly/weather-searcher)
11 |
12 | ## Installation
13 |
14 | Just clone it to your local directory.
15 |
16 | ```bash
17 | git clone https://github.com/Rishi-Sudhakar/weather.git
18 | ```
19 |
20 | Now, you can just double click on the HTML file to run it locally in your device. If you just want to try it out, click on the [link.](bit.ly/weather-searcher)
21 |
22 | ## Some Screenshots
23 |
24 | 
25 |
26 | 
27 |
28 | 
29 |
30 |
31 |
32 | ## Acknowledgments
33 |
34 | I would like to extend my sincere gratitude to the following resources and individuals:
35 |
36 | - [Open Meteo](https://open-meteo.com/) for providing the free API used in this project to fetch accurate weather data.
37 | - [BGJar](https://bgjar.com/) for providing high-quality free SVG images used for dynamic background animations in the web application.
38 |
39 | ## Easter?!
40 |
41 | Small details you might not notice.
42 |
43 |
44 | * **SVG Backgrounds** : If you look well, you might notice that the background changes based on cities with respect to their temperatures. It's just two for now (less than 30 degrees = Snow, More than 30 degrees = Cloudy), Expecting to add more in the future.
45 | * **Known issue** : World map svg is supposed to be the default background but the webpage just refreshes so soon moving it to the animated background.
46 |
47 | ## Contributing
48 |
49 | Pull requests are welcome. For major changes, please open an issue first
50 | to discuss what you would like to change.
51 |
--------------------------------------------------------------------------------
/cloudy.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/animatedshape.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/styles.css:
--------------------------------------------------------------------------------
1 | /* Basic reset */
2 | * {
3 | margin: 0;
4 | padding: 0;
5 | box-sizing: border-box;
6 | }
7 |
8 | body {
9 | font-family: 'Roboto', sans-serif;
10 | background: linear-gradient(to right, #6a11cb, #2575fc);
11 | display: flex;
12 | justify-content: center;
13 | align-items: center;
14 | height: 100vh;
15 | color: #fff;
16 | overflow: hidden;
17 | }
18 |
19 | .container {
20 | text-align: center;
21 | background: rgba(255, 255, 255, 0.1);
22 | padding: 20px;
23 | border-radius: 10px;
24 | box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
25 | backdrop-filter: blur(10px);
26 | width: 80%;
27 | max-width: 600px;
28 | animation: fadeIn 1s ease-in-out;
29 | }
30 |
31 | .title {
32 | margin-bottom: 20px;
33 | font-size: 2.5em;
34 | font-weight: 500;
35 | animation: bounceIn 1s ease-in-out;
36 | }
37 |
38 | .search-box {
39 | display: flex;
40 | justify-content: center;
41 | margin-bottom: 20px;
42 | }
43 |
44 | #city {
45 | padding: 10px;
46 | border: none;
47 | border-radius: 5px;
48 | margin-right: 10px;
49 | font-size: 1em;
50 | width: 70%;
51 | max-width: 300px;
52 | }
53 |
54 | #search {
55 | padding: 10px 20px;
56 | background-color: #4CAF50;
57 | color: white;
58 | border: none;
59 | border-radius: 5px;
60 | cursor: pointer;
61 | transition: background-color 0.3s, transform 0.2s;
62 | }
63 |
64 | #search:hover {
65 | background-color: #45a049;
66 | transform: scale(1.1);
67 | }
68 |
69 | .weather-data {
70 | margin-top: 20px;
71 | }
72 |
73 | .weather-card {
74 | background: rgba(255, 255, 255, 0.2);
75 | padding: 20px;
76 | border-radius: 10px;
77 | box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
78 | transition: transform 0.3s ease;
79 | animation: fadeIn 1s ease-in-out;
80 | }
81 |
82 | .weather-card:hover {
83 | transform: scale(1.05);
84 | }
85 |
86 | .weather-info {
87 | margin-top: 10px;
88 | animation: fadeIn 1s ease-in-out;
89 | }
90 |
91 | .hidden {
92 | display: none;
93 | }
94 |
95 | .background-animation {
96 | position: absolute;
97 | top: 0;
98 | left: 0;
99 | width: 100%;
100 | height: 100%;
101 | pointer-events: none;
102 | background: url('worldmap.svg') no-repeat center center/cover;
103 | opacity: 0.3;
104 | animation: moveBackground 20s linear infinite;
105 | }
106 |
107 | @keyframes fadeIn {
108 | from {
109 | opacity: 0;
110 | transform: translateY(-20px);
111 | }
112 | to {
113 | opacity: 1;
114 | transform: translateY(0);
115 | }
116 | }
117 |
118 | @keyframes bounceIn {
119 | from {
120 | opacity: 0;
121 | transform: scale(0.3);
122 | }
123 | 50% {
124 | opacity: 1;
125 | transform: scale(1.05);
126 | }
127 | to {
128 | transform: scale(1);
129 | }
130 | }
131 |
132 | @keyframes moveBackground {
133 | from {
134 | background-position: 0 0;
135 | }
136 | to {
137 | background-position: 100% 100%;
138 | }
139 | }
140 |
141 | .loader {
142 | border: 4px solid #f3f3f3;
143 | border-radius: 50%;
144 | border-top: 4px solid #3498db;
145 | width: 40px;
146 | height: 40px;
147 | animation: spin 2s linear infinite;
148 | margin: 20px auto;
149 | }
150 |
151 | @keyframes spin {
152 | 0% { transform: rotate(0deg); }
153 | 100% { transform: rotate(360deg); }
154 | }
155 |
156 | .hourly-forecast {
157 | margin-top: 20px;
158 | }
159 |
160 | .hourly-forecast-item {
161 | display: inline-block;
162 | margin: 5px;
163 | padding: 10px;
164 | background: rgba(255, 255, 255, 0.3);
165 | border-radius: 5px;
166 | text-align: center;
167 | transition: transform 0.3s ease;
168 | cursor: pointer;
169 | }
170 |
171 | .hourly-forecast-item:hover {
172 | transform: scale(1.1);
173 | }
174 |
175 | .daily-forecast {
176 | margin-top: 20px;
177 | display: flex;
178 | flex-wrap: wrap;
179 | justify-content: center;
180 | }
181 |
182 | .daily-forecast-item {
183 | background: rgba(255, 255, 255, 0.2);
184 | padding: 10px;
185 | border-radius: 10px;
186 | margin: 5px;
187 | text-align: center;
188 | width: 80px;
189 | transition: transform 0.3s ease;
190 | }
191 |
192 | .daily-forecast-item:hover {
193 | transform: scale(1.1);
194 | }
195 |
196 | .tooltip {
197 | position: relative;
198 | display: inline-block;
199 | }
200 |
201 | .tooltip .tooltiptext {
202 | visibility: hidden;
203 | width: 120px;
204 | background-color: black;
205 | color: #fff;
206 | text-align: center;
207 | border-radius: 6px;
208 | padding: 5px;
209 | position: absolute;
210 | z-index: 1;
211 | bottom: 125%;
212 | left: 50%;
213 | margin-left: -60px;
214 | opacity: 0;
215 | transition: opacity 0.3s;
216 | }
217 |
218 | .tooltip:hover .tooltiptext {
219 | visibility: visible;
220 | opacity: 1;
221 | }
222 |
223 | /* Additional background styles */
224 | .bg-snow {
225 | background: url('snow.svg') no-repeat center center/cover;
226 | }
227 |
228 | .bg-cloudy {
229 | background: url('cloudy.svg') no-repeat center center/cover;
230 | }
231 |
232 | .bg-animated {
233 | background: url('animatedshape.svg') no-repeat center center/cover;
234 | }
235 |
--------------------------------------------------------------------------------
/script.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function(){
2 | const initialBackground = 'worldmap.svg';
3 | const snowBackground = 'snow.svg';
4 | const cloudyBackground = 'cloudy.svg';
5 | const animatedBackground = 'animatedshape.svg';
6 |
7 | // Function to set the background image
8 | function setBackground(image) {
9 | $('#background-animation').css('background-image', 'url(' + image + ')');
10 | }
11 |
12 | // Initial background on page load
13 | setBackground(initialBackground);
14 |
15 | // Set the background to animatedshape.svg on page reload
16 | $(window).on('load', function() {
17 | setBackground(animatedBackground);
18 | });
19 |
20 | $('#search').click(function(){
21 | var city = $('#city').val();
22 | if(city === "") {
23 | alert("Please enter a city name.");
24 | return;
25 | }
26 |
27 | $('#loader').removeClass('hidden');
28 | $('#weather-data').addClass('hidden');
29 |
30 | var geocodingUrl = 'https://nominatim.openstreetmap.org/search?format=json&q=' + city;
31 |
32 | $.ajax({
33 | url: geocodingUrl,
34 | type: 'GET',
35 | dataType: 'json',
36 | success: function(data){
37 | if(data.length > 0) {
38 | var location = data[0];
39 | var latitude = location.lat;
40 | var longitude = location.lon;
41 | var weatherUrl = 'https://api.open-meteo.com/v1/forecast?latitude=' + latitude + '&longitude=' + longitude + '¤t_weather=true&hourly=temperature_2m,relative_humidity_2m,wind_speed_10m&daily=temperature_2m_max,temperature_2m_min,precipitation_sum&timezone=auto';
42 |
43 | $.ajax({
44 | url: weatherUrl,
45 | type: 'GET',
46 | dataType: 'json',
47 | success: function(weatherData){
48 | var temperature = weatherData.current_weather.temperature;
49 | var windSpeed = weatherData.current_weather.windspeed;
50 | var humidity = weatherData.hourly.relative_humidity_2m[0];
51 |
52 | // Change background based on temperature
53 | if (temperature < 30) {
54 | setBackground(snowBackground);
55 | } else {
56 | setBackground(cloudyBackground);
57 | }
58 |
59 | $('#city-name').text('Weather in ' + city);
60 | $('#temperature').html(' ' + temperature + '°C');
61 | $('#wind-speed').html(' ' + windSpeed + ' m/s');
62 | $('#humidity').html(' ' + humidity + '%');
63 |
64 | var hourlyForecastHtml = '';
65 | for(var i = 0; i < 6; i++) {
66 | hourlyForecastHtml += '';
72 | }
73 | $('#hourly-forecast').html(hourlyForecastHtml);
74 |
75 | var dailyForecastHtml = '';
76 | for(var i = 0; i < 5; i++) {
77 | dailyForecastHtml += '';
78 | dailyForecastHtml += '
' + weatherData.daily.time[i].substring(5, 10) + '
';
79 | dailyForecastHtml += '
' + weatherData.daily.temperature_2m_max[i] + '°C
';
80 | dailyForecastHtml += '
' + weatherData.daily.temperature_2m_min[i] + '°C
';
81 | dailyForecastHtml += '
' + weatherData.daily.precipitation_sum[i] + 'mm
';
82 | dailyForecastHtml += '
';
83 | }
84 | $('#daily-forecast').html(dailyForecastHtml);
85 |
86 | $('#weather-data').removeClass('hidden').hide().fadeIn(1000);
87 | $('#loader').addClass('hidden');
88 | },
89 | error: function(xhr, status, error){
90 | $('#weather-data').html('Error fetching weather data
').removeClass('hidden').hide().fadeIn(1000);
91 | $('#loader').addClass('hidden');
92 | }
93 | });
94 | } else {
95 | $('#weather-data').html('City not found
').removeClass('hidden').hide().fadeIn(1000);
96 | $('#loader').addClass('hidden');
97 | }
98 | },
99 | error: function(xhr, status, error){
100 | $('#weather-data').html('Error fetching geolocation data
').removeClass('hidden').hide().fadeIn(1000);
101 | $('#loader').addClass('hidden');
102 | }
103 | });
104 | });
105 | });
106 |
--------------------------------------------------------------------------------
/snow.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/worldmap.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------