Dynamically change background images in React from local folder - javascript

I've been trying to load background images dynamically on my React app, but it only works when I link to my Google drive. I want to do this locally, and I've pasted the images on the immediate directory. But it still won't load on my app.
I have 21 images from 0-20 all png format in src folder
var bgp = Math.floor(Math.random() * 20);
this.setState({
chrome: color,
photo: bgp,
quote: randomQuote.quote,
author: randomQuote.name
})
render() {
var bodyP = {
backgroundImage: `url(${onUse}.png)`,
transition: 'all linear 2.5s',
height: '100vh',
width: '100vw',
}
return ( <div id = "wrapper" onLoad = {this.getQuote} style = {bodyP} >
</div>
)

if it worked fine with goggle drive before then I'm pretty sure this is a problem with how you've written your directory path.
try creating an and write your path leading to one of these pictures if the image didn't render, then keep trying to find the right way to write your path or take a look at some documentation until u see the image render, after that, u can use the right directory path in your code.
hope this works for u.

I've figured it out. I moved the photo folder to the public folder and then used the (process.env.PUBLIC_URL) file path description to the public path as explained by https://create-react-app.dev/docs/using-the-public-folder/ and navigated to the photo folder. So my code looks like:
getPhoto() {
var bgp = Math.floor(Math.random() * 20);
this.setState({
photo: bgp,
})
}
var onUse = process.env.PUBLIC_URL + "/Quote-photos/"+ this.state.photo + '.png';
var bodyP = {backgroundImage: `url(${onUse})`,
transition: 'all linear 2.5s',
height: '100vh',
width: '100vw'}

Related

React-planner Threejs doesn't load texture

I have installed react-planner that uses three.js as a package into a react app and managed to get it to render etc. The planner uses a catalog that contains several items that have their own respective textures, I have saved this alongside my src folder in the main app as well according to how their demo is set up.
When loading the app in the react app it doesn't load the textures or any images and leaves the elements without the required textures, instead its a simple gray colour in the case of the wall.
However when I run the package by itself through its own webpack config it does manage to load all the required textures and files.
This is the code for the wall:
import {ElementsFactories} from 'react-planner';
const info = {
title: 'wall',
tag: ['wall'],
description: 'Wall with bricks or painted',
image: require('./wall.png'),
visibility: {
catalog: true,
layerElementsVisible: true
}
};
const textures = {
bricks: {
name: 'Bricks',
uri: require('./textures/bricks.jpg'),
lengthRepeatScale: 0.01,
heightRepeatScale: 0.01,
normal: {
uri: require('./textures/bricks-normal.jpg'),
lengthRepeatScale: 0.01,
heightRepeatScale: 0.01,
normalScaleX: 0.8,
normalScaleY: 0.8
}
},
};
export default ElementsFactories.WallFactory('wall', info, textures);
This is the part of my wall-factory-3d.js that I presume takes in the texture and is what I presume responsible for applying the texture to the wall object:
const applyTexture = (material, texture, length, height) => {
let loader = new TextureLoader();
if (texture) {
material.map = loader.load(texture.uri);
material.needsUpdate = true;
material.map.wrapS = RepeatWrapping;
material.map.wrapT = RepeatWrapping;
material.map.repeat.set(length * texture.lengthRepeatScale, height * texture.heightRepeatScale);
if (texture.normal) {
material.normalMap = loader.load(texture.normal.uri);
material.normalScale = new Vector2(texture.normal.normalScaleX, texture.normal.normalScaleY);
material.normalMap.wrapS = RepeatWrapping;
material.normalMap.wrapT = RepeatWrapping;
material.normalMap.repeat.set(length * texture.normal.lengthRepeatScale, height * texture.normal.heightRepeatScale);
}
}
};
The catalog isn't registering the JPG and the PNG files for the textures nor the elements.
This is what I see when I run the app using its own webpack
And this is what I see when I use it as a package, it is getting the planner-element.js file but not registering the textures or any images from the catalog folder for some reason?
What should I look for or investigate? The main app is a standard react app, the package is using older webpack and is a class based app that has no maintainers anymore so its not possible for me to get help from them unfortunately.
I am wondering if it is loading the URL wrong for the textures/images?
Any pointers would be appreciated, thanks!

Split image file in two separate image

I have on my server an image file with an height of 50 000px.
I want to save 2 files of 25 000px each (first and second part of the original image)
Any suggestions about how to do that ?
Thanks
The sharp image package might be useful for this scenario. More specifically the extract method.
I've added a link to the documentation but here's a possible implementation to split up the image.
const sharp = require("sharp");
const originalFilename = "image.jpg";
const image = sharp(originalFilename);
// this is just a placeholder
const imageWidth = 500;
image
.extract({ left: 0, top: 0, width: imageWidth, height: 25000 })
.toFile("top.jpg", function(err) {
// Save the top of the image to a file named "top.jpg"
});
image
.extract({ left: 0, top: 25000, width: imageWidth, height: 25000 })
.toFile("bottom.jpg", function(err) {
// Save the bottom of the image to a file named "bottom.jpg"
});
I'm assuming you can reuse the original sharp image object to call the extract function twice. If not you might need to call the sharp constructor again.

iOS - Setting image src in javascript IPA build with cordova

I have a javascript application for iOS where I take photos and I would like to show them in a image component.
{
xtype: 'image',
itemId: 'camaraFoto1',
id: 'camaraFoto1',c
src: 'img/camara.png',
reference: 'camaraFoto1',
cls: 'imagen_capturada'
}
Once I take the photo, it is stored in a temp directory (cordova.file.tempDirectory) but this directory gets empty when I logout so I can´t use it cause I want persistence.
So I tried to move the photo to other directory (cordova.file.dataDirectroy) and then set the correct src to the image but the image component doesn´t load the image. What could be the problem?
This is part of the code where I take the photo and set the src to the image:
navigator.camera.getPicture(me.photoSuccess, me.photoFailure, {
quality: quality1,
destinationType: navigator.camera.DestinationType.FILE_URI, //DATA_URL
sourceType: navigator.camera.PictureSourceType.CAMERA,
encodingType: navigator.camera.EncodingType.JPEG,
targetWidth: targetWidth1,
targetHeight: targetHeight1,
correctOrientation : correctOrientation1
});
photoSuccess: function (tempImage) {
const newBaseFilesystemPath = cordova.file.dataDirectory;
window.resolveLocalFileSystemURL(
tempImage,
function(fileEntry){
newFileUri = newBaseFilesystemPath;
newFileName = tempImage.substr(tempImage.lastIndexOf('/') + 1) + ".spc";
window.resolveLocalFileSystemURL(newFileUri,
function(dirEntry) {
// move the file to a new directory and rename it
fileEntry.moveTo(dirEntry, newFileName,
function ok() {
var img = Ext.ComponentQuery.query("#camaraFoto1")[0];
img.setSrc(newBaseFilesystemPath + newFileName );
...
Note: if I don´t move the photo from the tempDirectory all this issue works and I can see the image on the component.
These is the full root when I use tempDirectory and dataDirectory. First one works, second one doesn`t:
file:///var/mobile/Containers/Data/Application/827A7500-309C-4521-BC0F-303D6D16AE3D/tmp/cdv_photo_1589965037.jpg
file:///var/mobile/Containers/Data/Application/9E3095A3-4D87-493B-A13D-398051179B54/Library/NoCloud/cdv_photo_1590070416.jpg
Make sure to add the cordova preference in your config.xml file, such as
<preference name="iosExtraFilesystems" value="library,library-nosync" />
and
<preference name="iosPersistentFileLocation" value="Library" />
as stated on cordova docs, see iOS Persistent storage location

loading cached fonts at the right time

I have some webfonts that get loaded via Webfontloader load like this ...
<script src="//ajax.googleapis.com/ajax/libs/webfont/1.5.10/webfont.js"></script>
<script>
WebFont.load({
custom: {
families: ['BlenderProBook', 'BlenderProMedium']
}
});
</script>
And it works great when first loading the page ... Problems is, when refreshing the page it only retrieves the cached fonts when requested in html and not before my ReactJS app runs (when the Webfontloader normally gets them). This is too late for me, because I'm using them in pre-generated SVG.
Is there a way to force it to get the uncached fonts each time? Or better, load the cached fonts at the correct time.
I found a solution to this, which I will take as my answer if no-one else can supply a better one.
My font is being used extensively in the app to calculate text widths and therefore layout ... (which is why it needs to be loaded before the app runs), so I decided to use the text width code as a test to block the app from running.
Here's the code
var testFont = require('./components/svgText.js');
var timer = setInterval(function () {
var test = (testFont('TEST', 'BlenderProBook', 20).width === 39.75);
if (test) {
clearInterval(timer);
Router.run(routes, function (Handler) {
React.render(<Handler/>, document.body);
});
}
}, 50);
where svgTest.js uses Raphael SVG to generate SVG text and retrieve the measurements like this:-
renderedTextSize = function (string, font, fontSize) {
var paper = Raphael(0, 0, 0, 0);
paper.canvas.style.visibility = 'hidden';
var el = paper.text(0, 0, string);
el.attr('font-family', font);
el.attr('font-size', fontSize);
var bBox = el.getBBox();
paper.remove();
return {
width: bBox.width,
height: bBox.height
};
};
module.exports = renderedTextSize;
This seems to work quite nicely, even though it feels a bit hacky to be testing against a magic number (width).

Images not preloaded properly

I am having a jQuery script that loads 15 images and their hover versions (the hover versions are used when... hovering, not when the page loads). In both Chrome and Firefox in the Network tab, i see this :
images/img1.png
images_hover/img1.png
This must mean the hover images are preloaded correctly, but... when i actually hover and those images are used, they are being loaded again. Here is the preload code :
var prel = new Image();
prel.src = "http://hdodov.byethost15.com/color-game/graphics/parts_hover/" + id + ".png";
I tried using the whole path - http://hdodov.byethost15.com/color-game/graphics/parts_hover/ and the short path too (where the root and the script is) - graphics/parts_hover/. It made no difference.
Could this be caused because my images have the same name? They are in different directories though.
For the next question, you really should paste more code, which makes it easier to help you. I checked your URL you provided, but for other people that might have the same problem, it will be hard to understand what went wrong...
OK, as I said, you are always requesting he images again on hover state...
This worked for me:
var context = new Array(15),
canvas = new Array(15),
canvasNum = -1,
hElem,
hElemPrev,
mousePos = {x:-1, y:-1},
images = [], //<-- Store preloaded images here
imagesHover = []; //<-- Store preloaded images here
... then save them on building like this:
function drawMenuItems(id, width, height){
var canNumHolder, createCanvas;
$('#canvas_holder').append($('<canvas></canvas>')
.attr({
width:width,
height:height,
id:id
})
);
canvasNum++;
canvas[canvasNum] = document.getElementById(id);
context[canvasNum] = canvas[canvasNum].getContext('2d');
canNumHolder = canvasNum;
images[id].crossOrigin = 'Anonymous';
images[id].onload = function(){
context[canNumHolder].drawImage(images[id],0,0);
};
images[id].src = 'graphics/parts/' + id + '.png';
//Hover states
imagesHover[id] = new Image();
imagesHover[id].src = "graphics/parts_hover/" + id + ".png";
}
... give just the id...
function hoverStateChange() {
//....rest of the code
if(hElem >= 0){
drawImageOnCanvas(
canvas[hElem],
context[hElem],
"hover", //pass somethink to checke what you want to do
$(canvas[hElem]).attr('id')
);
//....rest of the code
//change to normal texture
if(hElemPrev >= 0){
drawImageOnCanvas(
canvas[hElemPrev],
context[hElemPrev],
"", //pass empty for other state
$(canvas[hElemPrev]).attr('id')
);
$(canvas[hElemPrev]).removeClass('active');
$('#text_holder').removeClass('a' + hElemPrev);
}
.. and finally
function drawImageOnCanvas(canv, contxt, state, src){
contxt.clearRect(0,0,400,400);
if(state == "hover"){
contxt.drawImage(imagesHover[src],0,0);
}else {
contxt.drawImage(images[src],0,0);
}
}
Like this, you chache you images and not calling them again and again...
I hope it helps.
Yuo can preload images with css like this:-
#preload-01 { background: url(http://domain.tld/image-01.png) no-repeat -9999px -9999px; }

Categories