Your browser lacks required capabilities. Please upgrade it or switch to another to continue.
Loading…
Testing the code in the starting passage. Move your mouse over Mario to see the "title" tooltip or click him to go to the next passage.
<div class="resizable">\
<img @src="setup.ImagePath+'MarioScreen.png'" usemap="#image-map" width="80%" class="imageMapObserve">\
</div>\
<map name="image-map">
<area alt="It's a me! Mario!" title="It's a me! Mario!" data-passage="Next"
coords="383,527,341,536,330,511,345,492,357,483,380,482,387,500" shape="poly">
</map>
[[Next]]
[[Source Code]]
Move the mouse over Mario. Try changing the window size. The image is set to width="80%". Click on Mario to go to another passage, where the same image is set to width="50%".
<img @src="setup.ImagePath+'MarioScreen.png'" usemap="#image-map" width="80%">\
<map name="image-map">
<area alt="It's a me! Mario!" title="It's a me! Mario!" data-passage="Smaller" coords="383,527,341,536,330,511,345,492,357,483,380,482,387,500" shape="poly"></map>
[[Start]]
[[Smaller]]
[[Source Code]]
Click on Mario to go to back.
<img @src="setup.ImagePath+'MarioScreen.png'" usemap="#image-map" width="50%">\
<map name="image-map">
<area alt="It's a me! Mario!" title="It's a me! Mario!" data-passage="Next" coords="383,527,341,536,330,511,345,492,357,483,380,482,387,500" shape="poly"></map>
[[Start]]
[[Back|Next]]
[[Source Code]]
To make all of the <a href="https://www.w3schools.com/html/html_images_imagemap.asp">image maps</a> in your own Twine project able to scale the <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area">{{{<area>}}} element</a> automatically when the image is resized, simply add the following code to your game's JavaScript section:
{{{
/*! Image Map Resizer
* Desc: Resize HTML imageMap to scaled image.
* Copyright: (c) 2014-15 David J. Bradshaw - dave@bradshaw.net
* License: MIT
* Modified for use in Twine/SugarCube by: HiEv (2020) v1.0
*/
(function() {
function scaleImageMap() {
function resizeMap() {
function resizeAreaTag(cachedAreaCoords, idx) {
function scale(coord) {
var dimension = 1 === (isWidth = 1 - isWidth) ? "width" : "height";
return (padding[dimension] + Math.floor(Number(coord) * scalingFactor[dimension]));
}
var isWidth = 0;
areas[idx].coords = cachedAreaCoords.split(",").map(scale).join(",");
}
if (image) {
var scalingFactor = {
width: $(image).width() / image.naturalWidth,
height: $(image).height() / image.naturalHeight,
};
var padding = {
width: parseInt(
window.getComputedStyle(image, null).getPropertyValue("padding-left"),
10
),
height: parseInt(
window.getComputedStyle(image, null).getPropertyValue("padding-top"),
10
),
};
cachedAreaCoordsArray.forEach(resizeAreaTag);
}
}
function getCoords(e) {
// Normalize coord-string to csv format without any space chars
return e.coords.replace(/ *, */g, ",").replace(/ +/g, ",");
}
function debounce() {
clearTimeout(timer);
timer = setTimeout(resizeMap, 250);
}
function start() {
function setupMap () {
if ($("img").width()) {
resizeMap();
} else {
if (++tries < 100) {
setTimeout(setupMap, 20);
}
}
}
var tries = 0;
if (image) {
setupMap();
$(context).off("mouseup", ".imageMapObserve", resizeMap);
$(context).find(".imageMapObserve").on("mouseup", resizeMap);
if (window.ResizeObserver) {
new ResizeObserver(debounce).observe($(context)[0].querySelector(".imageMapObserve"));
}
}
}
function addEventListeners() {
if (image) {
image.addEventListener("load", resizeMap, false); // Detect late image loads in IE11
}
window.addEventListener("focus", resizeMap, false); // Cope with window being resized whilst on another tab
window.addEventListener("resize", debounce, false);
window.addEventListener("readystatechange", resizeMap, false);
document.addEventListener("fullscreenchange", resizeMap, false);
$("#ui-bar-toggle").click(debounce);
}
function beenHere() {
return "function" === typeof map._resize;
}
function getImg(name) {
return $(context).find('img[usemap="' + name + '"]')[0];
}
function setup() {
areas = map.getElementsByTagName("area");
cachedAreaCoordsArray = Array.prototype.map.call(areas, getCoords);
image = getImg("#" + map.name) || getImg(map.name);
map._resize = resizeMap; // Bind resize method to HTML map element
}
var /* jshint validthis:true */
map = this, areas = null,
cachedAreaCoordsArray = null,
image = null, timer = null;
if (!beenHere()) {
setup();
addEventListeners();
start();
} else {
if ($(context).find(".imageMapObserve").length) {
$(context).off("mouseup", ".imageMapObserve", resizeMap);
$(context).find(".imageMapObserve").on("mouseup", resizeMap);
if (window.ResizeObserver) {
new ResizeObserver(debounce).observe($(context)[0].querySelector(".imageMapObserve"));
}
}
map._resize(); // Already setup, so just resize map
}
}
function factory() {
function chkMap(element) {
if (!element.tagName) {
throw new TypeError("Object is not a valid DOM element");
} else if ("MAP" !== element.tagName.toUpperCase()) {
throw new TypeError("Expected <MAP> tag, found <" + element.tagName + ">.");
}
}
function init(element) {
if (element) {
chkMap(element);
scaleImageMap.call(element);
maps.push(element);
}
}
var maps;
return function imageMapResizeF(target) {
maps = []; // Only return maps from this call
switch (typeof target) {
case "undefined":
case "string":
Array.prototype.forEach.call(context.querySelectorAll(target || "map"), init);
break;
case "object":
init(target);
break;
default:
throw new TypeError("Unexpected data type (" + typeof target + ").");
}
return maps;
};
}
var context = document;
if (typeof define === "function" && define.amd) {
define([], factory);
} else if (typeof module === "object" && typeof module.exports === "object") {
module.exports = factory(); // Node for browserfy
} else {
window.imageMapResize = factory();
}
if ("jQuery" in window) {
window.jQuery.fn.imageMapResize = function $imageMapResizeF() {
context = this.prevObject;
return this.filter("map").each(scaleImageMap).end();
};
}
})();
$(document).on(":passagerender", function (event) {
$(event.content).find("map").imageMapResize();
});
/* Image Map Resizer - End */
}}}
If you have an element which can be resized using a different method than any of the more common methods, then simply add the "imageMapObserve" class to the image element or the element which is used for resizing the image.
[[Start]]