首页 > web前端 > css教程 > 放大缩小画布中的粘着点

放大缩小画布中的粘着点

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
发布: 2024-07-18 05:56:57
原创
1032 人浏览过

使用粘点进行放大缩小是我们在 Figma 等设计或构建工具上遇到的常规用例。在这篇博客中,我将介绍一个通过 javascript、HTML 和 CSS 处理它的基本算法。

演示

示范

代码一步一步

1。创建一个容器和一个可扩展项目

1

2

3

4

5

<div id="app">

      <div class="parent">

        <div class="scalable-child"></div>

      </div>

</div>

登录后复制

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

.scalable-child {

  width: 300px;

  height: 300px;

  position: relative;

  top: 0;

  left: 0;

  pointer-events: none;

  transform-origin: left top;

  background-image: url('https://cdn4.vectorstock.com/i/1000x1000/17/58/caro-pattern-background-vector-2261758.jpg');

  background-size: contain;

}

.parent {

  position: relative;

  background-color: white;

  width: 100vw;

  height: 100vh;

}

登录后复制

在此示例中,我使用 div 作为类为“scalable-child”的可扩展项目,其容器是类为“parent”的 div。
请注意某些属性:

  • 上、左:0 是默认位置

  • Pointer-event:none,因为我们会将事件添加到父级,如果pointer-event !== none,算法将失败。

  • Transform-origin:左上,以坐标原点计算位置

2。添加滚轮事件监听

1

2

const parent = document.querySelector('.parent');

const child = document.querySelector('.scalable-child');

登录后复制

1

2

3

4

parent.addEventListener('wheel', wheelEventHandler, {

  passive: false,

  capture: true,

});

登录后复制

我们将使用 WheelEvent 来处理放大、缩小和移动子项

注意:此示例仅针对触控板进行演示。您还需要处理热键(Ctrl +、Ctr -)或鼠标的事件。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

let left = 0;

let top = 0;

let scale = 1;

 

const wheelEventHandler = (e) => {

  e.preventDefault();

  // Handle zoom with touch pad and hot key.

  const isZooming = e.ctrlKey || e.metaKey;

  let newValues = {};

  if (isZooming) {

    newValues = calculateOnZooming(e, scale, left, top);

  } else {

    newValues = calculateOnMoving(e, scale, left, top);

  }

 

  left = newValues.newLeft;

  top = newValues.newTop;

  scale = newValues.newScale;

 

  Object.assign(child.style, {

    transform: `scale(${scale})`,

    left: `${left}px`,

    top: `${top}px`,

  });

};

登录后复制

首先,我们有 isZooming 变量来检查是否缩放或移动子元素。

然后我们计算子元素的新位置和比例。左、上和比例被用作温度变量。

现在该将算法重点放在 2 个计算函数上:

3。缩放计算

1

2

3

4

5

6

7

8

9

10

11

const calculateOnZooming = (e, oldScale, oldLeft, oldTop) => {

  let newScale = oldScale - e.deltaY * oldScale * 0.01;

  newScale = Math.max(newScale, 0.1);

  const newLeft = oldLeft - (e.offsetX - oldLeft) * (newScale / scale - 1);

  const newTop = oldTop - (e.offsetY - oldTop) * (newScale / scale - 1);

  return {

    newScale,

    newLeft,

    newTop,

  };

};

登录后复制

缩放时,wheelEvent 将返回 deltaY 作为比例,我们可以用它来计算 newScale

  • deltaY > 0 =>缩小

  • deltaY 放大
    detalScale = e.deltaY * oldScale * 0.01 控制缩放速度

让我们看下图来更多地了解如何计算 newLeft 和 newTop 变量:

Image description
当鼠标位于 A 点时开始放大子项。这时,我们可以得到一些值:

  • e.offsetX:鼠标到父级左边缘之间的距离

  • e.offsetY:鼠标到父级上边缘之间的距离

  • left:当前孩子的左样式值

  • top:当前孩子的顶级样式值

子级从比例缩放到比例'比例,A点转到A'。
因此,为了使 A 点具有粘性(与父点),我们需要计算 deltaX 和 deltaY,然后以精确的 px 移动子点恢复。

detalX = x’ - x
= x * (比例’ / 比例) - x
= x * (比例’ / 比例 - 1)
= (e.offsetX - 左) * (scale’/scale - 1)

detalY = y’ - y
= y * (比例’ / 比例) - y
= y * (尺度' / 尺度 - 1)
= (e.offsetY - 顶部) * (scale’/scale - 1)

newLeft = 左 - detalX
newTop = 顶部 - detalY

4。搬家计算

1

2

3

4

5

6

7

const calculateOnMoving = (e, oldScale, oldLeft, oldTop) => {

  return {

    newLeft: oldLeft - e.deltaX * 2,

    newTop: oldTop - e.deltaY * 2,

    newScale: oldScale,

  };

};

登录后复制

在移动事件中,我们只需要计算 newLeft 和 newTop 值。我们还 *2 每个增量值来提高速度。

这就是我们需要处理的一切。我希望它有帮助。感谢您的观看!
您可以在此处查看完整的源代码。

以上是放大缩小画布中的粘着点的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板