Reputation: 320
Depicted below is a floor plan which is displayed in a regular html file. It is just 1 big image which should have the numbered element blocks pixel perfectly placed over it before a style can even be applied.
The numbered boxes need to have a hover status that turns their background color orange and their number white.
I'd like to know if its possible to achieve this without having to resort to flash. Is it?
Upvotes: 2
Views: 559
Reputation: 13099
I can think of a couple of ways to do it. They all rely on html5 though. I'd use a transparent canvas placed in-front of the image. My natural inclination would be to overlay the image with a coloured rectangle, though it's not too much trouble to access the pixels in the image directly and create an accurate 'negative' of the hovered area.
Following on from a quesrtion that asked about highlighting imgmap area tags on hover, I came up with the following solution. You can click to define points on the right-hand image (min 3 for usefull shape), click add poly, then hover the same area on the image on the left.
Please consider it more as an example for a way of highlighting part of an image, rather than how-to make a image-map area defining-tool.. :)
Oh, before I forget - you can look at the page in developer-mode to copy the created area tags - I really should have copied them into a text-area for easy copy paste..
Code is tested with Chrome.
<!DOCTYPE html>
<html>
<head>
<script>
var canvas, hdc, markerImg;
var curPoints;
function byId(e){return document.getElementById(e);}
function canvasClick2(e)
{
e = e || event;
var x, y;
x = e.offsetX;
y = e.offsetY;
curPoints.push(x);
curPoints.push(y);
hdc.drawImage(markerImg, x- markerImg.width/2, y-markerImg.height/2);
n = curPoints.length;
var str = ''
for (i=0; i<n; i++)
{
if (i != 0)
str += ', ';
str += curPoints[i];
}
byId('coords').innerHTML = str;
}
function myInit()
{
curPoints = new Array();
canvas = byId('canvas1');
hdc = canvas.getContext('2d');
markerImg = new Image();
// just a 5x5 pixel +
markerImg.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2NkQID/QCYjiAsmoABFEMRBAThVYmgHAAhoBQWHhfyYAAAAAElFTkSuQmCC";
canvas.addEventListener('click', canvasClick2, false);
var img = byId('img1');
canvas.setAttribute('width', img.width);
canvas.setAttribute('height', img.height);
// canvas.style.backgroundImage = 'url(img/gladiators.png)';
canvas.style.backgroundImage = 'url(https://i.sstatic.net/Rw5pL.png)';
var x,y, w,h;
// get it's position and width+height
x = img.offsetLeft;
y = img.offsetTop;
w = img.clientWidth;
h = img.clientHeight;
// move the canvas, so it's contained by the same parent as the image
var imgParent = img.parentNode;
var can = byId('canvas2');
imgParent.appendChild(can);
// place the canvas in front of the image
can.style.zIndex = 1;
// position it over the image
can.style.left = x+'px';
can.style.top = y+'px';
// make same size as the image
can.setAttribute('width', w+'px');
can.setAttribute('height', h+'px');
var ctx = can.getContext('2d');
ctx.lineWidth = 3;
ctx.strokeStyle = 'red';
}
function myClear()
{
hdc.clearRect(0,0, canvas.width, canvas.height);
curPoints.length = 0;
byId('coords').innerHTML = '';
}
function myAddShapePoly()
{
var src, tgt = byId('imgMap1'), coordStr;
src = byId('coords');
coordStr = src.innerHTML;
var newArea = document.createElement('area');
newArea.setAttribute('shape', 'polygon');
newArea.setAttribute('coords', coordStr);
newArea.setAttribute('title', 'polygon');
newArea.setAttribute('onclick', 'alert("area clicked");');
newArea.onmouseout = myLeave;
newArea.onmouseover = function(){myHover2(this);};
tgt.appendChild(newArea);
myClear();
}
function myHover2(element)
{
var hoveredElement = element;
var coordStr = element.getAttribute('coords');
var areaType = element.getAttribute('shape');
switch (areaType)
{
case 'polygon':
case 'poly':
fillPoly(coordStr);
break;
case 'rect':
fillRect(coordStr);
}
// byId('img1').style.cursor = 'pointer';
}
function myLeave()
{
var canvas = byId('canvas2');
var hdc = canvas.getContext('2d');
hdc.clearRect(0, 0, canvas.width, canvas.height);
// byId('img1').style.cursor = '';
}
function fillRect(coOrdStr)
{
var canvas = byId('canvas2');
var hdc = canvas.getContext('2d');
var mCoords = coOrdStr.split(',');
var top, left, bot, right;
left = mCoords[0];
top = mCoords[1];
right = mCoords[2];
bot = mCoords[3];
var canvas = byId('myCanvas');
var tmp = hdc.fillStyle;
hdc.fillStyle = "rgba(255,0,0,0.3);";
hdc.fillRect(left,top,right-left,bot-top);
hdc.strokeRect(left,top,right-left,bot-top);
hdc.fillStyle = tmp;
}
// takes a string that contains coords eg - "227,307,261,309, 339,354, 328,371, 240,331"
// draws a line from each co-ord pair to the next - assumes starting point needs to be repeated as ending point.
function fillPoly(coOrdStr)
{
var mCoords = coOrdStr.split(',');
var i, n;
n = mCoords.length;
var canvas = byId('canvas2');
var hdc = canvas.getContext('2d');
hdc.beginPath();
hdc.moveTo(mCoords[0], mCoords[1]);
for (i=2; i<n; i+=2)
{
hdc.lineTo(mCoords[i], mCoords[i+1]);
}
hdc.lineTo(mCoords[0], mCoords[1]);
tmp=hdc.fillStyle;
hdc.fillStyle = "rgba(255,0,0,0.3);";
hdc.stroke();
hdc.fill();
hdc.fillStyle = tmp;
}
</script>
<style>
body
{
background-color: gray;
}
#canvas1
{
cursor: crosshair;
}
#canvas2
{
pointer-events: none; /* make the canvas transparent to the mouse - needed since canvas is position infront of image */
position: absolute;
}
.heading
{
font-weight: bold;
font-size: 24px;
}
</style>
</head>
<body onload='myInit();'>
<div align='center'>
<img src='https://i.sstatic.net/Rw5pL.png' id='img1' usemap='#imgMap1'/>
<map name='imgMap1' id='imgMap1'>
</map>
<canvas id='canvas2'></canvas>
<canvas id='canvas1' width='200' height='200'></canvas>
<br>
<input type='button' onclick='myClear();' value='clear'/>
<input type='button' onclick='myAddShapePoly();' value='addPolygon'/>
<br>
<span id='coords'></span>
</div>
</body>
</html>
Upvotes: 0
Reputation: 485
If the whole thing, including the boxes and numbers are an image, you can't change the images per se with CSS using the hover attributes and trying to change the color. You can overlay s and have them appear above or you can overlay another version of each box with an image. Using Photoshop/Image Ready you can slice up the image and create the hover-over effects; exporting the whole thing as a usable web page.
Upvotes: 0
Reputation: 16456
It's entirely possible. Normally elements in HTML are positioned in a 'flow', but you can take them out using absolute
positioning. This allows you to give percentage- or pixel-based values to any of the top
, left
, bottom
, right
properties and the elements will be positioned at that location offset to their nearest ancestor element with position set to relative
, absolute
or fixed
.
Here's a reduced example containing a couple of rooms from your image. You should be able to extend it by copy and pasting then adding new rooms into the markup, and changing their shape and position by giving new ID-based #roomXXXX
rules in the CSS.
http://jsfiddle.net/barney/kBvsr/
EDIT: Amended example to allow hover in IE6 as pointed out by @Marcio.
Upvotes: 4
Reputation: 3626
Define a class name to all the boxes with numbers and use CSS pseudo class as follows
.classname:hover
{
background-color:color;
font-color:color;
}
Upvotes: 0