Browse Source

change the photo ratios to fix all but portrait-orientation on mobile-emulation

kb/add-usage-guide
Trent Larson 8 months ago
parent
commit
c49c55d394
  1. 2
      CHANGELOG.md
  2. 2
      README.md
  3. 4
      package-lock.json
  4. 2
      package.json
  5. 2
      project.task.yaml
  6. 105
      src/components/GiftedPhotoDialog.vue

2
CHANGELOG.md

@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Nothing - Nothing
## [0.3.2] - 2024.03.17 ## [0.3.3] - 2024.03.18
### Added ### Added
- Photo on gift record - Photo on gift record
### Fixed ### Fixed

2
README.md

@ -42,7 +42,7 @@ npm run lint
``` ```
# (See .env.development for more details.) # (See .env.development for more details.)
# The test BVC_MEETUPS_PROJECT_CLAIM_ID does not resolve as a URL because it's only in the test DB and the prod redirect won't redirect there. # The test BVC_MEETUPS_PROJECT_CLAIM_ID does not resolve as a URL because it's only in the test DB and the prod redirect won't redirect there.
APP_TITLE="TimeSafari_Test" VUE_APP_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HNTZYJJXTGT0EZS3VEJGX7AK VUE_APP_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch VUE_APP_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app npm run build TIME_SAFARI_APP_TITLE="TimeSafari_Test" VUE_APP_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HNTZYJJXTGT0EZS3VEJGX7AK VUE_APP_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch VUE_APP_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app npm run build
``` ```
* Production * Production

4
package-lock.json

