MMapRuler

The MMapRuler class displays a ruler on the map, allowing to measure the distance between points and the area of a described shape. The class only calculates the distance and displays a geodetic line between reference points. The display of markers and their texts is determined on the user side.

Note

This class is a JS API module component that is not included in the core API, but can be utilized for specific tasks.

Modules are developed and maintained by the Mappable Maps JS API team. They constitute an integral part of the JS API, just like the core API.

Usage

When creating a ruler on the map, you need to specify an array of reference points (points), a ruler type (type), geometry parameters (geometry), a preview point type (previewPoint), and a callback function that creates new reference points (point).

The current point state and functions (onDelete, onDragMove, and others) are passed from the callback function that must be called whenever any action is performed with the point. Points are updated when any of the following events occurs: changing, adding, or removing points, changing the ruler type, or toggling the "Available for editing" flag.

The ruler also provides a set of callbacks for common events you can subscribe to: onUpdate to receive notifications each time the ruler is updated, onUpdateStart to start editing the ruler, and onUpdateEnd to indicate that editing is complete.

Ruler API

Parameter

Description

type(RulerType)

Ruler type.

ruler

Line that measures the distance

planimeter

Polygon that measures the area.

points (LngLat[])

Ruler reference points.

editable (boolean)

Flag that the ruler can be edited (the default value is true).

geometry (RulerGeometry)

Object with parameters for the element geometry on the map.

style(DrawingStyle)

Line and polygon styles.

source (string)

Name of the ruler data source (the default name is mappable-ruler)

zIndex (number)

Base z index for the ruler's layer (the default value is 2600). For additional information, see Ruler layers.

onUpdate (UpdateCommonFn)

Callback function when updating a ruler. Returns total measurement results (length of the entire ruler in meters or area of the entire ruler in square meters) and ruler points (LngLat[])

onUpdateStart (UpdateStartFn)

Callback function when starting a ruler update. For correct operation, you need to pass onDragStart events to the ruler.

onUpdateEnd (UpdateEndFn)

Callback function when the ruler update ends. For correct operation, you need to pass onDragEnd events to the ruler.

previewPoint

Preview point to be displayed when hovering over the ruler line. Versions have differences:

  • vanilla: HTMLElement
  • react: ReactElement
  • vue: named slot previewPoint

point

Callback that gets values at this point and returns the point. For additional information, see Point rendering. The returned value has the following differences:

  • vanilla: Returns the MMapEntity<RenderPointArgs> entity
  • react: Returns ReactElement
  • vue: named slot point

Ruler layers

Ruler points and geometry are displayed on internal layers. This is necessary to correctly arrange points, geometries, and the blocking layer:

  • Blocking layer: Added only if prop is editable = true and the layer zIndex is _props.zIndex + 0,1.
  • Geometry layer: Displays the object geometry, the layer zIndex is _props.zIndex + 0.1.
  • Point layer: Displays points, the layer zIndex is _props.zIndex + 0.2.

Ruler layers have a zIndex between _props.zIndex and _props.zIndex + 1 and are a closed API.

Since markers are created on the user side, we pass the data source ID outwards so that markers are added to that particular layer.

Point rendering

Ruler points are visualized using the point callback. The arguments are an object with parameters for visualization:

  • state: Current point state.
    • index (number): Point index on the ruler (starting from 0).
    • totalCount (number): Total number of points on the ruler.
    • coordinates (LngLat): Current point coordinates.
    • measurements (Measurements): Measurement values at this point.
    • editable (boolean): Flag that the ruler can be edited.
    • source (string): ID of the data source the marker should be added to.
  • onDragMove(coordinates: LngLat): Callback called when the point is moved.
  • onDragStart(coordinates: LngLat): Callback called when the point starts moving.
  • onDragEnd(coordinates: LngLat): Callback called when the point stops moving.
  • onDelete(): Callback called if the point should be deleted.

Marker behavior is set up on the user side, so you should use a callback to send information about changes to the point.

Measurements depend on the ruler type:

  • If the type is ruler
    • type: ruler
    • distance: Distance in meters between the starting point and the current position.
    • segmentDistance: Distance in meters between the previous point and the current point.
    • totalDistance: Total ruler length in meters.
  • If the type is planimeter
    • type: planimeter
    • area: Picture area specified in square meters.

previewPoint requires no special movement settings. Instead, you only need to provide an HTML element to be used as a preview filler.

Usage example

// Ruler point object
class RulerPoint extends mappable.MMapComplexEntity<RenderPointArgs> {
  constructor(props: RenderPointArgs) {
    super(props);

    const point = document.createElement('div');
    // Customizing the point appearance

    /**
     * abstract delete button that calls a callback for deletion
     * so the ruler inside deletes this point
     */
    const deleteButton = document.createElement('button');
    deleteButton.addEventListener('click', () => this._props.onDelete());

    const {coordinates, editable, source} = this._props.state;

    this._pointMarker = new MMapMarker(
      {
        coordinates, // current point coordinates
        draggable: editable, // "draggable" only if the ruler can be edited
        source, // ID of the data source that the marker should be added to
        onDragMove: this._props.onDragPoint // callback when the point moves
      },
      point // html element point
    );
    this.addChild(this._pointMarker);
  }

