繁体   English   中英

在React中设置标记超时

[英]Set marker timeout in React

使用标记的数组,此Marker组件渲染中的动画道具会得到一个标记,如果有一个则反弹,如果有多个则下降。

<Marker
  key={index}
  position={{lat: marker.lat, lng: marker.lng}}
  onClick={() => props.handleMarkerClick(marker)}
  animation={array.length === 1 ? google.maps.Animation.BOUNCE : google.maps.Animation.DROP}
>

但是,我的目标是为反弹设置750ms超时(基于对另一个SO问题的答案 )。 我无法使用条件三元运算符执行此操作,因此我为此进行了两次尝试创建一个函数,将Marker组件中的animation属性替换为animation={array.length === 1 ? bounceMarker() : google.maps.Animation.DROP} animation={array.length === 1 ? bounceMarker() : google.maps.Animation.DROP}都出现了问题。

我以为可以使用,但是使用google.maps.Animation.BOUNCE; 引发ESLint错误“预期分配或函数调用,而是看到一个表达式。”

  const bounceMarker = () => {
    google.maps.Animation.BOUNCE;
    setTimeout(() => {
      marker.setAnimation(null);
    }, 750);
  };

该函数基于Google的标记教程 ,并导致错误“ marker.getAnimation不是函数”:

      const bounceMarker = () => {
        if (marker.getAnimation() !== null) {
          marker.setAnimation(null);
        } else {
          marker.setAnimation(google.maps.Animation.BOUNCE);
          setTimeout(() => {
            marker.setAnimation(null);
          }, 750);
        }
      };

如果有用的话,这是此文件中的完整代码,其中注释了两个功能:

// Specifies global variable to ESLint (bundled with create-react-app), circumventing no-undef rule. See https://eslint.org/docs/user-guide/configuring#specifying-globals
/* global google */
// This component's code is from react-google-maps implementation instructions https://tomchentw.github.io/react-google-maps/#installation

import React, { Component , Fragment } from 'react';
import { withScriptjs , withGoogleMap, GoogleMap, Marker, InfoWindow } from 'react-google-maps';

const MyMapComponent = withScriptjs(
  withGoogleMap(props => (
    <GoogleMap
      zoom={props.zoom}
      defaultCenter={{ lat: 47.6093, lng: -122.3309 }}
    >
      {/* If there are markers, filters all visible markers (creating new array) then maps over newly created array taking the marker and marker's array index as arguments, rendering each Marker component with the marker index set as the key and the marker's lat and long as the position */}
      {props.markers &&
        props.markers.filter(marker => marker.isVisible)
        // "Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity ... When you don’t have stable IDs for rendered items, you may use the item index as a key as a last resort" https://reactjs.org/docs/lists-and-keys.html
        .map((marker, index, array) => {
          // const bounceMarker = () => {
          //   if (marker.getAnimation() !== null) {
          //     marker.setAnimation(null);
          //   } else {
          //     marker.setAnimation(google.maps.Animation.BOUNCE);
          //     setTimeout(() => {
          //       marker.setAnimation(null);
          //     }, 750);
          //   }
          // };
          // const bounceMarker = () => {
          //   google.maps.Animation.BOUNCE;
          //   setTimeout(() => {
          //     marker.setAnimation(null);
          //   }, 750);
          // };

          const venueInfo = props.venues.find(venue => venue.id === marker.id);
          return (
            <Marker
            key={index}
            position={{lat: marker.lat, lng: marker.lng}}
            // Marker click event listener, defined in App component class
            onClick={() => props.handleMarkerClick(marker)}
            animation={array.length === 1 ? bounceMarker() : google.maps.Animation.DROP}
            >
            {/* Show marker's InfoWindow when its isOpen state is set to true (set in app.js) */}
            {marker.isOpen &&
              <InfoWindow>
                {/* If a venueInfo is not falsey and: 1) if there's a name and bestPhoto property, return the venue photo and name; 2) if there's only a name property, display the name only; 3) if there's only a photo property, display the photo only. If neither are available and/or venueInfo is falsy display text indicating no info available. See SO question about multiple ternary operators https://stackoverflow.com/questions/7757549/multiple-ternary-operators */}
                {venueInfo && venueInfo.name && venueInfo.bestPhoto ?
                <Fragment>
                <p>{venueInfo.name}</p>
                <img src={`${venueInfo.bestPhoto.prefix}200x200${venueInfo.bestPhoto.suffix}`}
                // Screen readers already announce as image; don't need the word "image", "photo", etc.
                alt={"Venue"}
                />
                </Fragment> : venueInfo && venueInfo.name ? <p>{venueInfo.name}</p> : venueInfo && venueInfo.bestPhoto ? <img    src={`${venueInfo.bestPhoto.prefix}200x200${venueInfo.bestPhoto.suffix}`}
                // Screen readers already announce as image; don't need the word "image", "photo", etc.
                alt={"Venue"}
                /> : <p>No info available</p>}
              </InfoWindow>
            }
            </Marker>
          );
      })}
    </GoogleMap>
  ))
);

export default class Map extends Component {
  render() {
    return (
      <MyMapComponent
        // This is making the this.setState passed into Map component (as its prop) inside App's component class's render method available to MyMapComponent, which is how props from this.setState are eventually included inside MyMapComponent class (such as zoom={props.zoom})
        {...this.props}
        isMarkerShown
        googleMapURL="https://maps.googleapis.com/maps/api/js?v=3.exp&key=AIzaSyDjl8LxY7Edfulq6t_VDaQsYY4ymPjwN0w"
        // CSS declarations are placed in double curly braces because attributes accept JS objects; this is how to include an object literal. See https://stackoverflow.com/questions/22671582/what-is-the-purpose-of-double-curly-braces-in-reacts-jsx-syntax
        loadingElement={<div style={{ height: `100%` }} />}
        containerElement={<div style={{ height: `100%`, width: `75%` }} />}
        mapElement={<div style={{ height: `100%` }} />}
      />
    );
  }
}

您收到此错误

marker.getAnimation不是一个函数

因为marker不是实际的google.maps.Marker对象。

而不是渲染标记并随后更新Marker.animation属性,如何渲染具有超时的标记(基本上与使用setTimeout()的“标记动画”示例中演示的方法相同)?

为此,建议引入一种状态来保持动画标记

class MarkersAnimation extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      markers: []
    };
  }

  render() {
    return (
      <GoogleMap
        defaultZoom={this.props.zoom}
        defaultCenter={this.props.center}
      >
        {this.state.markers.map((place, i) => {
          return (
            <Marker
              animation={google.maps.Animation.BOUNCE}
              id={place.id}
              key={place.id}
              position={{ lat: place.lat, lng: place.lng }}
            />
          );
        })}
      </GoogleMap>
    );
  }

  componentDidMount() {
    const { markers, delay } = this.props;
    this.interval = setInterval(() => {
      this.setState(prev => ({
        markers: prev.markers.concat([markers.shift()])
      }));
      if (!markers.length) clearInterval(this.interval);
    }, delay);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }
}

这是一个演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM