условная установка атрибута стиля в зависимости от размера изображения, выбираемого через URL - PullRequest
0 голосов
/ 31 мая 2019

Моя цель - передать 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 Ответ

1 голос
/ 31 мая 2019

Задача № 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);
});

Promise

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, реагировать на асинхронный рендеринг

Поскольку функции рендеринга реагирующих компонентов являются синхронными, я считаю, что для этого вам необходимо добавить некоторое состояние. Вы можете использовать другой useState хук, как тот, который у вас уже есть. Что-то вроде:

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

//...

// update the state once it's available
getMeta('...').then((dims) => {
    setImageUrl('...');
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...