Skip to content

Commit

Permalink
image: apply various fixes
Browse files Browse the repository at this point in the history
1.  set preview `:initial-index` to `0` if src is not in previewSrcList
and also fix preview example
2. fix ESC won't close preview for the second time
ElemeFE#19027
ElemeFE#18906
3. fix undesired `overflow: scroll` style
ElemeFE#18967
4. fix a race condition if src changes too frequently
https://github.com/ElemeFE/element/pull/18837/files
5. add `close-on-click-modal` prop
https://github.com/ElemeFE/element/pull/18947/files
  • Loading branch information
CarterLi committed Mar 30, 2020
1 parent 51cad38 commit 70ce479
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 131 deletions.
13 changes: 7 additions & 6 deletions examples/docs/zh-CN/image.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,14 @@

### 大图预览

:::demo 可通过 `previewSrcList` 开启预览大图的功能。
:::demo 可通过 `previewSrcList` 开启预览大图的功能。设置`close-on-click-modal`允许用户点击遮罩层关闭预览
```html
<div class="demo-image__preview">
<el-image
<el-image
style="width: 100px; height: 100px"
:src="url"
:preview-src-list="srcList">
:src="url"
:preview-src-list="srcList"
close-on-click-modal>
</el-image>
</div>

Expand All @@ -126,6 +127,7 @@
return {
url: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
srcList: [
'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
'https://fuss10.elemecdn.com/8/27/f01c15bb73e1ef3793e64e6b7bbccjpeg.jpeg',
'https://fuss10.elemecdn.com/1/8e/aeffeb4de74e2fde4bd74fc7b4486jpeg.jpeg'
]
Expand All @@ -147,6 +149,7 @@
| scroll-container | 开启懒加载后,监听 scroll 事件的容器 | string / HTMLElement || 最近一个 overflow 值为 auto 或 scroll 的父元素 |
| preview-src-list | 开启图片预览功能 | Array || - |
| z-index | 设置图片预览的 z-index | Number || 2000 |
| close-on-click-modal | 是否可以通过点击 modal 关闭预览。设置此属性后不显示关闭图标| boolean || false |

### Events
| 事件名称 | 说明 | 回调参数 |
Expand All @@ -159,5 +162,3 @@
|---------|-------------|
| placeholder | 图片未加载的占位内容 |
| error | 加载失败的内容 |


159 changes: 74 additions & 85 deletions packages/image/src/image-viewer.vue
Original file line number Diff line number Diff line change
@@ -1,59 +1,59 @@
<template>
<transition name="viewer-fade">
<div tabindex="-1" ref="el-image-viewer__wrapper" class="el-image-viewer__wrapper" :style="{ 'z-index': zIndex }">
<div class="el-image-viewer__mask"></div>
<!-- CLOSE -->
<span class="el-image-viewer__btn el-image-viewer__close" @click="hide">
<i class="el-icon-circle-close"></i>
<div tabindex="-1" ref="el-image-viewer__wrapper" class="el-image-viewer__wrapper" :style="{ 'z-index': zIndex }">
<div class="el-image-viewer__mask" @click="closeOnClickModal && onClose()"></div>
<!-- CLOSE -->
<span
v-if="!closeOnClickModal"
class="el-image-viewer__btn el-image-viewer__close"
@click="onClose"
>
<i class="el-icon-circle-close"></i>
</span>
<!-- ARROW -->
<template v-if="!isSingle">
<span
class="el-image-viewer__btn el-image-viewer__prev"
:class="{ 'is-disabled': !infinite && isFirst }"
@click="prev">
<i class="el-icon-arrow-left"/>
</span>
<!-- ARROW -->
<template v-if="!isSingle">
<span
class="el-image-viewer__btn el-image-viewer__prev"
:class="{ 'is-disabled': !infinite && isFirst }"
@click="prev">
<i class="el-icon-arrow-left"/>
</span>
<span
class="el-image-viewer__btn el-image-viewer__next"
:class="{ 'is-disabled': !infinite && isLast }"
@click="next">
<i class="el-icon-arrow-right"/>
</span>
</template>
<!-- ACTIONS -->
<div class="el-image-viewer__btn el-image-viewer__actions">
<div class="el-image-viewer__actions__inner">
<i class="el-icon-zoom-out" @click="handleActions('zoomOut')"></i>
<i class="el-icon-zoom-in" @click="handleActions('zoomIn')"></i>
<i class="el-image-viewer__actions__divider"></i>
<i :class="mode.icon" @click="toggleMode"></i>
<i class="el-image-viewer__actions__divider"></i>
<i class="el-icon-refresh-left" @click="handleActions('anticlocelise')"></i>
<i class="el-icon-refresh-right" @click="handleActions('clocelise')"></i>
</div>
</div>
<!-- CANVAS -->
<div class="el-image-viewer__canvas">
<img
v-for="(url, i) in urlList"
v-if="i === index"
ref="img"
class="el-image-viewer__img"
:key="url"
:src="currentImg"
:style="imgStyle"
@load="handleImgLoad"
@error="handleImgError"
@mousedown="handleMouseDown">
<span
class="el-image-viewer__btn el-image-viewer__next"
:class="{ 'is-disabled': !infinite && isLast }"
@click="next">
<i class="el-icon-arrow-right"/>
</span>
</template>
<!-- ACTIONS -->
<div class="el-image-viewer__btn el-image-viewer__actions">
<div class="el-image-viewer__actions__inner">
<i class="el-icon-zoom-out" @click="handleActions('zoomOut')"></i>
<i class="el-icon-zoom-in" @click="handleActions('zoomIn')"></i>
<i class="el-image-viewer__actions__divider"></i>
<i :class="mode.icon" @click="toggleMode"></i>
<i class="el-image-viewer__actions__divider"></i>
<i class="el-icon-refresh-left" @click="handleActions('rotateLeft')"></i>
<i class="el-icon-refresh-right" @click="handleActions('rotateRight')"></i>
</div>
</div>
</transition>
<!-- CANVAS -->
<div class="el-image-viewer__canvas">
<img
ref="img"
class="el-image-viewer__img"
:key="currentImg"
:src="currentImg"
:style="imgStyle"
@load="handleImgLoad"
@error="handleImgError"
@mousedown="handleMouseDown">
</div>
</div>
</template>

<script>
import { on, off } from 'element-ui/src/utils/dom';
import { rafThrottle, isFirefox } from 'element-ui/src/utils/util';
import { rafThrottle } from 'element-ui/src/utils/util';
const Mode = {
CONTAIN: {
Expand All @@ -66,8 +66,6 @@ const Mode = {
}
};
const mousewheelEventName = isFirefox() ? 'DOMMouseScroll' : 'mousewheel';
export default {
name: 'elImageViewer',
Expand All @@ -91,13 +89,16 @@ export default {
initialIndex: {
type: Number,
default: 0
},
closeOnClickModal: {
type: Boolean,
default: false
}
},
data() {
return {
index: this.initialIndex,
isShow: false,
infinite: true,
loading: false,
mode: Mode.CONTAIN,
Expand Down Expand Up @@ -138,33 +139,26 @@ export default {
}
},
watch: {
index: {
handler: function(val) {
this.reset();
this.onSwitch(val);
}
index(val) {
this.reset();
this.onSwitch(val);
},
currentImg(val) {
this.$nextTick(_ => {
const $img = this.$refs.img[0];
if (!$img.complete) {
this.$nextTick(() => {
if (!this.$refs.img.complete) {
this.loading = true;
}
});
}
},
methods: {
hide() {
this.deviceSupportUninstall();
this.onClose();
},
deviceSupportInstall() {
this._keyDownHandler = rafThrottle(e => {
const keyCode = e.keyCode;
switch (keyCode) {
// ESC
case 27:
this.hide();
this.onClose();
break;
// SPACE
case 32:
Expand All @@ -189,25 +183,17 @@ export default {
}
});
this._mouseWheelHandler = rafThrottle(e => {
const delta = e.wheelDelta ? e.wheelDelta : -e.detail;
if (delta > 0) {
this.handleActions('zoomIn', {
zoomRate: 0.015,
enableTransition: false
});
} else {
this.handleActions('zoomOut', {
zoomRate: 0.015,
enableTransition: false
});
}
this.handleActions(e.deltaY > 0 ? 'zoomIn' : 'zoomOut', {
zoomRate: 0.015,
enableTransition: false
});
});
on(document, 'keydown', this._keyDownHandler);
on(document, mousewheelEventName, this._mouseWheelHandler);
on(document, 'wheel', this._mouseWheelHandler);
},
deviceSupportUninstall() {
off(document, 'keydown', this._keyDownHandler);
off(document, mousewheelEventName, this._mouseWheelHandler);
off(document, 'wheel', this._mouseWheelHandler);
this._keyDownHandler = null;
this._mouseWheelHandler = null;
},
Expand All @@ -216,7 +202,7 @@ export default {
},
handleImgError(e) {
this.loading = false;
e.target.alt = '加载失败';
e.target.alt = this.t('el.image.error');
},
handleMouseDown(e) {
if (this.loading || e.button !== 0) return;
Expand Down Expand Up @@ -276,18 +262,18 @@ export default {
switch (action) {
case 'zoomOut':
if (transform.scale > 0.2) {
transform.scale = parseFloat((transform.scale - zoomRate).toFixed(3));
transform.scale -= zoomRate;
}
break;
case 'zoomIn':
transform.scale = parseFloat((transform.scale + zoomRate).toFixed(3));
break;
case 'clocelise':
transform.deg += rotateDeg;
transform.scale += zoomRate;
break;
case 'anticlocelise':
case 'rotateLeft':
transform.deg -= rotateDeg;
break;
case 'rotateRight':
transform.deg += rotateDeg;
break;
}
transform.enableTransition = enableTransition;
}
Expand All @@ -297,6 +283,9 @@ export default {
// add tabindex then wrapper can be focusable via Javascript
// focus wrapper so arrow key can't cause inner scroll behavior underneath
this.$refs['el-image-viewer__wrapper'].focus();
},
beforeDestroy() {
this.deviceSupportUninstall();
}
};
</script>
35 changes: 25 additions & 10 deletions packages/image/src/main.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@
:src="src"
:style="imageStyle"
:class="{ 'el-image__inner--center': alignCenter, 'el-image__preview': preview }">
<template v-if="preview">
<image-viewer :z-index="zIndex" :initial-index="imageIndex" v-show="showViewer" :on-close="closeViewer" :url-list="previewSrcList"/>
</template>
<transition name="viewer-fade" v-if="preview">
<image-viewer
v-if="showViewer"
:z-index="zIndex"
:initial-index="imageIndex"
:on-close="closeViewer"
:url-list="previewSrcList"
:close-on-click-modal="closeOnClickModal" />
</transition>
</div>
</template>

Expand Down Expand Up @@ -62,7 +68,8 @@
zIndex: {
type: Number,
default: 2000
}
},
closeOnClickModal: Boolean
},
data() {
Expand Down Expand Up @@ -94,7 +101,8 @@
return Array.isArray(previewSrcList) && previewSrcList.length > 0;
},
imageIndex() {
return this.previewSrcList.indexOf(this.src);
const itemIndex = this.previewSrcList.indexOf(this.src) ;
return itemIndex > 0 ? itemIndex : 0 ;
}
},
Expand All @@ -108,6 +116,10 @@
},
mounted() {
const img = this._loadingImage = new Image();
img.onerror = this.handleError;
img.onload = this.handleLoad;
if (this.lazy) {
this.addLazyLoadListener();
} else {
Expand All @@ -127,20 +139,22 @@
this.loading = true;
this.error = false;
const img = new Image();
img.onload = e => this.handleLoad(e, img);
img.onerror = this.handleError.bind(this);
// bind html attrs
// so it can behave consistently
/** @type {HTMLImageElement} */
const img = this._loadingImage;
while (img.attributes.length) {
img.attributes.removeNamedItem(img.attributes[0].name);
}
Object.keys(this.$attrs)
.forEach((key) => {
const value = this.$attrs[key];
img.setAttribute(key, value);
});
img.src = this.src;
},
handleLoad(e, img) {
handleLoad(e) {
const img = this._loadingImage;
this.imageWidth = img.width;
this.imageHeight = img.height;
this.loading = false;
Expand Down Expand Up @@ -217,6 +231,7 @@
}
},
clickHandler() {
if (!this.preview) return;
// prevent body scroll
prevOverflow = document.body.style.overflow;
document.body.style.overflow = 'hidden';
Expand Down
Loading

0 comments on commit 70ce479

Please sign in to comment.