Custom MapBox Icons in React without geojson - reactjs

I am trying to create custom icons for my map markers in my mapbox in React, however essentially all of the existing documentation describes how to accomplish this when you are using a geojson wrapper to define a set amount of markers. This solution doesn't work for me, since the amount of markers for this application needs to be dynamic.
var el = document.createElement("div");
el.className = 'marker';
el.style.backgroundImage = 'url(droneIconSVG.svg)';
el.style.width = "50000px";
el.style.height = "50000px";
console.log(el.style.backgroundImage);
console.log(image01);
var drones = {};
firebase
.database()
.ref("drones")
.on("child_added", function(snapshot) {
var drone = new mapboxgl.Marker(el).setLngLat([snapshot.val().lat, snapshot.val().lng]).addTo(map);
drones[snapshot.val().id] = drone;
});
This code shows the creation of a marker, and assignment of that marker to every "drone" icon that has been added to my real time database in firebase. Any ideas as to why it might not be representing my "droneIconSVG.svg" file properly? It is a normal SVG file that I exported from illustrator.
Thank you

Related

Problem with initializing existing canvas with PixiJs

As titled,
Is it possible to initialize canvas with image on it using Pixi so that i can add filter on top of it? Im using gsap 3.2.6 and Pixi 5.2.4.
I have the canvas created like this (using React btw)
useEffect(() => {
let ctx = imgDisplayer.current.getContext('2d');
let img = new Image();
img.onload = function(){
imgDisplayer.current.width = img.width; // To set canvas width to image width
imgDisplayer.current.height = img.height; // To set canvas height to image height
ctx.drawImage(img, 0, 0);
setCanvas(imgDisplayer.current);
}
img.src = source;
}, []);
That setCanvas is to store the loaded canvas into state, so that i can use it to initialize Pixi.
if (canvas){
const app = new Pixi.Application({
width: 1300,
height: 866,
backgroundColor: 0x000000,
autoResize: true,
view: canvas
});
}
Problem is, this throws me the following error
Error: This browser does not support WebGL. Try using the canvas renderer
If only i could fetch an https image (direct image link) then this wouldn't be a problem, and i can load the image using Pixi.Sprite insteaad.. but because of cross origin, i cannot think of way on how to render the image. I can render it just fine on canvas, but not with Pixi.
The error you pasted is saying that your browser does not support WebGL.
Please check WebGL support on those pages: https://get.webgl.org/ , https://webglreport.com/
Can you try to initialize Pixi on some simpler page just to check if it works for you? I mean, just create simple html page (without React etc), try to setup Pixi there and try to draw anything (some red circle etc).

Loading mesh(OBJ+MTL+JPG) with react-three-fiber, Texture is not working

In my react app, I am trying to make a view page which shows 3d-mesh exported from pix4d. This mesh consists of three types of files, (.obj, .mtl, .jpg) pix4d.com.
I am new, with react-three-fiber, which I suppose is best way to achieve my solution to my problem.
Below is whole code of react component used to load and render 3D-Model.
code
Thanks in Advance!
I want to understand how to attach texture & material to my obj rendered model.
I was looking for this answer for a couple of weeks, finally I've found a way to make it work.
Material loader is not resolving by itself the import of remote files (it does on web, not in mobile, maybe in the future it will). So, I'm creating material and assigning it images by hand.
Something like this:
import { TextureLoader } from 'expo-three';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader';
// useThree is used to get scene reference
import { useThree } from 'react-three-fiber';
const textureLoader = new TextureLoader();
const mapImage = textureLoader.load(require('path/to/image1.png'))
const normalMapImage = textureLoader.load(require('path/to/image2.png'))
Note that TextureLoader from expo-three can handle the file resource returned from require()
const loaderObj = new OBJLoader();
const loaderMtl = new MTLLoader();
export default props => {
const { scene } = useThree();
loaderMtl.load(
'https://url_to/material.mtl',
mtl => {
mtl.preload();
loaderObj.setMaterials(mtl);
loaderObj.load(
'https://url_to/model.obj',
obj => {
// simple logic for an obj with single child
obj.children[0].material.map = mapImage;
obj.children[0].material.normalMap = normalMapImage;
scene.add(obj)
}
)
}
)
return null;
}
This is my first successful attempt to render an obj with mtl including a map and a normal map, so since it works, we can keep updating the code for improvements.
Another way to load model with texture is by specifying the path where your texture has been stored. In one case, mtl + obj + texture files are stored in your react project's directory 'public/models/'. So you can specify the path by calling setPath() function prior loading your material or object file and it should load your texture on the material. You may also want to make sure that in ./mtl file the texture name is correct. It should be called following by map_Kd in .mtl file.
const Model = () => {
const materialLoader = new MTLLoader().setPath('./model/').load(MaterialFile);
const objLoader = new OBJLoader().setMaterials(materialLoader).load(OojectFile);
return <primitive object={objLoader} />;
};

