反应本机mapbox gl动画点导致滞后

时间:2019-01-31 18:20:20

标签: javascript performance react-native mapbox-gl react-native-mapbox-gl

我想实现一个相当复杂的功能,将一次全部动画在以GeoJSON多的FeatureCollection点(在网络上类似的项目:https://hvv.live/)。 我尝试使用react native映射框库随附的官方Drive线路示例,并将其修改为可用于多个点。

的问题是,具有多于6到7分动画后的性能显著点更新只有几次,而不是下降,并且平稳地进行动画的第二个。我的猜测是,这是由高数上由多个听众产生以GeoJSON几何的setState呼叫引起在RouteSimulator类的requestAnimationFrame方法被解雇。

我认为,解决办法是莫名其妙地等待RouteSimulator与新GeoJSON的源计算下一个点所有的点,然后更新状态,但是,我无法弄清楚如何做到这一点。任何帮助将不胜感激。

RouteSimulator类用于处理所有动画:

import { Animated, Easing } from 'react-native'
import MapboxGL from '@mapbox/react-native-mapbox-gl'
import cheapRuler from 'cheap-ruler'

var ruler = cheapRuler(55.7)

class Polyline {
    constructor(lineStringFeature) {
        this._trip = lineStringFeature.properties.trip
        this._coordinates = lineStringFeature.geometry.coordinates
        this._timestamps = lineStringFeature.properties.time
        this._lineStringFeature = lineStringFeature
        this._totalDistance = 0
        this._departureTime = lineStringFeature.properties.time[0] / 1000
        this._arrivalTime =
            lineStringFeature.properties.time[
                lineStringFeature.properties.time.length - 1
            ] / 1000
        this._totalTime = this._arrivalTime - this._departureTime
        this._totalDistance += ruler.lineDistance(this._coordinates)
        this._speed = this._totalDistance / this._totalTime / 30
    }

    coordinateFromStart(distance) {
        const pointAlongCheap = ruler.along(this._coordinates, distance)
        const trip = this._trip
        const pointAlong = MapboxGL.geoUtils.makePoint(pointAlongCheap, {
            distance,
            trip
        })
        return pointAlong
    }

    get totalDistance() {
        return this._totalDistance
    }
}

class RouteSimulator {
    constructor(lineStrings) {
        this._lineStrings = lineStrings.map(line => ({
            polyline: new Polyline(line),
            curDist: 0,
            prevDist: 0
        }))
    }

    addListener(listener) {
        this._listener = listener
    }

    start() {
        this.tick()
    }

    reset() {
        this._previousDistance = 0
        this._currentDistance = 0
        this.start()
    }

    stop() {
        if (this._anim) {
            this._anim.stop()
        }
    }

    tick() {
        requestAnimationFrame(() => {
            const animArray = []
            this._lineStrings.forEach(line => {
                line.prevDist = line.curDist
                line.curDist += line.polyline._speed

                const listener = step => {
                    const currentPosition = line.polyline.coordinateFromStart(
                        step.value
                    )
                    this.emit(currentPosition)
                }

                line._animatedValue = new Animated.Value(line.prevDist)
                line._animatedValue.addListener(listener)
                line._listener = listener
                animArray.push(
                    Animated.timing(line._animatedValue, {
                        toValue: line.curDist,
                        duration: 1,
                        easing: Easing.linear,
                        useNativeDriver: false
                    })
                )
            })
            Animated.parallel(animArray).start(() => {
                this._lineStrings.forEach(line => {
                    line._animatedValue.removeListener(line.listener)
                })
                this.tick()
            })
        })
    }
    emit(pointFeature) {
        this._listener(pointFeature)
    }
}

export default RouteSimulator

然后我在具有地图的屏幕中调用此类

    class MainMap extends React.Component {
        constructor() {
            super()
            this.state = {
                stopsAround: Mapbox.geoUtils.makeFeatureCollection(),
                zoomLevel: 13,
                fetching: false,
                routes: null,
                newRoutes: Mapbox.geoUtils.makeFeatureCollection(),
                bounds: null,
                currentPoint: null,
                routeSimulator: null
            }
        }

    componentDidMount() {
        this.setState(
            {
                routes: nowTrips
            },
            () => {
                this.onStart()
            }
        )
    }

        onStart() {
            const routeSimulator = new RouteSimulator(this.state.routes)
            routeSimulator.addListener(currentPoint => {
//Check if zoomed in to show the animation
                if (this.state.zoomLevel >= 13) {
                    const newTransit = this.state.newRoutes
    //Check if element was already added to the feature collection or is it the first time the function was called
                    const index = newTransit.features.findIndex(
                        element =>
                            element.properties.trip.id ===
                            currentPoint.properties.trip.id
                    )
                    if (index > -1) {
                        newTransit.features[index] = currentPoint
                    } else {
                        Mapbox.geoUtils.addToFeatureCollection(
                            newTransit,
                            currentPoint
                        )
                    }
//This is fired as much as possible and I think is causing all of the lag and problems
                    this.setState({ newRoutes: newTransit })
                }
            })
            routeSimulator.start()
        }

     renderCurrentPoint() {
            if (!this.state.newRoutes) {
                return
            }
            return (
                <Mapbox.ShapeSource id="animatable" shape={this.state.newRoutes}>
                    <Mapbox.CircleLayer
                        id="animatableStop"
                        style={{
                            circleRadius: 7,
                            circleColor: '#266ef1',
                            circleStrokeWidth: 3,
                            circleStrokeColor: '#FFFFFF'
                        }}
                    />
                </Mapbox.ShapeSource>
            )
        }

初始数据只是带有一堆时间戳记的geoJSON Linestrings数组。余计算开始和结束时间,然后内插。

0 个答案:

没有答案