图像地图突出显示在图像下方

时间:2015-10-20 13:05:38

标签: javascript jquery html imagemap

我在使用David Lynch's Maphilight的编辑版本悬停时会有一个高亮显示的图像地图但由于某种原因,高光部分位于图像下方,我需要在图像顶部。

jsFiddle Demo - 在这里你可以看到我到目前为止所拥有的一切。

我使用的HTML是 -

<p style="background-color: #eeeeee;">
    <img src="http://www.motoryachtalaska.com/img/main-deck.png" usemap="#findusmap" style="display: block; margin-left: auto; margin-right: auto; position: relative;" class="map" height="208" width="1000" />
</p>
<p>
    <map name="findusmap" id="findusmap">
        <area alt="" title="area-1" href="#" shape="poly" coords="200,18,167,169,588,190,535,21" />
    </map>
</p>

和JS -

(function($) {
    var has_VML, has_canvas, create_canvas_for, add_shape_to, clear_canvas, shape_from_area,
    canvas_style, hex_to_decimal, css3color, is_image_loaded, options_from_area;

    var margin_left;

    has_canvas = !!document.createElement('canvas').getContext;


    // VML: more complex
    has_VML = (function() {
        var a = document.createElement('div');
        a.innerHTML = '<v:shape id="vml_flag1" adj="1" />';
        var b = a.firstChild;
        b.style.behavior = "url(#default#VML)";
        return b ? typeof b.adj == "object": true;
    })();

    if(!(has_canvas || has_VML)) {
        $.fn.maphilight = function() { return this; };
        return;
    }

    if(has_canvas) {
        hex_to_decimal = function(hex) {
            return Math.max(0, Math.min(parseInt(hex, 16), 255));
        };

        css3color = function(color, opacity) {
            return 'rgba('+hex_to_decimal(color.substr(0,2))+','+hex_to_decimal(color.substr(2,2))+','+hex_to_decimal(color.substr(4,2))+','+opacity+')';
        };


        //create the canvas where we'll draw the area shapes
        create_canvas_for = function(img) {
            var c = $('<canvas style="display: block; margin-left:'+ margin_left +'px; position: absolute; width:'+img.width+'px;height:'+img.height+'px;"></canvas>').get(0);

            c.width  = img.width;
            c.height = img.height;
            c.getContext("2d").clearRect(0, 0, img.width, img.height);
            return c;
        };

        var draw_shape = function(context, shape, coords, x_shift, y_shift) {
            x_shift = x_shift || 0;
            y_shift = y_shift || 0;
            context.beginPath();
            if(shape == 'rect') {
                // x, y, width, height
                context.rect(coords[0] + x_shift, coords[1] + y_shift, coords[2] - coords[0], coords[3] - coords[1]);
            } else if(shape == 'poly') {

                context.moveTo(coords[0] + x_shift, coords[1] + y_shift);
                //context.moveTo(coords[0] , coords[1]);
                for(i=2; i < coords.length; i+=2) {
                    //context.lineTo(coords[i] + x_shift, coords[i+1] + y_shift);
                    context.lineTo(coords[i], coords[i+1] );
                }
            } else if(shape == 'circ') {
                // x, y, radius, startAngle, endAngle, anticlockwise
                context.arc(coords[0] + x_shift, coords[1] + y_shift, coords[2], 0, Math.PI * 2, false);
            }
            context.closePath();
        }

        add_shape_to = function(canvas, shape, coords, options, name) {
            var i, context = canvas.getContext('2d');

            // Because I don't want to worry about setting things back to a base state

            // Shadow has to happen first, since it's on the bottom, and it does some clip /
            // fill operations which would interfere with what comes next.

            if(options.shadow) {
                context.save();
                if(options.shadowPosition == "inside") {
                    // Cause the following stroke to only apply to the inside of the path
                    draw_shape(context, shape, coords);
                    context.clip();
                }

                // Redraw the shape shifted off the canvas massively so we can cast a shadow
                // onto the canvas without having to worry about the stroke or fill (which
                // cannot have 0 opacity or width, since they're what cast the shadow).
                var x_shift = canvas.width * 100;
                var y_shift = canvas.height * 100;
                draw_shape(context, shape, coords, x_shift, y_shift);

                context.shadowOffsetX = options.shadowX - x_shift;
                context.shadowOffsetY = options.shadowY - y_shift;
                context.shadowBlur = options.shadowRadius;
                context.shadowColor = css3color(options.shadowColor, options.shadowOpacity);

                // Now, work out where to cast the shadow from! It looks better if it's cast
                // from a fill when it's an outside shadow or a stroke when it's an interior
                // shadow. Allow the user to override this if they need to.
                var shadowFrom = options.shadowFrom;
                if (!shadowFrom) {
                    if (options.shadowPosition == 'outside') {
                        shadowFrom = 'fill';
                    } else {
                        shadowFrom = 'stroke';
                    }
                }
                if (shadowFrom == 'stroke') {
                    context.strokeStyle = "rgba(0,0,0,1)";
                    context.stroke();
                } else if (shadowFrom == 'fill') {
                    context.fillStyle = "rgba(0,0,0,1)";
                    context.fill();
                }
                context.restore();

                // and now we clean up
                if(options.shadowPosition == "outside") {
                    context.save();
                    // Clear out the center
                    draw_shape(context, shape, coords);
                    context.globalCompositeOperation = "destination-out";
                    context.fillStyle = "rgba(0,0,0,1);";
                    context.fill();
                    context.restore();
                }
            } 


            context.save();

            draw_shape(context, shape, coords);

            // fill has to come after shadow, otherwise the shadow will be drawn over the fill,
            // which mostly looks weird when the shadow has a high opacity
            if(options.fill) {
                context.fillStyle = css3color(options.fillColor, options.fillOpacity);
                context.fill();
            }

            // Likewise, stroke has to come at the very end, or it'll wind up under bits of the
            // shadow or the shadow-background if it's present.
            if(options.stroke) {
                context.strokeStyle = css3color(options.strokeColor, options.strokeOpacity);
                context.lineWidth = options.strokeWidth;
                context.stroke();
            }

            context.restore();

            if(options.fade) {
                $(canvas).css('opacity', 0).animate({opacity: 1}, 100);
            }
        };


        clear_canvas = function(canvas) {
            canvas.getContext('2d').clearRect(0, 0, canvas.width,canvas.height);
        };


    } 
    else { // ie executes this code
        //console.log('iexplorer');
        create_canvas_for = function(img) {
            return $('<var style="display:block;width:'+img.width+'px;height:'+img.height+'px;position:absolute; margin-left:'+ margin_left +'px;"></var>').get(0);
            console.log('create ie8 canvas');
        };
        add_shape_to = function(canvas, shape, coords, options, name) {
            var fill, stroke, opacity, e;
            fill = '<v:fill color="#'+options.fillColor+'" opacity="'+(options.fill ? options.fillOpacity : 0)+'" />';
            stroke = (options.stroke ? 'strokeweight="'+options.strokeWidth+'" stroked="t" strokecolor="#'+options.strokeColor+'"' : 'stroked="f"');
            opacity = '<v:stroke opacity="'+options.strokeOpacity+'"/>';
            if(shape == 'rect') {
                e = $('<v:rect name="'+name+'" filled="t" '+stroke+' style="z-index:999; zoom:1;margin:0;padding:0;display:block;position:absolute;left:'+coords[0]+'px;top:'+coords[1]+'px;width:'+(coords[2] - coords[0])+'px;height:'+(coords[3] - coords[1])+'px;"></v:rect>');
            } else if(shape == 'poly') {
                e = $('<v:shape name="'+name+'" filled="t" '+stroke+' coordorigin="0,0" coordsize="'+canvas.width+','+canvas.height+'" path="m '+coords[0]+','+coords[1]+' l '+coords.join(',')+' x e" style="z-index:999; zoom:1;margin:0;padding:0;display:block;position:absolute;top:0px;left:0px;width:'+canvas.width+'px;height:'+canvas.height+'px;"></v:shape>');
            } else if(shape == 'circ') {
                e = $('<v:oval name="'+name+'" filled="t" '+stroke+' style="z-index:999;zoom:1;margin:0;padding:0;display:block;position:absolute;left:'+(coords[0] - coords[2])+'px;top:'+(coords[1] - coords[2])+'px;width:'+(coords[2]*2)+'px;height:'+(coords[2]*2)+'px;"></v:oval>');
            }
            e.get(0).innerHTML = fill+opacity;
            $(canvas).append(e);
        };
        clear_canvas = function(canvas) {
            $(canvas).find('[name=highlighted]').remove();
        };
    }



    shape_from_area = function(area) {
        var i, coords = area.getAttribute('coords').split(',');
        for (i=0; i < coords.length; i++) { 
            coords[i] = parseFloat(coords[i]); 
        }
        return [area.getAttribute('shape').toLowerCase().substr(0,4), coords];
    };

    options_from_area = function(area, options) {
        var $area = $(area);
        return $.extend({}, options, $.metadata ? $area.metadata() : false, $area.data('maphilight'));
    };

    is_image_loaded = function(img) {
        if(!img.complete) { return false; } // IE
        if(typeof img.naturalWidth != "undefined" && img.naturalWidth === 0) { return false; } // Others

        return true;
    };

    /*
    canvas_style = {
        position: 'absolute',
        left: 0,
        top: 0,
        padding: 0,
        border: 0
    };
    */
    canvas_style = {};

    var ie_hax_done = false;
    $.fn.maphilight = function(opts) {
        opts = $.extend({}, $.fn.maphilight.defaults, opts);

        if(!has_canvas && !ie_hax_done) {
            document.namespaces.add("v", "urn:schemas-microsoft-com:vml");
            var style = document.createStyleSheet();
            var shapes = ['shape','rect', 'oval', 'circ', 'fill', 'stroke', 'imagedata', 'group','textbox'];
            $.each(shapes,
                function() {
                    style.addRule('v\\:' + this, "behavior: url(#default#VML); antialias:true");
                }
            );
            ie_hax_done = true;
        }

        return this.each(function() {
            var img, wrap, options, map, canvas, canvas_always, mouseover, highlighted_shape, usemap;
            img = $(this);

            if(!is_image_loaded(this)) {
                // If the image isn't fully loaded, this won't work right. Try again later.
                return window.setTimeout(function() {
                    img.maphilight(opts);
                }, 200);
            }

            options = $.extend({}, opts, $.metadata ? img.metadata() : false, img.data('maphilight'));

            // jQuery bug with Opera, results in full-url#usemap being returned from jQuery's attr.
            // So use raw getAttribute instead.
            usemap = img.get(0).getAttribute('usemap');

            if (!usemap) {
                return;
            }

            map = $('map[name="'+usemap.substr(1)+'"]');

            if(!(img.is('img,input[type="image"]') && usemap && map.size() > 0)) {
                return;
            }

            if(img.hasClass('maphilighted')) {
                // We're redrawing an old map, probably to pick up changes to the options.
                // Just clear out all the old stuff.
                console.log('has class maphilighted');
                var wrapper = img.parent();
                img.insertBefore(wrapper);
                wrapper.remove();
                $(map).unbind('.maphilight').find('area[coords]').unbind('.maphilight');
            }


            /*
            wrap = $('<div></div>').css({
                display:'block',
                background:'url("'+this.src+'")',
                position:'relative',
                padding:0,
                width:this.width,
                height:this.height
            });
            */

            wrap = $('<div></div>').css({
                display:'block',

                position:'relative',
                marginLeft: 'auto',
                marginRight: 'auto',
            });


            if(options.wrapClass) {
                if(options.wrapClass === true) {
                    wrap.addClass($(this).attr('class'));
                } else {
                    wrap.addClass(options.wrapClass);
                }
            }

            //firefox doesn't process marginLeft(it returns 0)
            var div_offset;
            if ( $.browser.mozilla) {
                margin_left=img.before(wrap).offset().left;
                div_offset =wrap.offset().left;
                margin_left=margin_left-div_offset; 
            } else {
                margin_left=img.css("marginLeft").replace('px', '');
            }




            img.before(wrap).css('opacity', 1).css(canvas_style).remove();
            if(has_VML) { 
            //img.css('filter', 'Alpha(opacity=1)'); 
            }
            wrap.append(img);

            canvas = create_canvas_for(this);
            $(canvas).css(canvas_style);
            //canvas.height = this.height;
            //canvas.width = this.width;

            mouseover = function(e) {

                var shape, area_options;
                area_options = options_from_area(this, options);
                if(
                !area_options.neverOn
                &&
                !area_options.alwaysOn
                ) {
                    shape = shape_from_area(this);

                    add_shape_to(canvas, shape[0], shape[1], area_options, "highlighted");
                    /*
                    if(area_options.groupBy) {
                        var areas;
                        // two ways groupBy might work; attribute and selector
                        if(/^[a-zA-Z][\-a-zA-Z]+$/.test(area_options.groupBy)) {
                            areas = map.find('area['+area_options.groupBy+'="'+$(this).attr(area_options.groupBy)+'"]');
                        } else {
                            areas = map.find(area_options.groupBy);
                        }
                        var first = this;
                        areas.each(function() {
                            if(this != first) {
                                var subarea_options = options_from_area(this, options);
                                if(!subarea_options.neverOn && !subarea_options.alwaysOn) {
                                    var shape = shape_from_area(this);
                                    add_shape_to(canvas, shape[0], shape[1], subarea_options, "highlighted");
                                }
                            }
                        });
                    }

                    */
                    // workaround for IE7, IE8 not rendering the final rectangle in a group
                    if(!has_canvas) {
                        $(canvas).append('<v:rect></v:rect>');
                    }
                }
            }

            /*

            $(map).bind('alwaysOn.maphilight', function() {
                // Check for areas with alwaysOn set. These are added to a *second* canvas,
                // which will get around flickering during fading.
                if(canvas_always) {
                    clear_canvas(canvas_always);
                }
                if(!has_canvas) {
                    $(canvas).empty();
                }
                $(map).find('area[coords]').each(function() {
                    var shape, area_options;
                    area_options = options_from_area(this, options);
                    if(area_options.alwaysOn) {
                        if(!canvas_always && has_canvas) {
                            canvas_always = create_canvas_for(img[0]);
                            $(canvas_always).css(canvas_style);
                            canvas_always.width = img[0].width;
                            canvas_always.height = img[0].height;
                            img.before(canvas_always);
                        }
                        area_options.fade = area_options.alwaysOnFade; // alwaysOn shouldn't fade in initially
                        shape = shape_from_area(this);
                        if (has_canvas) {
                            add_shape_to(canvas_always, shape[0], shape[1], area_options, "");
                        } else {
                            add_shape_to(canvas, shape[0], shape[1], area_options, "");
                        }
                    }
                });
            });

            */

            $(map).trigger('alwaysOn.maphilight').find('area[coords]')
            .bind('mouseover.maphilight', mouseover)
            .bind('mouseout.maphilight', function(e) { clear_canvas(canvas); });

            img.before(canvas); // if we put this after, the mouseover events wouldn't fire.

            img.addClass('maphilighted');
        });
    };



    $.fn.maphilight.defaults = {
        fill: true,
        fillColor: 'aac144',
        fillOpacity: 0.6,
        stroke: true,
        strokeColor: 'aac144',
        strokeOpacity: 1,
        strokeWidth: 2,
        fade: true,
        alwaysOn: false,
        neverOn: false,
        groupBy: false,
        wrapClass: true,
        // plenty of shadow:
        shadow: false,
        shadowX: 0,
        shadowY: 0,
        shadowRadius: 6,
        shadowColor: '000000',
        shadowOpacity: 0.8,
        shadowPosition: 'outside',
        shadowFrom: false
    };
})(jQuery);;

jQuery(document).ready(function($){
    $('img[usemap]').maphilight();
});

重申我希望突出显示(当悬停时)位于图像的顶部,而不是在下面!

任何帮助将不胜感激,谢谢!

0 个答案:

没有答案