I have lots of identical images which share a common map:
<map name="mymap">
<area shape="polygon" coords="0,0,64,0,32,32" href="ref1">
<area shape="polygon" coords="64,0,64,64,32,32" href="ref2">
</map>
<img src="image.jpg" usemap="#mymap">
<img src="image.jpg" usemap="#mymap">
and I would like the followed link to depend on:
1. which image was clicked,
2. where in the image the click was.
Above, I differentiate the locations in the image, but I wonder if there is a way to do something different depending on which image was clicked?
You could write some JavaScript to clone the map, rename it and assign it to a list of images.
or
Capture the mouse click coordinates and determine where the click is is relation to which image. If they're in a row you only need to check one coordinate.
You can trigger JavaScript using the href:
<area shape="polygon" coords="0,0,64,0,32,32" href="javascript:myFunction(1)">
<area shape="polygon" coords="0,0,64,0,32,32" href="javascript:myFunction(2)">
if you give each image an id attribute, i think you might be able to use a little bit of jquery to target the map element of each image and change the location of the window in javascript.
something along the lines of
$("#imgId map").click(function(){
window.location = "http://www.google.com";
}
$("#imgId2 map").click(function(){
window.location = "http://www.stackoverflow.com";
}
depending on the amount of images you have, if this seems like a lot or too repetitive, there might be a smarter way of being able to handle the links in javascript automatically.
Related
Is it possible to link an image map from one page to an img within a different page using usemap?
I have my image on "first page" and got the image map on "second page" and I want to link em using usemap attribute, I know that the hash symbol before the map name in usemap value is to indicates that this map exists in this page so I was wondering if I can, in this case, link an image map from another page
here is what I have done :
this is from the first page which contains the img only, this page name is "first.html"
<img src="https://i.pinimg.com/564x/c5/79/c0/c579c0ebf4c0ea8f7e7f932c87af1cce.jpg" alt="product" usemap="second.html#mapo">
and this is from the second page which contains the img map only, this page name is "second.html"
<map name="mapo">
<area shape="rect" coords="390,417,172,191" href="https://www.pinterest.com/pin/506655026846033319/">
</map>
both pages/html files r in the same folder
I tried what I mentioned above but it didn't work and I don't know why
I added AMP-Pinterest to my AMPed page. I'd like to set the propery
data-pin-hover="true" to get the PinIt button on the image. For some reason it doesn't work.
Here is what I have so far:
That's in <head>:
<script async custom-element="amp-pinterest" src="https://cdn.ampproject.org/v0/amp-pinterest-0.1.js"></script>
(and of course other AMP stuff)
That's in <body>:
<amp-pinterest height=28 width=56
data-do="buttonPin"
data-url="URL"
data-media="IMG_URL"
data-pin-hover="true"
data-description="DESC">
</amp-pinterest>
I also added data-pin-nopin="false" and data-pin-no-hover="false" to my amp-img's declaration (just in case, if it's not by default set to false. More info here: https://www.ampproject.org/docs/reference/components/amp-pinterest):
<amp-img alt="NAME" src="IMG_URL" width="600"
height="400" layout="responsive" data-pin-nopin="false"
data-pin-no-hover="false" />
But it still doesn't work (the PinIt button shows up above/below amp-img).
Question:
Now I'm wondering if I did something wrong or it's simply not supported using AMP-Pinterest to hover an image? (I can't find any example).
Unfortunately, this option doesn't to be available for amp-pinterest at the moment (going through the docs and other examples). However, if you don't prefer for the Pin It button to not appear above or below, you can instead have it embedded in the image, as seen in the amp-pinterest samples:
Embed pin widget
To embed the pin widget, set data-do to embedPing. The data-url attribute must contain the fully-qualified URL of the Pinterest resource.
HTML has supported image maps since time immemorial. You know, this sort of thing
<img src="url/to/your/image.jpg" alt="" usemap="#Map" />
<map name="Map" id="Map">
<area href="#" shape="poly" coords="381,90,386,64,421,32,462,19,501,32,535,62,540,83" />
<area href="#" shape="poly" coords="509,115,511,127,492,132,483,119,487,112" />
<area href="#" shape="poly" coords="425,113,433,108,449,118,444,128,429,128" />
</map>
I have some data in a database that determines the source for an image and defines named sets of area coordinates. This is stored as a string of JSON which parses into an object graph, and knockout renders it all into a web page complete with click handlers that return the correct identifier for each area.
All this works just fine, and I mention it only to provide operational context.
When the user clicks an area, I'd like to toggle its visibility. For example, imagine indicating one or more affected regions for an injury on an anatomical diagram, or the bent bits of the car in an insurance claim app, that sort of thing.
The problem is making an area visible. Areas do not render. So I need to draw over the image. I know it can be done; google maps does it.
I don't know where to start or what to search for. This is the first time I've ever needed to draw directly - normally I supply elements and let the browser render as it will.
So, how about some search terms, key words and perhaps even links to video tutorials? In particular I need to overlay the image so I need to draw in the same coordinate space. While you're all busy downvoting this question I'll be researching "canvas" and "drawing over images".
You can "highlight" mapped portions of your img like this:
Exactly overlay a canvas element of the same size using CSS
Tell canvas not to respond to mouse/touch events: pointer-events:none
When a mapped area is clicked, tell canvas to draw that area in a low-opacity fill using path commands:
context.beginPath();
context.moveTo(381,90);
context.lineTo(386,64);
context.lineTo(421,32);
context.lineTo(462,19);
context.lineTo(501,32);
context.lineTo(535,62);
context.lineTo(540,83);
context.closePath();
// fill the path area with a low-opacity red (or color of you choosing)
context.globalAlpha=0.15;
context.fillStyle='red';
context.fill(); // this fills the path
context.globalAlpha=1.00; // just resetting to default opacity
That allows you to keep your existing code that uses img.
Alternatively, if your design permits significant refactoring, you can draw the image on canvas and use context.isPointInPath to hit-test each path versus the mouse-click position. Then fill the hit path with the low-opacity fill.
[ Addition: Saving area coordinates for later use in hit-testing ]
Warning: untested code, might need tweaking
For easy re-use of each areas coordinates, you can put each set of coordinates in an object and put those objects in an array:
var areas=[];
// first area coordinates
arrays.push([ {x:381,y:90}, {x:386,y:64}, ... etc ]);
// second area coordinates
arrays.push([ {x:509,y:115}, {x:511,y:127}, ... etc ]);
...
Then use those saved area coordinates to do your hit-testing:
function isMouseInArea(mouseX,mouseY){
var index; // index of any "hit" area. leave it initially null
for(var i=0;i<areas.length;i++){
// create a path from this area's coordinates
defineAreaPath(areas[i]);
// test if the mouse is inside this area
if(ctx.isPointInPath(mouseX,mouseY)){
index=i;
}
}
// return any "hit" index of areas[] or return null if no hits
return(index);
}
// utility function to define a path from the supplied coordinates
function defineAreaPath(pts){
// create a path from this area's coordinates
ctx.beginPath();
ctx.moveTo(pts[0].x,pts[0].y);
for(var i=1;i<pts.length;i++){
ctx.lineTo(pts[i].x,pts[i].y);
}
ctx.closePath();
}
And you can use the isMouseInArea function like this:
var index=isMouseInArea(mouseX,mouseY)
if( index ){
// draw the area path that was "hit" by the mouse
defineAreaPath(areas[index]);
// fill that path with low-opacity fill
ctx.globalAlpha=0.15;
ctx.fillStyle='red';
ctx.fill();
ctx.globalAlpha=1.00;
}
From responses to other related questions it appears the HTML committee has been squabbling about image maps for canvas for five years.
Short version: you can't.
Long version: Use a canvas, set the image as its background and do your own hit testing.
Is there a way to control the load order of images on a web page? I was thinking of trying to simulate a preloader by first loading a light-weight 'LOADING' graphic. Any ideas?
Thanks
Use Javascript, and populate the image src properties later. The # tells the browser to link to a URL on the page, so no request will be sent to the server. (If the src property was empty, a request is still made to the server - not great.)
Assemble an array of image addresses, and recurse through it, loading your images and calling a recursive function when the onload or onerror method for each image returns a value.
HTML:
<img src='#' id='img0' alt='[]' />
<img src='#' id='img1' alt='[]' />
<img src='#' id='img2' alt='[]' />
JS:
var imgAddresses = ['img1.png','img2.jpg','img3.gif'];
function loadImage(counter) {
// Break out if no more images
if (counter==imgAddresses.length) { return; }
// Grab an image obj
var I = document.getElementById("img"+counter);
// Monitor load or error events, moving on to next image in either case
I.onload = I.onerror = function() { loadImage(counter+1); }
//Change source (then wait for event)
I.src = imgAddresses[counter];
}
loadImage(0);
You could even play around with a document.getElementsByTagName("IMG").
By the way, if you need a loading image, this is a good place to start.
EDIT
To avoid multiple requests to the server, you could use almost the same method, only don't insert image elements until you're ready to load them. Have a <span> container waiting for each image. Then, loop through, get the span object, and dynamically insert the image tag:
var img = document.createElement("IMG");
document.getElementById('mySpan').appendChild(img);
img.src = ...
Then the image request is made only once, when the element is created.
I think this article https://varvy.com/pagespeed/defer-images.html gives a very good and simple solution. Notice the part which explains how to create "empty" <img> tags with:
<img src="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" data-src="your-image-here">
to avoid <img src="">
To display a loading image, just put it in the HTML and change it later at the appropriate moment/event.
Just include the 'loading' image before any other images. usually they are included at the very top of the page and then when the page loading completes, they are hidden by a JS.
Here's a small jQuery plugin that does this for you: https://github.com/AlexandreKilian/imageorder
I've got a web page that automatically reloads every few seconds and displays a different random image. When it reloads, however, there is a blank page for a second, then the image slowly loads. I'd like to continue to show the original page until the next page is loaded into the browser's memory and then display it all at once so that it looks like a seamless slideshow. Is there a way to do this?
is the only thing changing the image? if so it might be more efficient to use something like the cycle plugin for jQuery instead of reloading your whole page.
http://malsup.com/jquery/cycle/
Here is the JS needed if you used jQuery -
Say this was your HTML:
<div class="pics">
<img src="images/beach1.jpg" width="200" height="200" />
<img src="images/beach2.jpg" width="200" height="200" />
<img src="images/beach3.jpg" width="200" height="200" />
</div>
Here would be the needed jQuery:
$(function(){
$('div.pics').cycle();
});
no need to worry about different browsers- complete cross browser compatibility.
If you're just changing the image, then I'd suggest not reloading the page at all, and using some javascript to just change the image. This may be what the jquery cycle plugin does for you.
At any rate, here's a simple example
<img id="myImage" src="http://someserver/1.jpg" />
<script language="javascript">
var imageList = ["2.jpg", "3.jpg", "4.jpg"];
var listIndex = 0;
function changeImage(){
document.getElementById('myImage').src = imageList[listIndex++];
if(listIndex > imageList.length)
listIndex = 0; // cycle around again.
setTimeout(changeImage, 5000);
};
setTimeout(changeImage, 5000);
</script>
This changes the image source every 5 seconds. Unfortunately, the browser will download the image progressively, so you'll get a "flicker" (or maybe a white space) for a few seconds while the new image downloads.
To get around this, you can "preload" the image. This is done by creating a new temporary image which isn't displayed on the screen. Once that image loads, you set the real image to the same source as the "preload", so the browser will pull the image out of it's cache, and it will appear instantly. You'd do it like this:
<img id="myImage" src="http://someserver/1.jpg" />
<script language="javascript">
var imageList = ["2.jpg", "3.jpg", "4.jpg"];
var listIndex = 0;
var preloadImage = new Image();
// when the fake image finishes loading, change the real image
function changeImage(){
document.getElementById('myImage').src = preloadImage.src;
setTimeout(preChangeImage, 5000);
};
preloadImage.onload = changeImage;
function preChangeImage(){
// tell our fake image to change it's source
preloadImage.src = imageList[listIndex++];
if(listIndex > imageList.length)
listIndex = 0; // cycle around again.
};
setTimeout(preChangeImage, 5000);
</script>
That's quite complicated, but I'll leave it as an exercise to the reader to put all the pieces together (and hopefully say "AHA!") :-)
If you create two divs that overlap in the image area, you can load one with a new image via AJAX, hide the current div and display the one with the new image and you won't have a web page refresh to cause a the "bad transition". Then repeat the process.
If there's only a small number of images and they're always displayed in the same order, you can simply create an animated GIF.
Back in the dark old days (2002) I handled this kind of situation by having an invisible iframe. I'd load content into it and in the body.onload() method I would then put the content where it needed to go.
Pre-AJAX that was a pretty good solution.
I'm just mentioning this for completeness. I'm not recommending it but it's worth noting that Ajax is not a prerequisite.
That being said, in your case where you're simply cycling an image, use Ajax or something like the jQuery cycle plug-in to cycle through images dynamically without reloading the entire page.