How to do a custom interactive "map" with an image with React? - reactjs

I'm trying to set up an interactive "map" using react but I don't see how to set it up.
my interactive map is an aerial image of a place on which I would like to add hotspots that display a preview of the place with another image.
Afterwards if I click on a preview I would like to display the image in real size but I don't see how to do it...
I use React
I am open to any advice and any proposal!
thank you all

Look into Leaflet https://leafletjs.com/reference-1.6.0.html, it has npm packages that integrate it with react https://react-leaflet.js.org/.
Leaflet allows you to display a map and create custom HTML based Marker components. These markers can listen to user interaction events such as onClick and onMouseOver. On catching a user click or hover event, you can render whatever you need on top of the marker - such as your image, maybe with a nice title, description or whatever else you might need.
On clicking the image, you might want to display the image with different CSS styles in another view, so that you can display it in full width and height, or you might even setup a link to the original image URL, which would be much simpler, but at the same time it would drive users temporarily out of your site.
import React from 'react'
import { divIcon } from 'leaflet'
import { Marker } from 'react-leaflet'
import { renderToStaticMarkup } from 'react-dom/server'
import PropTypes from 'proptypes'
import 'leaflet/dist/leaflet.css'
const Index = props => {
const iconMarkup = renderToStaticMarkup(
<i
className="dispatcher-marker fa fa-map-marker-alt"
style={{ color: props.location.color }}
/>
)
const customMarkerIcon = divIcon({
html: iconMarkup
})
return (
<Marker
position={[ props.location.lat, props.location.lng ]}
icon={customMarkerIcon}
opacity={props.opacity}
onClick={() => props.handleClick(props.location.id, props.route)}
/>
)
}
Index.propTypes = {
handleClick: PropTypes.func,
location: PropTypes.object.isRequired,
route: PropTypes.object.isRequired,
opacity: PropTypes.number.isRequired,
}
export default Index

Related

How can you use images in a list of objects and use them in react?

I imported pictures into my portfolio component and used each of them as a property in a list of objects. But when I try to send them over as a prop, the image disappears, and instead shows up as a missing picture. If I made an image tag with the pictures within the component I import them in, they appear just fine. But when I pass them as a prop, that's when they disappear. I import them in a Portfolio component, and try to send them as a prop in a Project component. Someone said earlier to not try to pass an object to a src attribute, and instead try to send the image url as a prop, but if I'm using a the map function to go through each element, I'm not sure how I can send each image URL.
Here is a few of the imports in the Portfolio component:
import video_player from "../../images/portfolioImages/video_player.png";
import weather_app from "../../images/portfolioImages/weather_app.png";
Here is a bit of the array of objects:
const projects = [
{
name: "Real-Time-Chatroom",
type: "Web Page",
description:
"Discord-like webpage that allows for several different users to send messages to a variety of different servers/chatrooms.",
picture: { chatroom },
},
{
name: "Weather App",
type: "Web Page",
description:
"Weather application that uses user's location to find the correct weather, and display that information on screen, with CSS styling that changes depending on the weather conditions of the user's area.",
picture: { weather_app },
},
];
And here is my Projects component code:
import React from "react";
import "./Project.css";
const Project = ({ name, type, description, image }) => {
return (
<div className="project">
<h1>{name}</h1>
<img src={image} alt={name}/>
</div>
);
};
export default Project;

Tree shakable icon component

I am creating a custom design system on top of ChakraUI and bootstrap icons.
Bootstrap icons contains 1000+ svg icons.
I created an abstract Icon component to have abstraction over the icon name, that seems IMO more convenient.
However, I am not sure this module will be tree-shaked, and I can't figure out how to change the implementation to make it tree-shakable.
Icon.tsx
import React from 'react'
import * as bootstrapIcons from '#emotion-icons/bootstrap'
// Union of all icon names: 'Alarm' | 'Circle' | 'Square' ...
type IconNames = keyof typeof bootstrapIcons
export const Icon: FC<{name: IconNames}> = ({name}) => {
const Icon = bootstrapIcons[name]
return (
<div>
<Icon style={{...}} />
</div>
)
}
App.tsx
import React from 'react'
import { Icon } from './Icon'
const App = () => {
return <div>
<Icon name="Alarm" />
</div>
}
Astrix imports cannot be tree shaken.
Generally when it comes to Icons you can have a Sprite Sheet or Tree Shaking but not both.
To make this particular library tree shake out icons you'll have to change your imports and usage to look like this (haven't tested but should work).
import { Alarm } from '#emotion-icons/bootstrap/Alarm';
const Use = () => <Alarm/>
There's definitely a caveat here where it would be possible to build a build-time plugin that changes...
<Icon name="Alarm"/>
// to.
import { Alarm } from '#emotion-icons/bootstrap/Alarm';
<Alarm/>
and removes the import.
The reason why astrix imports can't be tree shaken is because javascript is a very dynamic language and static analysis of which keys are used is sometimes very difficult.
Consider the following code
import * as bootstrapIcons from '#emotion-icons/bootstrap'
bootstrapIcons["mralA".reverse()] // which icons should be tree shaken?
const Icons = new Proxy(bootstrapIcons) // which icons should be included? using proxy traps.
const SubSet = PullSubset(bootstrapIcons) // which icons should be included? no matter what the implementation of PullSubset is it will be impossible to preform static analysis on it to determine which icons have been used.

