DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • The Technology Stack Needed To Build a Web3 Application
  • How to Build a Full-Stack App With Next.js, Prisma, Postgres, and Fastify
  • 5 Simple Tips to Keep Dockerized Apps Secure
  • Beginners Guide for Web Scraping Using Selenium

Trending

  • The Cypress Edge: Next-Level Testing Strategies for React Developers
  • Start Coding With Google Cloud Workstations
  • Measuring the Impact of AI on Software Engineering Productivity
  • Artificial Intelligence, Real Consequences: Balancing Good vs Evil AI [Infographic]
  1. DZone
  2. Coding
  3. Languages
  4. How to Create a Seating Layout Using Essential JS 2 Maps Control

How to Create a Seating Layout Using Essential JS 2 Maps Control

Create dynamic, customizable shapes and visualizations in minutes.

By 
Jayavigneshwaran G user avatar
Jayavigneshwaran G
·
Aug. 30, 19 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
17.6K Views

Join the DZone community and get the full member experience.

Join For Free

back-of-bus-looking-at-purple-bus-seats-and-bronze-poles

Seats open for booking with our booking simulator

The primary goal of the Essential JS 2 Maps control is to render SVG shapes using GeoJSON data. Using this control, you can render various maps along with simple geographical features. In addition, you can also render custom shapes to simulate concepts like travel seat selection, sports stadium seating, construction plans, and much more. In this blog, I will walk you through the step-by-step procedure to simulate a bus seat selection concept by rendering custom shapes and applying other EJ 2 Maps control features.

The following GIF image shows the final output of this blog, where the bus seats can be selected by clicking on the shapes and the selected seats are displayed at the right.

Bus seating layout simulation
Bus seating layout simulation

Rendering Custom Shapes

Since the EJ 2 Maps control renders shapes from GeoJSON data, you need to build GeoJSON data with coordinates that render a bus seating layout. You also need to add properties like seat number and fill color for each shape. Colors should be specified to each shape to differentiate the booked and available seats. The following code does all of this:

