Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [JavaScript] draggable problem z pozycją obiektu podczas ruchu.
Forum PHP.pl > Forum > Po stronie przeglądarki
KotWButach
Witam,
mam problem, mianowicie podczas ruchu, przenoszenia obiektu, obiekt dostawia się po prawej stronie myszki od dołu.
Jak zniwelować ten efekt?
Głowie się już cały dzień sad.gif

  1.  
  2. <!DOCTYPE html>
  3. <html>
  4.  
  5. <head>
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
  7. <title>Drag/Drop/Bounce</title>
  8. <style>
  9. #container {
  10. width: 100%;
  11. height: 400px;
  12. background-color: #333;
  13. overflow: hidden;
  14. border-radius: 7px;
  15. touch-action: none;
  16. position: relative;
  17. }
  18.  
  19. #item, #item2 {
  20. width: 100px;
  21. height: 100px;
  22. background-color: rgb(245, 230, 99);
  23. border: 10px solid rgba(136, 136, 136, .5);
  24. border-radius: 50%;
  25. touch-action: none;
  26. user-select: none;
  27. position: absolute;
  28. top: 100px;
  29. left: 400px;
  30. }
  31.  
  32. #item:active, #item2:active {
  33. background-color: rgba(168, 218, 220, 1.00);
  34. }
  35.  
  36. #item:hover, #item2:hover {
  37. cursor: pointer;
  38. border-color: rgba(168, 218, 220, .70);
  39. }
  40. </style>
  41. </head>
  42.  
  43. <body>
  44.  
  45.  
  46. <div id="outerContainer">
  47. <div id="container">
  48. <div id="item2">
  49.  
  50. </div>
  51. </div>
  52. </div>
  53.  
  54. <script>
  55.  
  56.  
  57. class Move {
  58. constructor(element) {
  59.  
  60. this.element = undefined;
  61. this.draggable = undefined;
  62.  
  63. this.getElement(element);
  64. this.initDraggable();
  65. this.moveDraggable();
  66. this.removeDraggable();
  67.  
  68. }
  69.  
  70. getElement(element) {
  71. this.element = document.querySelector(element);
  72. }
  73.  
  74. initDraggable() {
  75. this.element.onmousedown = () => {
  76. this.draggable = this.element;
  77. }
  78. }
  79.  
  80. moveDraggable() {
  81. document.onmousemove = (e) => {
  82.  
  83. let mouseDownX = e.clientX;
  84. let mouseDownY = e.clientY;
  85.  
  86. if (this.draggable == undefined)
  87. return;
  88.  
  89. this.draggable.style.left = mouseDownX + "px";
  90. this.draggable.style.top = mouseDownY + "px";
  91. }
  92. }
  93.  
  94. removeDraggable() {
  95. document.onmouseup = (e) => {
  96. this.draggable = undefined;
  97. }
  98. }
  99.  
  100. }
  101.  
  102.  
  103. new Move('#item2');
  104.  
  105. </script>
  106. </body>
  107.  
  108. </html>
  109.  
trueblue
Po prostu przesuń go o połowę szerokości i wysokości.
KotWButach
Chodzi o to, by element nie przesunął się względem wcześniejszej pozycji a więc, jeżeli chwyciłem go w np prawym dolnym rogu, to żebym za ten róg ciągnął. I problemem jest to gdzie wywoływać i co sad.gif.
trueblue
W momencie łapania oblicz różnicę między położeniem kursora, a położeniem elementu. Tej różnicy używaj podczas przesuwania.
KotWButach
Mam dalej niestety problem, proszę pomóż, co robię źle.
Jeżeli odejmę różnice to box stoi w miejscu sad.gif.

Aktualnie całość wygląda tak:

https://codepen.io/kotbezbutow/pen/VJMbeK

  1. moveDraggable() {
  2. document.onmousemove = (e) => {
  3.  
  4. let elementX = this.element.offsetLeft;
  5. let elementY = this.element.offsetTop;
  6.  
  7. let mouseDownX = e.clientX;
  8. let mouseDownY = e.clientY;
  9.  
  10.  
  11.  
  12. if (this.draggable == undefined) {
  13. return;
  14. }
  15.  
  16. // console.log('elementX ' + elementX);
  17. // console.log('elementY ' + elementY);
  18. // console.log('mouseDownX ' + mouseDownX);
  19. // console.log('mouseDownY ' + mouseDownY);
  20. console.log('x ' + (mouseDownX - elementX));
  21. // console.log('x ' + (mouseDownX - (mouseDownX - elementX)));
  22.  
  23. let roznica = (mouseDownX - elementX);
  24.  
  25. this.draggable.style.left = mouseDownX - roznica + "px";
  26. this.draggable.style.top = mouseDownY - 40 + "px";
  27. }
  28. }


trueblue
Przeczytaj jeszcze raz mój post.
KotWButach
w momencie łapania, dobra będę próbował smile.gif.

Dzieki za pomoc smile.gif
  1. class Move {
  2. constructor(element) {
  3.  
  4. this.border = undefined;
  5. this.draggable = undefined;
  6.  
  7. document.querySelector("body").addEventListener("mousedown", (e) => {
  8.  
  9. // get element and init draggable
  10. this.draggable = e.target.closest(element);
  11.  
  12. let mouseDownX = e.clientX;
  13. let mouseDownY = e.clientY;
  14.  
  15. let elementX = this.draggable.offsetLeft;
  16. let elementY = this.draggable.offsetTop;
  17.  
  18. this.differanceX = mouseDownX - elementX;
  19. this.differanceY = mouseDownY - elementY;
  20.  
  21. // move draggable
  22. document.addEventListener('mousemove', (e) => {
  23.  
  24. // return if end
  25. if (this.draggable == undefined) {
  26. return;
  27. }
  28.  
  29. let mouseDownX = e.clientX;
  30. let mouseDownY = e.clientY;
  31.  
  32. this.draggable.style.left = mouseDownX - this.differanceX + "px";
  33. this.draggable.style.top = mouseDownY - this.differanceY + "px";
  34.  
  35. });
  36.  
  37. document.addEventListener('mouseup', (e) => {
  38. this.draggable = undefined;
  39. });
  40.  
  41. });
  42. }
  43. }
SmokAnalog
Przeciąganie działa ładnie, ale mam sporo uwag do Twojego kodu:

  1. Jeśli parametr nazywa się "element", to powinien przyjmować rzeczywisty element DOM, a nie selektor.
  2. No właśnie, moim zdaniem kod JS powinien działać na elementach, a nie na selektorach.
  3. document.querySelector("body") to po prostu document.body.
  4. Jeśli zrezygnujesz z selektora, to this.draggable = e.target.closest(element) nie będzie miało sensu, bo mechanizm bąbelkowania sam zadba o to, żeby event.target miał możliwość nasłuchiwania mousedown.
  5. Pisze się difference, a nie differance.
  6. Twoje mousemove i mouseup rejestrują się za każdym razem, kiedy rozpoczyna się przeciąganie, czyli jak ktoś będzie przeciągał milion razy, to zarejestruje się milion listenerów mousemove i mouseup.


Bardziej wydajnym pomysłem byłoby rejestrować tylko jedno zdarzenie każdego typu i sprawdzać czy event.target to jeden z elementów, które zarejestrowaliśmy do przeciągania. W ten sposób też elementy nie będą się gryzły - teraz przy próbie wprawienia w ruch kilku elementów wyskakuje błąd, bo this.draggable będzie nullem dla każdego elementu, którego aktualnie nie przeciągamy.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2024 Invision Power Services, Inc.