Моя цель - иметь возможность передать 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() не определено. (что бы это ни стоило, я попытался просто скопировать и вставить неизмененную версию функции и вызвать ее с помощью кнопки, и она работала нормально, предупредив меня о загрузке с размерами)
Я получил ту же ошибку при попытке немного другого подхода:
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
, поэтому я думаю, что это большая проблема. Это не то, что я когда-либо видел, чтобы люди говорили импортировать @Rikin
Я только что посмотрел, и, видимо, это действительный конструктор JS. developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image Может быть, React думает иначе, не уверен
Ваш оператор 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);
});
Поскольку функции рендеринга реагирующих компонентов синхронны, я считаю, что вам нужно добавить для этого какое-то состояние. Вы можете использовать другой крючок useState
, такой как тот, который у вас уже есть. Что-то типа:
const [imageUrl, setImageUrl] = React.useState(null);
//...
// update the state once it's available
getMeta('...').then((dims) => {
setImageUrl('...');
});
спасибо за подробный ответ - я немного лучше знаком с обещаниями, поэтому я решил пойти по этому пути и обновил нижнюю часть своего ответа, чтобы показать, как я интерпретировал ваш ответ, который на данный момент я пробовал печатать как необработанный html и моя функция backgroundCss
ничего не возвращает
@ ark0n Я добавил информацию об использовании его с реакцией
Он жалуется, что
Image
не определено. Попробуйте заменить его наdocument.createElement('img')