How to create a HTML draggable and scrollable map with inertia using Phaser framework

Today I am showing you how to create a HTML draggable and scrollable map with an inertia effect which can be used in several ways. I already blogged about a similar topic in the post Create an HTML5 level selection screen using a scrollable map like in “Hero Emblems” game using Phaser but I prefer the version I am about to show you now because it allows to drag the map and make it scroll swiping on it with an inertia effect. This is what we are going to build:
Drag the map to simply move it, or swipe to make it scroll with the inertia effect: the tendency of objects to keep moving in a straight line at constant velocity. Once the map is scrolling on its own, drag it again. It should work exactly as you imagine. Thanks to Phaser draggable inputs, making it was quite a joke, have a look at the source code:
var game;
var speedMult = 0.7;
// this is the friction which will slow down the map. Must be less than 1
var friction = 0.99;

window.onload = function() {	
	game = new Phaser.Game(480, 480, Phaser.AUTO, "");
     game.state.add("PlayGame", playGame);
     game.state.start("PlayGame");
}

var playGame = function(game){};
playGame.prototype = {
     preload: function(){
          game.load.image("map", "map.png");
     },
     create: function(){  
          // the big map to scroll
          this.scrollingMap = game.add.image(0, 0, "map");
          // map will accept inputs
          this.scrollingMap.inputEnabled = true;
          // map can be dragged
          this.scrollingMap.input.enableDrag(false);
          // custom property: we save map position
          this.scrollingMap.savedPosition = new Phaser.Point(this.scrollingMap.x, this.scrollingMap.y);
          // custom property: the map is not being dragged at the moment
          this.scrollingMap.isBeingDragged = false; 
          // custom property: map is not moving (or is moving at no speed)
          this.scrollingMap.movingSpeed = 0; 
          // map can be dragged only if it entirely remains into this rectangle
          this.scrollingMap.input.boundsRect = new Phaser.Rectangle(game.width - this.scrollingMap.width, game.height - this.scrollingMap.height, this.scrollingMap.width * 2 - game.width, this.scrollingMap.height * 2 - game.height);
          // when the player starts dragging...
          this.scrollingMap.events.onDragStart.add(function(){
               // set isBeingDragged property to true
               this.scrollingMap.isBeingDragged = true;
               // set movingSpeed property to zero. This will stop moving the map
               // if the player wants to drag when it's already moving
               this.scrollingMap.movingSpeed = 0;
          }, this);
          // when the player stops dragging...
          this.scrollingMap.events.onDragStop.add(function(){
               // set isBeingDragged property to false
               this.scrollingMap.isBeingDragged = false;
          }, this);
     },
     update:function(){
          // if the map is being dragged...
          if(this.scrollingMap.isBeingDragged){
               // save current map position
               this.scrollingMap.savedPosition = new Phaser.Point(this.scrollingMap.x, this.scrollingMap.y);
          }
          // if the map is NOT being dragged...
          else{
               // if the moving speed is greater than 1...
               if(this.scrollingMap.movingSpeed > 1){
                    // adjusting map x position according to moving speed and angle using trigonometry
                    this.scrollingMap.x += this.scrollingMap.movingSpeed * Math.cos(this.scrollingMap.movingangle);
                    // adjusting map y position according to moving speed and angle using trigonometry
                    this.scrollingMap.y += this.scrollingMap.movingSpeed * Math.sin(this.scrollingMap.movingangle);
                    // keep map within boundaries
                    if(this.scrollingMap.x < game.width - this.scrollingMap.width){
                         this.scrollingMap.x = game.width - this.scrollingMap.width;
                    }
                    // keep map within boundaries
                    if(this.scrollingMap.x > 0){
                         this.scrollingMap.x = 0;
                    }
                    // keep map within boundaries
                    if(this.scrollingMap.y < game.height - this.scrollingMap.height){
                         this.scrollingMap.y = game.height - this.scrollingMap.height;
                    }
                    // keep map within boundaries
                    if(this.scrollingMap.y > 0){
                         this.scrollingMap.y = 0;
                    }
                    // applying friction to moving speed
                    this.scrollingMap.movingSpeed *= friction;
                    // save current map position
                    this.scrollingMap.savedPosition = new Phaser.Point(this.scrollingMap.x, this.scrollingMap.y);
               }
               // if the moving speed is less than 1...
               else{
                    // checking distance between current map position and last saved position
                    // which is the position in the previous frame
                    var distance = this.scrollingMap.savedPosition.distance(this.scrollingMap.position);
                    // same thing with the angle
                    var angle = this.scrollingMap.savedPosition.angle(this.scrollingMap.position);
                    // if the distance is at least 4 pixels (an arbitrary value to see I am swiping)
                    if(distance > 4){
                         // set moving speed value
                         this.scrollingMap.movingSpeed = distance * speedMult;
                         // set moving angle value
                         this.scrollingMap.movingangle = angle;
                    }
               }
          }
     }
}
There are a lot of possible uses for this kind of movement, I am showing you some of them this week, meanwhile download the source code.