@ -1,12 +1,12 @@
{ {
"name": "TimeSafari", "name": "TimeSafari",
"version": "0.3.2", "version": "0.3.3",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "TimeSafari", "name": "TimeSafari",
"version": "0.3.2", "version": "0.3.3",
"dependencies": { "dependencies": {
"@dicebear/collection": "^5.3.5", "@dicebear/collection": "^5.3.5",
"@dicebear/core": "^5.3.5", "@dicebear/core": "^5.3.5",

2
package.json

@ -1,6 +1,6 @@
{ {
"name": "TimeSafari", "name": "TimeSafari",
"version": "0.3.2", "version": "0.3.3",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve",

2
project.task.yaml

@ -1,6 +1,8 @@
tasks : tasks :
- bug - landscape doesn't show full camera
- but - portrait stretches pic
- bug maybe - a new give remembers the previous project - bug maybe - a new give remembers the previous project
- alert & stop if give amount < 0 - alert & stop if give amount < 0
- onboarding video - onboarding video

105
src/components/GiftedPhotoDialog.vue

@ -13,7 +13,7 @@
</div> </div>
<!-- Heading --> <!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4"> <h1 id="ViewHeading" class="text-center font-bold">
<span v-if="uploading"> Uploading... </span> <span v-if="uploading"> Uploading... </span>
<span v-else-if="blob"> Look Good? </span> <span v-else-if="blob"> Look Good? </span>
<span v-else> Say "Cheese"! </span> <span v-else> Say "Cheese"! </span>
@ -30,6 +30,7 @@
> >
<span>Upload</span> <span>Upload</span>
</button> </button>
<!--{{ imageHeight }} {{ imageWidth }} {{ imageWarning }}-->
<button <button
@click="retryImage" @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-2 rounded-full"
@ -37,16 +38,20 @@
<span>Retry</span> <span>Retry</span>
</button> </button>
</div> </div>
<img :src="URL.createObjectURL(blob)" class="mt-2 w-full" /> <div
:style="'height: ' + imageHeight + 'px; width: ' + imageWidth + 'px;'"
>
<img :src="URL.createObjectURL(blob)" class="mt-2" />
</div>
</div> </div>
<div v-else> <div v-else>
<!-- <!--
Camera "resolution" doesn't change how it shows on screen but rather stretches the result, eg the following which just stretches it vertically: Camera "resolution" doesn't change how it shows on screen but rather stretches the result, eg the following which just stretches it vertically:
:resolution="{ width: 375, height: 812 }" :resolution="{ width: 375, height: 812 }"
It even messes up when trying to match the ratio with imageHeight and imageWidth.
--> -->
<camera facingMode="environment" autoplay ref="camera"> <camera facingMode="environment" autoplay ref="camera">
<div class="absolute bottom-0 w-full flex justify-center pb-4"> <div class="absolute top-0 w-full flex justify-center pb-4">
<!-- Button -->
<button <button
@click="takeImage" @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 py-2 px-2 rounded-full"
@ -78,6 +83,9 @@ export default class GiftedPhotoDialog extends Vue {
activeDid = ""; activeDid = "";
blob: Blob | null = null; blob: Blob | null = null;
setImage: (arg: string) => void = () => {}; setImage: (arg: string) => void = () => {};
imageHeight?: number = window.innerHeight / 2;
imageWidth?: number = window.innerWidth / 2;
imageWarning = ".";
uploading = false; uploading = false;
visible = false; visible = false;
@ -115,7 +123,55 @@ export default class GiftedPhotoDialog extends Vue {
async takeImage(/* payload: MouseEvent */) { async takeImage(/* payload: MouseEvent */) {
const cameraComponent = this.$refs.camera as InstanceType<typeof Camera>; const cameraComponent = this.$refs.camera as InstanceType<typeof Camera>;
this.blob = await cameraComponent?.snapshot(); // png is default; if that changes, change extension in formData.append console.log("cameraComponent", cameraComponent, cameraComponent.resolution);
this.imageHeight = cameraComponent?.resolution?.height;
this.imageWidth = cameraComponent?.resolution?.width;
const initialImageRatio = this.imageWidth / this.imageHeight;
console.log(
"initialImageRatio",
initialImageRatio,
this.imageWidth,
this.imageHeight,
);
const windowRatio = window.innerWidth / window.innerHeight;
console.log(
"windowRatio",
windowRatio,
window.innerWidth,
window.innerHeight,
);
if (initialImageRatio > 1 && windowRatio < 1) {
this.imageWarning = "?";
// For some reason, mobile in portrait orientation renders a horizontally-stretched image.
// We're gonna force it opposite.
this.imageHeight = cameraComponent?.resolution?.width;
this.imageWidth = cameraComponent?.resolution?.height;
} else if (initialImageRatio < 1 && windowRatio > 1) {
// Haven't seen this happen, but just in case.
this.imageWarning = "??";
this.imageHeight = cameraComponent?.resolution?.width;
this.imageWidth = cameraComponent?.resolution?.height;
}
const newImageRatio = this.imageWidth / this.imageHeight;
console.log(
"newImageRatio",
newImageRatio,
this.imageWidth,
this.imageHeight,
);
if (newImageRatio < windowRatio) {
this.imageHeight = window.innerHeight / 2;
this.imageWidth = this.imageHeight * newImageRatio;
} else {
this.imageWidth = window.innerWidth / 2;
this.imageHeight = this.imageWidth / newImageRatio;
}
// The resolution is only necessary because of that mobile portrait-orientation case.
// But setting this screws up desktop the mobile emulation.
this.blob = await cameraComponent?.snapshot({
height: this.imageHeight,
width: this.imageWidth,
}); // png is default; if that changes, change extension in formData.append
if (!this.blob) { if (!this.blob) {
this.$notify( this.$notify(
{ {
@ -134,6 +190,45 @@ export default class GiftedPhotoDialog extends Vue {
this.blob = null; this.blob = null;
} }
/****
Here's an approach without a library, which works similarly and looks ugly.
<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() {
const video = document.querySelector("#video");
const canvas = document.querySelector("#canvas");
console.log("snap_photo clicked");
if (
canvas instanceof HTMLCanvasElement &&
video instanceof HTMLVideoElement
) {
canvas
?.getContext("2d")
?.drawImage(video, 0, 0, canvas.width, canvas.height);
const image_data_url = canvas?.toDataURL("image/jpeg");
// data url of the image
console.log(image_data_url);
}
}
****/
async uploadImage() { async uploadImage() {
this.uploading = true; this.uploading = true;
const identifier = await getIdentity(this.activeDid); const identifier = await getIdentity(this.activeDid);

Loading…
Cancel
Save