123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- <template>
- <el-dialog
- :class="prefixCls"
- :visible.sync="modalIsShow"
- title="图片预览"
- :close-on-click-modal="false"
- :close-on-press-escape="false"
- :show-close="false"
- fullscreen
- append-to-body
- @open="visibleChange"
- >
- <div slot="footer"></div>
- <div slot="title"></div>
- <div :class="[`${prefixCls}-close`]" @click="modalIsShow = false">
- <i class="el-icon-circle-close"></i>
- </div>
- <div :class="[`${prefixCls}-header`]" v-if="!headerHide">
- <h3>{{ curFile.name }}</h3>
- <div :class="[`${prefixCls}-index`]">
- {{ this.curIndex }} / {{ this.lastIndex }}
- </div>
- </div>
- <div :class="[`${prefixCls}-body`]" ref="ReviewBody">
- <div
- :class="[`${prefixCls}-guide`, `${prefixCls}-guide-prev`]"
- @click="showPrev"
- >
- <i class="el-icon-arrow-left"></i>
- </div>
- <div
- :class="[`${prefixCls}-guide`, `${prefixCls}-guide-next`]"
- @click="showNext"
- >
- <i class="el-icon-arrow-right"></i>
- </div>
- <div
- :class="[
- `${prefixCls}-imgs`,
- { [`${prefixCls}-imgs-nosition`]: nosition }
- ]"
- :style="styles"
- v-move-ele.prevent="{ mouseMove }"
- >
- <img
- :src="curFile.url"
- :alt="curFile.name"
- v-if="curFile.url"
- ref="PreviewImgDetail"
- />
- </div>
- </div>
- <div :class="[`${prefixCls}-footer`]">
- <ul>
- <li title="合适大小" @click="toOrigin">
- <i class="el-icon-full-screen"></i>
- </li>
- <li
- title="放大"
- @click="toMagnify"
- :class="{
- 'li-disabled': transform.scale === maxScale
- }"
- >
- <i class="el-icon-zoom-in"></i>
- </li>
- <li
- title="缩小"
- @click="toShrink"
- :class="{
- 'li-disabled': transform.scale === minScale
- }"
- >
- <i class="el-icon-zoom-out"></i>
- </li>
- <li title="旋转" @click="toRotate">
- <i class="el-icon-refresh-right"></i>
- </li>
- </ul>
- </div>
- </el-dialog>
- </template>
- <script>
- import MoveEle from "./move-ele";
- const prefixCls = "cc-image-preview";
- export default {
- name: "image-preview",
- props: {
- imageList: {
- type: Array,
- default() {
- return [];
- }
- },
- initIndex: {
- type: Number,
- default: 0
- },
- headerHide: {
- type: Boolean,
- default: false
- }
- },
- directives: {
- MoveEle
- },
- data() {
- return {
- prefixCls,
- modalIsShow: false,
- curFile: { name: "", url: null },
- curIndex: 1,
- minScale: 0.2,
- maxScale: 3,
- styles: { width: "", height: "", top: "100px", left: "", transform: "" },
- initWidth: 500,
- transform: {
- scale: 1,
- rotate: 0
- },
- nosition: false
- };
- },
- computed: {
- isFirst() {
- return this.curIndex === 1;
- },
- isLast() {
- return this.lastIndex === this.curIndex;
- },
- lastIndex() {
- return this.imageList.length;
- }
- },
- watch: {
- curIndex: {
- immediate: true,
- handler(val, oldVal) {
- this.curFileChange(val);
- }
- }
- },
- methods: {
- visibleChange() {
- if (!this.imageList.length) return;
- this.curIndex = this.initIndex + 1;
- },
- curFileChange(val) {
- this.nosition = true;
- this.curFile = this.imageList[val - 1];
- this.$nextTick(() => {
- this.fileLoad();
- });
- },
- setCurIndex(index) {
- this.curIndex = index;
- },
- fileLoad() {
- const imgDom = this.$refs.PreviewImgDetail;
- if (!imgDom) return;
- imgDom.onload = () => {
- const { naturalWidth, naturalHeight } = imgDom;
- const imageSize = this.getImageSizePos({
- win: {
- width: this.$refs.ReviewBody.clientWidth,
- height: this.$refs.ReviewBody.clientHeight
- },
- img: {
- width: naturalWidth,
- height: naturalHeight
- },
- rotate: 0
- });
- this.styles = Object.assign(this.styles, {
- width: imageSize.width + "px",
- height: imageSize.height + "px",
- top: imageSize.top + "px",
- left: imageSize.left + "px",
- transform: ""
- });
- this.transform = {
- scale: 1,
- rotate: 0
- };
- setTimeout(() => {
- this.nosition = false;
- }, 100);
- };
- },
- getImageSizePos({ win, img, rotate }) {
- const imageSize = {
- width: 0,
- height: 0,
- top: 0,
- left: 0
- };
- const isHorizontal = !!(rotate % 180);
- const rateWin = isHorizontal
- ? win.height / win.width
- : win.width / win.height;
- const hwin = isHorizontal
- ? {
- width: win.height,
- height: win.width
- }
- : win;
- const rateImg = img.width / img.height;
- if (rateImg <= rateWin) {
- imageSize.height = Math.min(hwin.height, img.height);
- imageSize.width = Math.floor(
- (imageSize.height * img.width) / img.height
- );
- } else {
- imageSize.width = Math.min(hwin.width, img.width);
- imageSize.height = Math.floor(
- (imageSize.width * img.height) / img.width
- );
- }
- imageSize.left = (win.width - imageSize.width) / 2;
- imageSize.top = (win.height - imageSize.height) / 2;
- return imageSize;
- },
- cancel() {
- this.modalIsShow = false;
- },
- open() {
- this.modalIsShow = true;
- },
- showPrev() {
- if (this.isFirst) {
- this.curIndex = this.lastIndex;
- } else {
- this.curIndex -= 1;
- }
- },
- showNext() {
- if (this.isLast) {
- this.curIndex = 1;
- } else {
- this.curIndex += 1;
- }
- },
- // dome-move
- mouseMove({ left, top }) {
- this.styles.left = left + "px";
- this.styles.top = top + "px";
- },
- setStyleTransform() {
- const { scale, rotate } = this.transform;
- this.styles.transform = `scale(${scale}, ${scale}) rotate(${rotate}deg)`;
- },
- toOrigin() {
- this.transform.scale = 1;
- this.setStyleTransform();
- },
- toMagnify() {
- const scale = (this.transform.scale * 1.2).toFixed(2);
- this.transform.scale = scale >= this.maxScale ? this.maxScale : scale;
- this.setStyleTransform();
- },
- toShrink() {
- const scale = (this.transform.scale * 0.75).toFixed(2);
- this.transform.scale = scale <= this.minScale ? this.minScale : scale;
- this.setStyleTransform();
- },
- toRotate() {
- this.transform.rotate = this.transform.rotate + 90;
- this.setStyleTransform();
- // 调整图片尺寸
- const { naturalWidth, naturalHeight } = this.$refs.PreviewImgDetail;
- const imageSize = this.getImageSizePos({
- win: {
- width: this.$refs.ReviewBody.clientWidth,
- height: this.$refs.ReviewBody.clientHeight
- },
- img: {
- width: naturalWidth,
- height: naturalHeight
- },
- rotate: this.transform.rotate
- });
- this.styles = Object.assign(this.styles, {
- width: imageSize.width + "px",
- height: imageSize.height + "px",
- top: imageSize.top + "px",
- left: imageSize.left + "px"
- });
- // 360度无缝切换到0度
- setTimeout(() => {
- if (this.transform.rotate >= 360) {
- this.nosition = true;
- this.transform.rotate = 0;
- this.setStyleTransform();
- setTimeout(() => {
- this.nosition = false;
- }, 100);
- }
- }, 200);
- }
- }
- };
- </script>
|