类似antdesign modal效果
https://ant.design/components/modal-cn/

scale1.gif


核心

  1. popup.style.cssText =
  2. `transform-origin: ${leftBtn.getBoundingClientRect().x - window.innerWidth / 2}px ${leftBtn.getBoundingClientRect().y - window.innerHeight / 2}px`;

因为我的弹窗默认在屏幕中间,所以要减去屏幕宽高的一半,如果默认在左上角则不用减了,直接就是鼠标点击位置就行了。

transform-origin

设置transform-origin
第一个参数为
鼠标点击的位置的x轴坐标 - 屏幕宽度 / 2
第二个参数为 1
y轴坐标 - 屏幕高度 / 2

完整demo

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>Document</title>
  7. <style>
  8. .popup {
  9. width: 600px;
  10. height: 400px;
  11. position: fixed;
  12. left: 50%;
  13. top: 50%;
  14. transition: all 0.28s;
  15. transform: scale(0) translate(-50%, -50%);
  16. background-color: burlywood;
  17. z-index: 2;
  18. }
  19. .popup_show {
  20. transition: all 0.28s;
  21. transform: scale(1) translate(-50%, -50%);
  22. }
  23. .mask {
  24. position: fixed;
  25. top: 0;
  26. left: 0;
  27. width: 100%;
  28. height: 100%;
  29. background-color: rgba(0, 0, 0, 0.3);
  30. display: none;
  31. }
  32. .mask_show {
  33. display: block;
  34. }
  35. </style>
  36. </head>
  37. <body>
  38. <div>
  39. <button style="float: right;" id="left-btn">
  40. click me
  41. </button>
  42. <div id="mask" class="mask"></div>
  43. <div id="popup" class="popup">
  44. </div>
  45. </div>
  46. <script>
  47. window.onload = function () {
  48. const $ = (el) => document.querySelector(el)
  49. const leftBtn = $("#left-btn")
  50. , popup = $("#popup")
  51. , mask = $("#mask")
  52. // 初始化第一次的transform-origin位置
  53. popup.style.cssText =
  54. `transform-origin: ${leftBtn.getBoundingClientRect().x - window.innerWidth / 2}px ${leftBtn.getBoundingClientRect().y - window.innerHeight / 2}px`;
  55. // 点击按钮出现弹窗
  56. leftBtn.addEventListener('click', (e) => {
  57. popup.style.cssText =
  58. `transform-origin: ${e.x - window.innerWidth / 2}px ${e.y - window.innerHeight / 2}px`;
  59. popup.classList.add('popup_show')
  60. mask.classList.add('mask_show')
  61. })
  62. // 点击遮罩关闭弹窗
  63. mask.addEventListener('click', () => {
  64. popup.classList.remove('popup_show')
  65. mask.classList.remove('mask_show')
  66. })
  67. }
  68. </script>
  69. </body>
  70. </html>

效果

demo.gif