Skip to content

Commit

Permalink
Merge pull request #36 from nextcloud/enhancement/zooming
Browse files Browse the repository at this point in the history
Zoom scrolling enhancement
  • Loading branch information
jancborchardt authored Mar 14, 2019
2 parents b00631f + e382fc6 commit 05fae96
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 5 deletions.
143 changes: 140 additions & 3 deletions src/components/Images.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,21 @@

<template>
<img
:class="{
dragging,
zoomed: zoomRatio !== 1
}"
:src="data"
:style="{
height: height + 'px',
width: width + 'px'
height: zoomHeight + 'px',
width: zoomWidth + 'px',
marginTop: shiftY + 'px',
marginLeft: shiftX + 'px'
}"
@load="updateImgSize">
@load="updateImgSize"
@wheel="updateZoom"
@dblclick="resetZoom"
@mousedown="dragStart">
</template>

<script>
Expand All @@ -44,6 +53,22 @@ export default {
mixins: [
mime
],
data() {
return {
dragging: false,
shiftX: 0,
shiftY: 0,
zoomRatio: 1
}
},
computed: {
zoomHeight() {
return Math.round(this.height * this.zoomRatio)
},
zoomWidth() {
return Math.round(this.width * this.zoomRatio)
}
},
asyncComputed: {
data() {
if (this.mime !== 'image/svg+xml') {
Expand All @@ -52,10 +77,21 @@ export default {
return this.getBase64FromImage()
}
},
watch: {
active: function(val, old) {
// the item was hidden before and is now the current view
if (val === true && old === false) {
this.resetZoom()
}
}
},
mounted() {
// update image size on window resize
window.addEventListener('resize', debounce(() => {
this.updateImgSize()
}, 100))
// end the dragging if your mouse go out of the content
window.addEventListener('mouseout', this.dragEnd)
},
methods: {
// Updates the dimensions of the modal
Expand All @@ -80,6 +116,90 @@ export default {
async getBase64FromImage() {
const file = await axios.get(this.path)
return `data:${this.mime};base64,${btoa(file.data)}`
},

/**
* Handle zooming
*
* @param {Event} event the scroll event
* @returns {null}
*/
updateZoom(event) {
event.stopPropagation()
event.preventDefault()

// scrolling position relative to the image
const scrollX = event.clientX - this.$el.x - (this.width * this.zoomRatio / 2)
const scrollY = event.clientY - this.$el.y - (this.height * this.zoomRatio / 2)
const scrollPercX = Math.round(scrollX / (this.width * this.zoomRatio) * 100) / 100
const scrollPercY = Math.round(scrollY / (this.height * this.zoomRatio) * 100) / 100
const isZoomIn = event.deltaY < 0

const newZoomRatio = isZoomIn
? Math.min(this.zoomRatio + 0.1, 5) // prevent too big zoom
: Math.max(this.zoomRatio - 0.1, 1) // prevent too small zoom

// do not continue, img is back to its original state
if (newZoomRatio === 1) {
return this.resetZoom()
}

// calc how much the img grow from its current size
// and adjust the margin accordingly
const growX = this.width * newZoomRatio - this.width * this.zoomRatio
const growY = this.height * newZoomRatio - this.height * this.zoomRatio

// compensate for existing margins
this.disableSwipe()
this.shiftX = this.shiftX + Math.round(-scrollPercX * growX)
this.shiftY = this.shiftY + Math.round(-scrollPercY * growY)
this.zoomRatio = newZoomRatio
},

resetZoom() {
this.enableSwipe()
this.zoomRatio = 1
this.shiftX = 0
this.shiftY = 0
},

/**
* Dragging handlers
*
* @param {Event} event the event
*/
dragStart(event) {
event.preventDefault()
const { pageX, pageY } = event

this.dragX = pageX
this.dragY = pageY
this.dragging = true
this.$el.onmouseup = this.dragEnd
this.$el.onmousemove = this.dragHandler
},
dragEnd(event) {
event.preventDefault()

this.dragging = false
this.$el.onmouseup = null
this.$el.onmousemove = null
},
dragHandler(event) {
event.preventDefault()
const { pageX, pageY } = event

if (this.dragging && this.zoomRatio > 1 && pageX > 0 && pageY > 0) {
const moveX = this.shiftX + (pageX - this.dragX)
const moveY = this.shiftY + (pageY - this.dragY)
const growX = this.zoomWidth - this.width
const growY = this.zoomHeight - this.height

this.shiftX = Math.min(Math.max(moveX, -growX / 2), growX / 2)
this.shiftY = Math.min(Math.max(moveY, -growY / 2), growX / 2)
this.dragX = pageX
this.dragY = pageY
}
}
}
}
Expand All @@ -94,6 +214,11 @@ img {
max-height: 100%;
align-self: center;
justify-self: center;
// animate zooming/resize
transition: height 100ms ease,
width 100ms ease,
margin-top 100ms ease,
margin-left 100ms ease;
&:hover {
background-image: linear-gradient(45deg, #{$checkered-color} 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, #{$checkered-color} 75%),
Expand All @@ -102,5 +227,17 @@ img {
background-size: 2 * $checkered-size 2 * $checkered-size;
background-position: 0 0, 0 0, -#{$checkered-size} -#{$checkered-size}, $checkered-size $checkered-size;
}
&.zoomed {
position: absolute;
max-height: none;
max-width: none;
z-index: 10010;
cursor: move;
}

&.dragging {
transition: none !important;
cursor: move;
}
}
</style>
10 changes: 10 additions & 0 deletions src/mixins/Mime.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export default {
mime: {
type: String,
required: true
},
canSwipe: {
type: Boolean,
default: true
}
},

Expand Down Expand Up @@ -93,6 +97,12 @@ export default {
this.width = contentWidth
}
}
},
enableSwipe() {
this.$emit('update:canSwipe', true)
},
disableSwipe() {
this.$emit('update:canSwipe', false)
}
}
}
7 changes: 5 additions & 2 deletions src/views/Viewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
:has-previous="hasPrevious"
:has-next="hasNext"
:title="currentFileName"
:disable-swipe="disableSwipe"
:enable-swipe="canSwipe"
:size="isMobile ? 'full' : 'large'"
:style="{width: showSidebar ? `calc(100% - ${sidebarWidth}px)` : null}"
@close="close"
Expand Down Expand Up @@ -60,6 +60,7 @@
:mime="currentFile.mime"
:path="getPath(currentFile)"
:active="true"
:can-swipe.sync="canSwipe"
class="file-view"
@loaded="doneLoading"
@error="currentFailed" />
Expand Down Expand Up @@ -119,7 +120,7 @@ export default {
showSidebar: false,
sidebarWidth: 0,

disableSwipe: false,
canSwipe: true,
failed: false,
loading: true,

Expand Down Expand Up @@ -506,6 +507,8 @@ export default {
width: auto !important;
border-radius: 0 !important;
background-color: white;
justify-content: center;
align-items: center;
}

// dark bg while loading to avoid flashing white screen
Expand Down

0 comments on commit 05fae96

Please sign in to comment.