Skip to content

Commit

Permalink
update new function
Browse files Browse the repository at this point in the history
  • Loading branch information
sk5s committed Oct 30, 2021
1 parent b6465ba commit 452732a
Show file tree
Hide file tree
Showing 6 changed files with 285 additions and 7 deletions.
5 changes: 5 additions & 0 deletions css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,8 @@
background-color: hsl(200, 20%, 95%);
}
}

canvas {
width: 100%;
position: relative;
}
18 changes: 17 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@
<!-- css -->
<link rel="stylesheet" href="css/bulma.min.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css">
<script src="js/chart.min.js"></script>

<link rel="manifest" href="manifest.json" />

<link rel="stylesheet" href="css/style.css">

<script src="js/chart.min.js"></script>
<!-- <script src="https://cdn.jsdelivr.net/npm/chart.js@3.5.1/dist/chart.min.js"></script> -->
</head>
<body>
<!-- nav bar -->
Expand Down Expand Up @@ -67,6 +68,15 @@ <h5 class="title is-5">alsoweather</h5>
</div>
</div>

<!-- weather chart -->
<div class="card has-background-success-light mt-3 mb-3">
<div class="card-content">
<div class="content" id="weather_chart_inner_content">
<canvas id="weather_chart_canvas" width="400" height="200"></canvas>
</div>
</div>
</div>

<!-- some quote -->
<div class="card has-background-success-light mt-3 mb-3">
<div class="card-header">
Expand All @@ -90,6 +100,10 @@ <h5 class="title is-5">alsoweather</h5>
</div>
</div>


<!-- SpeechSynthesis config -->
<div id="speechSynthesis_config_container"></div>

</div>

<!-- footer -->
Expand All @@ -100,6 +114,8 @@ <h5 class="title is-5">alsoweather</h5>
</div>
</footer>

<script src="js/i18n.js"></script>
<script src="js/my-chart.js"></script>
<script src="js/app.js"></script>

</body>
Expand Down
158 changes: 155 additions & 3 deletions js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,41 @@ const CWB_API = `https://opendata.cwb.gov.tw/api/v1/rest/datastore/F-C0032-001?A
// api url
const QUOTE_API = `https://api.quotable.io/random`

cwb_location_select_value = ''
// accept speech lang (lower case)
let accept_speech_lang = ['zh-TW', 'en-US']

// variable to replace by javascript
let cwb_location_select_value = ''
let stored_speech_voice = ''

let voices = []
let available_and_accept_speech_voice = []
let speech_script = {
'zh-TW': '',
'en-US': '',
}

let populated_voice_select //html object

// grab html dom element
let cwb_location_select = document.getElementById('cwb_location_select')
let quote_block_inner_content = document.getElementById('quote_block_inner_content')
let weather_block_inner_content = document.getElementById('weather_block_inner_content')
let weather_chart_inner_content = document.getElementById('weather_chart_inner_content')
let speechSynthesis_container = document.getElementById('speechSynthesis_container')
let speechSynthesis_config_container = document.getElementById('speechSynthesis_config_container')

let weather_chart_canvas = document.getElementById('weather_chart_canvas')

// event
cwb_location_select.addEventListener('input', location_input_service)

// init
document.addEventListener('DOMContentLoaded', () => {
restore_location()
restore_speech_voice()
fresh()
// speech_synthesis_init()
speech_synthesis_init()
})

// fetch cwb api
Expand Down Expand Up @@ -51,6 +70,7 @@ async function fetch_cwb(url) {
let parsed_cwb_data = {
now: {},
}
// now
parsed_cwb_data.now.Wx =
data_all.data[data_all.location_index].weatherElement[0].time[0].parameter.parameterName
parsed_cwb_data.now.PoP =
Expand All @@ -61,10 +81,13 @@ async function fetch_cwb(url) {
data_all.data[data_all.location_index].weatherElement[3].time[0].parameter.parameterName
parsed_cwb_data.now.MaxT =
data_all.data[data_all.location_index].weatherElement[4].time[0].parameter.parameterName
// 3day
generate_weather_chart_data(data_all.data[data_all.location_index].weatherElement)
fillin_weather(generate_now_weather(parsed_cwb_data.now))
generate_now_weather_speech_script(parsed_cwb_data.now)
})
} catch (error) {
alert(error.message)
console.log(error)
}
}

