地圖熱點 jquery.image-maps.js 的使用

羊角辮兒發表於2020-07-21

在我悠閒了幾天之後,我們後端給了我個任務,地圖熱點問題。簡單來說,就是後臺劃出熱點區域,設定連結,前端拿到資料渲染頁面,顯示熱點區域。我主要使用了jquery.image-maps.js,並且新增了一些我所需要的功能。

前端是很好顯示的,獲取到資料後直接渲染頁面。

  主要是後端熱點區域位置座標的確定。

先看一下整體樣式功能圖,主要有新增熱點區域,單個刪除熱點區域,和全部刪除熱點區域,以及儲存劃出的熱點區域,還有拖拽上傳img圖片功能。以及雙擊熱點區域可填寫對應的連結。

上圖一觀,有點簡陋,相信各位小哥哥小姐姐能做的更好,勉強瞅瞅吧。

地圖熱點 jquery.image-maps.js 的使用

 

 

 首先呢,來看這個圖片,可愛的巴衛,如果不喜歡,可以把自己桌面上的圖片拖拽進選區,也可以點選選擇圖片,進行上傳,反正大家怎末喜歡怎末來。這個選區呢,我設定了400×400,但是圖片寬度400,高度自適應的,放心的,圖片不會變形的。相關程式碼如下:

 //   上傳圖片事件
        var dropBox
        window.onload = function () {
            dropBox = document.getElementById("imgMap");
            dropBox.ondragenter = ignoreDrag;
            dropBox.ondragover = ignoreDrag;
            dropBox.ondrop = drop;
        }
        function ignoreDrag(e) {
            //因為我們在處理拖放,所以應該確保沒有其他元素會取得這個事件
            e.stopPropagation();
            e.preventDefault();
        }
        function drop(e) {
            //取消事件傳播及預設行為
            e.stopPropagation();
            e.preventDefault();

            //取得拖進來的檔案
            var data = e.dataTransfer;
            var files = data.files;
            //將其傳給真正的處理檔案的函式
            processFiles(files);
        }
        function processFiles(files) {
            $('#dropBox').css({
                "height": '100%'
            })
            var file = files[0];
            var output = document.getElementById("fileOutput");
            //建立FileReader
            var reader = new FileReader();
            //告訴它在準備好資料之後做什麼
            reader.onload = function (e) {
                $('#dropBox').attr('src', e.target.result)
            };
            //讀取圖片
            reader.readAsDataURL(file);
        }

  

 新增熱點區域呢,這個選區是可以拖拽拉伸的,主要呢是確定矩形選區的位置座標,他主要是左上角的位置座標,以及矩形區域的寬度和高度來確定選取的位置。這是很重要的引數,用來確定熱點選取的位置。這樣前端才可以顯示相對應的熱點區域。他有相對應的事件,移動選取,位置改變,還有刪除選區,都是比較繁瑣的。把這些功能都放進了jquery.image-maps.js中,方便使用。

這就是jquery.image-maps.js,以及新增的部分功能。

/**
 * @name jQuery imageMaps plugin
 * @license GPL
 * @version 0.0.4
 * @date 11 22, 2010
 * @category jQuery plugin
 * @author Simon Tang (www@yiye.name)
 * @copyright (c) 2010 Simon Tang (http://yiye.name/)
 */
