How can we use vanilla JavaScript to implement an image zoom effect on mouse movement?

I'm attempting to implement an onmousemove event within an image that displays a zoomed image on the right side.

Issue:

  1. When I move my mouse inside the image, the black box and zoomed image flicker.
  2. The zoomed image does not align correctly in the black box.

How can I fix this? Perhaps my calculations are incorrect.

Here is my code snippet:

<div>
    <div id="cursor" style="background:black; opacity:0.5; width:100px; height:100px; position:absolute; display:none">
    
    </div>
    <div style="float:left;">
        <img id="img" src="http://www.animenewsnetwork.com/thumbnails/cover400x200/cms/news/102950/26902290903_3c8f2db0ea_b.jpg" onmousemove="getPos(event)" onmouseout="stopTracking()"/>
    </div>
    <div id="zoom" style="width:300px; height:300px; zoom:1; float:left;">
        qwe
    </div>
</div>
<script>
    function getPos(e){
        var x = e.clientX;
        var y = e.clientY;
        var width = document.getElementById("img").clientWidth;
        var height = document.getElementById("img").clientHeight;
        
        document.getElementById("cursor").style.left = x - 50;
        document.getElementById("cursor").style.top = y - 50;
        document.getElementById("cursor").style.display = "inline-block";
        
        document.getElementById("zoom").style.background = "url('http://www.animenewsnetwork.com/thumbnails/cover400x200/cms/news/102950/26902290903_3c8f2db0ea_b.jpg') "+x / width * 100+"% "+y / width * 100+"%";
    }

    function stopTracking(){
        document.getElementById("cursor").style.display = "none";
        document.getElementById("zoom").style.background = "transparent";
    }
</script>

Answer №1

By implementing a time delay of half a second, the annoying blinking effect has been eliminated successfully.

    function getPos(e){
   

    var delay=500; //Half a second

    setTimeout(function() {
      //Code execution after half a second
    var x = e.clientX;
    var y = e.clientY;
    var width = document.getElementById("img").clientWidth;
    var height = document.getElementById("img").clientHeight;

    document.getElementById("cursor").style.left = x - 50;
    document.getElementById("cursor").style.top = y - 50;
    document.getElementById("cursor").style.display = "inline-block";
    document.getElementById("zoom").style.background = "url('http://www.animenewsnetwork.com/thumbnails/cover400x200/cms/news/102950/26902290903_3c8f2db0ea_b.jpg') "+x / width * 100+"% "+y / width * 100+"%";
    }, delay);


}

Answer №2

Obtain the source code from my online store project (I am utilizing the GSAP library for animations, alternatively, you can design a custom CSS class with transitions):

<div class="grid col-10 rel z300">
  <div class="border padt20 padb20 padl20 padr20 zoom--in flex align-center">
    <img class="auto" src="img/prod.jpg" data-zoom="img/prod-large.jpg" alt="">
  </div>
</div>


export class zoom_in_gallery {
  constructor() {
    if (!this.setVars()) return;
    this.setEvents();
  }

  setVars() {
    let _this = this;

    _this.zoom = document.body.getElementsByTagName('section')[0].getElementsByClassName('zoom--in')[0];
    if (!this.zoom) return false;

    _this.img = this.zoom.firstElementChild;
    if (!this.img) return false;

    _this.zoom_pop = false;
    _this.act = false;

    return true;
  }

  setEvents() {
    let _this = this;

    function del(el) => {
      el = typeof el === 'string' ? document.body.getElementsByClassName(el)[0] : el;

      if (!el || !el.parentNode) return;
      return el.parentNode.removeChild(el);
    }

    this.obj.onmove = (e) => {
      if (_this.act) return;
      let y = e.offsetY ? (e.offsetY) : e.pageY - _this.img.offsetTop,
        x = e.offsetX ? (e.offsetX) : e.pageX - _this.img.offsetLeft;

      if (!_this.zoom_pop) {
        _this.zoom_pop = _this.render(e.target.parentNode, `<div class="top0 right0 abs o-hidden border" style="right:calc(-70%);left:initial;height:${_this.zoom.offsetWidth / 1.5}px;width:${_this.zoom.offsetWidth / 1.5}px"><div style="width:100%;height:100%;background: #fff url(${_this.img.dataset.zoom}) 0 0 / cover scroll no-repeat"></div></div>`);
        TweenLite.fromTo(_this.zoom_pop, .3, {autoAlpha: 0}, {autoAlpha: 1});
      }

      _this.zoom_pop.firstElementChild.style.backgroundPosition = `${x / 3.8}% ${y / 3.8}%`;
    };
    
    this.obj.onleave = () => {
      if (!_this.zoom_pop || _this.act) return;
      _this.act = true;

      TweenLite.to(_this.zoom_pop, .3, {
        autoAlpha: 0, onComplete: () => {
         del(_this.zoom_pop);
          _this.zoom_pop = false;
          _this.act = false;
        }
      });
    };

    this.zoom.addEventListener('mousemove', this.obj.onmove);
    this.zoom.addEventListener('mouseout', this.obj.onleave);
  }

  render(relEl, tpl, cfg = {}) {
    if (!relEl) return;
    const parse = typeof cfg.parse === 'undefined' ? true : cfg.parse, child;

    if (tpl.nodeName === 'TEMPLATE') {
      child = document.importNode(tpl.content, true);
    } else if (typeof tpl === 'string') {
      const range = document.createRange();
      range.selectNode(relEl);
      child = range.createContextualFragment(tpl);
    } else {
      child = tpl;
    }

    if (parse) {
      relEl.appendChild(child);
      return relEl.lastElementChild;
    }
    return {rel: relEl, el: child};
  }
}

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

