Skip to content

Commit 59cef22

Browse files
docs(vue): add context to code blocks and small changes to surrounding text
1 parent c152d58 commit 59cef22

File tree

1 file changed

+202
-53
lines changed

1 file changed

+202
-53
lines changed

docs/vue/your-first-app/2-taking-photos.md

Lines changed: 202 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,22 @@ Create a new file at `src/composables/usePhotoGallery.ts` and open it up.
1717
We will start by importing the various utilities we will use from Vue core and Capacitor:
1818

1919
```typescript
20+
// CHANGE: Add imports from `vue` and `capacitor`.
2021
import { ref, onMounted, watch } from 'vue';
2122
import { Camera, CameraResultType, CameraSource, Photo } from '@capacitor/camera';
2223
import { Filesystem, Directory } from '@capacitor/filesystem';
2324
import { Preferences } from '@capacitor/preferences';
2425
```
2526

26-
Next, create a function named usePhotoGallery:
27+
Next, create a function named `usePhotoGallery`:
2728

2829
```typescript
30+
import { ref, onMounted, watch } from 'vue';
31+
import { Camera, CameraResultType, CameraSource, Photo } from '@capacitor/camera';
32+
import { Filesystem, Directory } from '@capacitor/filesystem';
33+
import { Preferences } from '@capacitor/preferences';
34+
35+
// CHANGE: Create `usePhotoGallery` function.
2936
export const usePhotoGallery = () => {
3037
const takePhoto = async () => {
3138
const photo = await Camera.getPhoto({
@@ -45,33 +52,53 @@ Our `usePhotoGallery` function exposes a method called takePhoto, which in turn
4552

4653
Notice the magic here: there's no platform-specific code (web, iOS, or Android)! The Capacitor Camera plugin abstracts that away for us, leaving just one method call - `getPhoto()` - that will open up the device's camera and allow us to take photos.
4754

48-
The last step we need to take is to use the new function from the Tab2 page. Go back to `Tab2Page.vue` and import it:
49-
50-
```tsx
51-
import { usePhotoGallery } from '@/composables/usePhotoGallery';
52-
```
53-
54-
Destructure the `takePhoto` function from `usePhotoGallery` so we can use it in our `template`:
55+
The last step we need to take is to use the new function in the Tab2 page. Go back to `Tab2Page.vue`.
56+
57+
Import `usePhotoGallery` and destructure the `takePhoto` function so we can use it in our `template`:
58+
59+
```html
60+
<template>
61+
<ion-page>
62+
<ion-header>
63+
<ion-toolbar>
64+
<ion-title>Photo Gallery</ion-title>
65+
</ion-toolbar>
66+
</ion-header>
67+
<ion-content :fullscreen="true">
68+
<ion-header collapse="condense">
69+
<ion-toolbar>
70+
<ion-title size="large">Photo Gallery</ion-title>
71+
</ion-toolbar>
72+
</ion-header>
73+
<ion-fab vertical="bottom" horizontal="center" slot="fixed">
74+
<ion-fab-button @click="takePhoto()">
75+
<ion-icon :icon="camera"></ion-icon>
76+
</ion-fab-button>
77+
</ion-fab>
78+
</ion-content>
79+
</ion-page>
80+
</template>
5581

56-
```tsx
5782
<script setup lang="ts">
83+
import { camera, trash, close } from 'ionicons/icons';
5884
import {
59-
IonContent,
60-
IonCol,
61-
IonFab,
62-
IonFabButton,
63-
IonGrid,
6485
IonPage,
6586
IonHeader,
87+
IonFab,
88+
IonFabButton,
6689
IonIcon,
67-
IonImg,
68-
IonRow,
69-
IonTitle,
7090
IonToolbar,
91+
IonTitle,
92+
IonContent,
93+
IonGrid,
94+
IonRow,
95+
IonCol,
96+
IonImg,
7197
} from '@ionic/vue';
72-
import { camera, trash, close } from 'ionicons/icons';
98+
// CHANGE: Add `usePhotoGallery` import.
7399
import { usePhotoGallery } from '@/composables/usePhotoGallery';
74100
101+
// CHANGE: Destructure `takePhoto` from `usePhotoGallery().
75102
const { takePhoto } = usePhotoGallery();
76103
</script>
77104
```
@@ -86,68 +113,190 @@ After taking a photo, it disappears right away. We still need to display it with
86113

87114
## Displaying Photos
88115

89-
First we will create a new type to define our Photo, which will hold specific metadata. Add the following UserPhoto interface to the `usePhotoGallery.ts` file, somewhere outside of the main function:
116+
First we will create a new type to define our Photo, which will hold specific metadata. Back in `usePhotoGallery.ts`, add the following `UserPhoto` interface below the main function:
90117

91-
```tsx
118+
```typescript
119+
export const usePhotoGallery = () => {
120+
// Same old code from before.
121+
};
122+
123+
// CHANGE: Add the `UserPhoto` interface.
92124
export interface UserPhoto {
93125
filepath: string;
94126
webviewPath?: string;
95127
}
96128
```
97129