How to load only needed CSS per component (React js)

I've started to code my first React app and it's awesome, but I can't figure out how to manage css files per-component(so the actual CSS won't load if it is not necessary).
React with webpack(correct me if I'm wrong please) wraps the project in such a way that at every given moment the app loads only what it needs(in terms of JS).
So if I have my main App component with only two buttons visible: btn-01 and btn-02, and inside of this component I have another two: component-01 and component-02, and they are hidden till the corresponded button is clicked(btn-01 for component-01), these components won't be loaded until the actual button is clicked(am I getting this right?), however this is not the same with css as I can tell, because I see the css of each of these(component-01 and component-02) components loaded right away the App is loaded, even though none of the buttons are clicked.
I'm not a big fan of inline styling, but I did test it with css module, but the result is the same in this aspect. So I'm not even sure if this is possible to implement in an easy way.
Here's a code, so perhaps I'm not implementing it correctly, but please don't mind the none-DRY code etc.
So as you may see, the style of Component-01 and -02 are loaded even though there is no need for them at the moment(none of the button is pressed).
App.js
import React, { Component } from "react";
import "./App.css";
import Component_01 from "./Component-01/Component-01";
import Component_02 from "./Component-02/Component-02";
class App extends Component {
state = {
isComponent_01: false,
isComponent_02: false,
};
toggleComponent01 = () => {
this.setState({
isComponent_01: !this.state.isComponent_01,
});
};
toggleComponent02 = () => {
this.setState({
isComponent_02: !this.state.isComponent_02,
});
};
render() {
let showComponent_01 = null;
if (this.state.isComponent_01) {
showComponent_01 = <Component_01 />;
}
let showComponent_02 = null;
if (this.state.isComponent_02) {
showComponent_02 = <Component_02 />;
}
return (
<div className="App">
<button className="btn-01" onClick={this.toggleComponent01}>
Btn-01
</button>
<button className="btn-02" onClick={this.toggleComponent02}>
Btn-02
</button>
{showComponent_01}
{showComponent_02}
</div>
);
}
}
export default App;
Component-01.js (and Component-02.js, just with -02.js)
import React from "react";
import style from "./Component-01.module.css";
function App() {
return <div className={style["component-01"]}>Component-01</div>;
}
export default App;

How can I navigate into components on react native?

I've fletched a list of items and rendered it into my app.
Its the first page of the app.
The thing that I want to do is:
Make each of the items "touchable", and when you touch it, you open a component filled with objects from a second fetch requisition.
I am new to react native, do you know if I have to use a lib or something to do it?
I'll try to answer your questions one by one.
Make each of the items "touchable"
Wrap your components with TouchableOpacity which you can import from react native like this import {TouchableOpacity} from "react-native";
when you touch it, you open a component filled with objects
You need to implement onPress method there and also react navigation to load other components.
<TouchableOpacity onPress={() => this.props.navigation.navigate("newScreenName")}>
<MyCustomComponent>
...
</MyCustomComponent>
</TouchableOpacity>
and creating screen will be like this :
import { createStackNavigator } from "react-navigation";
import Screen1 from "./Screen1";
import Screen2 from "./Screen2";
...
const customStackNavigator = createStackNavigator(
{
newScreenName: {
screen: Screen1
},
newScreenName1: {
screen: Screen2
}
},
{}
);
check API & Docs here
Also, Please check this example for more details

React - render imported .svg file

I need to render .svg files. I do not want to use dangerouslySetInnerHTML. I am able to successfully render an svg if I copy the svg contents directly and render it from a component.
However, this is not very reusable. I don't want to copy the contents from each .svg file. I would like to be able to import an svg file and pass that into my component that will then render the contents.
Here's what I have done so far, but it is not rendering my svg.
I have created a component that accepts an imported svg file, like this:
import React from "react";
class SvgComponent extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
props.svg // this works if I copy my .svg contents here (<svg>....</svg>)
);
}
};
SvgComponent.propTypes = {
svg: React.PropTypes.string.isRequired,
};
export default SvgComponent;
And here is how I am using that component:
import mySvg from './images/mySvg.svg';
const Icon = (props) => {
return (
<svgComponent svg={mySvg} />
);
};
Icon.propTypes = {
icon: React.PropTypes.string.isRequired,
};
export default Icon;
This does not work -- it does not show my svg on the webpage, or even in the dom. When I inspect the page, all I see is an empty svgComponent:
<svgComponent />
Any help on getting .svg files to display in react would great!
I created a module to solve this problem. With it you can load the svg and manipulate its elements using JSX without having to paste the svg code.
Npm package:https://www.npmjs.com/package/react-samy-svg
Check an example on Glitch: https://fossil-transport.glitch.me
It's simple to use
<Samy path="path to your svg file">
<Proxy select="#Star" fill="red"/>
</Samy>
Whenever you need to change some SVG attribute just create a Proxy element and use the 'select' prop (accepts CSS selectors). All props set on Proxy will be forwared as attributes to the SVG element(s)

Resources