Javascript放大/缩小到鼠标的x/y坐标 [英] Javascript zoom in/out to mouse x/y coordinates

查看:52
本文介绍了Javascript放大/缩小到鼠标的x/y坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我设法使鼠标拖动以滚动div,但是用鼠标进行的放大/缩小操作尚未完成.

它可以工作,但是我希望鼠标指针将图像保持在该位置并同时缩放它,就像这样:

在缩放之前,我需要使用 scrollBy()将滚动返回到上一个点.有人知道该怎么做吗?

这是某人

I managed to make the mouse dragging to scroll the div, but the zooming in/out with the mouse is not complete.

It works, but I would like for the mouse pointer to hold the image in that position and scale it at the same time, like so:

I need to use scrollBy() to return the scrolling back to the previous point before scaling. Anyone knows how to do that?

This is a fiddle made by someone https://jsfiddle.net/xta2ccdt/13/ and it's exactly what I need, but the code uses translate() and other things which don't apply here, since I have scrolling/dragging too.

Here's my jsfiddle code https://jsfiddle.net/catalinu/1f6e0jna/

And here's the code in stackoverflow:

Please help. I struggled with this for days.

for (const divMain of document.getElementsByClassName('main')) {
  // drag the section
  for (const divSection of divMain.getElementsByClassName('section')) {
  	// when mouse is pressed store the current mouse x,y
    let previousX, previousY
    divSection.addEventListener('mousedown', (event) => {
      previousX = event.pageX
      previousY = event.pageY
    })
    
    // when mouse is moved, scrollBy() the mouse movement x,y
    divSection.addEventListener('mousemove', (event) => {
    	// only do this when the primary mouse button is pressed (event.buttons = 1)
      if (event.buttons) {
        let dragX = 0
        let dragY = 0
        // skip the drag when the x position was not changed
        if (event.pageX - previousX !== 0) {
          dragX = previousX - event.pageX
          previousX = event.pageX
        }
        // skip the drag when the y position was not changed
        if (event.pageY - previousY !== 0) {
          dragY = previousY - event.pageY
          previousY = event.pageY
        }
        // scrollBy x and y
        if (dragX !== 0 || dragY !== 0) {
          divMain.scrollBy(dragX, dragY)
        }
      }
    })
  }

  // zoom in/out on the section
  let scale = 1
  const scaleFactor = 0.05
  divMain.addEventListener('wheel', (event) => {
  	// preventDefault to stop the onselectionstart event logic
    event.preventDefault()
    for (const divSection of divMain.getElementsByClassName('section')) {
    	// set the scale change value
      const scaleChange = (event.deltaY < 0) ? scaleFactor : -scaleFactor
      // don't allow the scale to go outside of [0,5 - 2]
      if (scale + scaleChange < 0.5 || scale + scaleChange > 2) {
        return
      }
      // round the value when using high dpi monitors
      scale = Math.round((scale + scaleChange) * 100) / 100

			// apply the css scale
      divSection.style.transform = `scale(${scale}, ${scale})`

      // re-adjust the scrollbars        
      const x = Math.round(divMain.scrollLeft * scaleChange)
      const y = Math.round(divMain.scrollTop * scaleChange)
      divMain.scrollBy(x, y)
    }
  })
}

body {
  margin: 0;
}

.main {
	width: 100%; /* percentage fixes the X axis white space when zoom out */
	height: 100vh; /* this is still an issue where you see white space when zoom out in the Y axis */
	overflow: scroll; /* needed for safari to show the x axis scrollbar */
}

.main .section {
	width: 200%;
	height: 200vh;
	background-image: url('https://iso.500px.com/wp-content/uploads/2014/07/big-one.jpg');
	transform-origin: 0 0;
}

<main class="main">
  <section class="section"></section>
</main>

解决方案

You issue is mostly around the below lines

const x = Math.round(divMain.scrollLeft * scaleChange)
const y = Math.round(divMain.scrollTop * scaleChange)

The way scroll with scale works like below

  • Calculate the unscaled x, y coordinate where zoom happens
  • Calculate the new scaled x, y coordinate my multiplying it with the new scale
  • Now you want this new coordinate remain at the same place where the existing coordinate was. So basically if you subtract the offset x,y from the new scaled x,y, you get the scroll left and top.

The updated code is like below

for (const divMain of document.getElementsByClassName('main')) {
  // drag the section
  for (const divSection of divMain.getElementsByClassName('section')) {
    // when mouse is pressed store the current mouse x,y
    let previousX, previousY
    divSection.addEventListener('mousedown', (event) => {
      previousX = event.pageX
      previousY = event.pageY
    })

    // when mouse is moved, scrollBy() the mouse movement x,y
    divSection.addEventListener('mousemove', (event) => {
        // only do this when the primary mouse button is pressed (event.buttons = 1)
      if (event.buttons) {
        let dragX = 0
        let dragY = 0
        // skip the drag when the x position was not changed
        if (event.pageX - previousX !== 0) {
          dragX = previousX - event.pageX
          previousX = event.pageX
        }
        // skip the drag when the y position was not changed
        if (event.pageY - previousY !== 0) {
          dragY = previousY - event.pageY
          previousY = event.pageY
        }
        // scrollBy x and y
        if (dragX !== 0 || dragY !== 0) {
          divMain.scrollBy(dragX, dragY)
        }
      }
    })
  }

  // zoom in/out on the section
  let scale = 1
  const factor = 0.05
  const max_scale =4

  divMain.addEventListener('wheel', (e) => {
    // preventDefault to stop the onselectionstart event logic
    for (const divSection of divMain.getElementsByClassName('section')) {
        e.preventDefault();
        var delta = e.delta || e.wheelDelta;
        if (delta === undefined) {
          //we are on firefox
          delta = e.originalEvent.detail;
        }
        delta = Math.max(-1,Math.min(1,delta)) // cap the delta to [-1,1] for cross browser consistency
            offset = {x: divMain.scrollLeft, y: divMain.scrollTop};
     image_loc = {
        x: e.pageX + offset.x,
        y: e.pageY + offset.y
     }

     zoom_point = {x:image_loc.x/scale, y: image_loc.y/scale}

        // apply zoom
        scale += delta*factor * scale
        scale = Math.max(1,Math.min(max_scale,scale))

     zoom_point_new = {x:zoom_point.x * scale, y: zoom_point.y * scale}

     newScroll = {
        x: zoom_point_new.x - e.pageX,
        y: zoom_point_new.y - e.pageY
     }


      divSection.style.transform = `scale(${scale}, ${scale})`
      divMain.scrollTop = newScroll.y
      divMain.scrollLeft = newScroll.x
    }


  })
}

The updated fiddle is

https://jsfiddle.net/uy390v8t/1/

这篇关于Javascript放大/缩小到鼠标的x/y坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