You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js图片纹理如何实现缩放适配并居中显示?

图片适配相框区域问题

我尝试将图片适配到相框及类似区域中,只有部分与图片尺寸相近的相框能正常显示,多数情况下无法正确适配。

原图

原图

异常适配效果

异常效果1
异常效果2
异常效果3
异常效果4

当前代码(仅适配尺寸相近的相框)

var texture = null; 
var material = null
const loader = new THREE.TextureLoader() 
texture = await loader.load(media, async img => {  
    if(invertX) {
        texture.wrapS = THREE.RepeatWrapping; 
            texture.repeat.x = - 1; 
    }

    if(invertY) {
        texture.flipY = false;
    } 
    material = new THREE.MeshBasicMaterial({
        map: texture
    });  
    elm.material = material;  
});

尝试过的无效代码片段

// const planeGeom = new THREE.PlaneGeometry(1,1)//(16, 9)   
// const planeAspect = planeGeom.parameters.width / planeGeom.parameters.height;
// const imageAspect = texture.image.width / texture.image.height; 
// const aspect = imageAspect / planeAspect;  

// 无效
// let imgRatio = img.image.width / img.image.height;
// let planeGeom = new THREE.PlaneGeometry(1,1)//16, 9) 
// let planeRatio = planeGeom.parameters.width / planeGeom.parameters.height; 
// texture.wrapS =  THREE.RepeatWrapping; // 
// texture.repeat.x = planeRatio / imgRatio;
// texture.offset.x = -0.5 * ((planeRatio / imgRatio) - 1);  

// 同样无效
// const aspectOfPlane = planeGeom.parameters.width / planeGeom.parameters.height;
// const aspectOfImage = image.width / image.height;
// let yScale = 1;
// let xScale = aspectOfPlane / aspectOfImage;
// if (xScale > 1) { // 无法覆盖,改用x轴基准
// xScale = 1;
// yScale = aspectOfImage / aspectOfPlane;
// }
// texture.repeat.set(xScale, yScale);
// texture.offset.set((1 - xScale) / 2, (1 - yScale) / 2);

// 另一次尝试,还是不行
// var repeatX, repeatY;
// texture.wrapS = THREE.RepeatWrapping;
// texture.wrapT = THREE.RepeatWrapping;
// if (img.image.height < img.image.width) {
//   repeatX = planeGeom.parameters.width  * img.image.height / (planeGeom.parameters.height *img.image.width);
//   repeatY = 1;
//   texture.repeat.set(repeatX, repeatY);
//   texture.offset.x = (repeatX - 1) / 2 * -1;
// } else {
//   repeatX = 1;
//   repeatY = planeGeom.parameters.width * img.image.width / (planeGeom.parameters.height  * img.image.height);
//   texture.repeat.set(repeatX, repeatY);
//   texture.offset.y = (repeatY - 1) / 2 * -1;
// } 

解决方案:自动缩放居中适配

核心是对比图片与相框平面的宽高比,通过调整纹理的repeat和offset参数,实现类似CSS object-fit的适配效果,以下提供两种常用适配方案:

方案1:覆盖式适配(填满相框,裁剪超出部分)

var texture = null; 
var material = null;
const loader = new THREE.TextureLoader();

texture = await loader.load(media, async (img) => {  
    // 保留原翻转逻辑
    if(invertX) {
        texture.wrapS = THREE.RepeatWrapping; 
        texture.repeat.x = -1; 
    }
    if(invertY) {
        texture.flipY = false;
    } 

    // 获取图片和相框平面的宽高比
    const imageAspect = img.width / img.height;
    const planeGeom = elm.geometry; // elm为你的相框网格对象
    const planeAspect = planeGeom.parameters.width / planeGeom.parameters.height;

    let repeatX, repeatY;
    let offsetX = 0, offsetY = 0;

    // 计算适配比例
    if (imageAspect > planeAspect) {
        // 图片更宽,按高度适配,裁剪左右
        repeatY = 1;
        repeatX = imageAspect / planeAspect;
        offsetX = (1 - repeatX) / 2;
    } else {
        // 图片更高,按宽度适配,裁剪上下
        repeatX = 1;
        repeatY = planeAspect / imageAspect;
        offsetY = (1 - repeatY) / 2;
    }

    // 设置纹理参数,避免重复显示
    texture.wrapS = THREE.ClampToEdgeWrapping;
    texture.wrapT = THREE.ClampToEdgeWrapping;
    texture.repeat.set(repeatX, repeatY);
    texture.offset.set(offsetX, offsetY);

    // 创建并应用材质
    material = new THREE.MeshBasicMaterial({
        map: texture,
        side: THREE.DoubleSide // 可选,根据相框是否需要双面显示
    });  
    elm.material = material;  
});

方案2:包含式适配(完整显示图片,留白填充)

如果需要完整展示图片,仅调整比例计算逻辑即可:

// 替换方案1中的比例计算部分
if (imageAspect > planeAspect) {
    // 图片更宽,按宽度适配,上下留白
    repeatX = 1;
    repeatY = planeAspect / imageAspect;
    offsetY = (1 - repeatY) / 2;
} else {
    // 图片更高,按高度适配,左右留白
    repeatY = 1;
    repeatX = imageAspect / planeAspect;
    offsetX = (1 - repeatX) / 2;
}

内容的提问来源于stack exchange,提问作者Caner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 17:57:27