有条件地设置样式属性,具体取决于通过url获取的图像大小

时间:2019-05-31 01:55:52

标签: javascript css reactjs image material-ui

我的目标是能够传递图像url并根据其尺寸决定是否要使用它。为了实现这一点,我使用了一个我在堆栈溢出时发现的函数,该函数应该能够仅使用url返回图像的尺寸。

这是他们回答的确切代码:

function getMeta(url){
    var img = new Image();
    img.onload = function(){
        alert(this.width + " " + this.height)
    };
    img.src = url;
}

出于我的目的,我需要能够评估宽度和高度,因此我进行了修改,并告诉我是否违反了js的一些主要规则:

function getMeta(url){
    var img = new Image();
    img.onload = function(){
        return [this.width, this.height]
    };
    img.src = url;
}

有了这个功能,我就可以用我准备的另一个功能来调用它:

function backgroundCss(url){
    const dims = getMeta(url);
    return (dims[0] >= 1000 && dims[1] >= 300) ? `url(${url})` : "none"
}

并在我的样式属性中调用它:

<Grid item xs={15} md={6} style={{
      backgroundImage: backgroundCss(url)
}}>

对我而言,未经训练的我的方法似乎很合理且没有错误,但是我不断收到此错误,指出未定义Image()。 (对于它的价值,我尝试简单地复制粘贴该函数的未更改版本,然后使用按钮调用它,并且效果很好,警告我加载了尺寸)

enter image description here

尝试稍微不同的方法时出现相同的错误:

const [imageText, setImageText] = React.useState(null);
function getMeta(url){
    var img = new Image();
    img.src = url;
    if(imageText == null){
        img.onload = () => setImageText((img.width >= 1000 && img.height >= 300) ? `url(${url})` : "none");
        getMeta(url);
        return false;
    }
    return imageText;
}
...
<Grid item xs={15} md={6} style={{
      backgroundImage: getMeta(url)
}}>

我正在尝试做的可能吗?我在哪里错了?

编辑:这是正确的方向吗?

function getMeta(url){
    return new Promise((resolve) => {
        var img = new Image();
        img.onload = function(){
            resolve([this.width, this.height]);
        };
        img.src = url;
    })
}

function backgroundCss(url) {
    getMeta(url).then((dims) => {
        return (dims[0] >= 1000 && dims[1] >= 300) ? `url(${url})` : "none"
    })
}

1 个答案:

答案 0 :(得分:1)

问题1,异步代码

您在return处理程序中的onload语句没有按照您的想法做:

function getMeta(url){
    var img = new Image();
    img.onload = function(){
        return [this.width, this.height]
        // ^^^ this returns for the `onload` handler, not `getMeta`
    };
    img.src = url;
}

为了解决此问题,您需要使用“回调”或Promise,以便一旦可用就可以异步提供返回值。

回调

function getMeta(url, callback){
    var img = new Image();
    img.onload = function(){
        // trigger the provided callback with the return value
        callback([this.width, this.height]);
    };
    img.src = url;
}

// used like so
getMeta('...', (dims) => {
    console.log(dims);
});

承诺

function getMeta(url, callback){
    return new Promise((resolve) => {
        var img = new Image();
        img.onload = function(){
            // resolve the promise with the return value
            resolve([this.width, this.height]);
        };
        img.src = url;
    })
}

// used like so
getMeta('...').then((dims) => {
    console.log(dims);
});

问题2,做出异步呈现

由于react组件渲染功能是同步的,因此我相信您需要为此添加一些状态。您可以使用另一个useState钩子,就像您已有的钩子一样。像这样:

const [imageUrl, setImageUrl] = React.useState(null);

//...

// update the state once it's available
getMeta('...').then((dims) => {
    setImageUrl('...');
});