Enalds
Enalds

Reputation: 47

Pure Javascript How to Zoom Image on mousemove?

I'm trying to create onmousemove event inside the image then show the zoomed image in the right side.

Problem:

  1. When I try to mousemove inside the image, the black box and zoomed image are blinking.
  2. The zoomed image is not match in the blackbox.

How do I do that? May computation is wrong.

This is my code.

<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>

Upvotes: 0

Views: 2069

Answers (2)

Paweł Kołodziejczak
Paweł Kołodziejczak

Reputation: 31

catch source from my e-commerce project (i'm using GSAP library for animation u can create custom CSS class with transitions instead):

<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};
  }
}

Upvotes: 0

T.Shah
T.Shah

Reputation: 2768

I added time delay of half a second, the blinking is gone.

    function getPos(e){


    var delay=500; //1/2  second

    setTimeout(function() {
      //your code to be executed after 1/2 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);


}

Upvotes: 2

Related Questions