【问题标题】:Get Zoomed Image to Translate Diagonally with JS使用 JS 获取缩放图像以对角线平移
【发布时间】:2023-01-14 08:01:57
【问题描述】:

下面是一个可运行的例子。确保在新页面中打开它并使用带有移动设备选项的开发工具,以便触摸事件起作用。我不知道如何让它对角线工作。目前,需要进行 if 检查以了解用户平移的方向。如何编写才能使其不会过度扩展、粘在边缘并沿对角线工作?

如果注释掉 swipeUp 和 swipeDown 功能,则 x 轴功能完美运行,反之亦然

给我带来很多麻烦的是,为什么它在 x 轴上或仅在 y 轴上运行完美,但两者都变得不稳定。我相信这是从 if 检查中发生的。

const image = {
  startX: undefined,
  startY: undefined,
  currentX: undefined,
  currentY: undefined,
  scrollX: undefined,
  scrollY: undefined,
  currentOffsetX: undefined,
  currentOffsetY: undefined,
  offsetY: undefined,
  offsetX: undefined,
  maxScrollX: undefined,
  maxScrollY: undefined
}

let isAlreadySwiped = false

const imageContainer = document.querySelector('.image-container')
const zoomImageWrapper = document.querySelector('.zoom-image-wrapper')

image.maxScrollX = imageContainer.offsetWidth - zoomImageWrapper.offsetWidth
image.maxScrollY = imageContainer.offsetHeight - zoomImageWrapper.offsetHeight
console.log(image.maxScrollY)

imageContainer.addEventListener('touchstart', e => {
  image.startX = e.touches[0].pageX
  image.startY = e.touches[0].pageY
})


imageContainer.addEventListener('touchmove', e => {
  image.currentX = e.touches[0].pageX
  image.currentY = e.touches[0].pageY

  const swipingLeft = image.startX > image.currentX
  const swipingRight = image.startX < image.currentX
  const swipingUp = image.startY > image.currentY
  const swipingDown = image.startY < image.currentY


  if (swipingLeft) {
    if (!isAlreadySwiped) {
      if (getImageOffsets(imageContainer).x >= image.maxScrollX) return
      image.scrollX = Math.abs(e.touches[0].pageX - image.startX)
      imageContainer.style.transform = `translate3d(-${image.scrollX}px, 0, 0)`
    } else {
      if (getImageOffsets(imageContainer).x >= image.maxScrollX) return
      image.scrollX = image.currentOffsetX + Math.abs(e.touches[0].pageX - image.startX)
      imageContainer.style.transform = `translate3d(-${image.scrollX}px, 0, 0)`
    }
  }

 if (swipingRight) {
    if (!isAlreadySwiped) {
      if (getImageOffsets(imageContainer).x <= 0) return
      image.scrollX = Math.abs(e.touches[0].pageX - image.startX)
      console.log(image.scrollX)
      imageContainer.style.transform = `translate3d(-${image.scrollX}px, 0, 0)`
    } else {
      if (getImageOffsets(imageContainer).x <= 0) return
      image.scrollX = image.currentOffsetX - Math.abs(e.touches[0].pageX - image.startX)
      imageContainer.style.transform = `translate3d(-${image.scrollX}px, 0, 0)`
    }
  }

  if (swipingUp) {
    if (!isAlreadySwiped) {
      if (getImageOffsets(imageContainer).y >= image.maxScrollY) return
      image.scrollY = Math.abs(e.touches[0].pageY - image.startY)
      imageContainer.style.transform = `translate3d(0, -${image.scrollY}px, 0)`
    } else {
      if (getImageOffsets(imageContainer).y >= image.maxScrollY) return
      image.scrollY = image.currentOffsetY + Math.abs(e.touches[0].pageY - image.startY)
      imageContainer.style.transform = `translate3d(0, -${image.scrollY}px, 0)`
    }
  }

  if (swipingDown) {
    if (!isAlreadySwiped) {
      if (getImageOffsets(imageContainer).y <= 0) return
      image.scrollY = Math.abs(e.touches[0].pageY - image.startY)
      imageContainer.style.transform = `translate3d(0, -${image.scrollY}px, 0)`
    } else {
      if (getImageOffsets(imageContainer).y <= 0) return
      image.scrollY = image.currentOffsetY - Math.abs(e.touches[0].pageY - image.startY)
      imageContainer.style.transform = `translate3d(0, -${image.scrollY}px, 0)`
    }
  }
    
})

imageContainer.addEventListener('touchend', e => {
  isAlreadySwiped = true
  image.currentOffsetX = getImageOffsets(imageContainer).x
  image.currentOffsetY = getImageOffsets(imageContainer).y
})

