Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image magnifier in Angular

I am trying to implement a image maginfier on hover.I tried to replicate the code as in w3schools which is purely of Javascript.I am trying to implement the following code in Angular

https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_image_magnifier_glass

I used the above method in typescript and called it from ngOnInit in Angular but i am not able to get any result from the method.I have ensured the id is passed correctly and validated the method is being called .But still not able to get any result .I wish not to use any npm packages for magnifier since most of them had bugs.

component.ts

ngOnInit(){

 this.magnify(imgID, zoom)

 }

magnify(imgID, zoom) {
  var img, glass, w, h, bw;
  img = document.getElementById(imgID);
  /*create magnifier glass:*/
  glass = document.createElement("DIV");
  glass.setAttribute("class", "img-magnifier-glass");
  /*insert magnifier glass:*/
  img.parentElement.insertBefore(glass, img);
  /*set background properties for the magnifier glass:*/
  glass.style.backgroundImage = "url('" + img.src + "')";
  glass.style.backgroundRepeat = "no-repeat";
  glass.style.backgroundSize = (img.width * zoom) + "px " + (img.height * zoom) + "px";
  bw = 3;
  w = glass.offsetWidth / 2;
  h = glass.offsetHeight / 2;
  /*execute a function when someone moves the magnifier glass over the image:*/
  glass.addEventListener("mousemove", moveMagnifier);
  img.addEventListener("mousemove", moveMagnifier);
  /*and also for touch screens:*/
  glass.addEventListener("touchmove", moveMagnifier);
  img.addEventListener("touchmove", moveMagnifier);
  function moveMagnifier(e) {
    var pos, x, y;
    /*prevent any other actions that may occur when moving over the image*/
    e.preventDefault();
    /*get the cursor's x and y positions:*/
    pos = getCursorPos(e);
    x = pos.x;
    y = pos.y;
    /*prevent the magnifier glass from being positioned outside the image:*/
    if (x > img.width - (w / zoom)) {x = img.width - (w / zoom);}
    if (x < w / zoom) {x = w / zoom;}
    if (y > img.height - (h / zoom)) {y = img.height - (h / zoom);}
    if (y < h / zoom) {y = h / zoom;}
    /*set the position of the magnifier glass:*/
    glass.style.left = (x - w) + "px";
    glass.style.top = (y - h) + "px";
    /*display what the magnifier glass "sees":*/
    glass.style.backgroundPosition = "-" + ((x * zoom) - w + bw) + "px -" + ((y * zoom) - h + bw) + "px";
  }
  function getCursorPos(e) {
    var a, x = 0, y = 0;
    e = e || window.event;
    /*get the x and y positions of the image:*/
    a = img.getBoundingClientRect();
    /*calculate the cursor's x and y coordinates, relative to the image:*/
    x = e.pageX - a.left;
    y = e.pageY - a.top;
    /*consider any page scrolling:*/
    x = x - window.pageXOffset;
    y = y - window.pageYOffset;
    return {x : x, y : y};
  }
}
like image 613
Sathya Narayanan GVK Avatar asked May 17 '19 05:05

Sathya Narayanan GVK


1 Answers

Here is a working stackblitz as per your requirements. It shows the implementation of image zoom functionality mentioned on w3school. https://stackblitz.com/edit/angular-w3school-image-magnification

You have not shown your html and css files. So, I am not totally sure but the following might be the reason why zoom is not working for you.

Problem is that img-magnifier-glass div element is created using classical DOM method 'document.createElement'. And then, class 'img-magnifier-glass' is applied to it, again using a classical DOM method (setAttribute). But, in angular, styles are encapsulated. So, if you have added a class definition of '.img-magnifier-glass' in app.component.css then that class won't be applied to glass div since it is not mentioned in the template (app.component.html). See this for more info - https://github.com/angular/angular/issues/7845

To fix this, you can either move definition of class '.img-magnifier-glass' to styles.css (Where global styles are defined)

or you can keep the class in app.component.css but use pseudo-selector ::ng-deep with it. Applying the ::ng-deep pseudo-class to any CSS rule completely disables view-encapsulation for that rule. Any style with ::ng-deep applied becomes a global style.

::ng-deep .img-magnifier-glass {
}

or you can stop style encapsulation for component by specifying

@Component({
// ...
encapsulation: ViewEncapsulation.None, //<<<<< this one!
styles: [
  // ...
]
})

It will be better will be if you use Renderer2 (https://angular.io/api/core/Renderer2) instead for creating dynamic elements like glass element here. Renderer2 will take care of correctly encapsulating class applied on elements created using it.

like image 158
Omkar Rajam Avatar answered Oct 20 '22 17:10

Omkar Rajam