Expand Down Expand Up @@ -115,6 +138,16 @@ function restore_location() {
}
}

// restore location
function restore_speech_voice() {
let data = localStorage.getItem('speechVoice')
if (data) {
stored_speech_voice = data
} else {
stored_speech_voice = ''
}
}

// fresh and refresh
function fresh() {
fetch_cwb(CWB_API)
Expand Down Expand Up @@ -147,6 +180,111 @@ function all_content_switch_to_loading() {
`
}

// speech
function speech_synthesis_init() {
const speech = window.speechSynthesis
if (speech.onvoiceschanged !== undefined) {
speech.onvoiceschanged = () => populateVoiceList()
}
}

function populateVoiceList() {
speechSynthesis_config_container.innerHTML = ''
let synth = window.speechSynthesis
voices = synth.getVoices()
if (!voices) return

let div = document.createElement('select')
available_and_accept_speech_voice = []

for (let i = 0; i < voices.length; i++) {
let option = document.createElement('option')
if (accept_speech_lang.includes(voices[i].lang)) {
available_and_accept_speech_voice.push(voices[i])
}
}

if (!available_and_accept_speech_voice) return

for (let i = 0; i < available_and_accept_speech_voice.length; i++) {
let option = document.createElement('option')
let voices = available_and_accept_speech_voice
option.textContent = voices[i].name + ' - ' + voices[i].lang

option.value = voices[i].name
option.setAttribute('data-lang', voices[i].lang)
option.setAttribute('data-name', voices[i].name)
if (stored_speech_voice) {
if (voices[i].name == stored_speech_voice) {
option.setAttribute('selected', true)
}
}
console.log('append')
div.appendChild(option)
}

// fill in read button
speechSynthesis_container.innerHTML = generate_read_button_html()

speechSynthesis_config_container.innerHTML += `
<div class="control has-icons-left mt-3 mb-3">
<div class="select is-large is-fullwidth">
<select id="populated_voice_select">
${div.innerHTML}
</select>
</div>
<div class="icon is-large is-left">
<i class="fas fa-volume-up"></i>
</div>
</div>
`
populated_voice_select = document.getElementById('populated_voice_select')
populated_voice_select.addEventListener('input', () => {
localStorage.setItem('speechVoice', populated_voice_select.value)
stored_speech_voice = populated_voice_select.value
})
}
// use now weather state object to generate html code
function generate_now_weather_speech_script(nowstate) {
speech_script[
'zh-TW'
] = `今天天氣${nowstate.CI}${nowstate.Wx},最高溫度維${nowstate.MaxT}度C,最低溫度維${nowstate.MinT}度C,降雨機率${nowstate.PoP}趴。`
speech_script[
'en-US'
] = `Today's High Temperature is ${nowstate.MaxT} Celsius, Low Temperature is${nowstate.MinT}Celsius, probability of precipitation is ${nowstate.PoP} percent`
}

function read_now_weather() {
if (!populated_voice_select || !speech_script || !stored_speech_voice) return
msg = speech_script
voices = available_and_accept_speech_voice
let speech = new SpeechSynthesisUtterance()
let lang = ''
for (let i = 0; i < voices.length; i++) {
if (voices[i].name == stored_speech_voice) {
speech.voice = voices[i]
if (voices[i].name.includes('Chinese')) {
lang = 'zh-TW'
} else {
lang = 'en-US'
}
}
}
speech.lang = lang
speech.text = msg[lang]
speech.volume = 1
speech.rate = 1.1
speech.pitch = 1
stop_speech_if_speaking()
window.speechSynthesis.speak(speech)
}

function stop_speech_if_speaking() {
if (window.speechSynthesis.speaking) {
window.speechSynthesis.cancel()
}
}

// generate

// generate location option
Expand Down Expand Up @@ -199,6 +337,20 @@ function generate_now_weather(nowstate) {
`
return div
}
function generate_read_button_html() {
return `
<div class="columns">
<div class="column">
<button class="button is-success is-outlined is-large is-fullwidth" onClick="read_now_weather()">
<span class="icon is-small">
<i class="fas fa-book-reader"></i>
</span>
<span class="ml-3">Read</span>
</button>
</div>
</div>
`
}

// fill in

Expand Down
6 changes: 3 additions & 3 deletions js/chart.min.js

Large diffs are not rendered by default.

Empty file added js/i18n.js
Empty file.
105 changes: 105 additions & 0 deletions js/my-chart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
let weather_chart_element

const CHART_COLORS = {
red: 'rgb(255, 99, 132)',
orange: 'rgb(255, 159, 64)',
yellow: 'rgb(255, 205, 86)',
green: 'rgb(75, 192, 192)',
blue: 'rgb(54, 162, 235)',
purple: 'rgb(153, 102, 255)',
grey: 'rgb(201, 203, 207)',
}

function generate_weather_chart_data(weatherElement) {
const time = (str) => {
let m = new Date(str)
let dateString = `${m.getUTCMonth() + 1}/${m.getUTCDate()} ${m.getUTCHours()}點`
return dateString
}

let maxt_chart_image_data = {
datasets: [],
}

let mint_chart_image_data = {
datasets: [],
}

let labels = []

// 產生標籤
let data = []
for (let z = 0; z < weatherElement[0].time.length; z++) {
const element = weatherElement[0].time[z]

data.push(time(element.startTime))
// 如果是最後一個Time
if (z == weatherElement[0].time.length - 1) {
data.push(time(element.endTime))
}
}
for (let y = 0; y < data.length - 1; y++) {
labels.push([`${data[y]} -`, data[y + 1]])
}

for (let i = 0; i < weatherElement.length; i++) {
let weatherElementName = weatherElement[i].elementName

// 如果是最大溫度
if (weatherElementName == 'MaxT') {
maxt_chart_image_data.datasets = [
{
label: '最大溫度',
data: [],
borderColor: CHART_COLORS.red,
},
]
for (let n = 0; n < weatherElement[i].time.length; n++) {
const element = weatherElement[i].time[n]
maxt_chart_image_data.datasets[0].data.push(element.parameter.parameterName)
}
console.log(JSON.stringify(maxt_chart_image_data))
}
// 如果是最小溫度
if (weatherElementName == 'MinT') {
mint_chart_image_data.datasets = [
{
label: '最小溫度',
data: [],
borderColor: CHART_COLORS.blue,
},
]
for (let n = 0; n < weatherElement[i].time.length; n++) {
const element = weatherElement[i].time[n]
mint_chart_image_data.datasets[0].data.push(element.parameter.parameterName)
}
console.log(JSON.stringify(mint_chart_image_data))
}
}
if (weather_chart_element != undefined) weather_chart_element.destroy()
weather_chart_canvas = document.getElementById('weather_chart_canvas')
console.log(weather_chart_canvas)
let config = {
type: 'line',
data: {
labels: labels,
datasets: [maxt_chart_image_data.datasets[0], mint_chart_image_data.datasets[0]],
},
options: {
plugins: {
title: {
display: true,
text: '36h天氣預測',
},
},
},
}
console.dir(config)
weather_chart_element = chart(weather_chart_canvas, config)
}

function chart(element, params) {
let canvas = new Chart(element, params)
if (canvas == null) console.error('canvas null')
return canvas
}

0 comments on commit 452732a

Please sign in to comment.