Resizing and scrolling issue (JS/HTML)

喜你入骨 提交于 2021-02-10 09:25:36

问题


There are two containers: the first is a small viewport and the second is huge workspace. So, user scroll the viewport to move within the workspace. I want to implement a zoom in/out feature via CSS property tranform, but during the process I faced one difficulty and could not find a precise solution for it.

The issue is: when user zooms in/out, elements at the workspace are shifted. This happens actually because the workspace is resized, not they. But if I resize each element at the workspace, the distances between them (in terms of top/left CSS values) will be changed, what is not preferred.

I see the following solution: change scrolls values after resizing, but I do not know what ratios or numbers to use. Is there any formulae or another solution to overcome such a problem?

For resizing use Alt + MouseWheel

let workspace = document.getElementsByClassName('workspace')[0];
workspace.onwheel = resize;

let current_scale = 1;

function resize(E) {
  E = E || window.event
  if (E.altKey) {
    E.preventDefault();
    let new_scale = Math.max(0.1, current_scale - E.deltaY / 360);
    workspace.style.setProperty('transform', 'scale(' + new_scale + ')');
    current_scale = new_scale;
  }
}
.viewport {
  width: 80vw;
  height: 80vh;
  box-sizing: border-box;
  overflow: scroll;
 
  transform: scale(1);
}

.workspace {
  position: relative;
  width: 1000px;
  height: 1000px;
  overflow: hidden;
}

.element {
  position: absolute;
  width: 10px;
  height: 10px;
}
<div class="viewport">
  <div class="workspace">
    <button class="element" style="top: 100px; left: 150px"></button>
    <button class="element" style="top 80px; left: 100px"></button>
    <button class="element" style="top: 230px; left: 130px"></button>
    <button class="element" style="top: 100px; left: 250px"></button>
  </div>
</div>

UPD: I attached some photos from the original project for clarification:

So, that's a look of the workspace with scale(1)

Then I resize it and get the following result:

But desirable result looks like this:

UPD2 I inserted <svg> element to show how lines are drawn and why resizing each button seems to me a not viable solution in my case

 let workspace = document.getElementsByClassName('workspace')[0];
    workspace.onwheel = resize;
    let current_scale = 1;
    function resize(E) {
        E = E || window.event;
        if (E.altKey) {
            E.preventDefault();
            let new_scale = Math.max(0.1, current_scale - E.deltaY / 360);
            var btns = workspace.getElementsByClassName('element');
            for(var i = 0; i <btns.length; i++) {
                btns[i].style.setProperty('transform', 'scale(' + new_scale + ')');
            }
            current_scale = new_scale;
        }
    }
.viewport {
            width: 80vw;
            height: 80vh;
            box-sizing: border-box;
            overflow: scroll;

            transform: scale(1);
            transform-origin: 0 0;
        }

        .workspace {
            position: relative;
            width: 1000px;
            height: 1000px;
            overflow: hidden;
        }

        .element {
            position: absolute;
            width: 10px;
            height: 10px;
        }
        .line-drawer
        {
            position:absolute;
            height:1000px;
            width:1000px;
        }
<div class="viewport">
    <div class="workspace">
        <svg class="line-drawer">
            <line x1="100px" x2="130px" y1="80px" y2="230px" style='stroke-width: 4px; stroke: black'></line>
        </svg>
        <button class="element" style="top: 100px; left: 150px"></button>
        <button class="element" style="top: 80px; left: 100px"></button>
        <button class="element" style="top: 230px; left: 130px"></button>
        <button class="element" style="top: 100px; left: 250px"></button>
    </div>
</div>

回答1:


Scaling the individual elements like this will keep them in there position

let workspace = document.getElementsByClassName('workspace')[0];
workspace.onwheel = resize;

let current_scale = 1;

function resize(E) {
  E = E || window.event
  if (E.altKey) {
    E.preventDefault();
    let new_scale = Math.max(0.1, current_scale - E.deltaY / 360);
    var btns = workspace.getElementsByClassName('element');
    for(var i = 0; i <btns.length; i++) { 
        btns[i].style.setProperty('transform', 'scale(' + new_scale + ')');
    }
    current_scale = new_scale;
  }
}
.viewport {
  width: 80vw;
  height: 80vh;
  box-sizing: border-box;
  overflow: scroll;
 
  transform: scale(1);
}

.workspace {
  position: relative;
  width: 1000px;
  height: 1000px;
  overflow: hidden;
}

.element {
  position: absolute;
  width: 10px;
  height: 10px;
}
<div class="viewport">
  <div class="workspace">
    <button class="element" style="top: 100px; left: 150px"></button>
    <button class="element" style="top 80px; left: 100px"></button>
    <button class="element" style="top: 230px; left: 130px"></button>
    <button class="element" style="top: 100px; left: 250px"></button>
  </div>
</div>


来源:https://stackoverflow.com/questions/62038601/resizing-and-scrolling-issue-js-html

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!