98-
At the top of the `usePhotoGallery` function, define an array so we can store each photo captured with the Camera. Make it a reactive variable using Vue's [ref function](https://v3.vuejs.org/guide/composition-api-introduction.html#reactive-variables-with-ref).
130+
At the top of the `usePhotoGallery` function, define an array so we can store each photo captured with the Camera. Make it a reactive variable using Vue's [ref function](https://vuejs.org/api/reactivity-core.html#ref).
99131

100-
```tsx
101-
const photos = ref<UserPhoto[]>([]);
132+
```typescript
133+
export const usePhotoGallery = () => {
134+
// CHANGE: Add the `photos` array.
135+
const photos = ref<UserPhoto[]>([]);
136+
137+
// other code
138+
};
102139
```
103140

104-
When the camera is done taking a picture, the resulting `Photo` returned from Capacitor will be added to the `photos` array. Update the `takePhoto` function, adding this code after the `Camera.getPhoto` line:
141+
When the camera is done taking a picture, the resulting `Photo` returned from Capacitor will be added to the `photos` array. Update the `takePhoto` function with the following:
105142

106-
```tsx
107-
const fileName = Date.now() + '.jpeg';
108-
const savedFileImage = {
109-
filepath: fileName,
110-
webviewPath: photo.webPath,
111-
};
143+
```typescript
144+
const takePhoto = async () => {
145+
const photo = await Camera.getPhoto({
146+
resultType: CameraResultType.Uri,
147+
source: CameraSource.Camera,
148+
quality: 100,
149+
});
150+
// CHANGE: Create the `fileName` with current timestamp.
151+
const fileName = Date.now() + '.jpeg';
152+
// CHANGE: Create `savedFileImage` matching `UserPhoto` interface.
153+
const savedFileImage = {
154+
filepath: fileName,
155+
webviewPath: photo.webPath,
156+
};
112157

113-
photos.value = [savedFileImage, ...photos.value];
158+
// CHANGE: Update the `photos` array with the new photo.
159+
photos.value = [savedFileImage, ...photos.value];
160+
};
114161
```
115162

116-
Next, update the return statement to include the photos array:
163+
Next, update the `userPhotoGallery` return statement to include the `photos` array:
117164

118-
```tsx
119-
return {
120-
photos,
121-
takePhoto,
165+
```typescript
166+
export const usePhotoGallery = () => {
167+
// other code
168+
169+
// CHANGE: Update return statement to include `photos` array.
170+
return {
171+
photos,
172+
takePhoto
173+
};
122174
};
123175
```
124176

125-
Back in the Tab2 component, update the import statement to include the `UserPhoto` interface:
177+
`usePhotoGallery.ts` should now look like this:
126178

127-
```tsx
128-
import { usePhotoGallery, UserPhoto } from '@/composables/usePhotoGallery';
179+
```typescript
180+
import { ref, onMounted, watch } from 'vue';
181+
import { Camera, CameraResultType, CameraSource, Photo } from '@capacitor/camera';
182+
import { Filesystem, Directory } from '@capacitor/filesystem';
183+
import { Preferences } from '@capacitor/preferences';
184+
185+
export const usePhotoGallery = () => {
186+
const photos = ref<UserPhoto[]>([]);
187+
188+
const takePhoto = async () => {
189+
const photo = await Camera.getPhoto({
190+
resultType: CameraResultType.Uri,
191+
source: CameraSource.Camera,
192+
quality: 100,
193+
});
194+
const fileName = Date.now() + '.jpeg';
195+
const savedFileImage = {
196+
filepath: fileName,
197+
webviewPath: photo.webPath,
198+
};
199+
200+
photos.value = [savedFileImage, ...photos.value];
201+
};
202+
203+
return {
204+
photos,
205+
takePhoto
206+
};
207+
};
208+
209+
export interface UserPhoto {
210+
filepath: string;
211+
webviewPath?: string;
212+
}
129213
```
130214

