Move the image inside the box without directly following the mouse cursor, but at a slightly faster pace

I am facing an issue with a Vue component that allows me to zoom in on an image and move it around the container. The problem is, when the image is zoomed in, it moves faster than the mouse due to using the scale transform.

Additionally, I noticed that clicking and dragging on the viewport seems to reverse values twice, though this is the only way I can move the square with the mouse.

// JS code here
// CSS code here
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <test></test>
</div>

<script type="text/x-template" id="template">
  <div class="media-360-viewer" ref="container">
    // HTML template here
  </div>
</script>

Any suggestions on how to fix these issues?

Edit

The updated code has been modified based on the accepted answer, but now the viewport square is going out of frame.

// Updated JS code here
// Updated CSS code here
// Updated HTML code here

Answer №1

Avoid Excessive Use of Math.floor

One issue in this problem stems from frequently calling the Math.floor function. Repeatedly using Math.floor can lead to reduced accuracy in subsequent calculations.

To maintain accuracy, it is advisable to round numbers only at the end of your calculation sequence or specifically where the variable is being utilized. For instance:

transform: function() {
  const translateX = Math.floor(this.translateX)
  const translateY = Math.floor(this.translateY)

  return `scale(${this.zoomLevel}) translateX(${translateX}px) translateY(${translateY}px)`;
}

Adjusting Scaling Factor

However, there seems to be a discrepancy in the speed of image movement compared to mouse movements.

This imbalance can be corrected by dividing the value being added to the translation by the scale factor determined by the zoomLevel, as illustrated below:

if (translate.left >= 0 && translate.right <= 0) {
    this.translateX += move.x / this.zoomLevel
}

if (translate.top >= 0 && translate.bottom <= 0) {
    this.translateY += move.y / this.zoomLevel
}

Adjusting Scaling Factor for Viewport

The viewport may still exhibit issues due to scaling effects. To address this, adjust the translation values based on the scale of the viewport stored in this.viewportScale. By combining solutions, consider the following code snippet:

if (translate.left >= 0 && translate.right <= 0) {
    if (viewport) {
        this.translateX += move.x / this.viewportScale
    } else {
        this.translateX += move.x / this.zoomLevel
    }
}

if (translate.top >= 0 && translate.bottom <= 0) {
    if (viewport) {
        this.translateY += move.y / this.viewportScale
    } else {
        this.translateY += move.y / this.zoomLevel
    }
}

Addressing Value Reversal

There appears to be redundant reversal of values when clicking and dragging within the viewport.

To streamline the code and avoid unnecessary value reversals, consider implementing separate inner translate functions that cater to different input sources (viewport or image). This approach results in cleaner code organization and facilitates future enhancements specific to each feature. You could structure your function as follows:

translate (positions, element, zooming, viewport) {
    positions = positions || {
        x: this.startX,
        y: this.startY
    }

    if (viewport) {
        this._translateFromViewport(positions, element, zooming)
    } else {
        this._translateFromImage(positions, element, zooming)
    }

    this.startX = positions.x
    this.startY = positions.y
}

The _translateFromViewport and _translateFromImage functions can contain feature-specific logic.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring the concept of union return types in TypeScript

