| @@ -8,9 +8,11 @@ | |||
| <canvas id="result-canvas" #canvasElement width="{{ width }}" height="{{ height }}"></canvas> | |||
| </div> | |||
| <img [src]="temp" *ngIf="temp" #temp class="test-img" width="100px" height="100px" alt=""> | |||
| <section class="temp-image" [ngClass]="{'active' : tempImg }"> | |||
| <img *ngIf="tempImg" src="{{ tempImg }}"> | |||
| </section> | |||
| <div class="action-buttons"> | |||
| <div class="action-buttons" *ngIf="!tempImg"> | |||
| <!-- <button *ngIf="areNeuralNetsLoaded" (click)="stopCameraStream()">Stop stream</button> --> | |||
| <!-- <button *ngIf="areNeuralNetsLoaded" (click)="toggleDetection()">{{ isDetecting ? 'Stop detection' : 'Detect and draw' }}</button> --> | |||
| @@ -19,4 +21,11 @@ | |||
| <button class="skin-button" *ngIf="areNeuralNetsLoaded" (click)="toggleDetection()" | |||
| [ngClass]="{'active' : isDetecting }"> <ion-icon name="glasses"></ion-icon> </button> | |||
| </div> | |||
| <section class="image-action-buttons" *ngIf="tempImg"> | |||
| <button (click)="approveImage()"> <img src="assets/icons/emojis/thumb-up.png"> </button> | |||
| <button (click)="tempImg = null"> <img src="assets/icons/emojis/thumb-up.png"> </button> | |||
| <button> <ion-icon name="share-social-outline"></ion-icon> </button> | |||
| </section> | |||
| </ion-content> | |||
| @@ -1,10 +1,24 @@ | |||
| @import '../colors'; | |||
| .test-img { | |||
| .temp-image { | |||
| position: fixed; | |||
| z-index: 1; | |||
| left: 50%; | |||
| top: 50%; | |||
| left: 0; | |||
| top: 0; | |||
| width: 100vw; | |||
| height: 100vh; | |||
| transform: scale(0); | |||
| transition: transform 0.1s; | |||
| &.active { | |||
| transform: scale(1); | |||
| } | |||
| img { | |||
| width: 100%; | |||
| height: 100%; | |||
| object-fit: contain; | |||
| } | |||
| } | |||
| .back-button { | |||
| @@ -13,7 +27,7 @@ | |||
| right: 10px; | |||
| width: 40px; | |||
| height: 40px; | |||
| background: rgba(white, 0.5); | |||
| background: rgba($pink, 0.5); | |||
| border: 0px; | |||
| border-radius: 50%; | |||
| display: flex; | |||
| @@ -29,6 +43,7 @@ | |||
| .container { | |||
| position: relative; | |||
| z-index: 0; | |||
| } | |||
| .glass-image { | |||
| @@ -75,6 +90,7 @@ | |||
| display: flex; | |||
| align-items: center; | |||
| width: 100%; | |||
| z-index: 1; | |||
| button { | |||
| width: 50px; | |||
| @@ -104,4 +120,43 @@ | |||
| } | |||
| } | |||
| } | |||
| } | |||
| .image-action-buttons { | |||
| position: fixed; | |||
| left: 0; | |||
| bottom: 20px; | |||
| width: 200px; | |||
| margin-left: calc(50% - 100px); | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: space-between; | |||
| padding: 10px; | |||
| background-color: rgba(black, 0.6); | |||
| border-radius: 30px; | |||
| z-index: 1; | |||
| button { | |||
| width: 50px; | |||
| height: 50px; | |||
| border-radius: 50%; | |||
| border: 1px solid rgba($blue-grey, 0.6); | |||
| background-color: transparent; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| &:nth-child(2) { | |||
| transform: rotate(180deg); | |||
| } | |||
| img { | |||
| width: 20px; | |||
| } | |||
| ion-icon { | |||
| color: white; | |||
| font-size: 20px; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,6 +1,7 @@ | |||
| import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; | |||
| import { detectSingleFace, loadFaceExpressionModel, loadFaceLandmarkModel, loadFaceLandmarkTinyModel, loadFaceRecognitionModel, loadSsdMobilenetv1Model, loadTinyFaceDetectorModel, TinyFaceDetectorOptions } from 'face-api.js'; | |||
| import { Location } from '@angular/common'; | |||
| import { ModalController } from '@ionic/angular'; | |||
| @Component({ | |||
| selector: 'app-ar-fan-cam', | |||
| @@ -24,14 +25,15 @@ export class ArFanCamPage implements OnInit { | |||
| areNeuralNetsLoaded = false; | |||
| isDetecting = false; | |||
| width = 360; | |||
| height = 270; | |||
| width: number; | |||
| height: number; | |||
| temp: string; | |||
| tempImg = ''; | |||
| stream: any; | |||
| constructor( | |||
| private location: Location | |||
| private location: Location, | |||
| private modalController: ModalController | |||
| ) { } | |||
| loadNeuralNetModels = async () => { | |||
| @@ -48,7 +50,7 @@ export class ArFanCamPage implements OnInit { | |||
| } | |||
| back() { | |||
| this.location.back(); | |||
| this.modalController.dismiss(); | |||
| this.stopCameraStream(); | |||
| } | |||
| @@ -107,6 +109,8 @@ export class ArFanCamPage implements OnInit { | |||
| const dataURI = canvas.toDataURL('image/png'); | |||
| this.capturedImageStrings.push(dataURI); | |||
| this.tempImg = dataURI; | |||
| context.resetTransform(); | |||
| context.clearRect(0, 0, window.innerWidth, window.innerHeight); | |||
| } | |||
| @@ -142,19 +146,22 @@ export class ArFanCamPage implements OnInit { | |||
| } | |||
| } | |||
| ngOnInit() { | |||
| ngOnInit() { | |||
| this.width = window.innerWidth; | |||
| this.height = window.innerHeight; | |||
| } | |||
| ngAfterViewInit() { | |||
| this.loadNeuralNetModels(); | |||
| const feedWidth = window.innerWidth; | |||
| const feedHeight = window.innerHeight; | |||
| this.width = feedWidth; | |||
| this.height = feedHeight; | |||
| this.getCameraStream().then(() => this.detectAndDrawFace(), (err) => console.log(err)); | |||
| } | |||
| approveImage() { | |||
| this.stopCameraStream(); | |||
| this.modalController.dismiss({ | |||
| imageData: this.tempImg | |||
| }); | |||
| } | |||
| } | |||
| @@ -26,11 +26,11 @@ | |||
| </div> | |||
| <ul class="stories"> | |||
| <li [routerLink]="['/ar-fan-cam']"> | |||
| <li (click)="presentCamModal()"> | |||
| <ion-icon name="add-circle-outline"></ion-icon> | |||
| <span> Add Story </span> | |||
| </li> | |||
| <li *ngFor="let story of fanStories; let i = index" [ngClass]="{'inactive' : story.opened }" | |||
| <li *ngFor="let story of reversed(fanStories); let i = index" [ngClass]="{'inactive' : story.opened }" | |||
| (click)="showSlides = true; story.opened = true; goToSlide(i)"> | |||
| <img [src]="story.profileImage"> | |||
| <span> {{ story.name }} </span> | |||
| @@ -38,7 +38,7 @@ | |||
| </ul> | |||
| <ul class="fan-feature-list"> | |||
| <li [routerLink]="['/ar-fan-cam']"> | |||
| <li (click)="presentCamModal()"> | |||
| <div> | |||
| <ion-icon name="camera-outline"></ion-icon> | |||
| @@ -1,10 +1,11 @@ | |||
| import { Component, OnInit, ViewChild } from '@angular/core'; | |||
| import { IonSlides } from '@ionic/angular'; | |||
| import { IonItemOption, IonSlides, ModalController } from '@ionic/angular'; | |||
| import { GooglePlus } from '@ionic-native/google-plus/ngx'; | |||
| import { Platform } from '@ionic/angular'; | |||
| import { AngularFireAuth } from '@angular/fire/auth'; | |||
| import firebase from 'firebase'; | |||
| import { ArFanCamPage } from '../ar-fan-cam/ar-fan-cam.page'; | |||
| @Component({ | |||
| selector: 'app-fan-zone', | |||
| @@ -59,6 +60,7 @@ export class FanZonePage implements OnInit { | |||
| private google: GooglePlus, | |||
| private fireAuth: AngularFireAuth, | |||
| private platform: Platform, | |||
| private modalController: ModalController, | |||
| ) { } | |||
| // async loginWithGoogle() { | |||
| @@ -193,4 +195,28 @@ export class FanZonePage implements OnInit { | |||
| }); | |||
| } | |||
| reversed(data: Array<any>) { | |||
| return data.reverse(); | |||
| } | |||
| async presentCamModal() { | |||
| const modal = await this.modalController.create({ | |||
| component: ArFanCamPage, | |||
| }); | |||
| modal.onDidDismiss().then((data: any) => { | |||
| if (data.data && data.data.imageData) { | |||
| this.fanStories.push({ | |||
| profileImage: this.googleUserData.profileImage, | |||
| name: this.googleUserData.name, | |||
| storyImage: data.data.imageData, | |||
| likeCount: 1, | |||
| opened: false | |||
| }); | |||
| } | |||
| }); | |||
| return await modal.present(); | |||
| } | |||
| } | |||