123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- <template>
- <div class="image-contain">
- <div
- v-if="showGuide"
- :class="[`${prefixCls}-guide`, `${prefixCls}-guide-prev`]"
- @click.stop="showPrev"
- >
- <i class="el-icon-arrow-left"></i>
- </div>
- <div
- v-if="showGuide"
- :class="[`${prefixCls}-guide`, `${prefixCls}-guide-next`]"
- @click.stop="showNext"
- >
- <i class="el-icon-arrow-right"></i>
- </div>
- <!-- image -->
- <div
- :class="[
- `${prefixCls}-image`,
- { [`${prefixCls}-image-nosition`]: nosition },
- ]"
- :style="styles"
- v-move-ele.prevent.stop="{ mouseMove }"
- >
- <img
- :key="image.url"
- :src="image.url"
- ref="PreviewImgDetail"
- @load="resizeImage"
- />
- </div>
- <div :class="[`${prefixCls}-none`]" v-if="!image.url">
- <i class="el-icon-picture"></i>
- <p>暂无数据</p>
- </div>
- <div :class="[`${prefixCls}-loading`]" v-show="loading">
- <i class="el-icon-loading"></i>
- </div>
- <!-- action -->
- <div v-if="showAction && image.url" :class="[`${prefixCls}-action`]">
- <ul>
- <li title="合适大小" @click.stop="toOrigin">
- <i class="el-icon-rank" />
- </li>
- <li title="旋转" @click.stop="toRotate">
- <i class="el-icon-refresh-right"></i>
- </li>
- </ul>
- </div>
- </div>
- </template>
- <script>
- import MoveEle from "../plugins/move-ele";
- const prefixCls = "image-contain";
- export default {
- name: "image-contain",
- props: {
- image: {
- type: Object,
- default() {
- return { url: "", filename: "" };
- },
- },
- showAction: {
- type: Boolean,
- default: true,
- },
- showGuide: {
- type: Boolean,
- default: true,
- },
- },
- directives: { MoveEle },
- data() {
- return {
- prefixCls,
- styles: { width: "", height: "", top: "", left: "", transform: "" },
- initWidth: 500,
- minScale: 0.5,
- maxScale: 5,
- transform: {
- scale: 1,
- rotate: 0,
- },
- loading: false,
- loadingSetT: null,
- nosition: false,
- };
- },
- // watch: {
- // "image.url": {
- // handler(val) {
- // if (val) {
- // this.loadingSetT = setTimeout(() => {
- // this.loading = true;
- // }, 300);
- // this.styles = {
- // width: "",
- // height: "",
- // top: "",
- // left: "",
- // transform: ""
- // };
- // }
- // }
- // }
- // },
- mounted() {
- this.registWheelHandle();
- },
- methods: {
- resizeImage() {
- const imgDom = this.$refs.PreviewImgDetail;
- const { naturalWidth, naturalHeight } = imgDom;
- const imageSize = this.getImageSizePos({
- win: {
- width: this.$el.clientWidth,
- height: this.$el.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",
- marginLeft: "auto",
- transform: "none",
- });
- this.transform = {
- scale: 1,
- rotate: 0,
- };
- this.loading = false;
- 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;
- },
- showPrev() {
- this.$emit("on-prev");
- },
- showNext() {
- this.$emit("on-next");
- },
- // dome-move
- registWheelHandle() {
- this.$el.addEventListener("wheel", (e) => {
- e.preventDefault();
- this.mouseWheel(e.wheelDeltaY);
- });
- },
- mouseMove({ left, top }) {
- this.styles.left = left + "px";
- this.styles.top = top + "px";
- },
- mouseWheel(delta) {
- if (delta < 0) {
- this.toMagnify();
- } else {
- this.toShrink();
- }
- },
- setStyleTransform() {
- const { scale, rotate } = this.transform;
- this.styles.transform = `scale(${scale}, ${scale}) rotate(${rotate}deg)`;
- },
- toOrigin() {
- this.transform.scale = 1;
- this.setStyleTransform();
- this.resizeImage();
- },
- 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();
- this.$emit(
- "on-rotate",
- this.transform.rotate >= 360 ? 0 : this.transform.rotate
- );
- // 调整图片尺寸
- const { naturalWidth, naturalHeight } = this.$refs.PreviewImgDetail;
- const imageSize = this.getImageSizePos({
- win: {
- width: this.$el.clientWidth,
- height: this.$el.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度
- if (this.transform.rotate >= 360) {
- setTimeout(() => {
- this.nosition = true;
- this.transform.rotate = 0;
- this.setStyleTransform();
- setTimeout(() => {
- this.nosition = false;
- }, 100);
- }, 200);
- // 200ms当次旋转动画持续时间
- }
- },
- },
- };
- </script>
|