hexag_on
Side Gig Pro
2
MONTHS
2 2 MONTHS OF SERVICE
LEVEL 1
100 XP
In this tutorial, you will learn how to Dynamically Map an Area of an Image using JavaScript/jQuery. This will help you to understand also on how to put a detection link on a specific part or area of the image. With the use of HTML Canvas, we can dynamically locate the specific position and size of the area we want to detect on the image.
Below, I have provided a simple source code of a simple web application. The application displays an image and allows users to add details on a specific area of an image. The user can simply click the "Map Area" button to start to draw in the image that will identify the area on the image, Next, the user will click the "Save Mapped Area" button to open a form modal where he/she will put the area details. Then, after saving the details the page will be reloaded and the mapped area will become a clickable area. When the area has been clicked, a modal will show on the window that displays the area details. Users can also update the area details and delete the mapped area.
Getting Started
The source code I created below, I used Bootstrap version 5 as the CSS Framework and jQuery Library. Please download the said framework and library in or display and run the application properly. The following are the links of the framework and library website to download.
After downloading the framework and library, compile them inside a single directory that will serve as your source code folder. Also, add an image file in the directory because the application does not have an upload feature.
Creating the Interface
The below code is a HTML Script that contains the user interfaces codes of the application. This holds the image, canvas, map, area, and modal HTML tag. Open a text editor and copy the script below and paste in into a new html file. Next, change the image source according to the image file location you desired to use. Save the file as index.html.
Creating the Main Script
The below script is a JavaScript codes that contains the drawing, map area creation, buttons actions, and modal triggers codes. Save the following file as script.js.
That's it. You can now try to run the application in your browser and see if it works as it was planned to. If you found any errors, kindly review the source code on your end. You can also download the working source code I created for this tutorial. The download button is located below this article.
DEMO VIDEO
That is the end of this tutorial. I hope you will find this tutorial useful for your future web application projects. Explore more on this website for more Tutorials and Free Source Codes.
Happy Coding :)
Download
Below, I have provided a simple source code of a simple web application. The application displays an image and allows users to add details on a specific area of an image. The user can simply click the "Map Area" button to start to draw in the image that will identify the area on the image, Next, the user will click the "Save Mapped Area" button to open a form modal where he/she will put the area details. Then, after saving the details the page will be reloaded and the mapped area will become a clickable area. When the area has been clicked, a modal will show on the window that displays the area details. Users can also update the area details and delete the mapped area.
Getting Started
The source code I created below, I used Bootstrap version 5 as the CSS Framework and jQuery Library. Please download the said framework and library in or display and run the application properly. The following are the links of the framework and library website to download.
After downloading the framework and library, compile them inside a single directory that will serve as your source code folder. Also, add an image file in the directory because the application does not have an upload feature.
Creating the Interface
The below code is a HTML Script that contains the user interfaces codes of the application. This holds the image, canvas, map, area, and modal HTML tag. Open a text editor and copy the script below and paste in into a new html file. Next, change the image source according to the image file location you desired to use. Save the file as index.html.
- <!DOCTYPE html>
- <html
lang
=
"en"
>
- <head
>
- <meta
charset
=
"UTF-8"
>
- <meta
http-equiv
=
"X-UA-Compatible"
content
=
"IE=edge"
>
- <meta
name
=
"viewport"
content
=
"width=device-width, initial-scale=1.0"
>
- <title
>
Mapping</
title
>
- <link
rel
=
"stylesheet"
href
=
"./css/bootstrap.min.css"
>
- <script
src
=
"./js/jquery-3.6.0.min.js"
></
script
>
- <script
src
=
"./js/bootstrap.min.js"
></
script
>
- <script
src
=
"./js/script.js"
></
script
>
- <!-- Custom CSS -->
- <style
>
- :root {
- --bs-success-rgb: 71, 222, 152 !important;
- }
- html,
- body {
- height: 100%;
- width: 100%;
- font-family: Apple Chancery, cursive;
- }
- #fp-canvas-container {
- height: 65vh;
- width: calc(100%);
- position: relative;
- }
- .fp-img,
- .fp-canvas,
- .fp-canvas-2 {
- position: absolute;
- width: calc(100%);
- height: calc(100%);
- top: 0;
- left: 0;
- z-index: 1;
- }
- #fp-map {
- position: absolute;
- width: calc(100%);
- height: calc(100%);
- top: 0;
- left: 0;
- z-index: 1;
- }
- .fp-canvas {
- z-index: 2;
- background: #0000000d;
- cursor: crosshair;
- }
- #fp-map {
- z-index: 2;
- }
- area {
- position: absolute;
- }
- area:hover {
- background: #cbcbcb0f;
- }
- #save,
- #cancel {
- display: none;
- }
- </
style
>
- <!-- End of Custom Css -->
- </
head
>
- <body
class
=
"bg-light"
>
- <nav class
=
"navbar navbar-expand-lg navbar-dark bg-primary bg-gradient"
id
=
"topNavBar"
>
- <div
class
=
"container"
>
- <a
class
=
"navbar-brand"
href
=
"https://sourcecodester.com"
>
- Sourcecodester
- </
a
>
- </
div
>
- </
nav>
- <div
class
=
"container py-3"
id
=
"page-container"
>
- <h3
>
Dynamically Map Area on an Image</
h3
>
- <hr
>
- <div
class
=
"content"
>
- <div
class
=
"row my-2"
>
- <!-- Action Buttons -->
- <div
class
=
"col-md-12"
>
- <button
class
=
"btn btn-primary rounded-0"
type
=
"button"
id
=
"map_area"
>
Map Area</
button
>
- <button
class
=
"btn btn-primary rounded-0"
type
=
"button"
id
=
"save"
>
Save Mapped Area</
button
>
- <button
class
=
"btn btn-secondary rounded-0"
type
=
"button"
id
=
"cancel"
>
Cancel</
button
>
- </
div
>
- <!-- End ofAction Buttons -->
- </
div
>
- <!-- Image/Canvas/Map Container -->
- <div
id
=
"fp-canvas-container"
>
- <map
name
=
"fp-map"
id
=
"fp-map"
>
- </
map
>
- <img
src
=
"./devices.jpg"
alt
=
"Floor Plan"
class
=
'fp-img'
id
=
"fp-img"
usemap
=
"#fp-map"
>
- <canvas class
=
"fp-canvas d-none"
id
=
"fp-canvas"
></
canvas>
- </
div
>
- </
div
>
- <!-- End of Image/Canvas/Map Container -->
- </
div
>
- </
div
>
- <!-- Mapped Area Add/Edit Details Form Modal -->
- <div
class
=
"modal fade"
id
=
"form_modal"
role=
'dialog'
data-bs-backdrop=
"static"
data-bs-keyboard=
"true"
>
- <div
class
=
"modal-dialog modal-md modal-dialog-centered"
role=
"document"
>
- <div
class
=
"modal-content"
>
- <div
class
=
"modal-header"
>
- <h5
class
=
"modal-title"
>
Mapped Area Details</
h5
>
- </
div
>
- <div
class
=
"modal-body"
>
- <form
action
=
""
id
=
"mapped-form"
>
- <input
type
=
"hidden"
name
=
"id"
value
=
""
>
- <input
type
=
"hidden"
name
=
"coord_perc"
value
=
""
>
- <div
class
=
"form-group"
>
- <label
for
=
"description"
class
=
"control-label text-primary"
>
Description</
label
>
- <textarea
name
=
"description"
id
=
"description"
cols
=
"30"
rows
=
"4"
class
=
"form-control rounded-0"
></
textarea
>
- </
div
>
- </
form
>
- </
div
>
- <div
class
=
"modal-footer py-1"
>
- <button
type
=
"submit"
class
=
"btn btn-sm rounded-0 btn-primary"
form=
"mapped-form"
>
Save</
button
>
- <button
type
=
"button"
class
=
"btn btn-sm rounded-0 btn-secondary"
data-bs-dismiss=
"modal"
>
Close</
button
>
- </
div
>
- </
div
>
- </
div
>
- </
div
>
- <!--End of Mapped Area Add/Edit Details Form Modal -->
- <!--Mapped Area View Details Modal -->
- <div
class
=
"modal fade"
id
=
"view_modal"
role=
'dialog'
data-bs-backdrop=
"static"
data-bs-keyboard=
"true"
>
- <div
class
=
"modal-dialog modal-md modal-dialog-centered"
role=
"document"
>
- <div
class
=
"modal-content"
>
- <div
class
=
"modal-header"
>
- <h5
class
=
"modal-title"
>
Area Details</
h5
>
- </
div
>
- <div
class
=
"modal-body"
>
- </
div
>
- <div
class
=
"modal-footer py-1"
>
- <button
type
=
"button"
class
=
"btn btn-sm rounded-0 btn-primary"
data-id
=
''
id
=
"edit-area"
>
Edit</
button
>
- <button
type
=
"button"
class
=
"btn btn-sm rounded-0 btn-danger"
data-id
=
''
id
=
"delete-area"
>
Delete</
button
>
- <button
type
=
"button"
class
=
"btn btn-sm rounded-0 btn-secondary"
data-bs-dismiss=
"modal"
>
Close</
button
>
- </
div
>
- </
div
>
- </
div
>
- </
div
>
- <!--End of Mapped Area View Details Modal -->
- </
body
>
- </
html
>
Creating the Main Script
The below script is a JavaScript codes that contains the drawing, map area creation, buttons actions, and modal triggers codes. Save the following file as script.js.
- // Canvas Position Variables
- var
cposX =
0
,
- cposY =
0
;
- // Mouse Down Position Variables
- var
posX =
0
,
- posY =
0
;
- // Mouse Moving Position Variables
- var
nposX =
0
,
- nposY =
0
;
- // Coordinate Position in Percentage Variables
- var
px1_perc =
0
,
- py1_perc =
0
,
- px2_perc =
0
,
- py2_perc =
0
;
- // Canvas Variable
- var
ctx;
- // Variable for checking if the mouse has started to draw or not
- var
isDraw =
false
;
- // Auto Increment sequence for the Store Data Identification [id]
- var
AI_seq =
$.parseJSON
(
localStorage.getItem
(
'seq'
)
)
||
0
;
- // Stored Data [Mapped Area Details]
- var
stored =
$.parseJSON
(
localStorage.getItem
(
'mapped'
)
)
||
{
}
;
- // Function that creates the Area tag and appends to the Map Tag
- function
mapped_area(
)
{
- if
(
Object
.keys
(
stored)
.length
>
0
)
{
- // Empty Map Tag First
- $(
'#fp-map'
)
.html
(
''
)
- // Looping Data
- Object
.keys
(
stored)
.map
(
k =>
{
- // Loop Current Data
- var
data =
stored[
k]
- // Creating New Area Tag
- var
area =
$(
"<area shape='rect'>"
)
- area.attr
(
'href'
,
"javascript:void(0)"
)
- // Coordinate Percentage
- var
perc =
data.coord_perc
- perc =
perc.replace
(
" "
,
''
)
- perc =
perc.split
(
","
)
- // Configuring Area Position, Height, and Width
- var
x =
$(
'#fp-img'
)
.width
(
)
*
perc[
0
]
;
- var
y =
$(
'#fp-img'
)
.height
(
)
*
perc[
1
]
;
- var
width =
Math
.abs
(
(
$(
'#fp-img'
)
.width
(
)
*
Math
.abs
(
perc[
2
]
)
)
-
x)
;
- var
height =
Math
.abs
(
(
$(
'#fp-img'
)
.height
(
)
*
Math
.abs
(
perc[
3
]
)
)
-
y)
;
- if
(
(
$(
'#fp-img'
)
.width
(
)
*
perc[
2
]
)
-
x <
0
)
- x =
x -
width
- if
(
(
$(
'#fp-img'
)
.height
(
)
*
perc[
3
]
)
-
y <
0
)
- y =
y -
height
- area.attr
(
'coords'
,
x +
", "
+
y +
", "
+
width +
", "
+
height)
- area.addClass
(
'fw-bolder text-muted'
)
- area.css
(
{
- 'height'
:
height +
'px'
,
- 'width'
:
width +
'px'
,
- 'top'
:
y +
'px'
,
- 'left'
:
x +
'px'
,
- }
)
- $(
'#fp-map'
)
.append
(
area)
- // Action to make if the Area Tag has been clicked
- area.click
(
function
(
)
{
- $(
'#view_modal'
)
.find
(
'#edit-area,#delete-area'
)
.attr
(
'data-id'
,
data.id
)
- data.description
=
data.description
.replace
(
/\n/gi
,
"<br>"
)
- $(
'#view_modal'
)
.find
(
'.modal-body'
)
.html
(
data.description
)
- $(
'#view_modal'
)
.modal
(
'show'
)
- }
)
- }
)
- }
- }
- $(
function
(
)
{
- cposX =
$(
'#fp-canvas'
)
[
0
]
.getBoundingClientRect
(
)
.x
- cposY =
$(
'#fp-canvas'
)
[
0
]
.getBoundingClientRect
(
)
.y
- ctx =
$(
'#fp-canvas'
)
[
0
]
.getContext
(
'2d'
)
;
- // Creates the Map Area on the Image
- mapped_area(
)
- // Re-initialize Map Area Creation when the window has been resized
- $(
window)
.on
(
'resize'
,
function
(
)
{
- mapped_area(
)
- }
)
- // Event Listener when the mouse is clicked on the canvas area
- $(
'.fp-canvas'
)
.on
(
'mousedown'
,
function
(
e)
{
- px1_perc =
(
e.clientX
-
cposX)
/
$(
'#fp-canvas'
)
.width
(
)
- py1_perc =
(
e.clientY
-
cposY)
/
$(
'#fp-canvas'
)
.height
(
)
- posX =
$(
'#fp-canvas'
)
[
0
]
.width
*
(
(
e.clientX
-
cposX)
/
$(
'#fp-canvas'
)
.width
(
)
)
;
- posY =
$(
'#fp-canvas'
)
[
0
]
.height
*
(
(
e.clientY
-
cposY)
/
$(
'#fp-canvas'
)
.height
(
)
)
;
- isDraw =
true
- }
)
- // Event Listener when the mouse is moving on the canvas area. For drawing the rectangular Area
- $(
'.fp-canvas'
)
.on
(
'mousemove'
,
function
(
e)
{
- if
(
isDraw ==
false
)
- return
false
;
- nposX =
$(
'#fp-canvas'
)
[
0
]
.width
*
(
(
e.clientX
-
cposX)
/
$(
'#fp-canvas'
)
.width
(
)
)
;
- nposY =
$(
'#fp-canvas'
)
[
0
]
.height
*
(
(
e.clientY
-
cposY)
/
$(
'#fp-canvas'
)
.height
(
)
)
;
- var
height =
nposY -
posY;
- var
width =
nposX -
posX;
- ctx.clearRect
(
0
,
0
,
$(
'.fp-canvas'
)
[
0
]
.width
,
$(
'.fp-canvas'
)
[
0
]
.height
)
;
- ctx.beginPath
(
)
;
- ctx.lineWidth
=
".3"
;
- ctx.strokeStyle
=
"pink"
;
- ctx.rect
(
posX,
posY,
width,
height)
;
- ctx.stroke
(
)
;
- }
)
- // Event Listener when the mouse is up on the canvas area. End of Drawing
- $(
'.fp-canvas'
)
.on
(
'mouseup'
,
function
(
e)
{
- px2_perc =
(
e.clientX
-
cposX)
/
$(
'#fp-canvas'
)
.width
(
)
- py2_perc =
(
e.clientY
-
cposY)
/
$(
'#fp-canvas'
)
.height
(
)
- nposX =
$(
'#fp-canvas'
)
[
0
]
.width
*
(
(
e.clientX
-
cposX)
/
$(
'#fp-canvas'
)
.width
(
)
)
;
- nposY =
$(
'#fp-canvas'
)
[
0
]
.height
*
(
(
e.clientY
-
cposY)
/
$(
'#fp-canvas'
)
.height
(
)
)
;
- var
height =
nposY -
posY;
- var
width =
nposX -
posX;
- ctx.clearRect
(
0
,
0
,
$(
'.fp-canvas'
)
[
0
]
.width
,
$(
'.fp-canvas'
)
[
0
]
.height
)
;
- ctx.beginPath
(
)
;
- ctx.lineWidth
=
".3"
;
- ctx.strokeStyle
=
"pink"
;
- ctx.rect
(
posX,
posY,
width,
height)
;
- ctx.stroke
(
)
;
- isDraw =
false
- }
)
- // Action when Map Are button is clicked
- $(
'#map_area'
)
.click
(
function
(
)
{
- $(
this
)
.hide
(
'slow'
)
- $(
'#save,#cancel'
)
.show
(
'slow'
)
- $(
'#fp-canvas'
)
.removeClass
(
'd-none'
)
- cposX =
$(
'#fp-canvas'
)
[
0
]
.getBoundingClientRect
(
)
.x
- cposY =
$(
'#fp-canvas'
)
[
0
]
.getBoundingClientRect
(
)
.y
- }
)
- // Action when Map Are cancel is clicked
- $(
'#cancel'
)
.click
(
function
(
)
{
- $(
'#save,#cancel'
)
.hide
(
'slow'
)
- $(
'#map_area'
)
.show
(
'slow'
)
- $(
'#fp-canvas'
)
.addClass
(
'd-none'
)
- }
)
- // Action when Map Are save is clicked
- $(
'#save'
)
.click
(
function
(
)
{
- var
cP =
px1_perc +
", "
+
py1_perc +
", "
+
px2_perc +
", "
+
py2_perc
- $(
'#form_modal'
)
.find
(
'input[name="coord_perc"]'
)
.val
(
cP)
- $(
'#form_modal'
)
.modal
(
'show'
)
- }
)
- // Saving the Mapped Area Details on local Storage
- $(
'#mapped-form'
)
.submit
(
function
(
e)
{
- e.preventDefault
(
)
;
- var
data;
- var
id =
$(
this
)
.find
(
'[name="id"]'
)
.val
(
)
- var
coord_perc =
$(
this
)
.find
(
'[name="coord_perc"]'
)
.val
(
)
- var
description =
$(
this
)
.find
(
'[name="description"]'
)
.val
(
)
- if
(
id ==
''
)
{
- id =
AI_seq +
1
;
- localStorage.setItem
(
'seq'
,
id)
- }
- data =
{
id:
id,
description:
description,
coord_perc:
coord_perc }
- stored[
id]
=
data;
- localStorage.setItem
(
'mapped'
,
JSON.stringify
(
stored)
)
- alert(
"Mapped Area Successfully saved."
)
- location.reload
(
)
- }
)
- // Edit Mapped Area Details
- $(
'#edit-area'
)
.click
(
function
(
)
{
- $(
'.modal'
)
.modal
(
'hide'
)
- id =
$(
this
)
.attr
(
'data-id'
)
- data =
stored[
id]
||
{
}
- $(
'#mapped-form'
)
.find
(
'[name="id"]'
)
.val
(
data.id
)
- $(
'#mapped-form'
)
.find
(
'[name="coord_perc"]'
)
.val
(
data.coord_perc
)
- $(
'#mapped-form'
)
.find
(
'[name="description"]'
)
.val
(
data.description
)
- $(
'#form_modal'
)
.modal
(
'show'
)
- }
)
- // Delete Mapped Area
- $(
'#delete-area'
)
.click
(
function
(
)
{
- $(
'.modal'
)
.modal
(
'hide'
)
- id =
$(
this
)
.attr
(
'data-id'
)
- data =
stored[
id]
||
{
}
- var
_conf =
confirm(
"Are you sure to delete the selected mapped area?"
)
- if
(
_conf ===
true
)
{
- if
(
!!
stored[
id]
)
- delete
stored[
id]
;
- }
- localStorage.setItem
(
'mapped'
,
JSON.stringify
(
stored)
)
- alert(
"Selected Mapped Area Successfully Deleted."
)
- location.reload
(
)
- }
)
- }
)
That's it. You can now try to run the application in your browser and see if it works as it was planned to. If you found any errors, kindly review the source code on your end. You can also download the working source code I created for this tutorial. The download button is located below this article.
DEMO VIDEO
That is the end of this tutorial. I hope you will find this tutorial useful for your future web application projects. Explore more on this website for more Tutorials and Free Source Codes.
Happy Coding :)
Download
You must upgrade your account or reply in the thread to view the hidden content.