专栏首页web秀JavaScript动态图片热区(绘制多个矩形并分别跳转链接)

JavaScript动态图片热区(绘制多个矩形并分别跳转链接)

前言

不知道大家有没有遇到一张图片上面有很多个商品展示图,需要给每个商品添加一个链接,点击跳转到各自商品详情页。 这个需求在前端其实有一个专业的术语“图像地图”,大家先看看w3c简单示例

<img src="planets.jpg" border="0" usemap="#planetmap" alt="Planets" />

<map name="planetmap" id="planetmap">
  <area shape="circle" coords="180,139,14" href ="venus.html" alt="Venus" />
  <area shape="circle" coords="129,161,10" href ="mercur.html" alt="Mercury" />
  <area shape="rect" coords="0,0,110,260" href ="sun.html" alt="Sun" />
</map>

上图,点击各个星球,会做不同跳转。

基础知识

代码主要是img标签上的usemap属性,关联下方的map标签。map有多个areaarea就是点击的区域,coords是坐标(如矩形x1,y1,x2,y2),shape是区域类型:

1、圆形(circ 或 circle) shape="circle",coords="x,y,z" 这里的 x 和 y 定义了圆心的位置("0,0" 是图像左上角的坐标),r 是以像素为单位的圆形半径。

2、多边形(poly 或 polygon) 每一对 "x,y" 坐标都定义了多边形的一个顶点("0,0" 是图像左上角的坐标)。定义三角形至少需要三组坐标;高纬多边形则需要更多数量的顶点。 多边形会自动封闭,因此在列表的结尾不需要重复第一个坐标来闭合整个区域。

3、矩形(rect 或 rectangle) shape="rectangle",coords="x1,y1,x2,y2" 第一个坐标是矩形的一个角的顶点坐标,另一对坐标是对角的顶点坐标,"0,0" 是图像左上角的坐标。请注意,定义矩形实际上是定义带有四个顶点的多边形的一种简化方法。

进阶

想法

下面我们回到正题:“一张图片上面有很多个商品展示图,需要给每个商品添加一个链接,点击跳转到各自商品详情页”,这个需求上面。

想法: 1、监听鼠标事件,点击记录起点位置,也就是coords左上角的坐标 2、鼠标移动至松开鼠标,记住最后位置,也就是coords右下角的坐标 3、这样2个点就是构成一个矩形,然后坐标生成img标签的map,实现点击链接

ok,有了想法,开始我们的表演

简单实现

html部分

<body>
    <ul id="map-list"></ul>
    <img id="img" src="../images/timg.jpg" border="0" usemap="#planetmap" alt="Planets" />
    <div id="maparea"></div>
</body>

css部分

* {
  padding: 0;
  margin: 0;
}
.hot_div {
  border: 1px dashed blue;
  background: #5a72f8;
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0.1;
  z-index: 9;
}
#map-list{
  position: absolute;
  top:0;
  z-index: 100;
  background: #fff;
  cursor: pointer;
}
#maparea{
  position: relative;
  z-index: 10;
}

js部分

var pointList = []; // 记录所有矩形坐标
window.onload = function() {
  document.onmousedown = function(e) {
    // 按下鼠标,我们得到起点位置
    var posx = e.clientX;
    var posy = e.clientY;

    // 我们创建一个hot_div来观察框选区域
    var div = document.createElement("div");
    div.className = "hot_div";
    div.id = "hot_div" + pointList.length;
    div.style.left = e.clientX + "px";
    div.style.top = e.clientY + "px";

    document.onmousemove = function(ev) {
      // 移动时监听鼠标位置,向hot_div添加left,top,width,height
      div.style.left = Math.min(ev.clientX, posx) + "px";
      div.style.top = Math.min(ev.clientY, posy) + "px";
      // Math.abs是取绝对值
      div.style.width = Math.abs(posx - ev.clientX) + "px";
      div.style.height = Math.abs(posy - ev.clientY) + "px";

      document.onmouseup = function() {
        document.onmousemove = null;
        document.onmouseup = null;
      }
    }
  }
})

记录矩形坐标

document.onmouseup = function() {
  // 选择区域后移除div(不删除点击不了,点击都在这个div上面)
  div.parentNode.removeChild(div);
  // left,top构成左上角坐标点,left+width,top+height构成右下角坐标点
  var point = {
      x1: parseInt(div.style.left),
      y1: parseInt(div.style.top),
      x2: parseInt(div.style.left) + parseInt(div.style.width),
      y2: parseInt(div.style.top) + parseInt(div.style.height),
      host: 'http://www.baidu.com'
  }
  // 都记录存起来
  pointList.push(point);

  // 创建map
  createMap();

  document.onmousemove = null;
  document.onmouseup = null;
}