export let busSeat: any = { "type": "FeatureCollection", "features": [ 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[0, 0], [0, 20], [20, 20], [20, 0], [0, 0]]], [[[0, 22], [0, 27], [20, 27], [20, 22], [0, 22]]]] }, "properties": { "seatNo": 19, "fill": "grey" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[0, 47], [0, 67], [20, 67], [20, 47], [0, 47]]], [[[0, 69], [0, 74], [20, 74], [20, 69], [0, 69]]]] }, "properties": { "seatNo": 18, "fill": "grey" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[0, 94], [0, 114], [20, 114], [20, 94], [0, 94]]], [[[0, 116], [0, 121], [20, 121], [20, 116], [0, 116]]]] }, "properties": { "seatNo": 13, "fill": "grey" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[0, 141], [0, 161], [20, 161], [20, 141], [0, 141]]], [[[0, 163], [0, 168], [20, 168], [20, 163], [0, 163]]]] }, "properties": { "seatNo": 12, "fill": "grey" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[0, 188], [0, 208], [20, 208], [20, 188], [0, 188]]], [[[0, 210], [0, 215], [20, 215], [20, 210], [0, 210]]]] }, "properties": { "seatNo": 7, "fill": "grey" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[0, 235], [0, 255], [20, 255], [20, 235], [0, 235]]], [[[0, 257], [0, 262], [20, 262], [20, 257], [0, 257]]]] }, "properties": { "seatNo": 6, "fill": "grey" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[0, 282], [0, 302], [20, 302], [20, 282], [0, 282]]], [[[0, 304], [0, 309], [20, 309], [20, 304], [0, 304]]]] }, "properties": { "seatNo": 1, "fill": "grey" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[50, 0], [50, 20], [70, 20], [70, 0], [50, 0]]], [[[50, 22], [50, 27], [70, 27], [70, 22], [50, 22]]]] }, "properties": { "seatNo": 20, "fill": "grey" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[50, 47], [50, 67], [70, 67], [70, 47], [50, 47]]], [[[50, 69], [50, 74], [70, 74], [70, 69], [50, 69]]]] }, "properties": { "seatNo": 17, "fill": "grey" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[50, 94], [50, 114], [70, 114], [70, 94], [50, 94]]], [[[50, 116], [50, 121], [70, 121], [70, 116], [50, 116]]]] }, "properties": { "seatNo": 14, "fill": "Orange" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[50, 141], [50, 161], [70, 161], [70, 141], [50, 141]]], [[[50, 163], [50, 168], [70, 168], [70, 163], [50, 163]]]] }, "properties": { "seatNo": 11, "fill": "grey" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[50, 188], [50, 208], [70, 208], [70, 188], [50, 188]]], [[[50, 210], [50, 215], [70, 215], [70, 210], [50, 210]]]] }, "properties": { "seatNo": 8, "fill": "grey" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[50, 235], [50, 255], [70, 255], [70, 235], [50, 235]]], [[[50, 257], [50, 262], [70, 262], [70, 257], [50, 257]]]] }, "properties": { "seatNo": 5, "fill": "grey" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[50, 282], [50, 302], [70, 302], [70, 282], [50, 282]]], [[[50, 304], [50, 309], [70, 309], [70, 304], [50, 304]]]] }, "properties": { "seatNo": 2, "fill": "Orange" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[80, 0], [80, 20], [100, 20], [100, 0], [80, 0]]], [[[80, 22], [80, 27], [100, 27], [100, 22], [80, 22]]]] }, "properties": { "seatNo": 21, "fill": "grey" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[80, 47], [80, 67], [100, 67], [100, 47], [80, 47]]], [[[80, 69], [80, 74], [100, 74], [100, 69], [80, 69]]]] }, "properties": { "seatNo": 16, "fill": "grey" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[80, 94], [80, 114], [100, 114], [100, 94], [80, 94]]], [[[80, 116], [80, 121], [100, 121], [100, 116], [80, 116]]]] }, "properties": { "seatNo": 15, "fill": "Orange" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[80, 141], [80, 161], [100, 161], [100, 141], [80, 141]]], [[[80, 163], [80, 168], [100, 168], [100, 163], [80, 163]]]] }, "properties": { "seatNo": 10, "fill": "grey" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[80, 188], [80, 208], [100, 208], [100, 188], [80, 188]]], [[[80, 210], [80, 215], [100, 215], [100, 210], [80, 210]]]] }, "properties": { "seatNo": 9, "fill": "grey" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[80, 235], [80, 255], [100, 255], [100, 235], [80, 235]]], [[[80, 257], [80, 262], [100, 262], [100, 257], [80, 257]]]] }, "properties": { "seatNo": 4, "fill": "grey" } }, 
  { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [[[[80, 282], [80, 302], [100, 302], [100, 282], [80, 282]]], [[[80, 304], [80, 309], [100, 309], [100, 304], [80, 304]]]] }, "properties": { "seatNo": 3, "fill": "grey" } } 
]};


Now, assign this to the  shapeData property in the EJ 2 Maps control. Also, since you need to render custom shapes, you must specify Normal for the geometryType property. The default value is Geographic, because it renders geographic maps by default.

import { busSeat } from './bus-seat'; 
import { Maps } from '@syncfusion/ej2-maps';    

let maps: Maps = new Maps({   
  height: '400',   
  layers: [     
    {       
      geometryType: 'Normal',       
      shapeData: busSeat     
    }   
  ] 
});   

maps.appendTo('#maps');


Bind Colors to Shapes

Colors are applied to the shapes to differentiate booked and available seats. To do this, bind the field with colors from the data source to the colorValuePath property.

let maps: Maps = new Maps({   
  height: '400',   
  layers: [     
    {       
      geometryType: 'Normal',       
      shapeData: busSeat,       
      shapeSettings: {         
        colorValuePath: 'fill'       
      }     
    }   
  ] 
});


