Условная установка атрибута стиля в зависимости от размера изображения, полученного через URL-адрес

Моя цель - иметь возможность передать 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() не определено. (что бы это ни стоило, я попытался просто скопировать и вставить неизмененную версию функции и вызвать ее с помощью кнопки, и она работала нормально, предупредив меня о загрузке с размерами)

Условная установка атрибута стиля в зависимости от размера изображения, полученного через URL-адрес

Я получил ту же ошибку при попытке немного другого подхода:

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"
    })
}

Он жалуется, что Image не определено. Попробуйте заменить его на document.createElement('img')

Rikin 31.05.2019 04:02

наверное определился? первая функция работает, и она использует Image, поэтому я думаю, что это большая проблема. Это не то, что я когда-либо видел, чтобы люди говорили импортировать @Rikin

notacorn 31.05.2019 04:04

Я только что посмотрел, и, видимо, это действительный конструктор JS. developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Im‌​age Может быть, React думает иначе, не уверен

Rikin 31.05.2019 04:06
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
3
40
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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.info(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.info(dims);
});

Проблема №2, реагировать на асинхронный рендеринг

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

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

//...

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

спасибо за подробный ответ - я немного лучше знаком с обещаниями, поэтому я решил пойти по этому пути и обновил нижнюю часть своего ответа, чтобы показать, как я интерпретировал ваш ответ, который на данный момент я пробовал печатать как необработанный html и моя функция backgroundCss ничего не возвращает

notacorn 31.05.2019 04:27

@ ark0n Я добавил информацию об использовании его с реакцией

Chris Deacy 31.05.2019 04:40

Другие вопросы по теме