mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
feat(ImagePreview): fit window resize (#6760)
* feat(ImagePreview): fit window resize * fix(ImagePreview): incorrect max move
This commit is contained in:
parent
7987287be0
commit
3748ab646c
@ -1,9 +1,11 @@
|
||||
// Utils
|
||||
import { inBrowser } from '../utils';
|
||||
import { bem, createComponent } from './shared';
|
||||
|
||||
// Mixins
|
||||
import { PopupMixin } from '../mixins/popup';
|
||||
import { TouchMixin } from '../mixins/touch';
|
||||
import { BindEventMixin } from '../mixins/bind-event';
|
||||
|
||||
// Components
|
||||
import Icon from '../icon';
|
||||
@ -12,10 +14,13 @@ import ImagePreviewItem from './ImagePreviewItem';
|
||||
|
||||
export default createComponent({
|
||||
mixins: [
|
||||
TouchMixin,
|
||||
PopupMixin({
|
||||
skipToggleEvent: true,
|
||||
}),
|
||||
TouchMixin,
|
||||
BindEventMixin(function (bind) {
|
||||
bind(window, 'resize', this.resize, true);
|
||||
}),
|
||||
],
|
||||
|
||||
props: {
|
||||
@ -72,10 +77,16 @@ export default createComponent({
|
||||
data() {
|
||||
return {
|
||||
active: 0,
|
||||
windowWidth: 0,
|
||||
windowHeight: 0,
|
||||
doubleClickTimer: null,
|
||||
};
|
||||
},
|
||||
|
||||
created() {
|
||||
this.resize();
|
||||
},
|
||||
|
||||
watch: {
|
||||
startPosition: 'setActive',
|
||||
|
||||
@ -95,6 +106,13 @@ export default createComponent({
|
||||
},
|
||||
|
||||
methods: {
|
||||
resize() {
|
||||
if (inBrowser) {
|
||||
this.windowWidth = window.innerWidth;
|
||||
this.windowHeight = window.innerHeight;
|
||||
}
|
||||
},
|
||||
|
||||
emitClose() {
|
||||
if (!this.asyncClose) {
|
||||
this.$emit('input', false);
|
||||
@ -151,6 +169,8 @@ export default createComponent({
|
||||
active={this.active}
|
||||
maxZoom={this.maxZoom}
|
||||
minZoom={this.minZoom}
|
||||
windowWidth={this.windowWidth}
|
||||
windowHeight={this.windowHeight}
|
||||
onScale={this.emitScale}
|
||||
onClose={this.emitClose}
|
||||
/>
|
||||
|
@ -27,25 +27,30 @@ export default {
|
||||
active: Number,
|
||||
minZoom: [Number, String],
|
||||
maxZoom: [Number, String],
|
||||
windowWidth: Number,
|
||||
windowHeight: Number,
|
||||
},
|
||||
|
||||
data() {
|
||||
this.windowWidth = window.innerWidth;
|
||||
this.windowHeight = window.innerHeight;
|
||||
|
||||
return {
|
||||
scale: 1,
|
||||
moveX: 0,
|
||||
moveY: 0,
|
||||
moving: false,
|
||||
zooming: false,
|
||||
vertical: false,
|
||||
imageRatio: 0,
|
||||
displayWidth: 0,
|
||||
displayHeight: 0,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
vertical() {
|
||||
const { windowWidth, windowHeight } = this;
|
||||
const windowRatio = windowHeight / windowWidth;
|
||||
return this.imageRatio > windowRatio;
|
||||
},
|
||||
|
||||
imageStyle() {
|
||||
const { scale } = this;
|
||||
const style = {
|
||||
@ -62,22 +67,29 @@ export default {
|
||||
},
|
||||
|
||||
maxMoveX() {
|
||||
if (this.displayWidth) {
|
||||
return Math.max(
|
||||
0,
|
||||
(this.scale * this.displayWidth - this.windowWidth) / 2
|
||||
);
|
||||
if (this.imageRatio) {
|
||||
const displayWidth = this.vertical
|
||||
? this.windowHeight / this.imageRatio
|
||||
: this.windowWidth;
|
||||
|
||||
return Math.max(0, (this.scale * displayWidth - this.windowWidth) / 2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
},
|
||||
|
||||
maxMoveY() {
|
||||
if (this.displayHeight) {
|
||||
if (this.imageRatio) {
|
||||
const displayHeight = this.vertical
|
||||
? this.windowHeight
|
||||
: this.windowWidth * this.imageRatio;
|
||||
|
||||
return Math.max(
|
||||
0,
|
||||
(this.scale * this.displayHeight - this.windowHeight) / 2
|
||||
(this.scale * displayHeight - this.windowHeight) / 2
|
||||
);
|
||||
}
|
||||
|
||||
return 0;
|
||||
},
|
||||
},
|
||||
@ -225,20 +237,8 @@ export default {
|
||||
},
|
||||
|
||||
onLoad(event) {
|
||||
const { windowWidth, windowHeight } = this;
|
||||
const { naturalWidth, naturalHeight } = event.target;
|
||||
const windowRatio = windowHeight / windowWidth;
|
||||
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;
|
||||
}
|
||||
this.imageRatio = naturalHeight / naturalWidth;
|
||||
},
|
||||
},
|
||||
|
||||
|
31
src/mixins/bind-event.js
Normal file
31
src/mixins/bind-event.js
Normal 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,
|
||||
};
|
||||
}
|
@ -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,
|
||||
};
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user