最近暑すぎません?!

私の地域では連日
熱中症警戒アラートが出ているほど
毎日30℃を大幅に超える日が続いています。

自宅で過ごしている時も
救急車の音がよく聞こえるようになり
熱中症の患者さんも増えているようです。心配。
園児はどこで遊んでる?!
そんな中、先日前職の幼稚園へ
遊びに行く機会がありました。
保育室はエアコンが効いており
涼しかったのですが
廊下や外は空気がモワモワしていて
とても暑かったです。
現在は夏休みに入ったそうですが
7月はずっとエアコンの効いた保育室内で
園児は遊んでいたようです。良かった。
そりゃそうか。でも・・

子どもたちの安全を守るために
考えてくれている
保育士さんたちに本当毎日感謝です。
環境は整っていましたが
次に気をつけることは水分補給です。
保育士は時間を見ることが多く
腕に時計をつけている方もいます。
時間を見て水分補給のタイミングを見て
保育士が一斉に子どもたちに促しています。
(顔色を見て個別に声かけることも追加であります)
遊んでいて夢中になる子どもたちに
いかに言葉的にも強制的にならず
自主的に飲めるか当時苦労していました。
なので保育現場の改革という意味でも
子どもたちが自主的に水分を
取れるようなものを・・・
ちなみにiphoneを見る余裕はないので
保育現場にぴったりな
AppleWatchでアプリを開発しました!

