Multi-point mark

The vgg-multi-point mark is used to plot multiple points. While visually indistinct from the Point mark, it renders a series of points as a collective mark, as opposed to the Point mark which renders one point per mark.

<vgg-multi-point
  :points="[
    [78, 44], [41, 43], [36, -37], [54, -17],
    [70, 29], [31, 0], [88, -50], [97, 15],
    [76, -34], [60, -47], [100, -24], [66, -2],
    [65, 4], [34, -10], [11, 50], [1, -11],
    [49, -49], [54, -40], [30, 49], [39, 39]
  ]"
/>

Properties

Positioning

Prop Input Types Required Default Unit(s)
points Array of coordinate pairs [x, y] Array see Usage undefined Local coordinates
geometry GeoJSON object of type MultiPoint Object see Usage undefined Local coordinates

Other aesthetics

Prop Required Types Default Input Unit(s)
radius false Number 3 Radius length Screen pixel
stroke false String 'none' Stroke color Named color, hex, rgb, hsl
stroke-width false Number 0 Stroke width Screen pixel
stroke-opacity false Number 1 Stroke opacity Number between 0 and 1
fill false String '#000000' Fill color Named color, hex, rgb, hsl
fill-opacity false Number 1 Fill opacity Number between 0 and 1
opacity false Number 1 Mark opacity Number between 0 and 1

These are analogous to the CSS properties of the same names.

Other properties

Prop Required Types Default Description
transition false Number 0 Time taken to animate changes to each point when data changes

Events

Event Description
click Triggered when user clicks on mark
hover Triggered when user hovers over mark
mouseover Triggered when user's mouse is above mark
mouseout Triggered when user's mouse leaves mark
select Triggered when mark is selected
deselect Triggered when mark is removed from selection

For more information on these events, see the Interactivity documentation.

Usage

Positioning

The Multi-point mark can be rendered with either the points or geometry prop.

points affords a quick way to plot a collection of circles. It may not be used with vgg-map and can only be scaled with the scale-x and scale-y props of its parent Section.

For instance, an input of

<vgg-section
  :x1="25"
  :x2="275"
  :y1="25"
  :y2="225"
  :scale-x="[0, 100]"
  :scale-y="[-50, 50]"
  >
  <!-- use the scale definitions above if scaling is desired -->

  <!-- vgg-map cannot be used here -->
  <vgg-multi-point
    :points="[
      [78, 44], [41, 43], [36, -37], [54, -17],
      [70, 29], [31, 0], [88, -50], [97, 15],
      [76, -34], [60, -47], [100, -24], [66, -2],
      [65, 4], [34, -10], [11, 50], [1, -11],
      [49, -49], [54, -40], [30, 49], [39, 39]
    ]"
  />

  <vgg-x-axis
    :scale="[0, 100]"
    :tickCount="5"
  />

  <vgg-y-axis
    :scale="[-50, 50]"
    :hjust="0"
    :tickCount="2"
  />

</vgg-section>

would result in

geometry should be used for geographic data containing GeoJSON MultiPoint objects only. To render other geometry types, see the overview on Geo marks.

Like other graphics where each row of the dataframe renders one mark, it is mapped with row.

<vgg-map v-slot="{ row }">
  <vgg-multi-point
    :geometry="row.geometry"
  />
</vgg-map>

For a more in-depth explanation on how mapping works, see the Map section under Core components.

Example

The graphic below adapted from Big Think depicts the estimated total wealth of African cities in 2017 in USD billions, and demonstrates how vgg-multi-point can be used with GeoJSON MultiPoint objects.

Each MultiPoint object defines a collection of cities given by their coordinates. Shown below is one such object containing the four cities in the lowest wealth group (indicated by category 1 under properties), and rendered as the smallest four circles on the map:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "MultiPoint",
        "coordinates": [
          [
            39.666667,
            -4.05
          ],
          [
            25.912222,
            -24.658056
          ],
          [
            32.583333,
            -25.966667
          ],
          [
            28.283333,
            -15.416667
          ]
        ]
      },
      "properties": {
        "wealth": "cat1" // there are 8 such categories
      }
    }
    ...
  ]
}

The vgg-multi-point mark definition then instructs the component to scale the radius of each collection of points according to their wealth category, and in order of increasing wealth:

