动态调整图像地图和图像的大小

Posted

技术标签:

【中文标题】动态调整图像地图和图像的大小【英文标题】:Dynamically resizing Image-maps and images 【发布时间】:2012-10-30 12:57:30 【问题描述】:

我目前正在尝试在我的网站上制作一个 Image-Map,它将根据窗口的大小调整大小...我想知道是否有任何方法可以使用 html 来执行此操作,或者我是否必须使用javascript 或其他语言。

<div style="text-align:center; width:1920px; margin-left:auto; margin-right:auto;">
<img id="Image-Maps_5201211070133251" src="Site.png" usemap="#Image-Maps_5201211070133251" border="0"    />
<map id="_Image-Maps_5201211070133251" name="Image-Maps_5201211070133251">
<area shape="poly" coords="737,116,1149,118,944,473," href="http://essper.bandcamp.com"  title="Bandcamp"   />
<area shape="poly" coords="1006,589,1418,590,1211,945," href="http://soundcloud.com/essper"  title="Soundcloud"   />
<area shape="poly" coords="502,590,910,591,708,944," href="http://facebook.com/the.essper"  title="Facebook"   />
</map>

【问题讨论】:

您可以使用 css 来调整 div 和/或 img 的大小,但由于该区域的坐标是绝对坐标,您可能必须使用 javascript 来执行此操作 如果我误解了您的问题,请纠正我。你有一个固定大小和居中的IMG,它不会根据窗口调整大小,现在你想要一个MAP,它总是只覆盖IMG的可见部分? 不,我正在为图像添加动态,然后地图会根据图像的大小调整大小 【参考方案1】:

我编写了一个小库来保持 imageMap 缩放为可调整大小的图像,因此地图在图像缩放时保持同步。当您想要映射百分比缩放图像等时很有用。

它可以与jQuery一起使用,也可以不与jQuery一起使用。

https://github.com/davidjbradshaw/imagemap-resizer

你可以看到它在工作。

http://davidjbradshaw.com/imagemap-resizer/example/

【讨论】:

这太棒了!我希望我能多次投票 这太棒了!但是有没有一种简单的方法来突出悬停区域? 这真是太棒了.. 工作就像一个魅力,为我节省了很多时间! @craphunter:在我看来,应该编写一个不同的插件来突出显示,大卫的这个库非常适合它的目的! @craphunter 您是否尝试过设置 CSS 大纲属性来做到这一点? 这是一个很棒的图书馆,谢谢。我确实建议对有关处理哈希更改的代码进行一些小改动。随着 SPA/React/Vue/ 等的兴起,它特别有用。【参考方案2】:

如果您最终使用 JavaScript 完成任务,这里有一个跨浏览器代码 n-p 用于调整 MAP 元素中所有区域的大小。

window.onload = function () 
    var ImageMap = function (map) 
            var n,
                areas = map.getElementsByTagName('area'),
                len = areas.length,
                coords = [],
                previousWidth = 1920;
            for (n = 0; n < len; n++) 
                coords[n] = areas[n].coords.split(',');
            
            this.resize = function () 
                var n, m, clen,
                    x = document.body.clientWidth / previousWidth;
                for (n = 0; n < len; n++) 
                    clen = coords[n].length;
                    for (m = 0; m < clen; m++) 
                        coords[n][m] *= x;
                    
                    areas[n].coords = coords[n].join(',');
                
                previousWidth = document.body.clientWidth;
                return true;
            ;
            window.onresize = this.resize;
        ,
        imageMap = new ImageMap(document.getElementById('map_ID'));
    imageMap.resize();

previousWidth 必须等于原始图像的宽度。您还需要在 HTML 中使用一些相对单位:

<div style="width:100%;">
<img id="Image-Maps_5201211070133251" src="Site.png" usemap="#Image-Maps_5201211070133251" border="0"   />

jsFiddle 的工作演示。如果你在 IE 中打开 fiddle,点击它们时实际上可以看到AREAs。

【讨论】:

@ultrazoid 在您的问题中您说图像会根据窗口调整大小,如果图像大小与窗口大小有关,则代码将在调整窗口大小时调整MAP窗口。 不错,不使用jQuery的解决方案!谢谢! 好的,我在这里发布了一个问题:***.com/questions/23752408/… @Steve 只需使用答案中的代码即可。 "previousWidth 必须等于原始图像的宽度。"答案中的措辞可能有点糟糕,previousWidth 是您最初为area 元素创建坐标时图像的宽度。 @Steve 你有没有注意到 Barry 的问题和my answer 。该答案中引入的一些小改动使 ImageMapper 更加通用。【参考方案3】:

这是我最简单的解决方案。 不需要 jquery 或任何插件。 请注意,此解决方案不会处理标记中的任何错误或尺寸不成比例的图像。