Not allow to require by using variable? [duplicate]

I have read several posts about issues that people are having with React Native and the require() function when trying to require a dynamic resource such as:
Dynamic (fails):
urlName = "sampleData.json";
data = require('../' + urlName);
vs. Static (succeeds):
data = require('../sampleData.json');
I have read on some threads that this is a bug in React Native and in others that this is a feature.
Is there a new way to require a dynamic resource within a function?
Related Posts (all fairly old in React time):
Importing Text from local json file in React native
React Native - Dynamically List/Require Files In Directory
React Native - Image Require Module using Dynamic Names
React Native: how to use require(path) with dynamic urls?
As i have heard of, react's require() only uses static url not variables, that means that you have to do require('/path/file'), take a look at this issue on github and this one for more alternative solutions, there are a couple of other ways to do it!
for e.g
const images = {
profile: {
profile: require('./profile/profile.png'),
comments: require('./profile/comments.png'),
},
image1: require('./image1.jpg'),
image2: require('./image2.jpg'),
};
export default images;
then
import Images from './img/index';
render() {
<Image source={Images.profile.comments} />
}
from this answer
Here is my solution.
Setup
File structure:
app
|--src
|--assets
|--images
|--logos
|--small_kl_logo.png
|--small_a1_logo.png
|--small_kc_logo.png
|--small_nv_logo.png
|--small_other_logo.png
|--index.js
|--SearchableList.js
In index.js, I have this:
const images = {
logos: {
kl: require('./logos/small_kl_logo.png'),
a1: require('./logos/small_a1_logo.png'),
kc: require('./logos/small_kc_logo.png'),
nv: require('./logos/small_nv_logo.png'),
other: require('./logos/small_other_logo.png'),
}
};
export default images;
In my SearchableList.js component, I then imported the Images component like this:
import Images from './assets/images';
I then created a new function imageSelect in my component:
imageSelect = network => {
if (network === null) {
return Images.logos.other;
}
const networkArray = {
'KL': Images.logos.kl,
'A1': Images.logos.a1,
'KC': Images.logos.kc,
'NV': Images.logos.nv,
'Other': Images.logos.other,
};
return networkArray[network];
};
Then in my components render function I call this new imageSelect function to dynamically assign the desired Image based on the value in the this.state.network:
render() {
<Image source={this.imageSelect(this.state.network)} />
}
The value passed into the imageSelect function could be any dynamic string. I just chose to have it set in the state first and then passed in.
I hope this answer helps. :)
For anyone reading this that cannot work with the existing answers, I have an alternative.
First I'll explain my scenario. We have a mono repo with a number of packages (large react-native app). I want to dynamically import a bunch of locale files for i18n without having to keep a central registry in some magic file. There could be a number of teams working in the same monorepo and the DX we want is for package developers to be able to just add their local files in a known folder {{packageName}}/locales/en.json and have our core i18n functionality pick up their strings.
After several less than ideal solutions, I finally landed on https://github.com/kentcdodds/babel-plugin-preval as an ideal solution for us. This is how I did it:
const packageEnFiles = preval`
const fs = require('fs');
const path = require('path');
const paths = [];
const pathToPackages = path.join(__dirname, '../../../../packages/');
fs.readdirSync(pathToPackages)
.filter(name => fs.lstatSync(path.join(pathToPackages, name)).isDirectory())
.forEach(dir => {
if (fs.readdirSync(path.join(pathToPackages, dir)).find(name => name === 'locales')) {
const rawContents = fs.readFileSync(path.join(pathToPackages, dir, 'locales/en.json'), 'utf8');
paths.push({
name: dir,
contents: JSON.parse(rawContents),
});
}
});
module.exports = paths;
`;
Then I can just iterate over this list and add the local files to i18next:
packageEnFiles.forEach(file => {
i18n.addResourceBundle('en', file.name, file.contents);
});
If you need to switch between multiple locally stored images, you can also use this way:
var titleImg;
var textColor;
switch (this.props.data.title) {
case 'Футбол':
titleImg = require('../res/soccer.png');
textColor = '#76a963';
break;
case 'Баскетбол':
titleImg = require('../res/basketball.png');
textColor = '#d47b19';
break;
case 'Хоккей':
titleImg = require('../res/hockey.png');
textColor = '#3381d0';
break;
case 'Теннис':
titleImg = require('../res/tennis.png');
textColor = '#d6b031';
break;
}
In this snippet I change variables titleImg and textColor depending of the prop. I have put this snippet directly in render() method.
I have found that a dynamic path for require() works when it starts with a static string. For example require("./" + path) works, whereas require(path) doesn't.
Simple to dynamic images (using require)
Example array(into state)
this.state={
newimage: require('../../../src/assets/group/kids_room.png'),
randomImages=[
{
image:require('../../../src/assets/group/kids_room.png')
},
{
image:require('../../../src/assets/group/kids_room2.png')
}
,
{
image:require('../../../src/assets/group/kids_room3.png')
}
]
}
Trigger image( like when press button(i select image random number betwenn 0-2))
let setImage=>(){
this.setState({newimage:this.state.randomImages[Math.floor(Math.random() * 3)];
})
}
view
<Image
style={{ width: 30, height: 30 ,zIndex: 500 }}
source={this.state.newimage}
/>
Hey lads I rounded another way to require It's ugly but works. Images dynamically. Instead of storing your URL in the state you store the entire JSX. For an example:
state = {
image: []
};
Instead of
let imageURL = `'../assets/myImage.png'`
this.state.image = imageURL
You use
let greatImage = (<Image source={require(../assets/myImage.png)}></Image>)
this.state.image = greatImage
To render in the JSX
{this.state.image}
You can style your image in the variable too. I had to use some if statements to render some images dynamically and after break my head for 2 hours this was the way that solved my problem. Like I said It's ugly and probably wrong.
Are you using a module bundler like webpack?
If so, you can try require.ensure()
See: https://webpack.js.org/guides/code-splitting/#dynamic-imports
Reading through the docs, I've found a working answer and I'm able to use dynamic images, in the docs they refer to it as Network Images here
https://facebook.github.io/react-native/docs/images#network-images
Not sure if this can be applied to other file types, but as they list require with non image types
You would need to use the uri: call
data = {uri: urlName}
For me I got images working dynamically with this
<Image source={{uri: image}} />
Try the solution mentioned in this thread for Android. This solves the issue but unfortunately, it's only for android.
But make sure to run react-native run-android after every update. Else, the added images won't appear in the app.
This seems to work :
const {
messages,
} = require(`../${dynamicPath}/messages.specific`);

