fix(ui): use pixel-exact transform positioning for avatar display instead of background-size formula

This commit is contained in:
2026-07-09 14:43:52 +02:00
parent 52b88a3ba4
commit c9f08ea48e
4 changed files with 40 additions and 22 deletions

View File

@@ -36,13 +36,13 @@
<div class="cosplayer-banner-content">
<div class="cosplayer-avatar">
@if (person.ProfileAssetId.HasValue) {
var cx0 = person.ProfileCropX ?? 50;
var cy0 = person.ProfileCropY ?? 50;
var zoom0 = person.ProfileCropZoom ?? 0.6f;
var bgPosX = zoom0 >= 1 ? 50 : (float)((50 - cx0 / zoom0) / (1 - 1.0 / zoom0));
var bgPosY = zoom0 >= 1 ? 50 : (float)((50 - cy0 / zoom0) / (1 - 1.0 / zoom0));
<div class="cosplayer-avatar-img"
style="background-image: url('@ThumbUrl(person.ProfileAssetId.Value)'); background-position: @bgPosX% @bgPosY%; background-size: calc(100% / @zoom0)">
var cx = person.ProfileCropX ?? 50;
var cy = person.ProfileCropY ?? 50;
var z = person.ProfileCropZoom ?? 0.6f;
<div class="cosplayer-avatar-clip">
<img src="@ThumbUrl(person.ProfileAssetId.Value)" alt=""
class="cosplayer-avatar-img"
style="width: calc(100% / @z); transform: translate(calc(-@cx * 1%), calc(-@cy * 1%))" />
</div>
} else {
<i class="bi bi-person-circle cosplayer-avatar-placeholder"></i>

View File

@@ -52,13 +52,20 @@
flex-shrink: 0;
}
.cosplayer-avatar-img {
.cosplayer-avatar-clip {
width: 100%;
height: 100%;
border-radius: 50%;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
overflow: hidden;
position: relative;
}
.cosplayer-avatar-img {
position: absolute;
left: 50%;
top: 50%;
height: auto;
display: block;
}
.cosplayer-avatar-placeholder {

View File

@@ -37,12 +37,14 @@
var cx1 = person.ProfileCropX ?? 50;
var cy1 = person.ProfileCropY ?? 50;
var zoom1 = person.ProfileCropZoom ?? 0.6f;
var bgPX = zoom1 >= 1 ? 50 : (float)((50 - cx1 / zoom1) / (1 - 1.0 / zoom1));
var bgPY = zoom1 >= 1 ? 50 : (float)((50 - cy1 / zoom1) / (1 - 1.0 / zoom1));
<div class="cosplayer-card-img"
style="background-image: url('@ThumbUrl(person.ProfileAssetId.Value)'); background-position: @bgPX% @bgPY%; background-size: calc(100% / @zoom1)"></div>
<div class="cosplayer-card-fallback" style="display:none">
<i class="bi bi-person-circle"></i>
<div class="cosplayer-card-img-wrap">
<img src="@ThumbUrl(person.ProfileAssetId.Value)" alt=""
class="cosplayer-card-img"
style="width: calc(100% / @zoom1); transform: translate(calc(-@cx1 * 1%), calc(-@cy1 * 1%))"
onerror="this.style.display='none';this.nextElementSibling.style.display='flex'" />
<div class="cosplayer-card-fallback" style="display:none">
<i class="bi bi-person-circle"></i>
</div>
</div>
} else {
<div class="cosplayer-card-fallback">

View File

@@ -19,15 +19,24 @@
filter: brightness(1.15);
}
.cosplayer-card-img {
.cosplayer-card-img-wrap {
width: 100%;
height: 100%;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
overflow: hidden;
position: absolute;
top: 0;
left: 0;
}
.cosplayer-card-fallback {
.cosplayer-card-img {
position: absolute;
left: 50%;
top: 50%;
height: auto;
display: block;
}
.cosplayer-card-img-wrap .cosplayer-card-fallback {
width: 100%;
height: 100%;
display: flex;