  protected _onUpdate(props: Partial<RenderPointArgs>): void {
    // updating the point when its state changes
    if (props.state !== undefined) {
      const {coordinates, editable, source} = props.state;

      this._pointMarker.update({coordinates, draggable: editable, source});

      // abstract check that the point is at the end of the ruler
      if (props.state.index === props.state.totalCount - 1) {
        // ...
      }
    }
  }
}

const previewPoint = document.createElement('div');
// ... setting up a preview point

const ruler = new MMapRuler({
  points: RULER_COORDINATES,
  type: 'ruler',
  previewPoint,
  geometry: {lineStyle: FEATURE_LINE_STYLE, polygonStyle: FEATURE_POLYGON_STYLE},
  point: (params: RenderPointArgs) => new RulerPoint(props)
});
const RulerPoint = ({state, onDragPoint, onDelete}: RenderPointArgs) => {
const onDragMove = React.useCallback((coordinates) => {
  onDragPoint(coordinates);
}, []);

const onDeletePoint = React.useCallback(() => {
  onDelete();
}, []);

return (
  <MMapMarker
    coordinates={state.coordinates}
    source={state.source}
    draggable={state.editable}
    onDragMove={onDragMove}
  >
    <div className="point"></div>
  </MMapMarker>
);
};

const App = () => {
  const [geometry] = React.useState({lineStyle: FEATURE_LINE_STYLE, polygonStyle: FEATURE_POLYGON_STYLE});

  const onRender = React.useCallback(({state, onDelete, onDragPoint}: RenderPointArgs) => {
    return <RulerPoint state={state} onDragPoint={onDragPoint} onDelete={onDelete} />;
  }, []);

  return (
    <MMapRuler
      points={RULER_COORDINATES}
      type={'ruler'}
      point={onRender}
      geometry={geometry}
      previewPoint={<div className="preview-point"></div>}
    />
  );
};
const RulerPoint = Vue.defineComponent({
name: 'RulerPoint',
props: {
  state: Object as TVue.PropType<RenderPointArgs['state']>,
  onDragPoint: Function as TVue.PropType<RenderPointArgs['onDragPoint']>,
  onDelete: Function as TVue.PropType<RenderPointArgs['onDelete']>
},
setup(props) {
  const onDragMove = (coordinates) => {
    props.onDragPoint(coordinates);
  };
  const onDeletePoint = () => {
    props.onDelete();
  };
  return {onDragMove, onDeletePoint};
},
template: `
  <MMapMarker
      :coordinates="state.coordinates"
      :draggable="state.editable"
      :source="state.source"
      :onDragMove="onDragMove">
      <div class="point"></div>
  </MMapMarker>`
});

Vue.createApp({
  setup() {
    return {RULER_COORDINATES, FEATURE_LINE_STYLE, FEATURE_POLYGON_STYLE};
  },
  template: `
    <MMapRuler
        :points="RULER_COORDINATES"
        :geometry="{lineStyle: FEATURE_LINE_STYLE, polygonStyle: FEATURE_POLYGON_STYLE}"
        type="ruler">

        <!-- Named slot for point render -->
        <template #point="{state, onDragPoint, onDelete}">
            <RulerPoint
                :state="state"
                :onDragPoint="onDragPoint"
                :onDelete="onDelete" />
        </template>

        <!-- Named slot for preview point -->
        <template #previewPoint>
            <div class="preview-point"></div>
        </template>
    </MMapRuler>`
});

Detailed example.

Constructor

new MMapRuler(props)

Constructor parameters

Parameter

Type

props

MMapRulerProps

Redefines

MMapComplexEntity.constructor

Props

MMapRulerProps: [Omit](../../ref/modules/ruler/#omittype-keys)<\[MMapRulerCommonProps](#MMapRulerCommonProps-props), "point"> & {
	point: (`params`: RenderPointArgs) => MMapEntity<RenderPointArgs>
}

Parameters

Parameter

Type

editable?

boolean

geometry

RulerGeometry

onUpdate?

UpdateCommonFn

onUpdateEnd?

UpdateEndFn

onUpdateStart?

UpdateStartFn

point

RenderPointCommon

points

LngLat[]

previewPoint

HTMLElement

source?

string

type

RulerType

zIndex?

number

Methods

update

update(changedProps): void

Parameters

Parameter

Type

Description

changedProps

Partial<MMapRulerProps>

New props values.

Returns

void

Inherited from

MMapComplexEntity.update