FeatureLayer - won't render - reactjs

I have a rather simple code that creates a FeatureLayer where I try to add some client side graphic.
facilitiesLayer = new FeatureLayer({
title: 'Facilities layers',
objectIdField: 'id',
source: [
new Graphic({
geometry: new Point({ longitude: -96.1034353, latitude: 41.5333259 }),
attributes: {
id: 1,
},
}),
],
renderer: new SimpleRenderer({
symbol: new SimpleMarkerSymbol({
size: 32,
color: '#4652C2',
outline: {
color: 'rgba(137,144,215,0.7)',
width: 2,
},
}),
}),
});
mapView.current!.map.add(facilitiesLayer);
after I add the layer to the map I immediately see this in console. If I comment out add layer addition, the map is properly displayed, meaning all of the ESRI stuff is created correct.
How do I find where this conversion fails?
using #arcgis/core 4.18.0

Related

How to add custom local marker image to mapbox

I'm trying to add the local image as marker to mapbox (mapbox-gl: 2.9.2).
I can add marker from external url like https://placekitten.com/g/30/30, but can't add from local (from my project root dir). I'm using react.
My Attempts: (This shows nothing)
import myCatLogo from './assets/icons/my-cat-logo.png';
const imageCat: any = new Image(20, 20);
imageCat.src = myCatLogo;
map.addImage("myCat", imageCat);
map.addLayer({
id: "marker",
type: "symbol",
source: "datas",
layout: {
"icon-image": "myCat",
// "icon-size": [20, 20],
}
});
My another attempts: (Uncaught (in promise) Error: Not Found at eval)
map.loadImage(myCatLogo, (error, image) => { // the image path is correct!
if (error) throw error;
map.addImage("myCat", image);
});
map.addLayer({
id: "marker",
type: "symbol",
source: "datas",
layout: {
"icon-image": "myCat",
// "icon-size": [20, 20],
}
});
I can add other marker like circle:
map.addLayer({
id: "marker-circle",
type: "circle",
source: "datas",
paint: {
"circle-radius": 4,
"circle-color": "rgb(0, 0, 0)",
},
});

How to remove antd donut chart hover and select effect

In the donut chart in #ant-design/plots,
There is a black border around the individual sections of the donut chart when hovered.
The individual section is translated away from the center when selected.
How to stop/ control these behavior?
const config = {
appendPadding: 10,
data,
angleField: 'value',
colorField: 'type',
radius: 1,
innerRadius: 0.6,
label: {
type: 'inner',
offset: '-50%',
content: '{value}',
style: {
textAlign: 'center',
fontSize: 14,
},
},
interactions: [
{
type: 'element-selected',
},
{
type: 'element-active',
},
],
statistic: {
title: false,
content: {
style: {
whiteSpace: 'pre-wrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
},
content: 'AntV\nG2Plot',
},
},
};
Deal with interactions in config
There is a black border around the individual sections of the donut chart when hovered.
Remove the object type:'element-active'
Note: Removing is conveyed by commenting out in the code below.
interactions: [
...
// {
// type: 'element-active',
// },
]
The individual section is translated away from the center when selected.
Remove the object type: 'element-selected'
Note: Removing is conveyed by commenting out in the code below.
interactions: [
...
// {
// type: 'element-selected',
// },
]
To achieve both you can simply remove the interactions from the config object.

Trouble setting state with onClick function only with ImageMapper component (react-img-mapper)

