Skip to content

Commit

Permalink
Add Drag and Drop to 2D Map (#855)
Browse files Browse the repository at this point in the history
  • Loading branch information
pvargas authored Dec 1, 2023
1 parent f4c1ebe commit df331ad
Show file tree
Hide file tree
Showing 8 changed files with 294 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { useListenTo } from '../../../selection-checkbox/useBackbone.hook'
import { removeOldDrawing } from './drawing-and-display'
import { getIdFromModelForDisplay } from '../drawing-and-display'
import { StartupDataStore } from '../../../../js/model/Startup/startup'
import { Translation } from '../interactions.provider'
import { contrastingColor } from '../../../../react-component/location/location-color-selector'
const modelToRectangle = (model: any) => {
//ensure that the values are numeric
//so that the openlayer projections
Expand Down Expand Up @@ -95,16 +97,23 @@ export const drawBbox = ({
model,
rectangle,
id,
isInteractive,
translation,
}: {
map: any
model: any
rectangle: any
id: string
isInteractive?: boolean
translation?: Translation
}) => {
if (!rectangle) {
// handles case where model changes to empty vars and we don't want to draw anymore
return
}
if (translation) {
rectangle.translate(translation.longitude, translation.latitude)
}
const billboard = new ol.Feature({
geometry: rectangle,
})
Expand All @@ -113,8 +122,8 @@ export const drawBbox = ({
const color = model.get('color')
const iconStyle = new ol.style.Style({
stroke: new ol.style.Stroke({
color: color ? color : '#914500',
width: 3,
color: isInteractive ? contrastingColor : color ? color : '#914500',
width: isInteractive ? 6 : 4,
}),
})
billboard.setStyle(iconStyle)
Expand All @@ -133,10 +142,14 @@ const updatePrimitive = ({
map,
model,
id,
isInteractive,
translation,
}: {
map: any
model: any
id: string
isInteractive?: boolean
translation?: Translation
}) => {
const rectangle = modelToRectangle(model)
// make sure the current model has width and height before drawing
Expand All @@ -146,22 +159,38 @@ const updatePrimitive = ({
model.get('north') !== model.get('south') &&
model.get('east') !== model.get('west')
) {
drawBbox({ rectangle, map, model, id })
drawBbox({ rectangle, map, model, id, isInteractive, translation })
//only call this if the mouse button isn't pressed, if we try to draw the border while someone is dragging
//the filled in shape won't show up
// if (!this.buttonPressed) {
// drawBorderedRectangle(rectangle)
// }
}
}
const useListenToBboxModel = ({ model, map }: { model: any; map: any }) => {
const useListenToBboxModel = ({
model,
map,
isInteractive,
translation,
}: {
model: any
map: any
isInteractive?: boolean
translation?: Translation
}) => {
const callback = React.useMemo(() => {
return () => {
if (model && map) {
updatePrimitive({ map, model, id: getIdFromModelForDisplay({ model }) })
updatePrimitive({
map,
model,
id: getIdFromModelForDisplay({ model }),
isInteractive,
translation,
})
}
}
}, [model, map])
}, [model, map, isInteractive, translation])
useListenTo(
model,
'change:mapNorth change:mapSouth change:mapEast change:mapWest',
Expand All @@ -172,11 +201,15 @@ const useListenToBboxModel = ({ model, map }: { model: any; map: any }) => {
export const OpenlayersBboxDisplay = ({
map,
model,
isInteractive,
translation,
}: {
map: any
model: any
isInteractive?: boolean
translation?: Translation
}) => {
useListenToBboxModel({ map, model })
useListenToBboxModel({ map, model, isInteractive, translation })
React.useEffect(() => {
return () => {
if (map && model) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import { getIdFromModelForDisplay } from '../drawing-and-display'
import * as Turf from '@turf/turf'
import TurfCircle from '@turf/circle'
import { StartupDataStore } from '../../../../js/model/Startup/startup'
import { Translation } from '../interactions.provider'
import { contrastingColor } from '../../../../react-component/location/location-color-selector'
export function translateFromOpenlayersCoordinate(coord: any) {
return ol.proj.transform(
[Number(coord[0]), Number(coord[1])],
Expand Down Expand Up @@ -61,16 +63,23 @@ export const drawCircle = ({
model,
rectangle,
id,
isInteractive,
translation,
}: {
map: any
model: any
rectangle: any
id: string
isInteractive?: boolean
translation?: Translation
}) => {
if (!rectangle) {
// handles case where model changes to empty vars and we don't want to draw anymore
return
}
if (translation) {
rectangle.translate(translation.longitude, translation.latitude)
}
const point = Turf.point(
translateFromOpenlayersCoordinate(rectangle.getCenter())
)
Expand All @@ -91,8 +100,8 @@ export const drawCircle = ({
const color = model.get('color')
const iconStyle = new ol.style.Style({
stroke: new ol.style.Stroke({
color: color ? color : '#914500',
width: 3,
color: isInteractive ? contrastingColor : color ? color : '#914500',
width: isInteractive ? 6 : 4,
}),
})
billboard.setStyle(iconStyle)
Expand All @@ -111,36 +120,67 @@ const updatePrimitive = ({
map,
model,
id,
isInteractive,
translation,
}: {
map: any
model: any
id: string
isInteractive?: boolean
translation?: Translation
}) => {
const circle = modelToCircle({ model, map })
// make sure the current model has width and height before drawing
if (circle && !_.isUndefined(circle)) {
drawCircle({ model, rectangle: circle, map, id })
drawCircle({
model,
rectangle: circle,
map,
id,
isInteractive,
translation,
})
}
}
const useListenToBboxModel = ({ model, map }: { model: any; map: any }) => {
const useListenToBboxModel = ({
model,
map,
isInteractive,
translation,
}: {
model: any
map: any
isInteractive?: boolean
translation?: Translation
}) => {
const callback = React.useMemo(() => {
return () => {
if (model && map) {
updatePrimitive({ map, model, id: getIdFromModelForDisplay({ model }) })
updatePrimitive({
map,
model,
id: getIdFromModelForDisplay({ model }),
isInteractive,
translation,
})
}
}
}, [model, map])
}, [model, map, isInteractive, translation])
useListenTo(model, 'change:lat change:lon change:radius', callback)
callback()
}
export const OpenlayersCircleDisplay = ({
map,
model,
isInteractive,
translation,
}: {
map: any
model: any
isInteractive?: boolean
translation?: Translation
}) => {
useListenToBboxModel({ map, model })
useListenToBboxModel({ map, model, isInteractive, translation })
React.useEffect(() => {
return () => {
if (map && model) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ import {
locationColors,
contrastingColor,
} from '../../../../react-component/location/location-color-selector'
import { InteractionsContext } from '../interactions.provider'
import { Model } from 'backbone'

const DrawingMenu = menu.DrawingMenu
const makeEmptyGeometry = geometry.makeEmptyGeometry
Expand Down Expand Up @@ -316,6 +318,18 @@ export const OpenlayersDrawings = ({
null
)

const { interactiveGeo, translation, setInteractiveModels } =
React.useContext(InteractionsContext)

const nonDrawingModels = models.concat(filterModels)

useEffect(() => {
const models = nonDrawingModels.filter(
(model: Model) => model.get('locationId') === interactiveGeo
)
setInteractiveModels(models)
}, [interactiveGeo, models, filterModels])

const handleKeydown = React.useCallback(
(e: any) => {
if (e.key === 'Enter') {
Expand Down Expand Up @@ -378,68 +392,50 @@ export const OpenlayersDrawings = ({

return (
<>
{filterModels.map((model: any) => {
{nonDrawingModels.map((model: any) => {
const drawMode = getDrawModeFromModel({ model })
const isInteractive = model.get('locationId') === interactiveGeo
const shapeTranslation =
translation && isInteractive ? translation : undefined
switch (drawMode) {
case 'bbox':
return (
<OpenlayersBboxDisplay key={model.cid} model={model} map={map} />
)
case 'circle':
return (
<OpenlayersCircleDisplay
<OpenlayersBboxDisplay
key={model.cid}
model={model}
map={map}
isInteractive={isInteractive}
translation={shapeTranslation}
/>
)
case 'line':
return (
<OpenlayersLineDisplay key={model.cid} model={model} map={map} />
)
case 'poly':
return (
<OpenlayersPolygonDisplay
key={model.cid}
model={model}
map={map}
/>
)
default:
case 'circle':
return (
<OpenlayersPolygonDisplay
<OpenlayersCircleDisplay
key={model.cid}
model={model}
map={map}
isInteractive={isInteractive}
translation={shapeTranslation}
/>
)
}
})}
{models.map((model: any) => {
const drawMode = getDrawModeFromModel({ model })
switch (drawMode) {
case 'bbox':
return (
<OpenlayersBboxDisplay key={model.cid} model={model} map={map} />
)
case 'circle':
case 'line':
return (
<OpenlayersCircleDisplay
<OpenlayersLineDisplay
key={model.cid}
model={model}
map={map}
isInteractive={isInteractive}
translation={shapeTranslation}
/>
)
case 'line':
return (
<OpenlayersLineDisplay key={model.cid} model={model} map={map} />
)
case 'poly':
return (
<OpenlayersPolygonDisplay
key={model.cid}
model={model}
map={map}
isInteractive={isInteractive}
translation={shapeTranslation}
/>
)
default:
Expand All @@ -448,6 +444,8 @@ export const OpenlayersDrawings = ({
key={model.cid}
model={model}
map={map}
isInteractive={isInteractive}
translation={shapeTranslation}
/>
)
}
Expand Down
Loading

0 comments on commit df331ad

Please sign in to comment.