<vgg-map v-slot="{ row }">
  <vgg-multi-point
    :geometry="row.geometry"
    :radius="{
      val: row.wealth,
      scale: {
        range: [6, 30],
        domain: 'wealth',
        order: ['cat1', 'cat2', 'cat3', 'cat4', 'cat5', 'cat6', 'cat7', 'cat8' ]
      }
    }"
    fill="#bcd8b7"
    :opacity="0.5"
  />
</vgg-map>

Finally we are left with rendering the continent itself, which can be drawn with the Polygon mark. Here are the earlier code blocks in full context, with all other props required to generate the map:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "MultiPoint",
        "coordinates": [
          [
            39.666667,
            -4.05
          ],
          [
            25.912222,
            -24.658056
          ],
          [
            32.583333,
            -25.966667
          ],
          [
            28.283333,
            -15.416667
          ]
        ]
      },
      "properties": {
        "wealth": "cat1"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "MultiPoint",
        "coordinates": [
          [
            -5.8,
            35.766667
          ],
          [
            -8.008889,
            31.63
          ], 
          [
            38.74,
            9.03
          ],
          [
            32.581111,
            0.313611
          ],
          [
            7.483333,
            9.066667
          ],
          [
            17.083611,
            -22.57
          ]
        ]
      },
      "properties": {
        "wealth": "cat2"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "MultiPoint",
        "coordinates": [
          [
            39.283333,
            -6.8
          ],
          [
            -4.033333,
            5.316667
          ],
          [
            29.916667,
            31.2
          ]
        ]
      },
      "properties": {
        "wealth": "cat3"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "MultiPoint",
        "coordinates": [
          [
            -0.2,
            5.55
          ]
        ]
      },
      "properties": {
        "wealth": "cat4"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "MultiPoint",
        "coordinates": [
          [
            -7.583333,
            33.533333
          ],
          [
            36.817222, 
            -1.286389
          ],
          [
            13.234444,
            -8.838333
          ],
          [
            28.188056,
            -25.746111
          ],
          [
            31.05,
            -29.883333
          ]
        ]
      },
      "properties": {
        "wealth": "cat5"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "MultiPoint",
        "coordinates": [
          [
            3.384082,
            6.455027
          ]
        ]
      },
      "properties": {
        "wealth": "cat6"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "MultiPoint",
        "coordinates": [
          [ 
            18.423889,
            -33.925278
          ],
          [ 
            31.233333,
            30.033333
          ]
        ]
      },
      "properties": {
        "wealth": "cat7"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "MultiPoint",
        "coordinates": [
          [  
            28.045556,
            -26.204444
          ]
        ]
      },
      "properties": {
        "wealth": "cat8"
      }
    }
  ]
}
<template>

  <vgg-graphic
    v-if="dataLoaded"
    :width="600"
    :height="600"
    :data="polygons"
    :transform="{ reproject: {
      from: '+proj=moll +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs',
      to: 'WGS84'
    } }"
    >

    <vgg-section
      :x1="0"
      :x2="550"
      :y1="0"
      :y2="550"
      :scale-geo="{}"
    >

      <vgg-map v-slot="{ row }">
        <vgg-polygon
          :geometry="row.geometry"
          fill="#6ba292"
          stroke="#d3d3d3"
          :strokeWidth="0.05"
        />
      </vgg-map>

      <vgg-data
        v-if="multipoints"
        :data="multipoints"
      >

        <vgg-map v-slot="{ row }">
          <vgg-multi-point
            :geometry="row.geometry"
            :radius="{
              val: row.wealth,
              scale: {
                range: [6, 30],
                domain: 'wealth',
                order: ['cat1', 'cat2', 'cat3', 'cat4', 'cat5', 'cat6', 'cat7', 'cat8' ]
              }
            }"
            fill="#bcd8b7"
            :opacity="0.5"
          />
        </vgg-map>

      </vgg-data>

    </vgg-section>

  </vgg-graphic>

</template>


<script>
import { africa } from './africa.js'
import { cities } from './wealthiestCities.js'

export default {
  name: 'MarkMultiPointGeo',

  data () {
    return {
      polygons: {},
      multipoints: null,
    }
  },

  computed: {
    dataLoaded () {
      return this.polygons && Object.keys(this.polygons).length !== 0
    }
  },

  mounted () {
    this.loadData()
  },

  methods: {
    loadData () {
      africa().then(data => {
        this.polygons = Object.freeze(data)
      })
      cities().then(data => {
        this.multipoints = Object.freeze(data)
      })
    }
  }
}
</script>