I'm trying to create an interactive image map using the ImageMapper component from react-img-mapper (based on react-image-mapper) in my ReactJS app. I want to be able to click an "area" on ImageMapper map, and have it update clickedAreas state according to the function clickArea.
In the app, I render a list with checkmarks, and the checkmarks become green when the corresponding list item is included in clickedAreas state.
I call clickArea via onClick on list items themselves and it works as expected, but when I call it via the ImageMapper onClick prop it doesn't, and I'm having trouble figuring out why.
Here's a screen recording showing the differences in action.
NOTE: the ImageMapper onClick seems to be using the initially set state (useState([])), because when I give it an array with an element initially, it just keeps using that initial state with that element.
Here's a screenshot regarding the onClick prop from react-img-mapper documentation
Here's a screenshot of my code:
Here's my code also:
import React, { useState } from "react"
import ImageMapper from 'react-img-mapper';
function ImageMapQQ(props) {
const URL = "../images/qqmap.png"
const MAP = {
name: "qq-map",
areas: [
{ id: "NW1/4NW1/4", title: "NW1/4NW1/4", name: "NW1/4NW1/4", shape: "rect", coords: [0,0,50,50] },
{ id: "NE1/4NW1/4", title: "NE1/4NW1/4", name: "NE1/4NW1/4", shape: "rect", coords: [50,0,100,50] },
{ id: "NW1/4NE1/4", title: "NW1/4NE1/4", name: "NW1/4NE1/4", shape: "rect", coords: [100,0,150,50] },
{ id: "NE1/4NE1/4", title: "NE1/4NE1/4", name: "NE1/4NE1/4", shape: "rect", coords: [150,0,200,50] },
{ id: "SW1/4NW1/4", title: "SW1/4NW1/4", name: "SW1/4NW1/4", shape: "rect", coords: [0,50,50,100] },
{ id: "SE1/4NW1/4", title: "SE1/4NW1/4", name: "SE1/4NW1/4", shape: "rect", coords: [50,50,100,100] },
{ id: "SW1/4NE1/4", title: "SW1/4NE1/4", name: "SW1/4NE1/4", shape: "rect", coords: [100,50,150,100] },
{ id: "SE1/4NE1/4", title: "SE1/4NE1/4", name: "SE1/4NE1/4", shape: "rect", coords: [150,50,200,100] },
{ id: "NW1/4SW1/4", title: "NW1/4SW1/4", name: "NW1/4SW1/4", shape: "rect", coords: [0,100,50,150] },
{ id: "NE1/4SW1/4", title: "NE1/4SW1/4", name: "NE1/4SW1/4", shape: "rect", coords: [50,100,100,150] },
{ id: "NW1/4SE1/4", title: "NW1/4SE1/4", name: "NW1/4SE1/4", shape: "rect", coords: [100,100,150,150] },
{ id: "NE1/4SE1/4", title: "NE1/4SE1/4", name: "NE1/4SE1/4", shape: "rect", coords: [150,100,200,150] },
{ id: "SW1/4SW1/4", title: "SW1/4SW1/4", name: "SW1/4SW1/4", shape: "rect", coords: [0,150,50,200] },
{ id: "SE1/4SW1/4", title: "SE1/4SW1/4", name: "SE1/4SW1/4", shape: "rect", coords: [50,150,100,200] },
{ id: "SW1/4SE1/4", title: "SW1/4SE1/4", name: "SW1/4SE1/4", shape: "rect", coords: [100,150,150,200] },
{ id: "SE1/4SE1/4", title: "SE1/4SE1/4", name: "SE1/4SE1/4", shape: "rect", coords: [150,150,200,200] },
]
}
const areas = MAP.areas
const [clickedAreas, setClickedAreas] = useState([])
function clickArea(id) {
console.log("clickedAreas: ", clickedAreas)
if (clickedAreas.includes(id)) {
console.log("includes")
setClickedAreas(() => clickedAreas.filter(el => el != id))
}
else {
console.log("doesn't include")
setClickedAreas(() => [...clickedAreas, id])
}
}
return (
<>
<ImageMapper src={URL} map={MAP}
stayMultiHighlighted={true}
toggleHighlighted={true}
fillColor={"rgba(150, 213, 255, 0.6)"}
onClick={(area) => clickArea(area.id)} // THIS ONCLICK ISN'T WORKING CORRECTLY
/>
<div className="bold">AREAS</div>
{areas.map(area =>
<>
<div className="d-flex pointer" onClick={() => clickArea(area.id)}> {/* THIS ONCLICK IS WORKING CORRECTLY */}
<i className={`fas fa-check-circle ${clickedAreas.includes(area.id) ? "text-green" : "text-black opacity-10"}`}></i>
<div key={area.id}>{area.id}</div>
</div>
</>
)
}
</>
)
}
export default ImageMapQQ
I still don't know why it doesn't work as originally written, and would still like more insight on that if anyone's got it.
Ultimately, the ImageMapper onClick just keeps using the initial state (empty array) whenever a click occurs -- I can tell this because I have it console.log the current clickedAreas state at the start of the clickArea function that's called when the image map is clicked.
It seems to update the state (because the corresponding checkmark turns green), but it seems to always start from the initial state every time the ImageMapper onClick function is called (console.log shows empty array every time).
That all being said, I HAVE found a workaround to make it work as desired.
Instead of the ImageMapper onClick calling the clickArea function that later sets state, I changed it to setting a different state immediately (areaId), triggering a useEffect that then calls the clickArea function that later sets the state I actually wanted to be working with, lol. Hacky, but works.
(Added the nanoid in there to make it unique upon every click, so that the setAreaId function within ImageMapper onClick would always run -- if I just had area.id, it wouldn't run if that area.id was already the areaId state.... aka, I couldn't get the clickArea function to run to remove it from the clickedAreas state)
The small red circles 1-3 are the new parts of the code:

