Interacting with the Viewer

In PlanStudio, you can add a custom data field to a specific feature which helps you to describe each individual item. For example, you can add a new field to record when a photo has been taken, what model of security camera, or an asset ID.

In this section, we will use the SDK to interactively retrieve data values attached to Features and then display them in the Viewer.

Using Data Fields and Features

A data field describes custom data that is attached to features. You can add and modify data fields in PlanStudio administration tools.

Data fields in administration tools

Once a custom data field has been added, it will be visible in the inspector when selecting an item of eligible type. The data value can be modified within the inspector.

Additional data fields in document icon

In the SDK, you can retrieve information on data fields once a plan has successfully loaded.

<script>
  ...
  viewer.on('load', function (e) {
    const dataFields = viewer.getLoadedDataFields()
    console.log(dataFields)
  })
  viewer.loadPlan(VIEWER_TOKEN, { planCode: 'pln_xxx001' })
</script>

Querying Data Fields

Once the plan is loaded, you can find your custom data field by feature type. A list of feature types can be found in Features.

In the above screenshots, one custom field was added which applied to all Features, and two custom fields which applied directly to evacSign Features. When dataFields.getFieldsForFeatureType is called for the evacSign type, all three fields will be returned. You can then do additional filtering, such as finding a data field with a particular name.

For Feature types fixedIcon, leaderlineIcon, or zonedIcon, the optional parameter subType must be set to an iconType in dataFields.getFieldsForFeatureType(featureType, subType).

  const dataFields = viewer.getLoadedDataFields()
  const fields = dataFields.getFieldsForFeatureType('evacSign')
  console.log(fields.find(f => f.displayName === 'Asset ID'))

Expected result:

  {
    "key": "dfld_xxx03",
    "displayName": "Asset ID"
  }

Get Data from Features

You can also find a specific data field from a Feature object by searching for a name or key obtained from the previous step. The returned object will include the data field’s value.

  const features = viewer.getLoadedPlan().getFeatures()
  const evacSignFeatures = features.filter(f => f.getType() === 'evacSign')
  for (const evacSignFeature of evacSignFeatures) {
    const fields = evacSignFeature.getData()
    console.log(fields.find(f => f.displayName === 'Asset ID'))
  }

Expected result:

  {
    "key": "dfld_xxx03",
    "displayName": "Asset ID",
    "value": ""
  }

Adding Interactivity

To make the display area interactive, you can allow users to select an item and see its data field values. You can achieve this by listening to the Viewer’s click event. When fired, the Viewer will provide us with an event object containing a list of Features at the clicked position, ordered by layer.

Popups

The Viewer exposes several ways to add custom content. Popups can be used to present positioned information in a popup style, exposed via the viewer.addPopup API.

You can pass HTML content and specify the location at which to display a popup using the click location as in the example below or using a feature’s location feature.getPoint().

<script>
  ...
  function showDataFieldPopup (feature, point) {
    const dataFields = feature.getData()
    let content = ''
    for (const dataField of dataFields) {
      content += `<label for="${dataField.key}" >${dataField.displayName}</label>
                  <input type="text" id="${dataField.key}"" value="${dataField.value}" style="float: right;" disabled >
                  <br style="clear: both;">`
    }
    viewer.addPopup({ anchor: { latitude: point.latitude, longitude: point.longitude }, content })
  }

  viewer.on('click', function (e) {
    for (const feature of e.features) {
      if (['evacSign', 'exitSign', 'fixedIcon', 'leaderLineIcon', 'zonedIcon'].includes(feature.getType())) {
        showDataFieldPopup(feature, e.point)
      } else {
        console.log(feature.getData())
      }
    }
  })
</script>

Using Drawers

viewer.addDrawer allows you to create a drawer by providing a display direction and HTML content. viewer.addDrawer also returns a drawer instance which allows you to update the display. Please check Drawer for more information.

For this example, we simply add a button within the popup to call viewer.addDrawer.

Popup and drawer samples

<script>
  ...
  function showSampleDrawer() {
    const content = `<h2>Sample drawer</h2>
                    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc pretium mauris est. Nullam at dolor libero.</p>`
    viewer.addDrawer({ side: 'right', content, open: true })
  }

  function showDataFieldPopup (feature, point) {
    const dataFields = feature.getData()
    let content = ''
    for (const dataField of dataFields) {
      content += `<label for="${dataField.key}" >${dataField.displayName}</label>
                  <input type="text" id="${dataField.key}"" value="${dataField.value}" style="float: right;" disabled >
                  <br style="clear: both;">`
    }
    content += '<button onclick="showSampleDrawer()">More details</button>'
    viewer.addPopup({ anchor: { latitude: point.latitude, longitude: point.longitude }, content })
  }
  ...
</script>

Full Example Code

Here is the completed example for you to play around with. The current SDK script points to the live environment with a sample viewer token.