function mapResizer(maps) 
    if (!maps) maps = document.getElementsByTagName('map');
    for (const map of maps) 
        map.img = document.querySelectorAll(`[usemap="#$map.name"]`)[0];
        map.areas = map.getElementsByTagName('area');
        for (const area of map.areas) 
            area.coordArr = area.coords.split(',');
        
    
    function resizeMaps() 
        for (const map of maps) 
            const scale = map.img.offsetWidth / (map.img.naturalWidth || map.img.width);
            for (const area of map.areas) 
                area.coords = area.coordArr.map(coord => Math.round(coord * scale)).join(',');
            
        
    
    window.addEventListener('resize', () => resizeMaps());
    resizeMaps();

if (document.readyState == 'complete') 
    mapResizer();
 else 
    window.addEventListener('load', () => mapResizer());

【讨论】:

【参考方案4】:

作为一个类(ES6):

class ResponsiveImageMap 
    constructor(map, img, width) 
        this.img = img;
        this.originalWidth = width;
        this.areas = [];

        for (const area of map.getElementsByTagName('area')) 
            this.areas.push(
                element: area,
                originalCoords: area.coords.split(',')
            );
        

        window.addEventListener('resize', e => this.resize(e));
        this.resize();
    

    resize() 
        const ratio = this.img.offsetWidth / this.originalWidth;

        for (const area of this.areas) 
            const newCoords = [];
            for (const originalCoord of area.originalCoords) 
                newCoords.push(Math.round(originalCoord * ratio));
            
            area.element.coords = newCoords.join(',');
        

        return true;
    ;

用法:

var map = document.getElementById('myMapId');
var image = document.getElementById('myImageId');
new ResponsiveImageMap(map, image, 800);

【讨论】:

【参考方案5】:

您可以将坐标乘以原始图像和样式图像的比率。

<img id="paredea" usemap="#PAREDE-A"  src="https://i.imgur.com/o9nrUMR.png">

    <map name="PAREDE-A">
        <area id="paredea0" shape="rect"  onclick="alert('colmeia A')">
        <area id="paredea1" shape="rect"  onclick="alert('colmeia B')">
        <area id="paredea2" shape="rect"  onclick="alert('colmeia C')">
        <area id="paredea3" shape="rect"  onclick="alert('colmeia D')">
        <area id="paredea4" shape="rect"  onclick="alert('colmeia E')"> 

        <area id="paredea5" shape="rect"  onclick="alert('comeia F')">
        <area id="paredea6" shape="rect"  onclick="alert('colmeia G')">
        <area id="paredea7" shape="rect"  onclick="alert('colmeia H')">
        <area id="paredea8" shape="rect"  onclick="alert('colmeia I')">
        <area id="paredea9" shape="rect"  onclick="alert('colmeia J')">  

        <area id="paredea10" shape="rect"  onclick="alert('colmeia K')">
        <area id="paredea11" shape="rect"  onclick="alert('colmeia L')">
        <area id="paredea12" shape="rect"  onclick="alert('colmeia M')">
        <area id="paredea13" shape="rect"  onclick="alert('colmeia N')">
        <area id="paredea14" shape="rect"  onclick="alert('colmeia O')">  
    </map>

    <script>


        var coordsA = [];
        coordsA[0] = "0,0,200,130";
        coordsA[1] = "200,0,400,130";
        coordsA[2] = "400,0,600,130";
        coordsA[3] = "600,0,800,130";
        coordsA[4] = "800,0,1000,130";

        coordsA[5] = "0,160,200,240";
        coordsA[6] = "200,160,400,240";
        coordsA[7] = "400,160,600,240";
        coordsA[8] = "600,160,800,240";
        coordsA[9] = "800,160,1000,240";

        coordsA[10] = "0,270,200,400";
        coordsA[11] = "200,270,400,400";
        coordsA[12] = "400,270,600,400";
        coordsA[13] = "600,270,800,400";
        coordsA[14] = "800,270,1000,400";


        function setcoords(areaid, totalOfAreas) 
            document.getElementById('paredea').style.width = "auto";
            var width1 = document.getElementById('paredea').width;
            document.getElementById('paredea').style.width = "100%";
            var width2 = document.getElementById('paredea').width;
            var ratio = width2 / width1;

            for (var i = 0; i < totalOfAreas; i++) 
                var temp = coordsA[i].split(",");
                var newcoords = "";
                for (var j = 0; j < temp.length; j++) 
                    temp[j] *= ratio;
                    newcoords += temp[j] + ",";
                
                newcoords = newcoords.substr(0, newcoords.length - 1);

                document.getElementById(areaid + i).coords = newcoords;
            
        


       window.onload = function () 
            setcoords("paredea", 15);
        ;

        window.onresize = function () 
            setcoords("paredea", 15);
        ;
    </script>

【讨论】:

【参考方案6】:

如果您可以访问 Illustrator 或其他可以生成 SVG 的程序使用 SVG 创建动态图像映射非常容易

这不需要任何编程。

这里是 Illustrator 的说明 (只需几秒钟)

    在 Illustrator 中打开图像,以新名称保存

    将文档大小调整为与图像相同的大小

    为地图部分绘制填充矩形(有助于将不透明度设置为 50%)

    使用“属性”面板为每个矩形添加一个链接

    将所有矩形的不透明度更改为 0%

    选择图像并在“链接”调色板菜单中选择“取消嵌入...” (名字无关紧要,我们不会使用图像)

    文件 › 另存为 SVG(图像位置:链接,CSS 属性:样式 元素,已选中响应式)

    打开生成的 svg 文件

    删除前两行(XML 和 Adob​​e 注释)

    更新图片来源

    将 svg 代码粘贴到您的 html 文档中