Update chart with HighchartsReact is not working when a timer is used in React

I have the code to show data on my page using Highchart and React
var chart_nps_amigo = {
title: { text: '% Alunos x total de horas de acesso' },
chart: { height: 200, type: 'column' },
xAxis: {
type: 'category',
labels: {
rotation: -45,
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif'
}
}
},
yAxis: {
title: { text: 'Número de alunos' }
},
tooltip: {
pointFormat: 'Porcentagem: <b>{point.y:.1f} alunos</b>'
},
series: [{
name: 'Alunos',
data: [
['Nunca acessou', 24.2],
['Até 4h', 10.8],
['Até 8h', 22.5],
['Até 12h', 11],
['Até 16h', 9.3],
['Mais de 16h', 4.8]
],
dataLabels: {
enabled: true,
align: 'center',
format: '{point.y:.1f}', // one decimal
y: 10,
style: {
fontSize: '11px',
fontFamily: 'Verdana, sans-serif'
}
}
}]
}
I can use the following code to show the chart in my page
<HighchartsReact
highcharts={Highcharts}
options={chart_nps_amigo}
allowChartUpdate={true}
/>
With the code below I was able to update the charts
chart_nps_amigo.series[0].data.push( ['32h v1', 55] );
but I wanna update the chart with values that are coming from a web server using Redux and Redux-Saga.
To simulate that, I just create a timer event to update the chart using the following code:
const timer = setTimeout(() => {
chart_nps_amigo.series[0].data.push( ['32h v2', 24.8] );
console.log('This will run after 10 second!')
}, 10000);
But after 10 seconds, the log code shows in the browser console, but the chart is not updated.
How can I make this work ?
You should keep your config in the component state and update your data there, just like it is done here: https://github.com/highcharts/highcharts-react#optimal-way-to-update
I find a solution now. Based in the answer of #SebastianWędzel
The way that I describe data previously, it was an array in javascript, but it's not a valid json object.
series: [{
name: 'Alunos',
data: [
['Nunca acessou', 24.2],
['Até 4h', 10.8],
['Até 8h', 22.5],
['Até 12h', 11],
['Até 16h', 9.3],
['Mais de 16h', 4.8]
],
But since I recover this value from a web server using redux and redux-saga, I need a way to add a valid Json object.
When I look in the Highcharts documentation, I find another way to show the series data using a valid Json object
series: [{
name: 'Alunos',
data: [{
"name": "Nunca acessou",
"y": 24.2
}, {
"name": "Até 4h",
"y": 10.8
}],
Now I attach the value that I get from the web server only to the series data part of the chart
series: [{
name: 'Alunos',
data: chart.myData,
It's working now.

Adding multiple style layers in Mapbox / React js

I'm using mapbox gl in React to draw polygons on a map. Would like to fill these polygons, and also adjust the border width of the polygons. My understanding is that it is not possible to adjust the border width as a fill property, so a separate line style must be created.
The problem that I am having, is that when I attempt to add an additional style to set the line width, it does not work. Apparently what is happening is that the first style layer is the one that is rendered, and the second one is not, per the code below: "STYLE LAYERS #'S 1 AND 2." I can get the line style to render if I place it in the first position, but then I get no fill layer, and vice-versa.
Any thoughts on this?
useEffect(() => {
if (map.current) return;
map.current = new mapboxgl.Map({
container: mapContainer.current,
style: "mapbox://styles/mapbox/streets-v11",
center: [lng, lat],
zoom: zoom,
});
});
useEffect(() => {
if (!map.current) return;
map.current.on("move", () => {
console.log(map.current.getCenter().lng.toFixed(4));
setLng(map.current.getCenter().lng.toFixed(4));
setLat(map.current.getCenter().lat.toFixed(4));
setZoom(map.current.getZoom().toFixed(2));
});
});
useEffect(() => {
if (!map.current) return;
map.current.on("load", () => {
dataArray.map((item) => {
map.current.addSource(item.name, {
type: "geojson",
data: {
type: "Feature",
geometry: {
type: "Polygon",
coordinates: item.data,
},
properties: {
name: item.name,
},
},
});
//STYLE LAYER #1
map.current.addLayer({
id: item.name,
type: "fill",
source: item.name,
layout: {},
paint: {
"fill-color": "#aaa",
"fill-opacity": 0.25,
"fill-outline-color": "#000",
},
});
//STYLE LAYER #2
map.current.addLayer({
id: item.name,
type: "line",
source: item.name,
layout: {},
paint: {
"line-color": "#000",
"line-width": 2,
},
});
});
});
Each layer needs to have a unique id (see: https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/). So, you could append "-border" to the line layer id.

Resources