通过 js 检索和设置动态加载的图像大小

Retrieving and setting dynamically loaded image sizes via js

考虑这个 javascript 代码:

const profileImageURL = 'https://api.images.com/image/' + id +'/profile';
let profileImage = [];

async function getProfileImage() {
    const response = await fetch(profileImageURL);
    profileImage = await response.json();
};

和这个精巧的模板代码:

<div class="thumbImg">
    {#await getProfileImage()}
    <div class='spinnerHolder'
        in:fade={{duration: 500}} 
        out:fade={{duration: 500}} 
        on:introstart={() => doneLoading = false} 
        on:outroend={() => doneLoading = true}
        >
        <svg class="spinner" viewBox="0 0 50 50">
            <circle class="path" cx="25" cy="25" r="20" fill="none" stroke-width="5"></circle>
        </svg>
    </div>
    {:then value}
        {#if doneLoading}
            <img transition:fade alt='profile-image' src={profileImage.url}/>
        {/if}
    {/await}
</div>

和css:

.thumbImg {
    width: 64px;
    height: 64px;
    display:inline-block;
    background-color: var(--border-color);
    border: none;
    border-radius: var(--large-radius);
    overflow: hidden;

    img {
        min-width: 64px;
        border-radius: var(--large-radius);
        border-image-width: 0;
    }
}

以上加载的图像到达不同的宽度和高度。一些肖像和一些风景。它们都需要显示在一个 64px x 64px 的正方形 1:1 框中,侧面或底部没有白色 space。我怎样才能保持这些动态加载图像的纵横比,以便它们根据需要填充宽度或高度?理想情况下,它们也会偏移,因此它们位于 1:1 框的中心。

问题的视觉示例:

您可以使用百分比值使图像相对于父级 div 的宽度和高度,或者只将图像设置为所需的最大宽度和最大高度

.thumbImg {
    max-width: 64px;
    max-height: 64px;
    display:inline-block;
    background-color: var(--border-color);
    border: none;
    border-radius: var(--large-radius);
    overflow: hidden;

    img {
        max-width: 100%; //relative to the parent DIV
        border-radius: var(--large-radius);
        border-image-width: 0;
    }
}

根据下面 Rich 的评论更新了答案

您可以结合使用 object-fit and object-position CSS 属性来微调图像在其内容框中的显示方式:

.thumbImg {
    width: 64px;
    height: 64px;
    display:inline-block;
    background-color: var(--border-color);
    border: none;
    border-radius: var(--large-radius);
    overflow: hidden;

    img {
        height: 64px;
        width: 64px;
        object-fit: cover; // this will make the image cover the content box, clipping horizontally if the original image is landscape orientation, or vertically if it is portrait orientation
        object-position: 50% 50%; // this will center the image in the content box (i.e. clip on the left & right if source is landscape and clip top & bottom if source is portrait)
    }
}

有了这个,您就不需要再修改代码了。

原始答案,使用 CSS 背景图片

您可以使用背景图片 CSS 属性而不是 img 标签来实现所需的定位,例如:

.avatar {
    height: 64px;
    width: 64px;
    background-size: cover; // this will make the image cover the div, clipping horizontally if the original image is landscape orientation, or vertically if it is portrait orientation
    background-position: 50% 50%; // this will center the image (i.e. clip on the left & right if source is landscape and clip top & bottom if source is portrait)
}

有了这个,您所要做的就是用 <div class="avatar"> 标签替换 <img> 标签,并动态设置背景图片源:

<div class="thumbImg">
    {#await getProfileImage()}
    <div class='spinnerHolder'
        in:fade={{duration: 500}} 
        out:fade={{duration: 500}} 
        on:introstart={() => doneLoading = false} 
        on:outroend={() => doneLoading = true}
        >
        <svg class="spinner" viewBox="0 0 50 50">
            <circle class="path" cx="25" cy="25" r="20" fill="none" stroke-width="5"></circle>
        </svg>
    </div>
    {:then value}
        {#if doneLoading}
            <div
                transition:fade
                class="avatar"
                alt="Profile image"
                style="background-image: url('{profileImage.url}')"
            />
        {/if}
    {/await}
</div>

当然,缺点是您不再使用原生图像标签,也许这对您很重要。从好的方面来说,它无需使用基于 javascript 的 DOM 操作即可工作。