Using Leaflet plugins on react-leaflet

I am building a ReactJs application with react-leaflet.
Problem is that there are a lot of Leaflet plugins that has no support for react-leaflet.
I try to use this plugin
http://kartena.github.io/Leaflet.zoomslider/
Can somebody suggest a solution in this case?
Most Leaflet plugins don't have a React component. You can create custom components for React-Leaflet from the Leaflet plugin.
I was going to say you do it by getting a reference to the map object, but I don't think that's needed. But I have left that in at the base of this response as it a very helpful thing to know.
try the following:
var map = L.map('map', {
zoomsliderControl: true,
zoomControl: false,
layers: [layer]
}).setView([57.7, 11.9], 8);
Where 'map' is the id of the Map element.
===========================================
On your Map element get a reference to the map object.
<Map ref={(m) => this.leaf = m} etc...>
then in your react component.
where you have componentDidMount= () =>{
use the map object to add in the slider
var map = this.leaf.leafletElement;

Font type is different in html and canvas

I'm using html2canvas lib to render my html page to image, and then I put that to PDF using jspdf. But somehow my html page font is different from the font in the PDF file.
$scope.ConvertToPdf = function(obj){
$scope.downloadPdfArr = [];
$scope.downloadPdfArr = angular.copy(obj);
html2canvas($("#widget"),{
onrendered : function(canvas){
var imgData = canvas.toDataURL(
'image/png');
var doc = new jsPDF();
doc.addImage(imgData, 'PNG', 10, 10,200,100);
doc.save('sample-file.pdf');
}
})
}
This is my html page
This is the PDF I'm getting
html2canvas does not claim to handle all types of styling - if there is a font-style property on your page, perhaps it's not being handled correctly or at all. It can differ between browsers too - which browser are you using to get this result?
You can try debugging the html2canvas source in dev tools, such as the functions Font(family, size) and cloneNode(node, javascriptEnabled) to see how exactly the HTML of your page is being processed, and have a look inside the DOM node objects.

Resources