Image Map & Canvas

I had an interesting idea a few days…. make a canvas element, put a transparent gif over it, create an image map with some shapes and then read the coords property of the area elements to draw to the canvas. I whipped it up a day or two ago and am posting it now at 2 in the morning.

click here if you don’t know what an image map is…

Here is the slightly boring result, just roll over the shapes… code is below:

This is just an interesting experiment. Having mouse events in canvas is not necessary more most of the time. This code is a bit rough, but it’s a solid proof of concept:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
<!DOCTYPE html> 
<html> 
  <head> 
    <meta charset="utf-8" />
    <title>Canvas Map</title> 
    <script src="http://code.jquery.com/jquery-1.5.1.min.js"></script>
 
    <script>
      $(function(){
 
        var TWO_PI = Math.PI * 2;
 
        var map = $("#map");
        var areas = $("#areas");
        var canvas = $("#canvas")[0];
        canvas.width = 500;
        canvas.height = 500;
        var c = canvas.getContext("2d");
 
        $.fn.render = function(){ 
          this.data.apply(this, arguments);
          render();
        }
 
        function clear(){    
          c.fillStyle = "black";
          c.fillRect(0, 0, canvas.width, canvas.height);
        }
 
        // create a rectangle
        $('<area />', {
          shape : "rect",
          coords : "10, 10, 100, 100",
          href :  "#",
          alt : "rect"
        }).data({
 
          fillStyle: "red",
          strokeStyle : "white"
 
        }).mouseenter(function(){
          $(this).render("fillStyle", "orange");
 
        }).mouseleave(function(){
          $(this).render("fillStyle", "red");
 
        }).click(function(){
          alert("hello");
        }).appendTo(areas);
 
 
        // create a circle
        $('<area />', {
          shape : "circle",
          coords : "100, 300, 50",
          href :  "#",
          alt : "circ"
        }).data({
 
          fillStyle: "#a3bcd6",
          strokeStyle : "white",
          lineWidth : 5
 
        }).mouseenter(function(){
          $(this).render("strokeStyle", "red");
 
        }).mouseleave(function(){
          $(this).render("strokeStyle", "white");
 
        }).appendTo(areas);
 
        // create a poly
        $('<area />', {
          shape : "poly",
          coords : "300, 200, 350,250, 250, 350, 200, 250, 260, 280",
          href :  "#",
          alt : "poly"
        }).data({
 
          fillStyle: "#bf9c82",
          strokeStyle : "#ebce59",
          lineWidth : 2
 
        }).mouseenter(function(){
          $(this).render({strokeStyle: "#ede1b0",
                          fillStyle : "white"});
          render();
        }).mouseleave(function(){
          $(this).render({strokeStyle: "#ebce59",
                          fillStyle : "bf9c82"});
 
        }).appendTo(areas);
 
 
        render();
 
 
        function setStyle(fillStyle, strokeStyle, lineWidth){
          if (fillStyle){
            c.fillStyle = fillStyle; 
 
          }
          if (strokeStyle){
            if (lineWidth){
              c.lineWidth = lineWidth; 
            }
            c.strokeStyle = strokeStyle;   
          }
        }
 
        function fillStroke(fillStyle, strokeStyle){
          if (fillStyle) c.fill();
          if (strokeStyle) c.stroke();
        }
 
        function render(noClear){
          if (!noClear){
            clear();
          }
 
          areas.children().each(function(i){
            var area = $(this);
            var shape = area.attr("shape");
            var coords = area.attr("coords").split(",");
            var fillStyle = area.data("fillStyle");
            var strokeStyle = area.data("strokeStyle");
            var lineWidth = area.data("lineWidth");
 
            if (shape == "rect"){
 
              if (fillStyle){
                c.fillStyle = fillStyle; 
                c.fillRect(coords[0], coords[1], coords[2] – coords[0], coords[3] – coords[1]);
              }
              if (strokeStyle){
                if (lineWidth){
                  c.lineWidth = lineWidth; 
                }
                c.strokeStyle = strokeStyle; 
                c.strokeRect(coords[0], coords[1], coords[2] – coords[0], coords[3] – coords[1]);
              }
 
            }else if (shape == "circle"){
 
              setStyle(fillStyle, strokeStyle, lineWidth);
 
              c.beginPath();
              c.arc(coords[0], coords[1], coords[2], 0, TWO_PI, false);
              c.closePath();
 
              fillStroke(fillStyle, strokeStyle);
 
            }else if (shape == "poly"){
 
              if (fillStyle){
                c.fillStyle = fillStyle; 
 
              }
              if (strokeStyle){
                if (lineWidth){
                  c.lineWidth = lineWidth; 
                }
                c.strokeStyle = strokeStyle;   
              }
 
 
              c.beginPath();
              var leng = coords.length;
              c.moveTo(coords[0], coords[1]);
              for (var i = 2; i < leng; i+=2){
                c.lineTo(coords[i], coords[i+1]); 
              }
              c.closePath();
 
              fillStroke(fillStyle, strokeStyle);
 
            }
 
            c.lineWidth = 1;
          });
        }
      });
    </script>
    <style>
      .canvasMap{
        position : absolute;
        top : 0px;
        left : 0px;
        width : 500px;
        height : 500px;
      }
    </style>
  </head> 
 
  <body> 
 
    <div id="container">
      <map name="map">
        <div id="areas"> 
        </div>
      </map>
      <canvas class="canvasMap" id="canvas"></canvas>
      <img id="image" class="canvasMap" src="trans.gif" usemap="#map"/>
 
    </div>
 
  </body> 
</html>


 
 
 

4 Responses to “Image Map & Canvas”

  1. Zevan
    15. March 2012 um 10:29

    that’s cool. thanks

  2. Mateusz Paprocki
    22. March 2012 um 12:23

    Nice example, thanks!

    There’s a bug in rendering a rectangle though:
    - ‘s coords are: left, top, right, bottom
    - fillRect params are: x, y, width, height

    In your example the rectangle isn’t clickable in the lower right region because canvas shape is 100x100px (from (10,10) to (110, 110)) and area is 90x90px (from (10,10) to (100,100)).

    Quick Fix (shape will be the same size as defined ):
    c.fillRect(coords[0], coords[1], coords[2] – coords[0], coords[3] – coords[1]);

  3. Zevan
    22. March 2012 um 16:02

    Thanks Mateusz. Nice catch – I’ll update the code to reflect your fix :D

  4. Shishir
    26. November 2012 um 03:28

    Hi ..
    This Code are very helpful thanx.

    But for Image(with out transparent) its effect are not showing.
    Only Transparent image working

Leave a Reply

Spam protection by WP Captcha-Free