function getImageOffsets(img) {
  return {
    x: imageContainer.offsetWidth - img.getBoundingClientRect().right,
    y: imageContainer.offsetHeight - img.getBoundingClientRect().bottom
  }
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Home</title>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width" />
    <style>
      * {
        box-sizing: border-box;
      }

      .modal {
        height: 100%;
        width: 100%;
        z-index: 100000;
        position: fixed;
        display: flex;
        top: 0;
        left: 0;
        justify-content: center;
      }

      .modal__wrapper {
        display: flex;
        position: relative;
        background: #fff;
        flex-direction: column;
        height: 100%;
        width: 100%;
        align-items: center;
      }

      .modal__content {
        display: flex;
        flex-direction: column;
        overflow-x: hidden;
        overflow-y: scroll;
        padding: 0;
        margin: 0;
        height: 100%;
        white-space: nowrap; 
      }

      .zoom-container {
        position: relative;
        height: 100%;
      }

      .zoom-container-inner {
        position: absolute;
        z-index: 9;
        opacity: 1;
        top: 0;
        left: 0;
        height: 100%;
        width: 100%;

      }

      .image-container {
        position: relative;
        overflow: hidden;
      }

      .controls {
        display: flex;
        background: #fff;
        border: #ccc;
        width: 100%;
        flex: 0 0 auto;
        margin-top: auto;
        max-height: 73px;
        height: 73px;
      }

      .controls__inner {
        display: flex;
        justify-content: space-between;
        align-items: center;
        width: 100%;
        padding: 24px;
      }
    </style>
  </head>
  <body>
    
    <div class="modal">
      <div class="modal__wrapper">
        <div class="modal__content">
          <div class="zoom-container" style="margin: 0 auto; width: 375px;">
          <!-- <div class="zoom-container" style="margin: 0 auto; width: 469px;"> -->
          <div class="zoom-container-inner">
            <div style="height: 100%; width: 100%;">
                <div style="touch-action: none; height: 100%; width: 100%; overflow: hidden;" class="zoom-image-wrapper">
                <!-- <div style="touch-action: none; height: 677px; width: 469px; overflow: hidden;" class="zoom-image-wrapper"> -->
                  <div class="image-container"
                    style="overflow: hidden; will-change: transform; user-select: none; transform-origin: 0px 0px; transform: translate3d(0px, 0px, 0px); padding-top: 144%; width: 610px; height: 880px;"
                  >
                    <div style="position: absolute; top: 0; left: 0; height: 100%; width: 100%;">
                      <img src="https://img01.ztat.net/article/spp-media-p1/3a301a3d8a274a18821af76f9a21bfe4/137fd73e910c45db8be381e6d8c72fee.jpg?imwidth=1800&filter=packshot" style="max-width: 100%; position: relative; text-align: center; width: 100%; height: auto; display: block;">
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
        

        <div style="max-height: 73px;" class="controls">
          <div class="controls__inner">
            <div>1 of 5</div>
            <div>x</div>
          </div>
        </div>

      </div>
    </div>

    <script src="./index.js"></script>
  </body>
</html>

【问题讨论】:

    标签: javascript html css


    【解决方案1】:

    const image = {
      startX: undefined,
      startY: undefined,
      currentX: undefined,
      currentY: undefined,
      scrollX: undefined,
      scrollY: undefined,
      currentOffsetX: undefined,
      currentOffsetY: undefined,
      offsetY: undefined,
      offsetX: undefined,
      maxScrollX: undefined,
      maxScrollY: undefined
    }
    
    let isAlreadySwiped = false
    
    const imageContainer = document.querySelector('.image-container')
    const zoomImageWrapper = document.querySelector('.zoom-image-wrapper')
    
    image.maxScrollX = imageContainer.offsetWidth - zoomImageWrapper.offsetWidth + 100
    image.maxScrollY = imageContainer.offsetHeight - zoomImageWrapper.offsetHeight + 100
    console.log(image.maxScrollY)
    
    imageContainer.addEventListener('touchstart', e => {
      image.startX = e.touches[0].pageX
      image.startY = e.touches[0].pageY
    })
    
    
    imageContainer.addEventListener('touchmove', e => {
      image.currentX = e.touches[0].pageX
      image.currentY = e.touches[0].pageY
    
      const swipingLeft = image.startX > image.currentX
      const swipingRight = image.startX < image.currentX
      const swipingUp = image.startY > image.currentY
      const swipingDown = image.startY < image.currentY
    
      const {
        x,
        y
      } = getImageOffsets(imageContainer)
    
      if (Math.abs(x) >= image.maxScrollX || Math.abs(y) >= image.maxScrollY) return
    
      if (!isAlreadySwiped) {
        image.scrollX = Math.abs(e.touches[0].pageX - image.startX)
        image.scrollY = Math.abs(e.touches[0].pageY - image.startY)
        imageContainer.style.transform = `translate3d(-${image.scrollX}px, -${image.scrollY}px, 0)`
      } else {
        image.scrollX = image.currentOffsetX - Math.abs(e.touches[0].pageX - image.startX)
        image.scrollY = image.currentOffsetY - Math.abs(e.touches[0].pageY - image.startY)
        imageContainer.style.transform = `translate3d(-${image.scrollX}px, -${image.scrollY}px, 0)`
    
      }
    })
    
    imageContainer.addEventListener('touchend', e => {
      isAlreadySwiped = true
      image.currentOffsetX = getImageOffsets(imageContainer).x
      image.currentOffsetY = getImageOffsets(imageContainer).y
    })
    
    function getImageOffsets(img) {
      return {
        x: imageContainer.offsetWidth - img.getBoundingClientRect().right,
        y: imageContainer.offsetHeight - img.getBoundingClientRect().bottom
      }
    }
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <title>Home</title>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width" />
      <style>
        * {
          box-sizing: border-box;
        }
        
        .modal {
          height: 100%;
          width: 100%;
          z-index: 100000;
          position: fixed;
          display: flex;
          top: 0;
          left: 0;
          justify-content: center;
        }
        
        .modal__wrapper {
          display: flex;
          position: relative;
          background: #fff;
          flex-direction: column;
          height: 100%;
          width: 100%;
          align-items: center;
        }
        
        .modal__content {
          display: flex;
          flex-direction: column;
          overflow-x: hidden;
          overflow-y: scroll;
          padding: 0;
          margin: 0;
          height: 100%;
          white-space: nowrap;
        }
        
        .zoom-container {
          position: relative;
          height: 100%;
        }
        
        .zoom-container-inner {
          position: absolute;
          z-index: 9;
          opacity: 1;
          top: 0;
          left: 0;
          height: 100%;
          width: 100%;
        }
        
        .image-container {
          position: relative;
          overflow: hidden;
        }
        
        .controls {
          display: flex;
          background: #fff;
          border: #ccc;
          width: 100%;
          flex: 0 0 auto;
          margin-top: auto;
          max-height: 73px;
          height: 73px;
        }
        
        .controls__inner {
          display: flex;
          justify-content: space-between;
          align-items: center;
          width: 100%;
          padding: 24px;
        }
      </style>
    </head>
    
    <body>
    
      <div class="modal">
        <div class="modal__wrapper">
          <div class="modal__content">
            <div class="zoom-container" style="margin: 0 auto; width: 375px;">
              <!-- <div class="zoom-container" style="margin: 0 auto; width: 469px;"> -->
              <div class="zoom-container-inner">
                <div style="height: 100%; width: 100%;">
                  <div style="touch-action: none; height: 100%; width: 100%; overflow: hidden;" class="zoom-image-wrapper">
                    <!-- <div style="touch-action: none; height: 677px; width: 469px; overflow: hidden;" class="zoom-image-wrapper"> -->
                    <div class="image-container" style="overflow: hidden; will-change: transform; user-select: none; transform-origin: 0px 0px; transform: translate3d(0px, 0px, 0px); padding-top: 144%; width: 610px; height: 880px;">
                      <div style="position: absolute; top: 0; left: 0; height: 100%; width: 100%;">
                        <img src="https://img01.ztat.net/article/spp-media-p1/3a301a3d8a274a18821af76f9a21bfe4/137fd73e910c45db8be381e6d8c72fee.jpg?imwidth=1800&filter=packshot" style="max-width: 100%; position: relative; text-align: center; width: 100%; height: auto; display: block;">
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
    
    
          <div style="max-height: 73px;" class="controls">
            <div class="controls__inner">
              <div>1 of 5</div>
              <div>x</div>
            </div>
          </div>
    
        </div>
      </div>
    
      <script src="./index.js"></script>
    </body>
    
    </html>

    【讨论】:

    • 嘿谢谢你花时间回答这个问题。我在 devtools 中运行了你的例子,我遇到了我面临的同样问题。我有所有这些 if 检查的主要原因,即向左滑动,向右滑动等。这样我就可以防止图像过度扩展容器。当我运行您的示例时,第一个初始平移离开了,图像超出了容器的宽度。在我的示例中,当注释掉 y 轴代码时,x 轴工作完美。我进行了 if 检查,这样图像就不会过度延伸,然后就取消了对角线平移。设置对角线平移时,图像过度扩展
    • 我无法让它沿对角线平移并停止过度扩展,我的解决方案似乎是一种方式或另一种方式。
    猜你喜欢
    • 2017-01-29
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 2016-07-22
    • 2011-09-10
    • 1970-01-01
    • 1970-01-01
    • 2016-05-17
    相关资源
    最近更新 更多