这适用于所有主要浏览器。这是 Illustrator 的 SVG 导出设置的屏幕截图:

【讨论】:

【参考方案7】:

上周我遇到了同样的问题,我最终为此编写了一个 jQuery 插件。

这里是 gitHub 项目:

https://github.com/etienne-martin/mapify

基本用法:

$("img[usemap]").mapify();

实例

http://emartin.ca/mapify/

【讨论】:

文档不明确:它只适用于 .svg 图像还是适用于所有内容(jpg、png...)? 当然。看起来它只适用于 .svg 文件。如果是这样,你应该清楚地说明它。如果没有,你应该跳过所有关于 svg 的引用。这两件事都没有说清楚。 当然,但我认为我的建议仍然适用。如果我花了这么多时间来弄清楚,可能是我注意力不集中,但也很混乱。还是谢谢【参考方案8】:

为此,您需要拥有data-original-coords 属性,该属性具有coords 到原始图片

$(function () 
    function adjeustCoords() 
        var image=$('img'); //change that to your image selector
        var originalWidth=image[0].naturalWidth;
        var currentWidth=image.width();
        var ratio=currentWidth/originalWidth;
        $("map area").each(function()
            //change that to your area selector
            var coords=$(this).attr('data-original-coords').split(',');
            coords = coords.map(function (x) 
                return Math.round(x*ratio);
                //i don't know if all browsers can accept floating point so i round the result
            );
            $(this).attr('coords',coords.join());
        );
    
    adjeustCoords();
    $(window).resize(function()
        adjeustCoords();
    );
);

这适用于 chrome 、 firefox 和 edge minimum 版本

【讨论】:

【参考方案9】:

您可以使用 CSS 精灵来实现这一点。您将让图像片段仅适合一张图像,这样您只需发出一个 http 请求即可加载所有图像。此技术不需要 javascript,您只需使用 background-position; 属性来移动图像。

这是一种有效的页面优化技术。

【讨论】:

【参考方案10】:

我只测试了直角坐标,但我认为它应该推广到圆形或多边形

function wrap ( img, map ) 
  var originalCoords = [ ],
      test = new Image();

  for ( var i = 0; i < map.areas.length; ++i ) 
    var coords = map.areas[i].coords;
    originalCoords.push( coords.split( "," ).map( parseFloat ) );
  

  function resize () 
    var ratio = img.width / test.width;
    for ( var i = 0; i < map.areas.length; ++i ) 
      map.areas[i].coords = originalCoords[i].map( function ( n ) 
        return ratio * n;
       ).join( "," );
    
  

  test.addEventListener( "load", function () 
    window.addEventListener( "resize", resize, false );
    resize();
  , false );

  test.src = img.src;


var imgs = document.querySelectorAll( "img[usemap]" );
for ( var i = 0; i < imgs.length; ++i ) 
  var map = document.querySelector( "map[name=" + imgs[i].useMap.substring( 1 ) + "]" );
  wrap( imgs[i], map );

【讨论】:

【参考方案11】:

这是我刚刚写的另一个用于管理图像映射的插件:https://github.com/gestixi/pictarea

除其他外,这些区域会根据图像的大小自动缩放。请注意,它使用画布来渲染区域。

基本用法:

$(function() 
  $('#map').pictarea(
    rescaleOnResize: true
  );
);

【讨论】:

【参考方案12】:

我发现通过适当调整 background-size 和所有其他 CSS 属性大小和位置,我可以从单个图像映射中获得多个图像大小。

以下 CSS 用于包含多个社交网络图像的 ImageMap。使用 CSS,我可以拉出三个不同大小的单个 Twitter 图标。

.twitterIcon64  /* Actual Size */
    background-size: 300px 282px;
    background: url('/images/social-media-icons.png') no-repeat -18px -109px;
    width: 64px;
    height: 64px;

.twitterIcon32  /* 1/2 size */
    background-size: 150px 141px;
    background: url('/images/social-media-icons.png') no-repeat -9px -54px;
    width: 32px;
    height: 32px;

.twitterIcon21  /* 1/3 size */
    background-size: 100px 94px;
    background: url('/images/social-media-icons.png') no-repeat -6px -36px;
    width: 22px;  /* Round up to avoid truncation */
    height: 22px; /* Round up to avoid truncation */

这对媒体查询非常有效(非常动态)。

如有必要,可以使用 javascript 来选择适当的类或计算适当的大小。

在 IE 11、Edge、Firefox 和 Chrome 上测试。

【讨论】:

以上是关于动态调整图像地图和图像的大小的主要内容,如果未能解决你的问题,请参考以下文章

在窗口调整大小时调整图像地图大小

PHP图像动态调整大小与存储调整大小的图像

PHP图像动态调整大小和圆角图像

调整 Google 地图标记图标图像的大小

jQuery动态比例元素/图像调整大小

如何在css中动态调整图像大小?