Мышь перемещается с помощью мыши - PullRequest
1 голос
/ 27 октября 2019

Я пытаюсь добиться этой (построенной с использованием веб-потока) анимации и взаимодействия при наведении на элемент, но не могу этого сделать. Я нашел этот ответ здесь, но когда я попытался изменить его с помощью функции наведения, я все еще не мог заставить его работать.

Вот что я пробовал.

// Maximum offset for image
        var maxDeltaX = 50,
            maxDeltaY = 50,
            viewportWidth = 0,
            viewportHeight = 0,
            mouseX = 0,
            mouseY = 0,
            translateX = 0,
            translateY = 0;
        // Bind mousemove event to document
        jQuery('.image-content-right').on('mousemove', function(e) {
            // Get viewport dimensions
            viewportWidth = document.documentElement.clientWidth,
                viewportHeight = document.documentElement.clientHeight;
            // Get relative mouse positions to viewport
            // Original range: [0, 1]
            // Should be in the range of -1 to 1, since we want to move left/right
            // Transform by multipling by 2 and minus 1
            // Output range: [-1, 1]
            mouseX = e.pageX / viewportWidth * 2 - 1,
            mouseY = e.pageY / viewportHeight * 2 - 1;
            // Calculate how much to transform the image
            translateX = mouseX * maxDeltaX,
            translateY = mouseY * maxDeltaY;
            jQuery('.cyan').css('transform', 'translate(' + translateX + 'px, ' + translateY + 'px)');
            jQuery('.small-cyan').css('transform', 'translate(' + translateX + 'px, ' + translateY + 'px)');
            jQuery('.small-darktangirine').css('transform', 'translate(' + translateX + 'px, ' + translateY + 'px)');
        }).hover(function() {
            jQuery('.cyan').css('transform', 'translate(' + translateX + 'px, ' + translateY + 'px)');
            jQuery('.small-cyan').css('transform', 'translate(' + translateX + 'px, ' + translateY + 'px)');
            jQuery('.small-darktangirine').css('transform', 'translate(' + translateX + 'px, ' + translateY + 'px)');
        })

Это немного неуклюже и не так гладко, как то, чего я хочу достичь, и я бы хотел, чтобы оно вернулось в исходное положение, когда не зависло.

Ответы [ 3 ]

0 голосов
/ 27 октября 2019

Я не слишком уверен, как бы вы на самом деле сделали намного больше, чтобы сделать эту функцию немного более плавной, учитывая ее реальную зависимость от того, как часто сам jQuery будет выполнять свои события. На данный момент, возможно, я бы хотел разделить весь код в объявлении события jQuery на их соответствующие функции. Вам будет намного легче и чище работать с ним:)

function animateElementOnMouseMove() {
   // your translate code
}
function animateElementOnMouseHover() {
   // your initial hover animation code
}
$('.image-content-right').on('mousemove', animateElementOnMouseMove)
                         .on('hover', animateElementOnMouseHover);

, чтобы он вернулся в положение, в котором он находился, прежде чем вы сможете сохранить исходную непереведенную позицию каждого изэлементы ИЛИ, вы можете сохранить каждый из переводов в переменную count, а затем "отменить" переводы после того, как элемент стал не сфокусированным.

like:

var elementTranslateCountX = 0;
var elementTranslateCountY = 0;

// ON TRANSLATE
elementTranslateCountX += translateX;
elementTranslateCountY += translateY;

0 голосов
/ 27 октября 2019

По внешнему виду и ощущению веб-потока (если я правильно понимаю вашу цель) вы хотите иметь возможность перемещать ваш объект на полную величину maxDeltaX / Y в пределах области наведения. Если это так, ваша математика нуждается в некоторых корректировках: вам нужно определить источник (центр движущегося объекта, скорее всего) и нормализовать до [-1, 1] области наведения вокруг источника. Размещение объекта в мертвой точке окна наведения упрощает вычисления. Я публикую код во фрагменте, но его следует запускать на полной странице, потому что координаты рассчитаны неправильно. Как ни странно, если я запускаю его на codepen , он работает как положено в Chrome, но не в Safari. Чтобы избежать этой проблемы, вы должны обернуть все в родительский div и вычислить координаты относительно него

const page = document.getElementById("page-id");
const area = document.getElementById("area-id");
const box = document.getElementById("box-id");

// we want to move the object by 50px at most
const maxDeltaX = 50;
const maxDeltaY = 50;

let pageBox = page.getBoundingClientRect();
let pageTopLeft = {
  x: pageBox.x,
  y: pageBox.y
};

let areaBox = area.getBoundingClientRect();
let areaRange = {
  w: areaBox.width / 2.0,
  h: areaBox.height / 2.0
};

let boxBox = box.getBoundingClientRect();
let transformOrigin = {
  x: boxBox.x + (boxBox.width / 2.0),
  y: boxBox.y + (boxBox.height / 2.0)
};

