@ -1,43 +1,47 @@
< template >
< div v-if ="visible" class="dialog-overlay" >
<!-- Breadcrumb -- >
< div class = "dialog" >
<!-- Back -- >
< div class = "text-lg text-center font-light relative px-7" >
< h1
class = "text-lg text-center px-2 py-1 absolute -right-2 -top-1"
@ click = "close()"
< div v-if ="visible" class="dialog-overlay z-[60]" >
< div class = "dialog relative" >
< div class = "text-lg text-center font-light relative z-50" >
< div
id = "ViewHeading"
class = "text-center font-bold absolute top-0 left-0 right-0 px-4 py-2 bg-black/50 text-white leading-none"
>
< fa icon = "xmark" class = "fa-fw" > < / fa >
< / h1 >
< / div >
<!-- Heading -- >
< h1 id = "ViewHeading" class = "text-4xl text-center font-light pt-4" >
< span v-if ="uploading" > Uploading... < / span >
< span v -else -if = " blob " > Look Good ? < / span >
< span v-else > Say " Cheese " ! < / span >
< / h1 >
< / div >
< div
class = "text-lg text-center p-2 leading-none absolute right-0 top-0 text-white"
@ click = "close()"
>
< fa icon = "xmark" class = "w-[1em]" > < / fa >
< / div >
< / div >
< div v-if ="uploading" class="flex justify-center" >
< fa icon = "spinner" class = "fa-spin fa-3x text-center block" / >
< / div >
< div v -else -if = " blob " >
< div class = "flex justify-around" >
< div
class = "flex justify-center gap-2 absolute bottom-[1rem] left-[1rem] right-[1rem] bg-black/50 px-4 py-2"
>
< button
@ click = "uploadImage"
class = "bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-2 rounded-full"
class = "bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full"
>
< span > Upload < / span >
< / button >
< button
@ click = "retryImage"
class = "bg-slate-500 hover:bg-slate-700 text-white font-bold py-2 px-2 rounded-full"
class = "bg-slate-500 hover:bg-slate-700 text-white font-bold py-2 px-4 rounded-full"
>
< span > Retry < / span >
< / button >
< / div >
< img :src ="URL.createObjectURL(blob)" class = "mt-2 w-full" / >
< div class = "flex justify-center" >
< img :src ="URL.createObjectURL(blob)" class = "mt-2 rounded" / >
< / div >
< / div >
< div v-else >
<!--
@ -45,13 +49,14 @@
: resolution = "{ width: 375, height: 812 }"
-- >
< camera facingMode = "environment" autoplay ref = "camera" >
< div class = "absolute bottom-0 w-full flex justify-center pb-4" >
<!-- Button -- >
< div
class = "absolute portrait:bottom-0 portrait:left-0 portrait:right-0 landscape:right-0 landscape:top-0 landscape:bottom-0 flex landscape:flex-row justify-center items-center portrait:pb-2 landscape:pr-4"
>
< button
@ click = "takeImage"
class = "bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-2 rounded-full "
class = "bg-blue-500 hover:bg-blue-700 text-white font-bold p-3 rounded-full text-2xl leading-none "
>
< fa icon = "camera" class = "fa-fw " > < / fa >
< fa icon = "camera" class = "w-[1em] " > < / fa >
< / button >
< / div >
< / camera >
@ -78,6 +83,9 @@ export default class GiftedPhotoDialog extends Vue {
activeDid = "" ;
blob : Blob | null = null ;
setImage : ( arg : string ) => void = ( ) => { } ;
imageHeight ? : number = window . innerHeight / 2 ;
imageWidth ? : number = window . innerWidth / 2 ;
imageWarning = "." ;
uploading = false ;
visible = false ;
@ -105,17 +113,64 @@ export default class GiftedPhotoDialog extends Vue {
open ( setImageFn : ( arg : string ) => void ) {
this . visible = true ;
const bottomNav = document . querySelector ( "#QuickNav" ) as HTMLElement ;
if ( bottomNav ) {
bottomNav . style . display = "none" ;
}
this . setImage = setImageFn ;
}
close ( ) {
this . visible = false ;
const bottomNav = document . querySelector ( "#QuickNav" ) as HTMLElement ;
if ( bottomNav ) {
bottomNav . style . display = "" ;
}
this . blob = null ;
}
async takeImage ( /* payload: MouseEvent */ ) {
const cameraComponent = this . $refs . camera as InstanceType < typeof Camera > ;
this . blob = await cameraComponent ? . snapshot ( ) ; / / p n g i s d e f a u l t ; i f t h a t c h a n g e s , c h a n g e e x t e n s i o n i n f o r m D a t a . a p p e n d
/ * *
* This logic to set the image height & width correctly .
* Without it , the portrait orientation ends up with an image that is stretched horizontally .
* Note that it ' s the same with raw browser Javascript ; see the "drawImage" example below .
* Now that I 've done it, I can' t explain why it works .
* /
let imageHeight = cameraComponent ? . resolution ? . height ;
let imageWidth = cameraComponent ? . resolution ? . width ;
const initialImageRatio = imageWidth / imageHeight ;
const windowRatio = window . innerWidth / window . innerHeight ;
if ( initialImageRatio > 1 && windowRatio < 1 ) {
/ / t h e i m a g e i s w i d e r t h a n i t i s t a l l , a n d t h e w i n d o w i s t a l l e r t h a n i t i s w i d e
/ / F o r s o m e r e a s o n , m o b i l e i n p o r t r a i t o r i e n t a t i o n r e n d e r s a h o r i z o n t a l l y - s t r e t c h e d i m a g e .
/ / W e ' r e g o n n a f o r c e i t o p p o s i t e .
imageHeight = cameraComponent ? . resolution ? . width ;
imageWidth = cameraComponent ? . resolution ? . height ;
} else if ( initialImageRatio < 1 && windowRatio > 1 ) {
/ / t h e i m a g e i s t a l l e r t h a n i t i s w i d e , a n d t h e w i n d o w i s w i d e r t h a n i t i s t a l l
/ / H a v e n ' t s e e n t h i s h a p p e n , b u t w e ' l l d o i t j u s t i n c a s e .
imageHeight = cameraComponent ? . resolution ? . width ;
imageWidth = cameraComponent ? . resolution ? . height ;
}
const newImageRatio = imageWidth / imageHeight ;
if ( newImageRatio < windowRatio ) {
/ / t h e i m a g e i s a t a l l e r r a t i o t h a n t h e w i n d o w , s o f i t t h e h e i g h t f i r s t
imageHeight = window . innerHeight / 2 ;
imageWidth = imageHeight * newImageRatio ;
} else {
/ / t h e i m a g e i s a w i d e r r a t i o t h a n t h e w i n d o w , s o f i t t h e w i d t h f i r s t
imageWidth = window . innerWidth / 2 ;
imageHeight = imageWidth / newImageRatio ;
}
/ / T h e r e s o l u t i o n i s o n l y n e c e s s a r y b e c a u s e o f t h a t m o b i l e p o r t r a i t - o r i e n t a t i o n c a s e .
/ / T h e m o b i l e e m u l a t i o n i n a b r o w s e r s h o w s s o m e t h i n g s t r e t c h e d v e r t i c a l l y , b u t r e a l d e v i c e s w o r k f i n e .
this . blob = await cameraComponent ? . snapshot ( {
height : imageHeight ,
width : imageWidth ,
} ) ; / / p n g i s d e f a u l t ; i f t h a t c h a n g e s , c h a n g e e x t e n s i o n i n f o r m D a t a . a p p e n d
if ( ! this . blob ) {
this . $notify (
{
@ -134,6 +189,54 @@ export default class GiftedPhotoDialog extends Vue {
this . blob = null ;
}
/ * * * *
Here ' s an approach to photo capture without a library . It has similar quirks .
Now that we 've fixed styling for simple-vue-camera, it' s not critical to refactor . Maybe someday .
< button id = "start-camera" @click ="cameraClicked" > Start Camera < / button >
< video id = "video" width = "320" height = "240" autoplay > < / video >
< button id = "snap-photo" @click ="photoSnapped" > Snap Photo < / button >
< canvas id = "canvas" width = "320" height = "240" > < / canvas >
async cameraClicked ( ) {
console . log ( "camera_button clicked" ) ;
const video = document . querySelector ( "#video" ) ;
const stream = await navigator . mediaDevices . getUserMedia ( {
video : true ,
audio : false ,
} ) ;
if ( video instanceof HTMLVideoElement ) {
video . srcObject = stream ;
}
}
photoSnapped ( ) {
console . log ( "snap_photo clicked" ) ;
const video = document . querySelector ( "#video" ) ;
const canvas = document . querySelector ( "#canvas" ) ;
if (
canvas instanceof HTMLCanvasElement &&
video instanceof HTMLVideoElement
) {
canvas
? . getContext ( "2d" )
? . drawImage ( video , 0 , 0 , canvas . width , canvas . height ) ;
/ / . . . o r s e t t h e b l o b :
/ / c a n v a s ? . t o B l o b (
/ / ( b l o b ) = > {
/ / t h i s . b l o b = b l o b ;
/ / } ,
/ / " i m a g e / j p e g " ,
/ / 1 ,
/ / ) ;
/ / d a t a u r l o f t h e i m a g e
const image_data_url = canvas ? . toDataURL ( "image/jpeg" ) ;
console . log ( image_data_url ) ;
}
}
* * * * /
async uploadImage ( ) {
this . uploading = true ;
const identifier = await getIdentity ( this . activeDid ) ;