(function ($) {
    jQuery.fn.imageMaps = function (setting) {
        var $container = this;
        if ($container.length == 0) return false;
        $container.each(function () {
            var container = $(this);
            var $images = container.find('img[ref=imageMaps]');
            $images.wrap('<div class="image-maps-conrainer" style="position:relative;"></div>').css('border', '1px solid #ccc');
            $images.each(function () {
                var _img_conrainer = $(this).parent();
                _img_conrainer.prepend('<div class="button-conrainer"><input type="button" value="新增熱點區域" /><button class="saveAll">儲存</button><button class="deleteAll">全部刪除</button><button id="pictureClick">選擇圖片</button></div>').append('<div class="link-conrainer"></div>').append($.browser.msie ? $('<div class="position-conrainer" style="position:absolute"></div>').css({
                    background: '#fff',
                    opacity: 0
                }) : '<div class="position-conrainer" style="position:absolute"></div>');
                var _img_offset = $(this).offset();
                var _img_conrainer_offset = _img_conrainer.offset();
                _img_conrainer.find('.position-conrainer').css({
                    top: _img_offset.top - _img_conrainer_offset.top,
                    left: _img_offset.left - _img_conrainer_offset.left,
                    width: $(this).width(),
                    height: $(this).height()
                    // height: $(this)['0'].offsetHeight
                    // height: $('.position-conrainer').height()- 55
                    // border:'1px solid transparent'
                });
                var map_name = $(this).attr('usemap').replace('#', '');
                if (map_name != '') {
                    var index = 1;
                    // var _link_conrainer = _img_conrainer.find('.link-conrainer');
                    var _position_conrainer = _img_conrainer.find('.position-conrainer');
                    var image_param = $(this).attr('name') == '' ? '' : '[' + $(this).attr('name') + ']';
                    container.find('map[name=' + map_name + ']').find('area[shape=rect]').each(function () {
                        var coords = $(this).attr('coords');
                        // _link_conrainer.append('<p ref="'+index+'" class="map-link"><span class="link-number-text">Link '+index+'</span>: <input type="text" size="60" name="link'+image_param+'[]" value="'+$(this).attr('href')+'" /><input type="hidden" class="rect-value" name="rect'+image_param+'[]" value="'+coords+'" /></p>');
                        coords = coords.split(',');
                        _position_conrainer.append('<div ref="' + index + '" class="map-position" style="left:' + coords[0] + 'px;top:' + coords[1] + 'px;width:' + (coords[2] - coords[0]) + 'px;height:' + (coords[3] - coords[1]) + 'px;"><div class="map-position-bg"></div><span class="link-number-text">Link ' + index + '</span><span class="delete">X</span><span class="resize"></span></div>');
                        index++;
                    });
                }
            });

        });

        $('.button-conrainer input[type=button]').click(function () {
            var hhh = $('#dropBox').height()
            // console.log(hhh)
            // var _link_conrainer = $(this).parent().parent().find('.link-conrainer');
            var _position_conrainer = $(this).parent().parent().find('.position-conrainer');
            _position_conrainer.css({
                "height": hhh
            })
            var html = '<area shape="rect" coords="" href="" />'
            $('#Map').append(html)
            // var index = _link_conrainer.find('.map-link').length +1;
            var index = _position_conrainer.find('.map-position').length + 1
            var image = $(this).parent().parent().find('img[ref=imageMaps]').attr('name');
            image = (image == '' ? '' : '[' + image + ']');
            // _link_conrainer.append('<p ref="'+index+'" class="map-link"><span class="link-number-text">Link '+index+'</span>: <input type="text" size="60" name="link'+image+'[]" value="" /><input type="hidden" class="rect-value" name="rect'+image+'[]" value="10,10,100,40" /></p>');
            _position_conrainer.append('<div ref="' + index + '" class="map-position" style="left:0px;top:0px;width:90px;height:60px;"><div class="map-position-bg"></div><span class="link-number-text">Link ' + index + '</span><span class="delete">X</span><span class="resize"></span></div>');
            bind_map_event();
            define_css();
        });

        $('.button-conrainer .deleteAll').click(function (e) {
            $('.position-conrainer').empty()
            $('#Map area').remove()
        })
        // 儲存到本地
        $(' .button-conrainer .saveAll').click(function () {
            var savePart = $('#Map')['0'].outerHTML
            var img = $('#dropBox')['0'].outerHTML
            window.localStorage.setItem("site", savePart)
            window.localStorage.setItem("img", img)
        })
        //   上傳圖片事件
        var dropBox
        window.onload = function () {
            dropBox = document.getElementById("imgMap");
            dropBox.ondragenter = ignoreDrag;
            dropBox.ondragover = ignoreDrag;
            dropBox.ondrop = drop;
        }
        function ignoreDrag(e) {
            //因為我們在處理拖放,所以應該確保沒有其他元素會取得這個事件
            e.stopPropagation();
            e.preventDefault();
        }
        function drop(e) {
            //取消事件傳播及預設行為
            e.stopPropagation();
            e.preventDefault();

            //取得拖進來的檔案
            var data = e.dataTransfer;
            var files = data.files;
            //將其傳給真正的處理檔案的函式
            processFiles(files);
        }
        function processFiles(files) {
            $('#dropBox').css({
                "height": '100%'
            })
            var file = files[0];
            var output = document.getElementById("fileOutput");
            //建立FileReader
            var reader = new FileReader();
            //告訴它在準備好資料之後做什麼
            reader.onload = function (e) {
                //使用影像URL來繪製dropBox的背景
                $('#dropBox').attr('src', e.target.result)
            };
            //讀取圖片
            reader.readAsDataURL(file);
        }

        $('#fileinp').change(function (files) {
            processFiles(this.files)
        })
        $('#pictureClick').click(function () {
            $('#fileinp').click()
        })

        //繫結map事件
        function bind_map_event() {
            $('.position-conrainer .map-position .map-position-bg').each(function () {
                var map_position_bg = $(this);
                var conrainer = $(this).parent().parent();
                var map_position = map_position_bg.parent();
                map_position_bg.unbind('mousedown').mousedown(function (event) {
                    map_position_bg.data('mousedown', true);
                    map_position_bg.data('pageX', event.pageX);
                    map_position_bg.data('pageY', event.pageY);
                    map_position_bg.css('cursor', 'move');
                    return false;
                }).unbind('mouseup').mouseup(function (event) {
                    map_position_bg.data('mousedown', false);
                    map_position_bg.css('cursor', 'default');
                    return false;
                });
                conrainer.mousemove(function (event) {
                    if (!map_position_bg.data('mousedown')) return false;
                    var dx = event.pageX - map_position_bg.data('pageX');
                    var dy = event.pageY - map_position_bg.data('pageY');
                    if ((dx == 0) && (dy == 0)) {
                        return false;
                    }
                    var p = map_position.position();
                    var left = p.left + dx;
                    if (left < 0) left = 0;
                    var top = p.top + dy;
                    if (top < 0) top = 0;
                    var bottom = top + map_position.height();
                    if (bottom > conrainer.height()) {
                        top = top - (bottom - conrainer.height());
                    }
                    var right = left + map_position.width();
                    if (right > conrainer.width()) {
                        left = left - (right - conrainer.width());
                    }
                    map_position.css({
                        left: left,
                        top: top
                    });
                    map_position_bg.data('pageX', event.pageX);
                    map_position_bg.data('pageY', event.pageY);

                    bottom = top + map_position.height();
                    right = left + map_position.width();
                    console.log(left, top, right, bottom)
                    var arr = []
                    arr.push(left, top, right, bottom)
                    var coods = arr.join(',')
                    var k = map_position['0'].attributes.ref.value - 1 + ''
                    $('#Map area').prevObject['0'].links[k].coords = coods
                    // $('.link-conrainer p[ref='+map_position.attr('ref')+'] .rect-value').val(new Array(left,top,right,bottom).join(','));
                    return false;
                }).mouseup(function (event) {
                    map_position_bg.data('mousedown', false);
                    map_position_bg.css('cursor', 'default');
                    return false;
                });
               
            });
            $('.position-conrainer .map-position .resize').each(function () {
                var map_position_resize = $(this);
                var conrainer = $(this).parent().parent();
                map_position_resize.unbind('mousedown').mousedown(function (event) {
                    map_position_resize.data('mousedown', true);
                    map_position_resize.data('pageX', event.pageX);
                    map_position_resize.data('pageY', event.pageY);
                    return false;
                }).unbind('mouseup').mouseup(function (event) {
                    map_position_resize.data('mousedown', false);
                    return false;
                });
                conrainer.mousemove(function (event) {
                    if (!map_position_resize.data('mousedown')) return false;
                    var dx = event.pageX - map_position_resize.data('pageX');
                    var dy = event.pageY - map_position_resize.data('pageY');
                    if ((dx == 0) && (dy == 0)) {
                        return false;
                    }
                    var map_position = map_position_resize.parent();
                    var p = map_position.position();
                    var left = p.left;
                    var top = p.top;
                    var height = map_position.height() + dy;
                    if ((top + height) > conrainer.height()) {
                        height = height - ((top + height) - conrainer.height());
                    }
                    if (height < 20) height = 20;
                    var width = map_position.width() + dx;
                    if ((left + width) > conrainer.width()) {
                        width = width - ((left + width) - conrainer.width());
                    }
                    if (width < 50) width = 50;
                    map_position.css({
                        width: width,
                        height: height
                    });
                    map_position_resize.data('pageX', event.pageX);
                    map_position_resize.data('pageY', event.pageY);

                    bottom = top + map_position.height();
                    right = left + map_position.width();
                    // $('.link-conrainer p[ref='+map_position.attr('ref')+'] .rect-value').val(new Array(left,top,right,bottom).join(','));
                    return false;
                }).mouseup(function (event) {
                    map_position_resize.data('mousedown', false);
                    return false;
                });
            });
            $('.position-conrainer .map-position .delete').unbind('click').click(function () {
                var ref = $(this).parent().attr('ref');
                var num = ref - 1
                $('#map').context.links[num].remove()
                // var _link_conrainer = $(this).parent().parent().parent().find('.link-conrainer');
                var _position_conrainer = $(this).parent().parent().parent().find('.position-conrainer');
                // _link_conrainer.find('.map-link[ref='+ref+']').remove();
                _position_conrainer.find('.map-position[ref=' + ref + ']').remove();
                var index = 1;
                // _link_conrainer.find('.map-link').each(function(){
                //     $(this).attr('ref',index).find('.link-number-text').html('Link '+index);
                //     index ++;
                // });
                index = 1;
                _position_conrainer.find('.map-position').each(function () {
                    $(this).attr('ref', index).find('.link-number-text').html('Link ' + index);
                    index++;
                });


            });
        }

        bind_map_event();

        function define_css() {
            //樣式定義
            $container.find('.map-position').css({
                position: 'absolute',
                border: '1px solid #000',
                'font-weight': 'bold'
            });
            $container.find('.map-position .map-position-bg').css({
                position: 'absolute',
                background: '#0F0',
                opacity: 0.5,
                top: 0,
                left: 0,
                right: 0,
                bottom: 0
            });
            $container.find('.map-position .resize').css({
                display: 'block',
                position: 'absolute',
                right: 0,
                bottom: 0,
                width: 5,
                height: 5,
                cursor: 'nw-resize',
                background: '#000'
            });
            $container.find('.map-position .delete').css({
                display: 'block',
                position: 'absolute',
                right: 0,
                top: 0,
                width: 10,
                height: 12,
                'line-height': '11px',
                'font-size': 12,
                'font-weight': 'bold',
                background: '#000',
                color: '#fff',
                'font-family': 'Arial',
                'padding-left': '2px',
                cursor: 'pointer',
                opactiey: 1
            });
        }
        define_css();
    };
})(jQuery); 

 