Hello, I am facing an issue while trying to incorporate TypeScript in a way that may not be its intended use. I have created a custom hook called useGet in React which can return one of the following types: type Response<T> = [T, false, false] | [nul ...

What is the best way to organize text within messages?

Hey there! I have a messaging app with arrays of messages. [{"id":4, "user_id":1, "messageable_id":3, "messageable_type":"conversation", "text":"Text 1", "action":null, "target_id":null, "created_at":"2019-06-17 15:47:55", "updated_at":"2019-06-17 15:47:5 ...

The Vue/Vuetify wrapper component does not automatically pass on the `hide-details` parameter to the input component

I recently crafted a custom wrapper for the v-select input using Vuetify. Along with custom properties, I utilized the v-bind="$props"attribute to inherit all props. Upon testing, I observed that while this method applies to most props, it doesn ...

Altering the dimensions of radio buttons

I am a newcomer to using material-ui. I am currently working on incorporating radio buttons in a component and would like to reduce its size. While inspecting it in Chrome, I was able to adjust the width of the svg icon (1em). However, I am unsure how to a ...

Regular expression for selecting characters and numbers in jQuery using a selector

Can someone help me figure out how to select all IDs like this: r1 r2 r3 etc. and not the other IDs like helloWorld I attempted using the CSS selector with jQuery but I'm having trouble understanding how. I tried $('#r[0-9]') but it didn& ...

I am having trouble getting the (:active) pseudo-class to function properly with the menu on my WordPress theme

Purchased a theme called HelpGuru and encountering issues with the CSS of the menu. Reached out to support but they were unable to assist, directing me to a company that specializes in customizing WordPress themes instead. The link to the demo can be found ...

import all mongoose models in the express app.js

Every time I create a model in my express app's app.js, I find myself having to include the model by writing out the specific path. require('./models/Users') require('./models/Projects') Is there a shortcut or more streamlined wa ...

Saving categories in Laravel 5.7 using Vue.js: A step-by-step guide

Currently, I am utilizing Laravel 5.7 in conjunction with vuejs to showcase the parent_id from a MySQL table containing categories. My objective is to retrieve the name and gather all child categories associated with it regardless of their parent category. ...

The moment a file is uploaded from an HTML page, control is passed on to the servlet

Trying to incorporate file upload functionality in my application, I have implemented the following code in my HTML: <form action="http://localhost:8080/demo/Upload/a" method="post" enctype="multipart/form-data"> <input type="text" name="descript ...

The 3D hover effect is malfunctioning in the Firefox browser

I've been working on a 3D hover effect and my code is functioning properly in Opera and Chrome, but for some reason it's not working in Firefox. I've even attempted using vendor prefixes, but to no avail. The strange thing is that when I rem ...

The AJAX callback is malfunctioning

Attempted to create a basic callback function to become familiar with it, but encountering an issue where it doesn't work upon page load. $(document).ready(getVideoId(function (response) { alert(response); })); function getVideoId(callba ...

How to Dynamically Update Sass Styles with Webpack 2?

Currently, I am in the process of setting up a React application that utilizes Webpack2, webpack-dev-middleware, and HMR for the development phase. One peculiar issue that I have encountered is related to updating .scss files. When I make changes to my .sc ...

Ways to capture targeted requests

Utilizing NestJS and Angular 2, I have noticed that both frameworks have a similar approach when it comes to working with Interceptors. I am currently looking for the best practice to identify specific requests in order to perform additional tasks. When d ...

Learn to leverage JavaScript in Node-RED to dynamically display messages based on selected dropdown options

After reviewing this Node-red flow: https://i.stack.imgur.com/y4aDM.png I am struggling with the implementation in my function. There are 3 options in each dropdown, one for meat type and the other for doneness. Once I select a combination from the drop ...

Using CSS to leverage the power of both Grid and Flex simultaneously

Help Needed: CSS Challenge! I'm not a fan of CSS and can't seem to crack this code conundrum. Here's what I want the end result to look like: https://i.sstatic.net/z06qO.png Current Situation: #newOrderControl { border-style: solid ...

Failure to trigger jQuery.ajax success function on Windows XP operating system

Snippet: $.ajax({ type: "POST", url: "students/login", data:{"data[Student][email]":_email,"data[Student][password]":_password}, beforeSend: function(){ $("#confirm").text(""); }, error: function (xhr, status) { ale ...

How do I create a sliding dropdown notification bar?

Can anyone provide some guidance on how to create a sliding dropdown section for my homepage, similar to the one on this website: . (Please note, be cautious of potential malware) I'm interested in replicating the dropdown section that says "call for ...

Managing numerous range sliders in a Django form

My Request: I am looking to have multiple Range sliders (the number will change based on user selections) on a single page. When the sliders are moved, I want the value to be updated and displayed in a span element, as well as updating the model. The Issu ...

What sets returning a promise from async or a regular function apart?

I have been pondering whether the async keyword is redundant when simply returning a promise for some time now. Let's take a look at this example: async function thePromise() { const v = await Inner(); return v+1; } async function wrapper() ...

React: The peculiar contradiction of useEffect with eventHandler props

Having trouble with this specific example. The issue arises with an Input component that includes an onChange prop to manage internal data changes. Under normal circumstances, if the value is updated externally, the onChange prop does not trigger since t ...