improve MediaInput focalpoint selector
This commit is contained in:
@@ -4,13 +4,19 @@
|
|||||||
v-card
|
v-card
|
||||||
v-card-title {{$t('common.media')}}
|
v-card-title {{$t('common.media')}}
|
||||||
v-card-text
|
v-card-text
|
||||||
v-row
|
v-row.mt-1
|
||||||
v-col(:span='4' :cols='4')
|
v-col#focalPointSelector(
|
||||||
|
@mousedown='handleStart' @touchstart='handleStart'
|
||||||
|
@mousemove='handleMove' @touchmove='handleMove'
|
||||||
|
@mouseup='handleStop' @touchend='handleStop'
|
||||||
|
)
|
||||||
|
div.focalPoint(:style="{ top, left }")
|
||||||
|
img(v-if='mediaPreview' :src='mediaPreview')
|
||||||
|
|
||||||
|
v-col.col-12.col-sm-4
|
||||||
p {{$t('event.choose_focal_point')}}
|
p {{$t('event.choose_focal_point')}}
|
||||||
v-img(v-if='mediaPreview'
|
img.img.d-none.d-sm-block(v-if='mediaPreview'
|
||||||
:src='mediaPreview'
|
:src='mediaPreview' :style="{ 'object-position': position }")
|
||||||
aspect-ratio='1.7778'
|
|
||||||
:position="position")
|
|
||||||
|
|
||||||
v-textarea.mt-4(type='text'
|
v-textarea.mt-4(type='text'
|
||||||
label='Alternative text'
|
label='Alternative text'
|
||||||
@@ -23,18 +29,13 @@
|
|||||||
v-btn(text @click='openMediaDetails=false' color='warning') Cancel
|
v-btn(text @click='openMediaDetails=false' color='warning') Cancel
|
||||||
v-btn(text color='primary' @click='save') Save
|
v-btn(text color='primary' @click='save') Save
|
||||||
|
|
||||||
v-col(:span='8' :cols='8')
|
|
||||||
v-img.cursorPointer(
|
|
||||||
v-if='mediaPreview' :src='mediaPreview'
|
|
||||||
@click='selectFocal')
|
|
||||||
|
|
||||||
h3.mb-3.font-weight-regular(v-if='mediaPreview') {{$t('common.media')}}
|
h3.mb-3.font-weight-regular(v-if='mediaPreview') {{$t('common.media')}}
|
||||||
v-card-actions(v-if='mediaPreview')
|
v-card-actions(v-if='mediaPreview')
|
||||||
v-spacer
|
v-spacer
|
||||||
v-btn(text color='primary' @click='openMediaDetails = true') {{$t('common.edit')}}
|
v-btn(text color='primary' @click='openMediaDetails = true') {{$t('common.edit')}}
|
||||||
v-btn(text color='error' @click='remove') {{$t('common.remove')}}
|
v-btn(text color='error' @click='remove') {{$t('common.remove')}}
|
||||||
div(v-if='mediaPreview')
|
div(v-if='mediaPreview')
|
||||||
v-img.col-12.col-sm-2.ml-3(:src='mediaPreview' aspect-ratio='1.7778' :position='savedPosition')
|
img.img.col-12.ml-3(:src='mediaPreview' :style="{ 'object-position': savedPosition }")
|
||||||
span.float-right {{event.media[0].name}}
|
span.float-right {{event.media[0].name}}
|
||||||
v-file-input(
|
v-file-input(
|
||||||
v-else
|
v-else
|
||||||
@@ -57,7 +58,8 @@ export default {
|
|||||||
return {
|
return {
|
||||||
openMediaDetails: false,
|
openMediaDetails: false,
|
||||||
name: this.value.name || '',
|
name: this.value.name || '',
|
||||||
focalpoint: this.value.focalpoint || [0, 0]
|
focalpoint: this.value.focalpoint || [0, 0],
|
||||||
|
dragging: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -68,6 +70,12 @@ export default {
|
|||||||
const url = this.value.image ? URL.createObjectURL(this.value.image) : /^https?:\/\//.test(this.value.url) ? this.value.url : `/media/thumb/${this.value.url}`
|
const url = this.value.image ? URL.createObjectURL(this.value.image) : /^https?:\/\//.test(this.value.url) ? this.value.url : `/media/thumb/${this.value.url}`
|
||||||
return url
|
return url
|
||||||
},
|
},
|
||||||
|
top () {
|
||||||
|
return ((this.focalpoint[1] + 1) * 50) + '%'
|
||||||
|
},
|
||||||
|
left () {
|
||||||
|
return ((this.focalpoint[0] + 1) * 50) + '%'
|
||||||
|
},
|
||||||
savedPosition () {
|
savedPosition () {
|
||||||
const focalpoint = this.value.focalpoint || [0, 0]
|
const focalpoint = this.value.focalpoint || [0, 0]
|
||||||
return `${(focalpoint[0] + 1) * 50}% ${(focalpoint[1] + 1) * 50}%`
|
return `${(focalpoint[0] + 1) * 50}% ${(focalpoint[1] + 1) * 50}%`
|
||||||
@@ -90,22 +98,39 @@ export default {
|
|||||||
selectMedia (v) {
|
selectMedia (v) {
|
||||||
this.$emit('input', { image: v, name: v.name, focalpoint: [0, 0] })
|
this.$emit('input', { image: v, name: v.name, focalpoint: [0, 0] })
|
||||||
},
|
},
|
||||||
selectFocal (ev) {
|
handleStart (ev) {
|
||||||
const boundingClientRect = ev.target.getBoundingClientRect()
|
ev.preventDefault()
|
||||||
|
this.dragging = true
|
||||||
|
this.handleMove(ev, true)
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
handleStop (ev) {
|
||||||
|
this.dragging = false
|
||||||
|
},
|
||||||
|
handleMove (ev, manual = false) {
|
||||||
|
if (!this.dragging && !manual) return
|
||||||
|
ev.stopPropagation()
|
||||||
|
const boundingClientRect = document.getElementById('focalPointSelector').getBoundingClientRect()
|
||||||
|
|
||||||
|
const clientX = ev.changedTouches ? ev.changedTouches[0].clientX : ev.clientX
|
||||||
|
const clientY = ev.changedTouches ? ev.changedTouches[0].clientY : ev.clientY
|
||||||
|
|
||||||
// get relative coordinate
|
// get relative coordinate
|
||||||
let x = Math.ceil(ev.clientX - boundingClientRect.left)
|
let x = Math.ceil(clientX - boundingClientRect.left)
|
||||||
let y = Math.ceil(ev.clientY - boundingClientRect.top)
|
let y = Math.ceil(clientY - boundingClientRect.top)
|
||||||
|
|
||||||
// snap to border
|
// snap to border
|
||||||
x = x < 20 ? 0 : x > boundingClientRect.width - 20 ? boundingClientRect.width : x
|
x = x < 30 ? 0 : x > boundingClientRect.width - 30 ? boundingClientRect.width : x
|
||||||
y = y < 20 ? 0 : y > boundingClientRect.height - 20 ? boundingClientRect.height : y
|
y = y < 30 ? 0 : y > boundingClientRect.height - 30 ? boundingClientRect.height : y
|
||||||
|
|
||||||
|
// this.relativeFocalpoint = [x + 'px', y + 'px']
|
||||||
|
|
||||||
// map to real image coordinate
|
// map to real image coordinate
|
||||||
const posY = -1 + (y / boundingClientRect.height) * 2
|
const posY = -1 + (y / boundingClientRect.height) * 2
|
||||||
const posX = -1 + (x / boundingClientRect.width) * 2
|
const posX = -1 + (x / boundingClientRect.width) * 2
|
||||||
|
|
||||||
this.focalpoint = [posX, posY]
|
this.focalpoint = [posX, posY]
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,4 +140,36 @@ export default {
|
|||||||
cursor: crosshair;
|
cursor: crosshair;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.img {
|
||||||
|
width: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
object-position: top;
|
||||||
|
aspect-ratio: 1.7778;
|
||||||
|
}
|
||||||
|
|
||||||
|
#focalPointSelector {
|
||||||
|
position: relative;
|
||||||
|
cursor: move;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
justify-self: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#focalPointSelector img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focalPoint {
|
||||||
|
position: absolute;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
top: 100px;
|
||||||
|
left: 100px;
|
||||||
|
transform: translate(-25px, -25px);
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1px solid #ff6d408e;
|
||||||
|
box-shadow: 0 0 0 9999em rgba(0, 0, 0, .65);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user