接下來呢,給大家說說雙擊新增連結功能,每個熱點區域都有對應的連結,後端設定了連結,前端在顯示熱點區域時,點選選區就可以直接跳轉到後臺所設定的連結。這是單獨新增的功能,沒有放到jquery.image-maps.js 中。

$('.map-position ').unbind('dblclick').dblclick(function () {
          var k = $(this)['0'].attributes.ref.value - 1 + ''
          var lll = $('.link input').val().split('//')[1]
          var vvv = $('#Map area')[k].host
          if (!lll) {
            $('.link input')['0'].value = 'http://'
          } else {
            $('.link input')['0'].value = 'http://' + vvv
          }
          $('.bombBox').show()
          // 點選取消
          $('.Cancel').unbind('click').click(function () {
            $('.bombBox').hide()
          })
          // 點選確定 熱點連結新增完成
          $('.sure').unbind('click').click(function () {

            $('.bombBox').hide()
            var value = $('.link input').val()
            $('#Map area')[k].href = value

          })

        })

 

樣式結構呢如下,主要使用了 map > area的功能。

 <input type="file" id="fileinp" @change="processFiles(this.files)">
  <div id="debug"></div>
 
  <div id="imgMap">
    <img src="" name="test" id="dropBox" width="400" class="map" border="0" height="400" usemap="#Map" ref='imageMaps' />
    <map name="Map" id="Map">
    </map>
    <!-- 資訊填寫 -->
    <div class="bombBox">
      <p class="title">填寫熱點連結</p>
      <hr class="hr">
      <p class="link"><span>link:</span>
        <input type="text" size="60" value="http://" data-id="" />
      </p>
      <p class="btn">
        <button class="sure">確定</button>
        <button class="Cancel">取消</button>
      </p>
    </div>
  </div>

我主要呢,是吧img標籤以及map標籤內容都儲存在了本地中,前端獲取呢,只需要整體獲取,外面搭個盒子就可以顯示了。

在本地檢視可看到儲存的資料,

  window.localStorage.setItem("site", savePart)
    window.localStorage.setItem("img", img)

 

 

前端就可以獲取到img以及site來進行顯示熱點區域。

 <script>
        $(document).ready(function () {
            var site = window.localStorage.getItem('site')
            var img = window.localStorage.getItem('img')
            console.log(site)
            console.log(img)
            $('.box').append(img)
            $('.box').append(site)
            $('#Map area').attr('data-maphilight','{"stroke":true,"fillColor":"000000","fillOpacity":0,"alwaysOn":true}')
            $('.map').maphilight();
            $('#squidheadlink').mouseover(function (e) {
                $('#squidhead').mouseover();
            }).mouseout(function (e) {
                $('#squidhead').mouseout();
            }).click(function (e) { e.preventDefault(); });

        })
    </script>

至此呢。一個簡單的前後端都可以很簡單操作的地圖熱點就完成了,至於樣式部分呢,不嫌棄我的樣式醜的,可以在github上下載看看哦!

 github:https://github.com/hey-yst/demo

相關文章