본문 바로가기

프로그래밍/Vue.js

클릭하면 크게 볼 수 있는 이미지뷰어

 

<template>
  <div class="img-viewer">
    <img
      :src="src"
      ref="img"
      class="origin"
      @mousedown="isDrag=true"
      @mouseup="isDrag=false"
      @mousemove="moveImage"
      draggable="false"
    />
    <img class="btn-close" src="@/assets/icons/close.svg" @click="doClose" />
  </div>
</template>

<script>
export default {
  props: {
    src: {
      type: String,
      required: true,
    },
  },
  data() {
    return {
      isDrag: false,
      startPos: { x: 0, y: 0 },
    }
  },
  mounted() {
    this.resizeImage()
    const img = this.$refs.img
    img.addEventListener('touchstart', this.startHandler)
    img.addEventListener('touchmove', this.moveHandler)
    img.addEventListener('touchend', this.endHandler)

    img.addEventListener('mousedown', this.startHandler)
    img.addEventListener('mousemove', this.moveHandler)
    img.addEventListener('mouseup', this.endHandler)

    const body = document.querySelector('body')
    img.addEventListener('load', () => {
      img.style.left = `${body.clientWidth / 2 - img.clientWidth / 2}px`
      img.style.top = `${body.clientHeight / 2 - img.clientHeight / 2}px`
    })
  },
  methods: {
    getPos(event) {
      let x = 0
      let y = 0
      if (event.touches !== undefined) {
        x = event.touches[0].clientX
        y = event.touches[0].clientY
      } else {
        x = event.clientX
        y = event.clientY
      }

      return {
        x: x,
        y: y,
      }
    },
    startHandler(event) {
      const bound = this.$refs.img.getBoundingClientRect()
      this.startPos = this.getPos(event)
      this.startPos.x -= bound.left
      this.startPos.y -= bound.top
      this.isDrag = true
    },
    moveHandler(event) {
      if (!this.isDrag) return
      const pos = this.getPos(event)
      this.$refs.img.style.left = `${pos.x - this.startPos.x}px`
      this.$refs.img.style.top = `${pos.y - this.startPos.y}px`
    },
    endHandler(event) {
      this.isDrag = false
    },
    resizeImage() {
      const body = document.querySelector('body')
      const w = body.offsetWidth
      const h = body.offsetHeight
    },
    moveImage(event) {
      const ele = event.target
    },
    doClose() {
      this.$emit('close')
    },
  },
}
</script>

<style lang="scss" scoped>
.img-viewer {
  width: 100%;
  height: 100%;
  border: 2px solid #000;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background-color: #000;
  img.origin {
    position: absolute;
    -ms-user-select: none;
    -moz-user-select: -moz-none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    user-select: none;
  }
  img.btn-close {
    display: block;
    width: 40px;
    height: 40px;
    border: 2px solid #000;
    background-color: #fff;
    position: absolute;
    top: 1rem;
    right: 1rem;
  }
}
</style>

아이콘

 

close.svg
0.00MB

사용법 예시

<template>
	<img :src="rowData.photo" />
    <image-viewer v-if="showImage" :src="rowData.photo" @close="showImage=false" />
</template>

<script>
import ImageViewer from '@/components/widgets/image-viewer'

export default {
	components: {
    	ImageViewer,
    },
    data() {
    	return {
        	rowData: {
            	photo: 'http://..../img.jpg',
            },
        	showImage: false,
        },
    },
}
</script>​