首页 > 解决方案 > Fitting image to screen and allow default zoom behavior

问题描述

I want to fit an image to the viewport keeping the aspect ratio and the default zoom behavior of the browser. Basically the wanted behavior is exactly like opening a local image with Chrome or Firefox. Here is the detail of my project :

So right now when navigating to this page the image is displayed with its original size 4896x3264 which is way too tall for a regular screen. With CSS I can set the height and width to fit the viewport accordingly (and center it) as follow :

   img {
      max-height: 100%;
      display: block;
    }

However, with this solution I cannot zoom in to see the detail of the image anymore. Even if I zoom to 500% the image will stay fit (on my screen at 1536 x 722).

When opening the local image in the browser (Chrome or Firefox) I obtain the exact wanted behavior : By default (100% zoom) it fits at 1017x678. I can zoom to 4896x3264 by clicking it. And I can gradually zoom with ctrl + scroll. When inspecting the console I see that the width and height automatically changes when I zoom in and out : <img style="-webkit-user-select: none;margin: auto;cursor: zoom-in;"src="file:///D:/Videotec/Background.webp" width="1083" height="722">

Is there a way to get this behavior in my application ? I found a lot of topics on fitting images with css to the viewport but I couldn't find something like my project. As English is not my native language I might have poorly search the web, let me know if something similar has already been addressed.

Actual behavior screenshot : https://ibb.co/DLChrtp

Wanted default behavior screenshot : https://ibb.co/p0hLDxn

Thanks in advance for your help.

EDIT : I am not sure that I described comprehensively the wanted behavior (my vocabulary limits me). Check @NVRM answer for more details

EDIT Workaround : As I didn't find something out of the box I recreated the behavior with Typescript + CSS. My idea was simply to toggle ngClass from a responsive class (max-height: 100%) to a raw class with no width and height limitations. As in my game I have to retrieve the exact position of a click I used it also with scrollTo in order to center the view on the wanted coordinates.
I had to use lifecycleHook AfterViewChecked as I needed to scroll the view after the class was toggled. I had to use a scrolled flag (boolean), otherwise the scrollTo(x,y) was also triggered when I clicked to scrollOut. I know it is not a clean solution (I actually have more code than below, handling other stuff like dblclick etc. so some part might not seems optimal to you) but it does exactly the wanted behavior so I'll stick to it for now.

In .html

<div #videotecContainer class="videotec-container">
  <img
    #videotecImage
    src="../../assets/img/Videotec.webp"
    [ngClass]="zoomed ? 'zoomedIn' : 'zoomedOut'"
    (click)="onClick($event)"
  />
</div>

In .ts :

zoomed: boolean = false;
scrolled: boolean = false;
xPosition: number;
yPosition: number;
@ViewChild("videotecImage", { static: true }) videotecImage: ElementRef;
@ViewChild("videotecContainer", { static: true }) videotecContainer: ElementRef;

onClick(event: any) {
     const coordinates = this.getPixelPositions(event);
     this.xPosition = coordinates.px - coordinates.clientWidth / 2;
     this.yPosition = coordinates.py - coordinates.clientHeight / 2;
     this.zoomImage();
 }

zoomImage() {
    if (this.zoomed && this.scrolled) this.scrolled = false;
    this.zoomed = !this.zoomed;
  }

ngAfterViewChecked() {
    if (this.zoomed && !this.scrolled) {
      this.videotecContainer.nativeElement.scrollTo(
        this.xPosition,
        this.yPosition
      );
      this.scrolled = true;
    }

getPixelPositions(event) {
  //do some calculation based on Wolfgang Fahl answer here : 
  //questions/34867066
}

In .css :

.zoomedOut {
  max-height: 100%;
  max-width: 100%;
  display: block;
  margin: auto;
}

.zoomedIn {
  display: block;
}

#videotecImage {
  overflow: scroll;
}
   
.videotec-container {
  height: 100vh;
  overflow: scroll;
  background-color: black;
}

标签: javascripthtmlcssangularimage

解决方案


不确定,如果这是你所追求的?但基本上,一个 div 背景和一个固定的 witdh,使用一个不响应的绝对单位(如 px),几乎是缩放时的默认行为,它也会缩放图像吗?

单击«整页»查看它与缩放的作用。

div {
  height: 100vh;
  background-image: url("https://i.imgur.com/p2dQlq7.jpg");
  background-size: 500px auto;
  background-repeat: no-repeat;
}
<body>
 <div></div>
</body>


推荐阅读