2019/12/02 - [Mobile] - [ Ionic ] 웹개발자가 만드는 Ionic 어플 - 1탄 (설치, 오픈 소스 활용)
2020/04/04 - [Mobile] - [ Ionic ] 웹개발자가 만드는 Ionic 어플 - 3탄 (배포)
2020/04/14 - [Mobile] - [ Ionic ] 웹개발자가 만드는 Ionic 어플 - 4탄 (배포 후 문제점)
https://play.google.com/store/apps/details?id=devjoo.ionic.widmarkapp
지금어때 - 실시간 음주 계산기, 술게임, 혈중 알콜 농도 계산, 음주 측정 - Google Play 앱
혈중 알콜 농도를 계산하여 건강한 음주 생활을 즐기세요. 나와 함께 같이 마신 사람들의 혈중 알콜 농도 또한 확인 가능합니다. 혈중 알콜 농도 계산과 함께 간단한 술게임으로 재밌는 음주 되세요
play.google.com
1탄에서는 설치 및 오픈 소스를 활용하는 법을 포스팅하고 꽤 많은 시간이 흘렀다.
해당 앱개발을 하느라 포스팅을 미루고 있었는데 2탄을 올려본다.
개발하려는 앱에 대한 설명을 시작으로 포스팅을 하겠다.
앱 제목
본제 - 지금어때
부제 - 실시간 혈중 알콜 농도 계산기
앱 컨텐츠
소개 - 도로교통공단에서 제공되는 위드마크 공식을 사용하여 술자리에서 자신이 먹는 술의 양만큼 혈중 알콜 농도를 그래프로 가시화하여 보여주고 간단한 술게임들을 즐길 수 있게 한다.
목표는 1월 출시였는데 회사도 다니고 퇴사하고 하느라 생각보다는 오래걸렸다.
만들어진 앱에 대한 소개를 하도록 하겠다.
탭구성으로 페이지는 3개의 탭으로 나눠져 있는데 하나씩 포스팅할 것이다.
1. 프로필
- 기본 사용자에 대한 프로필을 저장하여 사용할 수 있도록 처리를 하였다.
- 하단에는 무한 스크롤바를 넣어서 이전에 먹은 음주 데이터들을 확인할 수가 있다.

- IonInfiniteScroll을 사용하여 무한 스크롤을 구현한 소스이다.
import { IonInfiniteScroll } from '@ionic/angular';
... 
  @ViewChild(IonInfiniteScroll,{static:false}) infiniteScroll: IonInfiniteScroll;
  eventSource = [];
...
    dataSet(dataId){
        var datas = JSON.parse(localStorage.getItem('data'+dataId));
        var members = JSON.parse(datas.memberData);
        var desc = '';
        members.forEach(function(member){
            desc += member.name+", ";
        },desc)
        var memname = ((members.length)>1)? members[0].name+', '+members[1].name:members[0].name;
        var startDate = new Date(datas.start);
        var theDate = startDate.getFullYear()+'/'+('0' + (startDate.getMonth()+1)).slice(-2)+'/'+('0' + startDate.getDate()).slice(-2);
        this.currentDataId = dataId;
        this.eventSource.push({
            id:dataId,
            title:memname+' 포함 총 '+(members.length)+'명',
            desc:desc,
            theDate:theDate
        });
    }
    loadData(event) {
      setTimeout(() => {
        event.target.complete();
        // App logic to determine if all data is loaded
        // and disable the infinite scroll
        for(let i=1; i<=5; i++){
          if (this.currentDataId > 1) {
              this.dataSet(this.currentDataId-1);
          }else{
              event.target.disabled = true;
              break;
          }
        }
      }, 500);
    }
      <ion-card *ngIf="eventSource.length > 0">
      <ion-list>
          <ion-item *ngFor="let event of eventSource">
              <ion-label class="label label-ios">{{event.id}} | {{ event.theDate }} | {{ event.title }} </ion-label>
              <button ion-button outline item-end (click)="goCalc(event.id)">자세히</button>
          </ion-item>
      </ion-list>
      <ion-infinite-scroll threshold="100px" (ionInfinite)="loadData($event)">
        <ion-infinite-scroll-content
          loadingSpinner="bubbles"
          loadingText="Loading more data...">
        </ion-infinite-scroll-content>
      </ion-infinite-scroll>
  </ion-card>
- 자세히 버튼을 누르게 되면 나타나는 화면이다.
- 도로교통공단의 음주 사고시 법적 책임에 대해 추가해두었다.