↓動いている様子です(早送りです)
水分補給の目安に推奨されている15分を
自動的に繰り返し、子どもたちも
この水分が減っていくのを客観的に見ることができ
自主的に飲みにいくきっかけになったり
月齢によっては
「喉が渇いているのかな?」と
自分が飲むことで
このキャラクターにお水をあげている
感覚になる姿も予測されます♡
こちらはシュミレーターなので
実際にご自身のxcodeから、作成手順内の
コード入れていただくと使用できます!
↓当時の保育現場での対応も書いています
プロダクトを一緒に作ろう!
準備するツール
💻 Xcode:https://developer.apple.com/jp/xcode/
Macのみ実装可能です!
[ 特徴 ]
→Appleが提供している統合開発環境(IDE)です。
iPhoneやiPad、MacなどのApple製端末で
使用するアプリを作成できます。
Swift(スウィフト)
アップルのiOSおよびMacOS、Linuxで利用出来る
プログラミング言語
→基本的にxcodeを使って開発をする
作り方
⚠️注意
初めてXcodeをダウンロードする方は
容量も大きく、時間もかかるため
事前準備に時間を要することを
覚えておいてもらえると良いです。
①Xcodeでログインし、「Create New Project」から
作成を始めます。(ver.が最新か確認してください)
③プロジェクトを始めるにあたり
項目の入力が必要になります。
Product Name:好きな名前を入れる
(日本語で入れないほうがいいです)
Team:選択できるので、自分の名前を選ぶ
Organization Identifier:com.の後に自分の好きな名前入れる
1番下の選択できるところは
今回はAppleWatchのみの開発なので
「Watch-only App」を選びましょう。
④ 左側の「ContentView.swift」を開きます
⑤既に書いてあるコードを削除し
下記のコードを挿入します。
コードはこちら
import SwiftUI
import UserNotifications
struct ContentView: View {
@State private var timeRemaining = 900 // 15分 = 900秒
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
GeometryReader { geometry in
ZStack {
Color.blue.opacity(0.2)
.edgesIgnoringSafeArea(.all)
VStack {
Text("いっしょに、のもう")
.font(.system(size: geometry.size.width * 0.06))
.padding(.top, geometry.size.height * 0.05)
Spacer()
// キャラクターを表示する
WaterCharacterView(timeRemaining: timeRemaining)
.frame(width: geometry.size.width * 0.7, height: geometry.size.height * 0.6)
Spacer()
// 時間の表示
Text(timeString(time: timeRemaining))
.font(.system(size: geometry.size.width * 0.08, weight: .bold))
.foregroundColor(.white) // テキストカラーを白に設定
.padding(.bottom, geometry.size.height * 0.05)
}
}
.onReceive(timer) { _ in
if timeRemaining > 0 {
timeRemaining -= 1
} else {
sendNotification()
timeRemaining = 900 // リセットして再スタート
}
}
}
}
func timeString(time: Int) -> String {
let minutes = Int(time) / 60 % 60
let seconds = Int(time) % 60
return String(format:"%02i:%02i", minutes, seconds)
}
func sendNotification() {
let content = UNMutableNotificationContent()
content.title = "水を飲む時間です!"
content.body = "休憩して水を飲みましょう。"
content.sound = .default
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil)
UNUserNotificationCenter.current().add(request)
}
}
struct WaterCharacterView: View {
let timeRemaining: Int
let totalTime = 900
var body: some View {
GeometryReader { geometry in
ZStack {
WaterDropShape(progress: CGFloat(timeRemaining) / CGFloat(totalTime))
CharacterFace()
.frame(width: geometry.size.width * 0.6, height: geometry.size.height * 0.3)
.position(x: geometry.size.width / 2, y: geometry.size.height * 0.4)
CharacterLimbs()
.frame(width: geometry.size.width, height: geometry.size.height)
}
.animation(.easeInOut(duration: 1), value: timeRemaining)
}
}
}
struct WaterDropShape: View {
let progress: CGFloat
var body: some View {
Circle()
.stroke(Color.black, lineWidth: 2)
.background(
Circle()
.fill(LinearGradient(
gradient: Gradient(colors: [Color.blue.opacity(0.7), Color.blue]),
startPoint: .top,
endPoint: .bottom))
.scaleEffect(x: 1, y: progress, anchor: .bottom)
)
.clipShape(Circle())
}
}
struct CharacterFace: View {
var body: some View {
VStack {
HStack {
Eye()
Eye()
}
Mouth()
}
}
}
struct CharacterLimbs: View {
var body: some View {
GeometryReader { geometry in
Group {
Hand()
.rotationEffect(.degrees(-45))
.position(x: geometry.size.width * 0.2, y: geometry.size.height * 0.6)
Hand()
.rotationEffect(.degrees(45))
.position(x: geometry.size.width * 0.8, y: geometry.size.height * 0.6)
Foot()
.rotationEffect(.degrees(20))
.position(x: geometry.size.width * 0.35, y: geometry.size.height * 0.85)
Foot()
.rotationEffect(.degrees(-20))
.position(x: geometry.size.width * 0.65, y: geometry.size.height * 0.85)
}
}
}
}
struct Eye: View {
var body: some View {
Circle()
.fill(Color.black)
.frame(width: 8, height: 8)
.padding(.horizontal, 4)
}
}
struct Mouth: View {
var body: some View {
Path { path in
path.move(to: CGPoint(x: 0, y: 0))
path.addQuadCurve(to: CGPoint(x: 16, y: 0), control: CGPoint(x: 8, y: 8))
}
.stroke(Color.black, lineWidth: 1)
.frame(width: 16, height: 8)
.offset(y: 4)
}
}
struct Hand: View {
var body: some View {
Capsule()
.fill(Color.blue)
.frame(width: 8, height: 24)
}
}
struct Foot: View {
var body: some View {
Capsule()
.fill(Color.blue)
.frame(width: 8, height: 16)
}
}
struct WaterReminderApp_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
シュミレーターにでてくるので
15分が自動的に繰り返し表示されます!
今後はこれもやりたい!!
💡
0分になった瞬間に振動したり
水の涼しい音が鳴るようになると
より楽しめるのでは??
💡
他にもiphoneでも開発してみたのですが
子どもたちが自主的に見るという点でも
大きな画面(ipadなど)で
常に表示しておくと良いのでは??
まだまだアップデートできそうな
夏にぴったりのアプリになりそうです!!
子どもに限らずわたしたち大人の皆さんも
たくさん水分補給していきましょ〜う!!
そしてこの暑い夏を乗り切りましょう!