mirror of
https://github.com/MarcZierle/photo-log-frontend.git
synced 2025-04-07 13:04:37 +00:00
implement photo cropping - simple bbox
This commit is contained in:
parent
a9c8e2cbda
commit
2fa9b70bc2
@ -88,4 +88,8 @@ export function updatePhoto(photo) {
|
||||
|
||||
export function deletePhoto(id) {
|
||||
return apiClient.delete('/deletephoto/'+id+'/')
|
||||
}
|
||||
|
||||
export function cropPhoto(id, mode) {
|
||||
return apiClient.get('/cropphoto/'+id+'/?mode='+mode)
|
||||
}
|
@ -1,13 +1,28 @@
|
||||
<template>
|
||||
<div>
|
||||
<cropper
|
||||
class="cropper"
|
||||
:src="src"
|
||||
:stencil-props="{
|
||||
aspectRatio: 1/1.41421356
|
||||
}"
|
||||
@change="change"
|
||||
/>
|
||||
<n-space justify="start">
|
||||
<cropper
|
||||
class="cropper"
|
||||
:src="src"
|
||||
:stencil-props="aspect_ratio"
|
||||
:auto-zoom="true"
|
||||
@change="change"
|
||||
ref="cropper"
|
||||
/>
|
||||
|
||||
<n-space vertical justify="space-between">
|
||||
<div>
|
||||
<h2>Preview</h2>
|
||||
<n-image
|
||||
class="preview"
|
||||
height="200"
|
||||
:src="preview_data_url"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<n-checkbox v-model:checked="lock_aspect_ratio">lock aspect ratio to flip chart size?</n-checkbox>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -28,15 +43,48 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
preview_data_url: null,
|
||||
lock_aspect_ratio: true,
|
||||
bbox: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
console.log(this.src)
|
||||
computed: {
|
||||
aspect_ratio() {
|
||||
if (this.lock_aspect_ratio) {
|
||||
return {
|
||||
aspectRatio: 1/1.41421356
|
||||
}
|
||||
}
|
||||
return {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
coordinates_to_bbox(coordinates) {
|
||||
let top_left = [
|
||||
coordinates.left,
|
||||
coordinates.top
|
||||
]
|
||||
let top_right = [
|
||||
coordinates.left + coordinates.width,
|
||||
coordinates.top
|
||||
]
|
||||
let bottom_right = [
|
||||
coordinates.left + coordinates.width,
|
||||
coordinates.top + coordinates.height
|
||||
]
|
||||
let bottom_left = [
|
||||
coordinates.left,
|
||||
coordinates.top + coordinates.height
|
||||
]
|
||||
|
||||
return [top_left, top_right, bottom_right, bottom_left]
|
||||
},
|
||||
change({ coordinates, canvas }) {
|
||||
console.log(coordinates, canvas)
|
||||
this.preview_data_url = canvas.toDataURL()
|
||||
this.bbox = this.coordinates_to_bbox(coordinates)
|
||||
},
|
||||
getResult() {
|
||||
return JSON.parse(JSON.stringify(this.bbox))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -48,4 +96,8 @@ export default {
|
||||
width: 600px;
|
||||
background: #DDD;
|
||||
}
|
||||
|
||||
.preview {
|
||||
max-width: 300px;
|
||||
}
|
||||
</style>
|
@ -105,11 +105,16 @@ export default {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 150,
|
||||
}
|
||||
},
|
||||
init_selection: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
emits: [
|
||||
'update:select',
|
||||
'update:delet',
|
||||
'update:delete',
|
||||
'update:crop',
|
||||
'update:ocr',
|
||||
'update:group',
|
||||
@ -126,6 +131,9 @@ export default {
|
||||
beforeMount() {
|
||||
this.imgSrcObj = new Image()
|
||||
this.imgSrcObj.src = this.src
|
||||
if (this.can_select && this.init_selection) {
|
||||
this.selected = true
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
imgSrcObj: {
|
||||
@ -202,6 +210,7 @@ export default {
|
||||
toggleSelection() {
|
||||
if (this.can_select) {
|
||||
this.selected = !this.selected
|
||||
this.$emit('update:select', this.selected)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -27,18 +27,18 @@
|
||||
:title="group.name"
|
||||
:name="group.id">
|
||||
|
||||
<n-image-group>
|
||||
<n-space>
|
||||
<n-image
|
||||
<PhotoItem
|
||||
v-for="photo in photos[group.id]"
|
||||
:key="photo.id"
|
||||
width="100"
|
||||
:src="photo.cropped_image !== null ? photo.cropped_image : photo.original_image"
|
||||
@click="toggle_select_photo(photo.id)"
|
||||
:class="{selected: is_photo_selected(photo.id)}"
|
||||
preview-disabled />
|
||||
:can_select="true"
|
||||
:init_selection="is_photo_selected(photo.id)"
|
||||
@update:select="toggle_select_photo(photo.id)"
|
||||
:ref="'photoitem-'+photo.id"
|
||||
/>
|
||||
</n-space>
|
||||
</n-image-group>
|
||||
|
||||
<template #header-extra>{{group.date}}</template>
|
||||
</n-collapse-item>
|
||||
@ -57,13 +57,13 @@
|
||||
<script>
|
||||
import { useMessage } from 'naive-ui'
|
||||
|
||||
//import PhotoItem from '@/components/PhotoItem'
|
||||
import PhotoItem from '@/components/PhotoItem'
|
||||
|
||||
export default {
|
||||
name: 'PhotoSelectModal',
|
||||
emits: [ 'closed', 'selected' ],
|
||||
components: {
|
||||
//PhotoItem
|
||||
PhotoItem
|
||||
},
|
||||
props: {
|
||||
showSelection: {
|
||||
@ -140,6 +140,7 @@ export default {
|
||||
if (this.selecions_left > 0) {
|
||||
this.selection.push(photo_id)
|
||||
} else {
|
||||
this.$refs['photoitem-'+photo_id][0].selected = false
|
||||
this.message.error('You can only select ' + this.max_select + ' photo(s)')
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
getPhotosByGroup,
|
||||
updatePhoto,
|
||||
deletePhoto,
|
||||
cropPhoto,
|
||||
} from '@/api'
|
||||
|
||||
export default createStore({
|
||||
@ -167,7 +168,20 @@ export default createStore({
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
cropPhoto({commit}, {id, mode}) {
|
||||
new Promise((resolve, reject) => {
|
||||
cropPhoto(id, mode).then((response) => {
|
||||
commit('UPDATE_PHOTO', {
|
||||
id: response.data.id,
|
||||
cropped_image: response.data.cropped_image
|
||||
})
|
||||
resolve()
|
||||
}).catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
getters: {
|
||||
photoLogById: (state) => (id) => {
|
||||
|
@ -16,7 +16,9 @@
|
||||
<n-space justify="space-around" >
|
||||
<n-space vertical>
|
||||
<h2>Documents</h2>
|
||||
<n-button type="primary">All Documents</n-button>
|
||||
<a target="_blank" href='https://dev.marczierle.com/zierle-training/generate_document/modify_document.php?selection=0'>
|
||||
<n-button type="primary">All Documents</n-button>
|
||||
</a>
|
||||
</n-space>
|
||||
<n-space vertical>
|
||||
<h2>Photo Logs</h2>
|
||||
|
@ -4,6 +4,7 @@
|
||||
<n-table :bordered="false" :single-line="true">
|
||||
<thead>
|
||||
<th>Photo Log Title</th>
|
||||
<th>PDF</th>
|
||||
<th>Date created</th>
|
||||
<th>delete</th>
|
||||
</thead>
|
||||
@ -12,6 +13,9 @@
|
||||
<router-link :to="{name: 'CreateLog', params: {e: photolog.id}}">
|
||||
<td>{{ photolog.title }}</td>
|
||||
</router-link>
|
||||
<td>
|
||||
<a :href="photolog.pdf" target="_blank">PDF</a>
|
||||
</td>
|
||||
<td>{{ photolog.date }}</td>
|
||||
<td>
|
||||
<n-button type="error" @click="askDeleteLog(photolog.id)">Delete</n-button>
|
||||
|
@ -40,15 +40,17 @@
|
||||
title="Adjust Photo Cropping"
|
||||
:bordered="true"
|
||||
>
|
||||
<template #header-extra> Header </template>
|
||||
|
||||
<PhotoCropper :src="current_photo_src" />
|
||||
|
||||
<template #footer> Footer </template>
|
||||
<PhotoCropper
|
||||
style="max-width:900px;margin:auto;"
|
||||
:src="current_photo_src"
|
||||
ref="cropper"
|
||||
/>
|
||||
|
||||
<template #action>
|
||||
<n-space justify="end">
|
||||
<n-button @click="showCropModal = false">Cancel</n-button>
|
||||
<n-button type="primary">Save</n-button>
|
||||
<n-button type="primary" @click="changeCrop">Save</n-button>
|
||||
</n-space>
|
||||
</template>
|
||||
</n-card>
|
||||
@ -242,6 +244,25 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
changeCrop() {
|
||||
let bbox = this.$refs.cropper.getResult()
|
||||
if (bbox && this.current_photo) {
|
||||
this.$store.dispatch('updatePhoto', {
|
||||
id: this.current_photo,
|
||||
bbox_coords: bbox
|
||||
}).then(()=>{
|
||||
setTimeout(()=>{
|
||||
this.$store.dispatch('cropPhoto', {
|
||||
id: this.current_photo,
|
||||
mode: 'bbox'
|
||||
}).then(()=>{
|
||||
this.current_photo = null
|
||||
this.showCropModal = false
|
||||
})
|
||||
}, 100)
|
||||
})
|
||||
}
|
||||
},
|
||||
changeOCRText(){
|
||||
if (this.current_ocr_text.length !== null && this.current_photo) {
|
||||
this.$store.dispatch('updatePhoto', {
|
||||
|
Loading…
Reference in New Issue
Block a user