- chart.js 와 chartjs-plugin-annotation을 사용하여 그래프를 출력할 수 있다.
- chartjs-plugin-annotation은 설정값에 따라 그래프에 색칠하거나 라인으로 범위를 나타내 줄 수 있는 플러그인이다.
- y축 범위에 따라 처벌기준이 달라지는 범위를 나타내준다.
import { Chart } from 'chart.js';
import * as ChartAnnotation from 'chartjs-plugin-annotation';
...
  ngOnInit(){
      Chart.pluginService.register([ChartAnnotation]);
      this.route.params.subscribe(
        data => {
          this.datas = JSON.parse(localStorage.getItem('data'+data.dataId))
          var startDate = new Date(this.datas.start);
          var endDate = new Date(this.datas.end);
          var datasets = [];
          var labels = [];
          this.title = (startDate.getMonth()+1)+'/'+startDate.getDate();
          this.title += ' ~ '+(endDate.getMonth()+1)+'/'+endDate.getDate();
          this.members = JSON.parse(this.datas.memberData);
          this.members.some(function(member){
            if(member.drinks.length == undefined || member.drinks.length <= 0) return false;
            this.drinksData.push(member.drinks);
            let color = this.setRandomColor();
            let startEatTime = member.drinks[0].eatTime - (member.drinks[0].eatTime%(30*60*1000)); //시간단위
            if(startEatTime < this.firstTime && this.firstTime!=0) this.firstTime = startEatTime;
            if(this.firstTime ==0) this.firstTime = startEatTime;
            let endEatTime = member.drinks[(member.drinks.length-1)].eatTime - (member.drinks[(member.drinks.length-1)].eatTime%(60*60*1000)) + (60*60*1000)
            if(endEatTime > this.endTime && this.endTime!=0) this.endTime = endEatTime;
            if(this.endTime ==0) this.endTime = endEatTime;
            let bacData = [];
            let time = this.firstTime;
            Object.setPrototypeOf(member, Member.prototype);
            let i=1;  //무조건 3번 검사후
            while(true){
              let bac = Number(member.getBAC(time));
              if(i>3 && bac<=0 && this.endTime < time){
                  bacData.push(0);
                  break;
              }
              i++;
              if(time > this.endTime) this.endTime = time;
              time += 30*60*1000 //30분씩 더하기
              bacData.push(bac);
            }
            datasets.push({
                label: member.name,
                backgroudColor:color,
                borderColor:color,
                fill:false,
                data: bacData
            });
        }, this);
        var time = this.firstTime;
        while(true){
          let timeDate = new Date(time);
          let label = timeDate.getHours() >= 10 ? (timeDate.getHours()) : '0'+ timeDate.getHours();
          label += ':'+(timeDate.getMinutes() >= 10 ? (timeDate.getMinutes()) : '0'+ timeDate.getMinutes());
          labels.push(label);
          if(this.endTime < time) break;
          time += 30*60*1000 //30분씩 더하기
        }
        this.bars = new Chart(this.memberChart.nativeElement, {
          type: 'line',
          data: {
            labels: labels,
            datasets: datasets
          },
          options: {
            scales: {
              yAxes: [{
                ticks: {
                  beginAtZero: true
                }
              }]
            },
            annotation: {
              annotations: [{
                  drawTime: 'beforeDatasetsDraw',
                  type: 'box',
                  id: 'a-box-1',
                  yScaleID: 'y-axis-0',
                  yMax: 0.08,
                  yMin:  0.03,
                  backgroundColor: 'rgba(255, 0, 0, 0.2)',
              },{
                  drawTime: 'beforeDatasetsDraw',
                  type: 'box',
                  id: 'a-box-2',
                  yScaleID: 'y-axis-0',
                  yMax: 0.2,
                  yMin:  0.08,
                  backgroundColor: 'rgba(255, 0, 0, 0.4)',
              },{
                  drawTime: 'beforeDatasetsDraw',
                  type: 'box',
                  id: 'a-box-3',
                  yScaleID: 'y-axis-0',
                  yMin:  0.2,
                  backgroundColor: 'rgba(255, 0, 0, 0.6)',
              }],
            }
          }
        });
        }
      )
  }
2. 혈중알콜농도
- 음주량을 기입하는 화면이다.
- 인원을 선택한 뒤 하단의 카테고리에서 먹은 술의 종류를 클릭하면 데이터가 입력된다.

3. 술게임
- 추후에도 게임을 추가할 수 있도록 리스트 형식으로 선택하게끔 만들었다.

3.1 Timebomb
- 시간을 선택한 뒤 시작을 하면 폭탄이미지가 노출되고 시간이 지나면 터진 이미지로 변환된다.



위와 같이 Ionic 과 angular 를 통하여 앱을 만들었다. 출시하는 과정은 다음 포스팅에서 소개하도록 하겠다.
'Mobile' 카테고리의 다른 글
| [ Ionic ] 웹개발자가 만드는 Ionic 어플 - 4탄 (배포 후 문제점) (0) | 2020.04.14 | 
|---|---|
| [ Ionic ] 웹개발자가 만드는 Ionic 어플 - 3탄 (배포) (0) | 2020.04.04 | 
| [ Ionic + Angular ] Chart.js 사용하여 그래프 생성하기 (0) | 2019.12.27 | 
| [ Ionic ] 태그 노출, 비노출 처리 (0) | 2019.12.08 | 
| [ Ionic ] 웹개발자가 만드는 Ionic 어플 - 1탄 (설치, 오픈 소스 활용) (2) | 2019.12.02 | 
 
										
									 
										
									 
										
									
댓글