我想将一张图片按照浏览器缩放比例适应于视口,并保持其长宽比。基本上,所需的行为与使用Chrome或Firefox打开本地图像完全相同。
- 我有一张4896x3264比例的巨大Unsplash图像
- 我想创建一种“沃尔多在哪里”游戏,用户必须缩放以检查图像的每个细节。默认情况下,我希望图像适合屏幕(在这种情况下,高度最大为100%)。然后,用户可以使用ctrl + scroll(或任何其他快捷键)进行缩放。
- 它显示在一个angular 9应用程序中,组件的html如下:
<img src="../../assets/img/Background.webp"/>
我通过我的<router-outlet>
访问此HTML。
所以现在当导航到该页面时,图像以其原始尺寸4896x3264显示,这对于普通屏幕来说太高了。使用CSS,我可以将高度和宽度设置为适应视口(并居中):
img {
max-height: 100%;
display: block;
}
然而,使用这种解决方案后,我无法缩放以查看图像的细节。即使我将缩放到500%,图像也会适合(在我的屏幕上为1536 x 722)。
在浏览器中打开本地图像(Chrome或Firefox)时,我获得了所需的完美行为: 默认情况下(100%缩放),它适合1017x678。我可以通过单击它将其缩放到4896x3264。我可以使用ctrl +滚轮逐渐缩放。 检查控制台时,我发现在我缩放时宽度和高度自动更改:
<img style="-webkit-user-select: none;margin: auto;cursor: zoom-in;"src="file:///D:/Videotec/Background.webp" width="1083" height="722">
有没有办法在我的应用程序中获得此行为?我找到了许多关于使用CSS将图像适配到视口的主题,但我找不到类似于我的项目的内容。由于英语不是我的母语,我可能在网上搜索得很差,请告诉我是否已经解决了类似的问题。实际行为截图:https://ibb.co/DLChrtp 所需默认行为截图:https://ibb.co/p0hLDxn 感谢您的帮助。
编辑: 我不确定是否全面描述了所需的行为(我的词汇限制了我)。有关更多详细信息,请查看@NVRM答案
编辑解决方法: 由于我没有找到现成的解决方案,因此我使用TypeScript + CSS重新创建了该行为。我的想法很简单,就是从响应类(max-height:100%)切换到没有宽度和高度限制的原始类中的ngClass。由于在我的游戏中必须检索单击的精确位置,因此我还将其用于scrollTo以便在所需的坐标上居中视图。 我必须使用lifecycleHook AfterViewChecked,因为我需要在切换类之后滚动视图。 我必须使用卷轴标志(布尔值),否则scrollTo(x,y)也会在我点击scrollOut时触发。 我知道这不是一个干净的解决方案(实际上我比下面的代码更多,处理其他东西,如dblclick等,所以某些部分可能对您不太理想),但它确实完全符合所需的行为,所以我现在要坚持它。
<div #videotecContainer class="videotec-container">
<img
#videotecImage
src="../../assets/img/Videotec.webp"
[ngClass]="zoomed ? 'zoomedIn' : 'zoomedOut'"
(click)="onClick($event)"
/>
</div>
在 .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
}
在 .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;
}