feat(ImagePreview): fit window resize (#6760)

* feat(ImagePreview): fit window resize

* fix(ImagePreview): incorrect max move
This commit is contained in:
neverland 2020-07-11 11:25:57 +08:00 committed by GitHub
parent 7987287be0
commit 3748ab646c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 58 deletions

View File

@ -1,9 +1,11 @@
// Utils // Utils
import { inBrowser } from '../utils';
import { bem, createComponent } from './shared'; import { bem, createComponent } from './shared';
// Mixins // Mixins
import { PopupMixin } from '../mixins/popup'; import { PopupMixin } from '../mixins/popup';
import { TouchMixin } from '../mixins/touch'; import { TouchMixin } from '../mixins/touch';
import { BindEventMixin } from '../mixins/bind-event';
// Components // Components
import Icon from '../icon'; import Icon from '../icon';
@ -12,10 +14,13 @@ import ImagePreviewItem from './ImagePreviewItem';
export default createComponent({ export default createComponent({
mixins: [ mixins: [
TouchMixin,
PopupMixin({ PopupMixin({
skipToggleEvent: true, skipToggleEvent: true,
}), }),
TouchMixin, BindEventMixin(function (bind) {
bind(window, 'resize', this.resize, true);
}),
], ],
props: { props: {
@ -72,10 +77,16 @@ export default createComponent({
data() { data() {
return { return {
active: 0, active: 0,
windowWidth: 0,
windowHeight: 0,
doubleClickTimer: null, doubleClickTimer: null,
}; };
}, },
created() {
this.resize();
},
watch: { watch: {
startPosition: 'setActive', startPosition: 'setActive',
@ -95,6 +106,13 @@ export default createComponent({
}, },
methods: { methods: {
resize() {
if (inBrowser) {
this.windowWidth = window.innerWidth;
this.windowHeight = window.innerHeight;
}
},
emitClose() { emitClose() {
if (!this.asyncClose) { if (!this.asyncClose) {
this.$emit('input', false); this.$emit('input', false);
@ -151,6 +169,8 @@ export default createComponent({
active={this.active} active={this.active}
maxZoom={this.maxZoom} maxZoom={this.maxZoom}
minZoom={this.minZoom} minZoom={this.minZoom}
windowWidth={this.windowWidth}
windowHeight={this.windowHeight}
onScale={this.emitScale} onScale={this.emitScale}
onClose={this.emitClose} onClose={this.emitClose}
/> />

View File

@ -27,25 +27,30 @@ export default {
active: Number, active: Number,
minZoom: [Number, String], minZoom: [Number, String],
maxZoom: [Number, String], maxZoom: [Number, String],
windowWidth: Number,
windowHeight: Number,
}, },
data() { data() {
this.windowWidth = window.innerWidth;
this.windowHeight = window.innerHeight;
return { return {
scale: 1, scale: 1,
moveX: 0, moveX: 0,
moveY: 0, moveY: 0,
moving: false, moving: false,
zooming: false, zooming: false,
vertical: false, imageRatio: 0,
displayWidth: 0, displayWidth: 0,
displayHeight: 0, displayHeight: 0,
}; };
}, },
computed: { computed: {
vertical() {
const { windowWidth, windowHeight } = this;
const windowRatio = windowHeight / windowWidth;
return this.imageRatio > windowRatio;
},
imageStyle() { imageStyle() {
const { scale } = this; const { scale } = this;
const style = { const style = {
@ -62,22 +67,29 @@ export default {
}, },
maxMoveX() { maxMoveX() {
if (this.displayWidth) { if (this.imageRatio) {
return Math.max( const displayWidth = this.vertical
0, ? this.windowHeight / this.imageRatio
(this.scale * this.displayWidth - this.windowWidth) / 2 : this.windowWidth;
);
return Math.max(0, (this.scale * displayWidth - this.windowWidth) / 2);
} }
return 0; return 0;
}, },
maxMoveY() { maxMoveY() {
if (this.displayHeight) { if (this.imageRatio) {
const displayHeight = this.vertical
? this.windowHeight
: this.windowWidth * this.imageRatio;
return Math.max( return Math.max(
0, 0,
(this.scale * this.displayHeight - this.windowHeight) / 2 (this.scale * displayHeight - this.windowHeight) / 2
); );
} }
return 0; return 0;
}, },
}, },
@ -225,20 +237,8 @@ export default {
}, },
onLoad(event) { onLoad(event) {
const { windowWidth, windowHeight } = this;
const { naturalWidth, naturalHeight } = event.target; const { naturalWidth, naturalHeight } = event.target;
const windowRatio = windowHeight / windowWidth; this.imageRatio = naturalHeight / naturalWidth;
const imageRatio = naturalHeight / naturalWidth;
this.vertical = imageRatio > windowRatio;
if (this.vertical) {
this.displayWidth = windowHeight / imageRatio;
this.displayHeight = windowHeight;
} else {
this.displayWidth = windowWidth;
this.displayHeight = windowWidth * imageRatio;
}
}, },
}, },

31
src/mixins/bind-event.js Normal file
View File

@ -0,0 +1,31 @@
/**
* Bind event when mounted or activated
*/
import { on, off } from '../utils/dom/event';
let uid = 0;
export function BindEventMixin(handler) {
const key = `binded_${uid++}`;
function bind() {
if (!this[key]) {
handler.call(this, on, true);
this[key] = true;
}
}
function unbind() {
if (this[key]) {
handler.call(this, off, false);
this[key] = false;
}
}
return {
mounted: bind,
activated: bind,
deactivated: unbind,
beforeDestroy: unbind,
};
}

View File

@ -1,33 +0,0 @@
/**
* Bind event when mounted or activated
*/
import { on, off } from '../utils/dom/event';
type BindEventMixinThis = {
binded: boolean;
};
type BindEventHandler = (bind: Function, isBind: boolean) => void;
export function BindEventMixin(handler: BindEventHandler) {
function bind(this: BindEventMixinThis) {
if (!this.binded) {
handler.call(this, on, true);
this.binded = true;
}
}
function unbind(this: BindEventMixinThis) {
if (this.binded) {
handler.call(this, off, false);
this.binded = false;
}
}
return {
mounted: bind,
activated: bind,
deactivated: unbind,
beforeDestroy: unbind,
};
}