0

In this ESRI measurement widget sample: https://developers.arcgis.com/javascript/jssamples/widget_measurement.html when you draw a line, it dynamically displays the segment length. And, when you measure subsequent segments lengths, it add it to the previous length.

How can I add another result which dynamically shows the current segment length?

4

As noted in the API reference, the measurement widget does not make event listeners available for the placement of individual nodes. that being said, our new geometryEngine can help you do calculations like this entirely on the clientside.

i was able to whip up a simple sample in which i listen for both map 'click' and 'mouse-move' and create new polylines representing the last drawn segment dynamically and calculate its length.

2

Credit should go to @John-Gravois but I needed a slightly more re-usable solution so here is the code to extend esri's measure tool and show both the length of the previous segment and the current one being drawn.

Demo

Source

define([
  "dojo/_base/declare",
  "dojo/_base/lang",
  "dojo/dom-construct",
  "dojo/number",

  "esri/dijit/Measurement",
  "esri/geometry/Polyline",
  "esri/geometry/geometryEngine"
], function (
  declare,
  lang,
  domConstruct,
  Number,
  esriMeasurement,
  Polyline,
  GeometryEngine,
  Units
) {
    return declare([esriMeasurement], {
      // description:
      //  extends esri's measure tool to add last segment and current segment properties

      //store our array of points as the user clicks
      arrMeasurePoints: [],
      //set this to false if you do not want to show the distance as the mouse moves. 
      mouseMoveMeasure: true,
      //div to display the results of the last segment measured
      resultMouseSegmentDiv: null,
      //div to display the current segment length as the mouse moves


      postCreate: function () {

        console.log('app.Measurement::postCreate', arguments);
        this.inherited(arguments);

        //hook into the map click event
        this.map.on('click', lang.hitch(this, this.calcDistance));

        //hook in to clear the points on draw end
        this.own(this.on("tool-change", lang.hitch(this, function () {
          this.arrMeasurePoints = [];
          this.resultSegmentDiv.innerHTML = " ";
          if (this.resultMouseSegmentDiv) this.resultMouseSegmentDiv.innerHTML = " ";
        })));
        this.own(this.on("measure-end", lang.hitch(this, function () {
          this.arrMeasurePoints = [];
        })));

        if (this.mouseMoveMeasure) {
          this.own(this.map.on('mouse-move', lang.hitch(this, this.calcMouseDistance)));
        }

        //add a new div to contain our mouse segment length
        if (this.mouseMoveMeasure) this.resultMouseSegmentDiv = domConstruct.create('div', { 'class': 'esriMeasurementResultSegment', innerHTML: ' ' }, this.resultValueContainer.domNode);
        //add a new div to contain our segment length
        this.resultSegmentDiv = domConstruct.create('div', { 'class': 'esriMeasurementResultSegment', innerHTML: ' ' }, this.resultValueContainer.domNode);

      },

      calcDistance: function (evt) {
        try {

          //we are only going to do this for distance
          if (!this.activeTool || this.activeTool.toString().toLowerCase() !== 'distance') return false;

          this.arrMeasurePoints.push(evt.mapPoint);

          //if we have more than two create a line and measure them
          if (this.arrMeasurePoints.length < 2) return false;

          var length = this._createAndMeasureLine(this.arrMeasurePoints[this.arrMeasurePoints.length - 2], this.arrMeasurePoints[this.arrMeasurePoints.length - 1]);

          this._displaySegmentResult(length);

          return true;

        } catch (e) {
          return false;
        }
      },

      calcMouseDistance: function (evt) {
        //if we have a point to work with we can continue
        try {

          //we are only going to do this for distance
          if (!this.activeTool || this.activeTool.toString().toLowerCase() !== 'distance') return false;

          if (this.arrMeasurePoints.length < 1) return false;

          var length = this._createAndMeasureLine(this.arrMeasurePoints[this.arrMeasurePoints.length - 1], evt.mapPoint);

          this._displayMouseSegmentResult(length);

          return true;

        } catch (e) {
          return false;
        }
      },

      _displaySegmentResult: function (length) {
        //format the number.
        length = this._formatNumberForDisplay(length);
        this.resultSegmentDiv.innerHTML = "Last Segment lengh: " + length + " " + this.getUnit();
      },

      _displayMouseSegmentResult: function (length) {
        //format the number.
        length = this._formatNumberForDisplay(length);
        this.resultMouseSegmentDiv.innerHTML = "Segment lengh: " + length + " " + this.getUnit();
      },

      _formatNumberForDisplay: function (num) {
        return Number.format(num, { pattern: this.numberPattern + "0" });
      },

      _createAndMeasureLine: function(point1, point2) {

        var line = new Polyline(this.map.spatialReference);
        //use the last two points 
        line.addPath([point1, point2]);

        //now use the geometry engine to measure it's lengh
        //is it WGS-84 or Web Mercator Auxiliary Sphere? If so use geodesic
        //geodesicLength(geometry, unit)
        var unit = this.getUnit();
        if (!unit) unit = 'kilometers';
        unit = unit.toLowerCase().replace(' ', '-');
        var length;
        if (this.map.spatialReference.isWebMercator()) {
          length = GeometryEngine.geodesicLength(line, unit);
        } else {
          length = GeometryEngine.planarLength(line, unit);
        }

        return length;
      }


    });
  });

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.