@@ -8,9 +8,11 @@ | |||||
<canvas id="result-canvas" #canvasElement width="{{ width }}" height="{{ height }}"></canvas> | <canvas id="result-canvas" #canvasElement width="{{ width }}" height="{{ height }}"></canvas> | ||||
</div> | </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)="stopCameraStream()">Stop stream</button> --> | ||||
<!-- <button *ngIf="areNeuralNetsLoaded" (click)="toggleDetection()">{{ isDetecting ? 'Stop detection' : 'Detect and draw' }}</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()" | <button class="skin-button" *ngIf="areNeuralNetsLoaded" (click)="toggleDetection()" | ||||
[ngClass]="{'active' : isDetecting }"> <ion-icon name="glasses"></ion-icon> </button> | [ngClass]="{'active' : isDetecting }"> <ion-icon name="glasses"></ion-icon> </button> | ||||
</div> | </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> | </ion-content> |
@@ -1,10 +1,24 @@ | |||||
@import '../colors'; | @import '../colors'; | ||||
.test-img { | |||||
.temp-image { | |||||
position: fixed; | position: fixed; | ||||
z-index: 1; | 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 { | .back-button { | ||||
@@ -13,7 +27,7 @@ | |||||
right: 10px; | right: 10px; | ||||
width: 40px; | width: 40px; | ||||
height: 40px; | height: 40px; | ||||
background: rgba(white, 0.5); | |||||
background: rgba($pink, 0.5); | |||||
border: 0px; | border: 0px; | ||||
border-radius: 50%; | border-radius: 50%; | ||||
display: flex; | display: flex; | ||||
@@ -29,6 +43,7 @@ | |||||
.container { | .container { | ||||
position: relative; | position: relative; | ||||
z-index: 0; | |||||
} | } | ||||
.glass-image { | .glass-image { | ||||
@@ -75,6 +90,7 @@ | |||||
display: flex; | display: flex; | ||||
align-items: center; | align-items: center; | ||||
width: 100%; | width: 100%; | ||||
z-index: 1; | |||||
button { | button { | ||||
width: 50px; | 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 { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; | ||||
import { detectSingleFace, loadFaceExpressionModel, loadFaceLandmarkModel, loadFaceLandmarkTinyModel, loadFaceRecognitionModel, loadSsdMobilenetv1Model, loadTinyFaceDetectorModel, TinyFaceDetectorOptions } from 'face-api.js'; | import { detectSingleFace, loadFaceExpressionModel, loadFaceLandmarkModel, loadFaceLandmarkTinyModel, loadFaceRecognitionModel, loadSsdMobilenetv1Model, loadTinyFaceDetectorModel, TinyFaceDetectorOptions } from 'face-api.js'; | ||||
import { Location } from '@angular/common'; | import { Location } from '@angular/common'; | ||||
import { ModalController } from '@ionic/angular'; | |||||
@Component({ | @Component({ | ||||
selector: 'app-ar-fan-cam', | selector: 'app-ar-fan-cam', | ||||
@@ -24,14 +25,15 @@ export class ArFanCamPage implements OnInit { | |||||
areNeuralNetsLoaded = false; | areNeuralNetsLoaded = false; | ||||
isDetecting = false; | isDetecting = false; | ||||
width = 360; | |||||
height = 270; | |||||
width: number; | |||||
height: number; | |||||
temp: string; | |||||
tempImg = ''; | |||||
stream: any; | stream: any; | ||||
constructor( | constructor( | ||||
private location: Location | |||||
private location: Location, | |||||
private modalController: ModalController | |||||
) { } | ) { } | ||||
loadNeuralNetModels = async () => { | loadNeuralNetModels = async () => { | ||||
@@ -48,7 +50,7 @@ export class ArFanCamPage implements OnInit { | |||||
} | } | ||||
back() { | back() { | ||||
this.location.back(); | |||||
this.modalController.dismiss(); | |||||
this.stopCameraStream(); | this.stopCameraStream(); | ||||
} | } | ||||
@@ -107,6 +109,8 @@ export class ArFanCamPage implements OnInit { | |||||
const dataURI = canvas.toDataURL('image/png'); | const dataURI = canvas.toDataURL('image/png'); | ||||
this.capturedImageStrings.push(dataURI); | this.capturedImageStrings.push(dataURI); | ||||
this.tempImg = dataURI; | |||||
context.resetTransform(); | context.resetTransform(); | ||||
context.clearRect(0, 0, window.innerWidth, window.innerHeight); | 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() { | ngAfterViewInit() { | ||||
this.loadNeuralNetModels(); | 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)); | this.getCameraStream().then(() => this.detectAndDrawFace(), (err) => console.log(err)); | ||||
} | } | ||||
approveImage() { | |||||
this.stopCameraStream(); | |||||
this.modalController.dismiss({ | |||||
imageData: this.tempImg | |||||
}); | |||||
} | |||||
} | } |
@@ -26,11 +26,11 @@ | |||||
</div> | </div> | ||||
<ul class="stories"> | <ul class="stories"> | ||||
<li [routerLink]="['/ar-fan-cam']"> | |||||
<li (click)="presentCamModal()"> | |||||
<ion-icon name="add-circle-outline"></ion-icon> | <ion-icon name="add-circle-outline"></ion-icon> | ||||
<span> Add Story </span> | <span> Add Story </span> | ||||
</li> | </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)"> | (click)="showSlides = true; story.opened = true; goToSlide(i)"> | ||||
<img [src]="story.profileImage"> | <img [src]="story.profileImage"> | ||||
<span> {{ story.name }} </span> | <span> {{ story.name }} </span> | ||||
@@ -38,7 +38,7 @@ | |||||
</ul> | </ul> | ||||
<ul class="fan-feature-list"> | <ul class="fan-feature-list"> | ||||
<li [routerLink]="['/ar-fan-cam']"> | |||||
<li (click)="presentCamModal()"> | |||||
<div> | <div> | ||||
<ion-icon name="camera-outline"></ion-icon> | <ion-icon name="camera-outline"></ion-icon> | ||||
@@ -1,10 +1,11 @@ | |||||
import { Component, OnInit, ViewChild } from '@angular/core'; | 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 { GooglePlus } from '@ionic-native/google-plus/ngx'; | ||||
import { Platform } from '@ionic/angular'; | import { Platform } from '@ionic/angular'; | ||||
import { AngularFireAuth } from '@angular/fire/auth'; | import { AngularFireAuth } from '@angular/fire/auth'; | ||||
import firebase from 'firebase'; | import firebase from 'firebase'; | ||||
import { ArFanCamPage } from '../ar-fan-cam/ar-fan-cam.page'; | |||||
@Component({ | @Component({ | ||||
selector: 'app-fan-zone', | selector: 'app-fan-zone', | ||||
@@ -59,6 +60,7 @@ export class FanZonePage implements OnInit { | |||||
private google: GooglePlus, | private google: GooglePlus, | ||||
private fireAuth: AngularFireAuth, | private fireAuth: AngularFireAuth, | ||||
private platform: Platform, | private platform: Platform, | ||||
private modalController: ModalController, | |||||
) { } | ) { } | ||||
// async loginWithGoogle() { | // 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(); | |||||
} | |||||
} | } |