table that can be scrolled horizontally

I am facing an issue similar to the one discussed in this thread about responsive design for html wide table. In essence, my problem involves a table that is wider than the container div, which has ten columns in width (using bootstrap). The challenge aris ...

When attempting to achieve a CSS percent width, the output is given in pixels instead. I am in search of a solution where the percentage remains the same as the

My styling is set as a percentage, like this: <style> #somediv {width:70%} </style> <div id="somediv"></div> jQuery's css() function returns the result in pixels $(document).ready(function(){ var css = $("#somediv").css( ...

Practical applications of flexible layouts in everyday life

I'm currently on the hunt for real-world examples of elastic layouts, specifically those based on using em's for widths. Surprisingly, I haven't been able to find much out there. If anyone knows of any examples, I would greatly appreciate it ...

The header component constantly refreshes upon switching routes in a React application

When clicking on the {Link} and changing the Route, the header component NavBar continues to re-render, even though it is located outside the Switch component from react-router-dom. Here are the relevant files: Main index.js file: import React from &a ...

The CSS fullscreen background appears to function properly in Dev-tools, but fails to display correctly in an actual browser

I recently created a Meteor App/Website and I am encountering an issue with the fullscreen background image at the top of the page (). While the image displays correctly in Chrome Developer tools and Safari Responsive Design mode, it appears zoomed in on ...

Selecting an element using jQuery with the `:eq(i)` selector

I'm attempting to set the height of 10 hi div classes to different values. I am aware of the method to do so. $(".hi:eq(0)").css("height",n[0]); $(".hi:eq(1)").css("height",n[1]); $(".hi:eq(2)").css("height",n[2]); .......... $(".hi:eq(9)").css(" ...

JavaScript: What is the best method for eliminating all square brackets from within the outer array?

let list = [ ["water", "earth"], [6, "light"], [32], ["fire", "air", 9] ]; The example provided shows the list made up of four elements, each being an array. Currently, the length of list is 4. I am curious if there is a way to eliminate all inner square ...

What is the best way to retrieve a file's creation date using the file System module in Node.js

I'm having trouble fetching the filename and file creation date to send to a client. I tried using fs.stat which provides birthtime but does not include the filename. So, my question is: is birthtime equivalent to the file created date? How can I sen ...

Although my header remains stationary, my body content flows smoothly as I scroll

After applying a high z-index to the header, it appears beautifully, but unfortunately, none of the links in other divs are clickable. I seem to be missing something obvious, yet can't pinpoint the issue. Any assistance would be greatly appreciated! ...

Having difficulty displaying a partial view within a view while making an AJAX call

Trying to figure out what's missing in my code. I have a view with some radio buttons and I want to display a different partial view when a radio button is selected. Here's the snippet of my code: Controller public ActionResult Method(string va ...

Using JavaScript to apply styling on images with overlays

I am currently facing an issue with placing an overlay on top of a background image. Despite my efforts, I am unable to get the background color to appear on top of the image. Any helpful suggestions on how to resolve this would be greatly appreciated. M ...

The Javascript driver allows me to search MongoDB's vast database of 500 million documents using regular expressions on two specific fields, without relying on a predefined schema

My MongoDB database contains approximately 500 million documents structured like this: { "_id": objectId, "Name": "John Smith", "Address": "132, My Street, Kingston, New York 12401" } I am looking to ...

My grid layout isn't behaving as expected when using media queries

My current issue involves the implementation of a "main" element with a "grid" display property. I have configured two different layouts for this grid based on the screen size, as seen in the code snippet below: main { display ...

Challenges with jQuery: Appending strings to a dynamically selected element

Hello everyone, I have a question regarding adding the string 'url(" ")' around my Any assistance you can provide would be greatly appreciated. Thank you! $(function() { $('#list li a').hover( function(){ $("#meow").css( " ...

Creating a stunning art exhibition using React Native

Currently, I am in the process of creating a gallery component that utilizes both the scrollview and image APIs. I'm curious about how the scrollview manages its child components when it scrolls down. Does it unmount the parts that are not currently ...

Navigating Floating Elements in Internet Explorer 7 versus Internet Explorer 8, Firefox, Chrome, and Safari

I'm feeling a bit stuck with this issue. The webpage in question is located here - . Currently, it appears fine on IE7 but I am struggling to make it work on other browsers. Right now, I had to place a couple of DIVs inside tables to ensure that the b ...

How to Incorporate a Glyphicon into an ASP.NET Button with Bootstrap

I'm a beginner with bootstrap/asp.net and I think I might be making a mistake somewhere. My goal is to have a bootstrap glyphicon appear next to my button. I believe I am not able to use asp:Button, but instead should use LinkButton. Here is the code ...

What is the best way to adjust the size of a column when hovering

What I am attempting to achieve is, I would like the column box to have a 100% width, and when it is hovered over, I want it to transition to the left, with the width of the column box being about 60%, revealing a second block that shows up as 20% width o ...

retrieve the position of a descendant element in relation to its ancestor element

I'm encountering a challenge while attempting to solve this issue. I have elements representing a child, parent, and grandparent. My goal is to determine the offset position of the child (positioned absolutely) in relation to the grandparent. However, ...

Tooltip remains visible even after formatting in highcharts

I have successfully hidden the datalabels with 0 values by formatting them. However, after formatting the tooltips for 0 valued data in a pie chart, there is an issue where hovering over the 0 valued portion shows a white box as shown in the picture. I hav ...