Get the most popular Phaser 3 book

Through 202 pages, 32 source code examples and an Android Studio project you will learn how to build cross platform HTML5 games and create a complete game along the way.

Get the book

215 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 1+2=3
// 100 rounds
// 10000000
// 2 Cars
// 2048
// A Blocky Christmas
// A Jumping Block
// A Life of Logic
// Angry Birds
// Angry Birds Space
// Artillery
// Astro-PANIC!
// Avoider
// Back to Square One
// Ball Game
// Ball vs Ball
// Ball: Revamped
// Balloon Invasion
// BallPusher
// Ballz
// Bar Balance
// Bejeweled
// Biggification
// Block it
// Blockage
// Bloons
// Boids
// Bombuzal
// Boom Dots
// Bouncing Ball
// Bouncing Ball 2
// Bouncy Light
// BoxHead
// Breakout
// Bricks
// Bubble Chaos
// Bubbles 2
// Card Game
// Castle Ramble
// Chronotron
// Circle Chain
// Circle Path
// Circle Race
// Circular endless runner
// Cirplosion
// CLOCKS - The Game
// Color Hit
// Color Jump
// ColorFill
// Columns
// Concentration
// Crossy Road
// Crush the Castle
// Cube Jump
// CubesOut
// Dash N Blast
// Dashy Panda
// Deflection
// Diamond Digger Saga
// Don't touch the spikes
// Dots
// Down The Mountain
// Drag and Match
// Draw Game
// Drop Wizard
// DROP'd
// Dudeski
// Dungeon Raid
// Educational Game
// Elasticity
// Endless Runner
// Erase Box
// Eskiv
// Farm Heroes Saga
// Filler
// Flappy Bird
// Fling
// Flipping Legend
// Floaty Light
// Fuse Ballz
// GearTaker
// Gem Sweeper
// Globe
// Goat Rider
// Gold Miner
// Grindstone
// GuessNext
// Helicopter
// Hero Emblems
// Hero Slide
// Hexagonal Tiles
// HookPod
// Hop Hop Hop Underwater
// Horizontal Endless Runner
// Hundreds
// Hungry Hero
// Hurry it's Christmas
// InkTd
// Iromeku
// Jet Set Willy
// Jigsaw Game
// Knife Hit
// Knightfall
// Legends of Runeterra
// Lep's World
// Line Rider
// Lumines
// Magick
// MagOrMin
// Mass Attack
// Math Game
// Maze
// Meeblings
// Memdot
// Metro Siberia Underground
// Mike Dangers
// Mikey Hooks
// Nano War
// Nodes
// o:anquan
// One Button Game
// One Tap RPG
// Ononmin
// Pacco
// Perfect Square!
// Perfectionism
// Phyballs
// Pixel Purge
// PixelField
// Planet Revenge
// Plants Vs Zombies
// Platform
// Platform game
// Plus+Plus
// Pocket Snap
// Poker
// Pool
// Pop the Lock
// Pop to Save
// Poux
// Pudi
// Pumpkin Story
// Puppet Bird
// Pyramids of Ra
// qomp
// Quick Switch
// Racing
// Radical
// Rebuild Chile
// Renju
// Rise Above
// Risky Road
// Roguelike
// Roly Poly
// Run Around
// Rush Hour
// SameGame
// SamePhysics
// Save the Totem
// Security
// Serious Scramblers
// Shrink it
// Sling
// Slingy
// Snowflakes
// Sokoban
// Space Checkers
// Space is Key
// Spellfall
// Spinny Gun
// Splitter
// Spring Ninja
// Sproing
// Stabilize!
// Stack
// Stairs
// Stick Hero
// String Avoider
// Stringy
// Sudoku
// Super Mario Bros
// Surfingers
// Survival Horror
// Talesworth Adventure
// Tetris
// The Impossible Line
// The Moops - Combos of Joy
// The Next Arrow
// Threes
// Tic Tac Toe
// Timberman
// Tiny Wings
// Tipsy Tower
// Toony
// Totem Destroyer
// Tower Defense
// Trick Shot
// Tunnelball
// Turn
// Turnellio
// TwinSpin
// vvvvvv
// Warp Shift
// Way of an Idea
// Whack a Creep
// Wheel of Fortune
// Where's my Water
// Wish Upon a Star
// Word Game
// Wordle
// Worms
// Yanga
// Yeah Bunny
// Zhed
// zNumbers