131-
Then, get access to the photos array:
215+
Back in `Tab2Page.vue`, update the import statement to include the `UserPhoto` interface and get access to the `photos` array:
132216

133-
```tsx
217+
```html
218+
<template>
219+
<!-- template code -->
220+
</template>
221+
222+
<script setup lang="ts">
223+
import { camera, trash, close } from 'ionicons/icons';
224+
import {
225+
IonPage,
226+
IonHeader,
227+
IonFab,
228+
IonFabButton,
229+
IonIcon,
230+
IonToolbar,
231+
IonTitle,
232+
IonContent,
233+
IonGrid,
234+
IonRow,
235+
IonCol,
236+
IonImg,
237+
} from '@ionic/vue';
238+
// CHANGE: Update import to include `UserPhoto` interface.
239+
import { usePhotoGallery, UserPhoto } from '@/composables/usePhotoGallery';
240+
241+
// CHANGE: Add `photos` array to destructure from `usePhotoGallery()`.
134242
const { photos, takePhoto } = usePhotoGallery();
243+
</script>
135244
```
136245

137246
With the photo(s) stored into the main array we can now display the images on the screen. Add a [Grid component](https://ionicframework.com/docs/api/grid) so that each photo will display nicely as they are added to the gallery, and loop through each photo in the Photos array, adding an Image component (`<ion-img>`) for each. Point the `src` (source) to the photo's path:
138247

139-
```tsx
140-
<ion-content>
141-
<ion-grid>
142-
<ion-row>
143-
<ion-col size="6" :key="photo.filepath" v-for="photo in photos">
144-
<ion-img :src="photo.webviewPath"></ion-img>
145-
</ion-col>
146-
</ion-row>
147-
</ion-grid>
148-
149-
<!-- <ion-fab> markup -->
150-
</ion-content>
248+
```html
249+
<template>
250+
<ion-page>
251+
<ion-header>
252+
<ion-toolbar>
253+
<ion-title>Photo Gallery</ion-title>
254+
</ion-toolbar>
255+
</ion-header>
256+
<ion-content :fullscreen="true">
257+
<ion-header collapse="condense">
258+
<ion-toolbar>
259+
<ion-title size="large">Photo Gallery</ion-title>
260+
</ion-toolbar>
261+
</ion-header>
262+
<!-- CHANGE: Add a grid component to display the photos. -->
263+
<ion-grid>
264+
<ion-row>
265+
<!-- CHANGE: Create a new column and image component for each photo. -->
266+
<ion-col size="6" :key="photo.filepath" v-for="photo in photos">
267+
<ion-img :src="photo.webviewPath"></ion-img>
268+
</ion-col>
269+
</ion-row>
270+
</ion-grid>
271+
<ion-fab vertical="bottom" horizontal="center" slot="fixed">
272+
<ion-fab-button @click="takePhoto()">
273+
<ion-icon :icon="camera"></ion-icon>
274+
</ion-fab-button>
275+
</ion-fab>
276+
</ion-content>
277+
</ion-page>
278+
</template>
279+
280+
<script setup lang="ts">
281+
import { camera, trash, close } from 'ionicons/icons';
282+
import {
283+
IonPage,
284+
IonHeader,
285+
IonFab,
286+
IonFabButton,
287+
IonIcon,
288+
IonToolbar,
289+
IonTitle,
290+
IonContent,
291+
IonGrid,
292+
IonRow,
293+
IonCol,
294+
IonImg,
295+
} from '@ionic/vue';
296+
import { usePhotoGallery, UserPhoto } from '@/composables/usePhotoGallery';
297+
298+
const { photos, takePhoto } = usePhotoGallery();
299+
</script>
151300
```
152301

153302
Save all files. Within the web browser, click the Camera button and take another photo. This time, the photo is displayed in the Photo Gallery!

0 commit comments

Comments
 (0)