Enabling Selection

For selecting shapes in maps, the selection feature should be enabled. All the shapes in the maps can be selected. Thus, you need to add code in the itemSelection event to prohibit the selection of already booked seats.

let maps: Maps = new Maps({    
  itemSelection: (args: ISelectionEventArgs) => {       
    // Prohibit selection on booked seats       
    if ((args.shapeData as SeatInfo).fill === 'Orange') {          
      args.fill = 'Orange !important';          
      document.getElementById(args.target).setAttribute('class', 'ShapeselectionMapStyle');          
      return;       
    }       

    args.fill = 'green';       
    let seat: number = (args.shapeData as SeatInfo).seatNo;       
    let connector: string = ' ';         

    // To add initial/connector text       
    if (seatInfo.innerHTML === '') {          
      seatInfo.innerHTML = '<span id="seat-info">Seats Selected -</span>';       
    } else {          
      connector = ', ';       
    }       

    let seatString: string = '<span class="seats">' + connector + seat + '</span>';       
    let seatString1: string = ' ' + seat + '<span class="seats">,</span>';       
    let lastString: string = '<span id="seat-info">Seats Selected -</span><span class="seats"> ' 
      + seat + '</span>';               

    // To add/remove the seat number from the selected list       
    if (seatInfo.innerHTML.indexOf(seatString) === -1 && 
        seatInfo.innerHTML.indexOf(seatString1) === -1 && 
        seatInfo.innerHTML.indexOf(lastString) === -1) 
    {                       
      seatInfo.innerHTML += '<span class="seats">' + connector + seat + '</span>';       
    } else {          
      seatInfo.innerHTML = seatInfo.innerHTML.replace(seatString, '');          
      seatInfo.innerHTML = seatInfo.innerHTML.replace(seatString1, '');          
      if (seatInfo.innerHTML === lastString) {             
        seatInfo.innerHTML = '';          
      }       
    }    
  },    
  height: '400',    
  width: '200',    
  zoomSettings: {       
    enable: false    
  },    
  layers: [    
    {       
      geometryType: 'Normal',       
      shapeData:busSeat,       
      shapeSettings: {          
        colorValuePath: 'fill'       
      },       
      selectionSettings: {          
        enable: true,          
        enableMultiSelect: true       
      }     
    }   
  ] 
});


In the previous code sample, I have prohibited the selection of already-booked seats. Also, I have displayed the seat number to the right of the map when clicking on not-booked seats.

Adding Customizations

You can add titles, images, and borders to maps in HTML to create the appearance of a bus seating layout. You can also add a button to clear the selection in HTML.

// code for clearing the seat selection 
document.getElementById('clear-btn').onclick = () => {   
  seatInfo.innerHTML = '';   
  let selected: HTMLCollection = document.getElementsByClassName('ShapeselectionMapStyle');                
  for (let i:number = 0, length:number = selected.length; i < length; i++) {     
    selected[0].setAttribute('class', '');   
  } 
};


Conclusion

With just a little bit of code, you have built a bus seating layout by rendering custom shapes using Essential JS 2 Maps component. An interactive version of this sample is available on Stackblitz.

In a similar way, you can render any desired custom shape using the Essential JS 2 Maps component. I hope that you will enjoy this custom shape rendering feature that makes the Maps component more usable. If you have any questions or require any clarifications, please let us know in the comments section below.

Data (computing) code style GeoJSON Property (programming) Concept (generic programming) HTML Build (game engine) Blog app GIF

Published at DZone with permission of Jayavigneshwaran G. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • The Technology Stack Needed To Build a Web3 Application
  • How to Build a Full-Stack App With Next.js, Prisma, Postgres, and Fastify
  • 5 Simple Tips to Keep Dockerized Apps Secure
  • Beginners Guide for Web Scraping Using Selenium

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!