// multipliers allow the full delta displacement within the hover area range
let multX = maxDeltaX / areaRange.w;
let multY = maxDeltaY / areaRange.h;

area.addEventListener("mousemove", onMove);
area.addEventListener("mouseleave", onLeave);
window.addEventListener("resize", onResize);

// mouse coords are computed wrt the wrapper top left corner and their distance from the object center is normalized
function onMove(e) {
  let dx = (((e.clientX - pageTopLeft.x) - transformOrigin.x));
  let dy = (((e.clientY - pageTopLeft.y) - transformOrigin.y));
  box.style.transform = "translate3d(" + (dx * multX) + "px, " + (dy * multY) + "px, 0)";
  
  /*
  // or you can add some fancy rotation as well lol
  let rotationDeg = Math.atan2(dy,dx) * (180/Math.PI);
  let rotationString = "rotate(" + rotationDeg + "deg)"; 
  box.style.transform = "translate3d(" + (dx * multX) + "px, " + (dy * multY) + "px, 0) " + rotationString;
  */
}

function onLeave(e) {
  box.style.transform = "translate3d(0, 0, 0)";
}

function onResize(e) {
  // redefine all the "let" variables
}
* {
  margin: 0;
  padding: 0;
}

.page {
  position: relative;
  width: 100%;
  height: 100vh;
  background-color: #ddd;
  display: grid;
  place-items: center;
}

.hover-area {
  position: relative;
  width: 50%;
  height: 100%;
  background-color: #888;
}

.box {
  position: absolute;
  left: calc(50% - 25px);
  top: calc(50% - 25px);
  width: 50px;
  height: 50px;
  border-radius: 25px;
  background-image: linear-gradient(45deg, #000, #aaa);
  transform: translate3d(0, 0, 0);
  transition: all 0.2s;
  will-change: transform;
}
<div id="page-id" class="page">
  <div id="area-id" class="hover-area">
    <div id="box-id" class="box" />
  </div>
</div>

Обратите внимание, что в Chrome работает плавнее, чем в Safari. Я не уверен, что divs и css - лучший способ для выступления. Если я неправильно понял окончательный результат, объясните подробнее, и я постараюсь помочь.

0 голосов
/ 27 октября 2019

Я представляю вам ... самый грязный (но работающий) код когда-либо!

Я думаю Я смог заставить его работать, добавив пару классов к элементам, которые вы хотитеперемещать и отслеживать, наведена ли мышь на изображение или нет.

Прежде всего, когда мышь наведет курсор на изображение, отследите состояние и удалите некоторые классы, которые означают, что элементы переводятся.

let hover = false;
    $(".image-content-right").hover(
        () => {
            hover = true;
            $(".cyan").removeClass("translated");
            $(".small-cyan").removeClass("translated");
            $(".small-darktangirine").removeClass("translated");
        },
        () => (hover = false)
    );

Теперь, когда вы знаете, когда мышь наводит курсор на изображение, вы можете использовать эту информацию, чтобы решить, когда переводить изображение.

  $(document).on("mousemove", function(e) {
        // If the mouse if currently hovering the image
        if (hover) {
            (viewportWidth = document.documentElement.clientWidth),
                (viewportHeight = document.documentElement.clientHeight);
            (mouseX = (e.pageX / viewportWidth) * 2 - 1),
                (mouseY = (e.pageY / viewportHeight) * 2 - 1);
            (translateX = mouseX * maxDeltaX),
                (translateY = mouseY * maxDeltaY);

            // Translate the elements
            jQuery(".cyan").css(
                "transform",
                "translate(" + translateX + "px, " + translateY + "px)"
            );
            jQuery(".small-cyan").css(
                "transform",
                "translate(" + translateX + "px, " + translateY + "px)"
            );
            jQuery(".small-darktangirine").css(
                "transform",
                "translate(" + translateX + "px, " + translateY + "px)"
            );
        } else {
            // If the mouse is no longer hovering the image, add a class that
            // adds a smooth transition to the elements, and translate them back
            $(".cyan")
                .addClass("translated")
                .css("transform", "translate(" + 0 + "px, " + 0 + "px)");
            $(".small-cyan")
                .addClass("translated")
                .css("transform", "translate(" + 0 + "px, " + 0 + "px)");
            $(".small-darktangirine")
                .addClass("translated")
                .css("transform", "translate(" + 0 + "px, " + 0 + "px)");
        }
    });

Для получения плавного изображенияВернувшись в исходное положение (вместо мгновенного возврата назад), я добавил немного стиля перехода в класс transform.

.translated {
    /* This will make the transition back to the original spot smooth */
    transition-duration: 0.2s;
    transition-timing-function: linear;
}

Надеюсь, это сработает для вас, извините, это так грязно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...