生成map

function createMap(){
    var li = '';
    var areaTpl = '';
    // 遍历生成模板
    pointList.forEach((item, index)=> {
        // li主要是生成一个list,用来管理map的
        // 可以操作修改链接和删除
        li += '<li class="pointli" data-index="'+index+'"> '+
        '我是第'+index+'个热区('+(item.host)+'), 点击修改链接 '+
        '<span class="delPoint" data-index="'+index+'">删除</span></li>';

        // map area模板
        areaTpl += '<area '+
        'shape="rectangle" '+
        'coords="'+item.x1+','+item.y1+','+item.x2+','+item.y2+'" '+
        'href ="'+(item.host)+'" '+
        'target ="_blank" '+
        'alt="web秀" />';
    })
    // 模板添加到网页中(map和area要同时添加)
    $('#map-list').html(li);
    $('#maparea').html('<map name="planetmap" id="planetmap">'+areaTpl+'</map>');
}

删除矩形坐标

// 简单“删除”点击事件
$(document).on('click', '.delPoint', function(e){
  // status状态主要是用来阻止鼠标按下事件的 
  status = true;
  document.onmousemove = null;
  document.onmouseup = null;
  // 获取下标
  var index = $(this).data('index');
  // 删除数组某个对象
  pointList.splice(index, 1);
  // 重新生成map
  createMap();
  // 1s后状态重置
  setTimeout(function(){
      status = false;
  }, 1000)
  return false;
})

所以需要在onmousedown添加一行代码

document.onmousedown = function(e) {
  // 阻止事件
  if (status) {
      return;
  }
  ...
  ...
}

修改热点链接

$(document).on('click', '.pointli', function(e){
  status = true;
  document.onmousemove = null;
  document.onmouseup = null;
  var index = $(this).data('index');
  let point = pointList[index];
  // 弹框提示输入新的链接
  var host = prompt("请输入新的链接", point.host);
  if (host) {
    // 更新数组
    point.host = host;
    pointList.splice(index, 1, point);
    // 重新渲染
    createMap();
  }
  setTimeout(function(){
      status = false;
  }, 1000)
})

最终演示效果

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Swiper如何快速上手?

    Swiper(Swiper master)是目前应用较广泛的移动端网页触摸内容滑动js插件。

    Javanx
  • CSS实用技巧第一讲:文字处理

    作为程序猿的我们,书写代码也需要大量的技巧。一份良好的代码能让人耳目一新,让人容易理解,同时也让自己成就感满满。因此,在这里简单的整理一些CSS开发技巧,希望能...

    Javanx
  • jquery如何模拟分页-小白进阶

    tips:上面代码没有初始化第一页数据,点击一下才会出来第一页的数据,所以可以在页面加载完毕,自动触发一下点击事件

    Javanx
  • JavaScript基础学习--零碎

    1、如果WINDOW对象是常规HTML页面,TOP就是SELF       var top = document.getElementById('top'); ...

    用户1148399
  • [Leetcode][python]Permutation Sequence/第k个排列

    来自:http://www.cnblogs.com/zuoyuan/p/3785530.html 我采用的方法是计算第k个Permutation。 假设...

    后端技术漫谈
  • 博客园美化博客随笔目录

    小小咸鱼YwY
  • 20140920遇到的问题--JAVA----JS------Tomcat7.0+Onselect灵敏度+fakepath等若干问题

    相信大家在配置tomcat的时候,运行之后有时候出现一个  8005的问题,这个解决很简单:

    wust小吴
  • IOS系统下虚拟键盘遮挡文本框问题的解决

    最近在项目中发现同样的代码在Android端微信网页中点击文本框唤出的虚拟键盘不会遮挡文本框,但是在IOS端的微信网页中点击文本框唤出的键盘却在大部分情况下会遮...

    lin_zone
  • 快!逃离裁员潮!大数据程序猿必备过冬指南!!!

    2019年2月15日,滴滴月度大会上,程维宣布滴滴整体裁员比例占全员的15%,整体裁减约2000人;

    腾讯NEXT学位
  • 前端基础-节点操作

    document.createElement() 用来生成网页元素节点,参数为元素的标签名;

    cwl_java

扫码关注云+社区

领取腾讯云代金券