I am working with React Leaflet right now and I need to get the coordinates of the position I clicked on the map. when I googled it I could only find latlng as a solution, but that is not working. any ideas? TIA
I found a solution, attached the code that could help you in your problem.
import React, {useState} from "react";
import {Map, Marker, TileLayer} from "react-leaflet";
const style = {
height: '400px',
width: '100%'
};
export const Ubication = () => {
const [position] = useState([-0.22021954674229854, -78.5127639770508]);//position intitial of map
const [marker, setMarker] = useState({lat: 0, lng: 0});
function changeUbication(e) {
let {lat, lng} = e.latlng;
console.info("Lat:", lat);
console.info("Lng: ",lng);
setMarker(e.latlng);
}
return (
<div id="map">
<Map center={position}
zoom={13}
onClick={changeUbication}
style={style}>
<TileLayer
url='https://{s}.tile.osm.org/{z}/{x}/{y}.png'
attribution='© OpenStreetMap contributors'/>
{(marker.lat !== 0 && marker.lng !== 0) &&
<Marker position={[marker.lat, marker.lng]}>
</Marker>}
</Map>
</div>)
}
Related
`Below mentioned is my code for intersection observer
useIntersectionObserver
/* eslint-disable #typescript-eslint/no-shadow */
import { RefObject, useEffect, useState } from 'react';
export default function useIntersectionObserver(
elementRef: RefObject<Element>,
{ threshold = 0, root = null, rootMargin = '0%' }
) {
const [entry, setEntry] = useState<IntersectionObserverEntry>();
const callBackFunction = ([entry]: IntersectionObserverEntry[]): void => {
setEntry(entry);
};
useEffect(() => {
const node = elementRef?.current; // DOM Ref
const isIOSupported = !!window.IntersectionObserver;
if (!isIOSupported || !node) return;
const observerOptions = { threshold, root, rootMargin };
const observer = new IntersectionObserver(
callBackFunction,
observerOptions
);
observer.observe(node);
return () => observer.disconnect();`your text`
}, [elementRef, JSON.stringify(threshold), root, rootMargin]);
return entry;
}
Below is the code mentioned where I am calling useInterSectionObserver hook
const scrollDivElementRef = useRef<null | HTMLDivElement>(null);
const chatDivRef = useRef<null | HTMLDivElement>(null);
const entry = useIntersectionObserver(scrollDivElementRef, {});
const isVisible = !!entry?.isIntersecting;
Here scrollDivElementRef is the ref of div which we are observing for the intersection.It is basically our sentinal element.
Below mentioned is the useEffect hook which is going to perform some action when isVisible will become true.
Below mentioned is a code in react-native webview ,basically we are opening our react web app inside ios app , but our intersection observer is not able to detect changes . We have implemented intersection observer for infinite loading of messages. Every time user will scroll upwards , we will get "isVisible" as true and we will make an API call to fetch more messages.
useEffect(() => {
if (isVisible) {
dispatch(
getPostsForChannel(inputChannelId, true, channelMessages[0].timestamp)
);
}
}, [isVisible]);
<View style={styles.container}>
<WebView
style={{ marginTop: 40 }}
//TODO: Update the url
source={{ uri: 'http://192.168.1.2:3000' }}
onLoad={(syntheticEvent) => {
const { nativeEvent } = syntheticEvent;
}}
javaScriptEnabled={true}
onError={(e) => {
const { nativeEvent } = e;
setUrl(HOME_URL);
}}
onHttpError={() => {
setUrl(HOME_URL);
}}
onMessage={onMessage}
limitsNavigationsToAppBoundDomains={true}
// injectedJavaScript="window.octNativeApp=true"
injectedJavaScriptBeforeContentLoaded={initializeNativeApp}
scalesPageToFit={false}
setBuiltInZoomControls={false}
useWebView2
allowsInlineMediaPlayback={true}
mediaPlaybackRequiresUserAction={false}
></WebView>
</View>`
It will be really very helpful , if you people can help me with this problem.
Thanks & Regards
Mohit
I tried giving the height & width to the webview but it is also not working.Tried almost every piece of advise available in other platforms but not able to fic this`
https://ant.design/components/transfer/
Hey all! I was just wondering is it possible to implement two separate functions on the transfer buttons. For example, I want to run add function when the user clicks transfer to the right and I want to add remove function when the user clicks transfer button to the left.
From the documentation all I could see was both the buttons just trigger onChange function and I dont want that.
The API of Transfer component uses only one function to change the data, but you can call different functions inside onChange depending on the direction:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import { Transfer } from "antd";
const mockData = [];
for (let i = 0; i < 20; i++) {
mockData.push({
key: i.toString(),
title: `content${i + 1}`,
description: `description of content${i + 1}`
});
}
const initialTargetKeys = mockData
.filter((item) => +item.key > 10)
.map((item) => item.key);
const App = () => {
const [targetKeys, setTargetKeys] = useState(initialTargetKeys);
const [selectedKeys, setSelectedKeys] = useState([]);
const handleAdd = (nextTargetKeys, moveKeys) => {
console.log("add");
setTargetKeys(nextTargetKeys);
};
const handleDelete = (nextTargetKeys, moveKeys) => {
console.log("delete");
setTargetKeys(nextTargetKeys);
};
const onChange = (nextTargetKeys, direction, moveKeys) => {
if (direction === "left") {
handleDelete(nextTargetKeys, moveKeys);
} else {
handleAdd(nextTargetKeys, moveKeys);
}
};
const onSelectChange = (sourceSelectedKeys, targetSelectedKeys) => {
setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
};
return (
<Transfer
dataSource={mockData}
titles={["Source", "Target"]}
targetKeys={targetKeys}
selectedKeys={selectedKeys}
onChange={onChange}
onSelectChange={onSelectChange}
render={(item) => item.title}
/>
);
};
ReactDOM.render(<App />, document.getElementById("container"));
I created a custom photo carousel component in React (because external libraries were either too hard to work with or did not do the things that I wanted it to do), where you can swipe to the next/previous photo on mobile. Everything works fine on Android, but it's just IOS Safari.
The Problem
I have a page that maps out several carousels. The first carousel in the map works perfectly fine. Subsequent carousels will swipe correctly AFTER the first slide, but once it transitions to the second slide, the touch events stop firing, and it will not swipe. What I want is all the carousels like the first carousel. No error messages seen either. See video:
Code
Here is the custom component:
import { useState, useEffect } from 'react'
const Carousel = ({ children }) => {
const IMG_WIDTH = 400
const [currentIndex, setCurrentIndex] = useState(0)
const [lastTouch, setLastTouch] = useState(0)
const [movement, setMovement] = useState(0)
const [transitionDuration, setTransitionDuration] = useState('')
const [transitionTimeout, setTransitionTimeout] = useState(null)
const maxLength = children.length - 1,
maxMovement = maxLength * IMG_WIDTH
useEffect(() => {
return () => {
clearTimeout(transitionTimeout)
}
}, [])
const transitionTo = (index, duration) => {
setCurrentIndex(index)
setMovement(index * IMG_WIDTH)
setTransitionDuration(`${duration}s`)
setTransitionTimeout(
setTimeout(() => {
setTransitionDuration('0s')
}, duration * 100))
}
const handleMovementEnd = () => {
const endPosition = movement / IMG_WIDTH
const endPartial = endPosition % 1
const endingIndex = endPosition - endPartial
const deltaInteger = endingIndex - currentIndex
let nextIndex = endingIndex
if (deltaInteger >= 0) {
if (endPartial >= 0.1) {
nextIndex++
}
} else if (deltaInteger < 0) {
nextIndex = currentIndex - Math.abs(deltaInteger)
if (endPartial > 0.9) {
nextIndex++
}
}
transitionTo(nextIndex, Math.min(0.5, 1 - Math.abs(endPartial)))
}
const handleMovement = delta => {
clearTimeout(transitionTimeout)
const maxLength = children.length - 1
let nextMovement = movement + delta
if (nextMovement < 0) {
nextMovement = 0
}
if (nextMovement > maxLength * IMG_WIDTH) {
nextMovement = maxLength * IMG_WIDTH
}
setMovement(nextMovement)
setTransitionDuration('0s')
}
const handleTouchStart = event => {
setLastTouch(event.nativeEvent.touches[0].clientX)
}
const handleTouchMove = event => {
const delta = lastTouch - event.nativeEvent.touches[0].clientX
setLastTouch(event.nativeEvent.touches[0].clientX)
handleMovement(delta)
}
const handleTouchEnd = () => {
handleMovementEnd()
setLastTouch(0)
}
return (
<div
className="main"
style={{ width: IMG_WIDTH }}
onTouchStart={handleTouchStart}
onTouchMove={handleTouchMove}
onTouchEnd={handleTouchEnd}>
<div
className="swiper"
style={{
transform: `translateX(${movement * -1}px)`,
transitionDuration: transitionDuration
}}>
{children} // This is just <img /> tags
</div>
<div className="bullets">
{[...Array(children.length)].map((bullet, index) => (
<div key={`bullet-${index}`} className={`dot ${currentIndex === index && 'red-dot'}`} />
))}
</div>
</div>
)
}
export default Carousel
And here is the part of my code where I am using the custom component:
return (
<>
<Announcement />
<Header />
<section className="tiles-section">
<Title />
{Component} // This is just a component that simply maps out the Carousel, nothing special and no extra styling
</section>
...
</>
)
And CSS:
.main {
overflow: hidden;
position: relative;
touch-action: pan-y;
}
.swiper {
display: flex;
overflow-x: visible;
transition-property: transform;
will-change: transform;
}
What I know/tried
Removing some of the components above the Carousel (eg. Title, Announcement, etc.) makes part of the slides other than the first slide swipable. It can be half of the height of the slide or 1/3 of the height that is swipable, depending on how much I remove. This excludes the first carousel, that one still works perfectly fine
I've tried removing a bunch of CSS, didn't work
Tried adding event listeners to the 'main' div, maybe I did something wrong but swiping one carousel ends up swiping all the carousels
Thought it had something to do with the touch event handler functions I created in my custom carousel component, but it seems like they work fine, because after changing them to console.logs and manually translating the slides, the touch events are still not firing.
Update #1
I put the touch event handlers in a new div that wraps {child}. The second slide is swipeable now but the third slide is still a bust.
References
This is the tutorial link I followed to create the carousel for more context to the custom carousel component.
After days and hours, the solution is kind of odd. I'm guessing you need to set the target correctly to the element's div id. I put this in the useEffect, so the result looks like this:
useEffect(() => {
document.getElementById(id).addEventListener('touchstart', () => false, { passive: false })
return () => {
clearTimeout(transitionTimeout)
}
}, [])
NOTE that the id MUST be unique especially if creating a map of the same component like what I did. Otherwise, swiping one carousel will swipe all carousels.
Original dependencies:
"dependencies": {
"highcharts": "^8.0.4",
"react-jsx-highstock": "^4.0.1"
},
Implemented an HOC to combine charts into one chart with multiple Yaxis.
As you can see with the image above all three charts and the correct axis ranges are visible.
Updated dependencies:
"highcharts": "^8.2.2",
"react-jsx-highstock": "^4.2.0"
We can see the differences between the two charts where the last series isn't visible. The range are the Yaxis is off.
Reverting the Highchart dependency to 8.1.0 is better so we suspect something is amiss with 8.1.1
Below is the root method where we render the series and we suspect the Yaxis issue.
renderMultiAxes = children => children.map((child, index) => {
const {
yAxisTitle,
disableYAxis,
disableGridLine,
yAxisLabelAlign,
yAxisLabelFormatter,
yAxisType,
removeYAxis,
referenceLine
} = child.props
const { color, series } = this.renderSeries(child.props, index)
const title = `
<div style="margin-top: 8px">
${color ? `<svg style="${symbolSvgStyle}"><circle cx="5" cy="5" r="3.5" fill=${color} /></svg>` : ''}
${yAxisTitle}
</div>
`
return <YAxis key={`yAxis_${index}`}
offset={undefined}
tickWidth={!disableYAxis && 0}
gridLineWidth={disableGridLine ? 0 : 1}
opposite={index % 2 === 1}
labels={{
align: yAxisLabelAlign || (index % 2 ? 'left' : 'right'),
enabled: !disableYAxis,
formatter: yAxisLabelFormatter
}} type={yAxisType} visible={!removeYAxis}
>
<YAxisTitle text={title} useHTML />
{series}{referenceLine}
</YAxis>
})
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { YAxis as JsxHighChartsYAxis } from 'react-jsx-highstock'
import { baseChartConfig } from '../BaseChart/BaseChartConfig'
import deepmerge from 'deepmerge'
export class Title extends Component {
render () {
const {
title
} = baseChartConfig.yAxis
return <JsxHighChartsYAxis.Title {...title} {...this.props} />
}
}
export default class YAxis extends Component {
static propTypes = {
/**
* yAxis labels
*/
labels: PropTypes.object
}
getLabelConfig = () => {
const {
labels
} = baseChartConfig.yAxis
const newlabels = deepmerge(this.props.labels, labels)
if (this.props.labels && this.props.labels.align === 'inner') {
newlabels.align = 'left'
newlabels.x = 4
newlabels.y = 14
}
return newlabels
}
render () {
const {
title,
labels,
...otherYAxisOptions
} = baseChartConfig.yAxis
return <JsxHighChartsYAxis
showFirstLabel={!(this.props.labels && this.props.labels.align === 'inner')}
{...otherYAxisOptions}
{...this.props}
labels={this.getLabelConfig()}
/>
}
}
Changing the size of the window will correctly re-render the chart. We suspect the Yaxis is the issue. We have no listener to the window resize method and none of our code is re-executed during the resize.
Thank you
Moving the
YAxisTitle text={title} useHTML
after {series}{referenceLine} solved the issue.
I'm fiddling around with vue for the first time and having troubles with getting v-bind:style="styleObject" getting to work properly. It works when styleObject only has one key/value-pair in it, but nothing comes when I have more than 1 key/value-pair.
When running console.log() the values comes out as they should.
My vue code:
<script>
import Vue from 'vue';
import ImageObject from './SkyCropImage.class';
export default Vue.component('sky-crop', {
props: {
src: String,
focalpoint: String,
mode: String,
round: String,
type: {
type: String,
default: 'img',
},
},
data() {
return {
image: new ImageObject(this.src),
srcString: '',
styleObject: { },
};
},
methods: {
anchorString(image) {
if (this.$el.firstChild.localName !== 'img') {
this.styleObject.backgroundPosition = `${image.anchor.x} ${image.anchor.y}`;
} else {
const pointX = (image.anchor.x.replace('%', '') * 1) / 100;
const pointY = (image.anchor.y.replace('%', '') * 1) / 100;
const differenceX = image.parent.width - image.calculatedInfo.width;
const differenceY = image.parent.height - image.calculatedInfo.height;
const anchorX = Math.min(0, differenceX * pointX);
const anchorY = Math.min(0, differenceY * pointY);
this.styleObject.transform = `translate(${anchorX}px, ${anchorY}px)`;
}
},
concatSrc(string) {
this.srcString = string;
if (this.type !== 'img') {
this.styleObject.backgroundImage = `url(${string})`;
}
},
},
created() {
this.image.mode = this.mode;
this.image.round = this.round;
this.image.anchor = {
x: this.focalpoint.split(',')[0],
y: this.focalpoint.split(',')[1],
};
},
mounted() {
this.image.setParentInfo(this.$el);
this.image.runCropJob();
this.anchorString(this.image);
this.concatSrc(this.image.outputUrl);
},
});
My template:
<div class="skyCrop-parent">
<img
class="skyCrop-element"
alt=""
v-if="type === 'img'"
v-bind:src="srcString"
v-bind:style="styleObject" />
// img result: <img alt="" src="https://source.unsplash.com/Ixp4YhCKZkI/700x394" class="skyCrop-element" style="transform: translate(-50px, 0px);">
<div
class="skyCrop-element"
v-bind:style="styleObject"
v-else>
</div>
//div result: <div class="skyCrop-element"></div>
</div>
How the component is called:
<sky-crop
src="https://source.unsplash.com/Ixp4YhCKZkI/1600x900"
focalpoint="50%,50%"
mode="width"
round="175"
type="div">
</sky-crop>
<sky-crop
src="https://source.unsplash.com/Ixp4YhCKZkI/1600x900"
focalpoint="50%,50%"
mode="width"
round="175">
</sky-crop>
The bug lies in the way Vue handles reactivity.
Since I tried to add key/value pair to styleObject like this:
this.styleObject.backgroundPosition = `${image.anchor.x} ${image.anchor.y}`;
Vue could not detect the change since the keys i tried to reference was not declare beforehand. The solution could be defining all future could be keys, which would work just fine. However using vm.$set() would be better since it handles creating the key and initiates the reactivity at the same time. In short this line (and the others which did the same):
this.styleObject.backgroundPosition = `${image.anchor.x} ${image.anchor.y}`;
Became this:
this.$set(this.styleObject, 'background-position', `${image.anchor.x} ${image.anchor.y}`);
Vue documentation about the reason for the change:
https://v2.vuejs.org/v2/guide/reactivity.html