9

我正在创建图像悬停效果,但我遇到了问题。当我将鼠标悬停在某些图像上时,会出现我想避免但不知道该怎么做的滚动条。我相信它与视口和计算有关,但不确定是如何完成的。

示例在这里

JSBin 代码

这是代码:

$('.simplehover').each(function(){
    var $this = $(this);        
    var isrc = $this[0].src, dv = null;
                        
    $this.mouseenter(function(e){
        dv = $('<div />')
            .attr('class', '__shidivbox__')
            .css({
                display: 'none',
                zIndex : 9999,
                position: 'absolute',
                top: e.pageY + 20,
                left: e.pageX + 20
            })
            .html('<img alt="" src="' + isrc + '" />')
            .appendTo(document.body);           
        dv.fadeIn('fast');
    })
    .mouseleave(function(){
        dv.fadeOut('fast');
    });         

});

任何人都可以帮助我如何做到这一点,以便悬停的图像出现在滚动条不出现的地方?(当然,如果图像尺寸非常大,我们不能避免滚动条)

我只想在缩放时显示原始图像,同时尽可能避免滚动条。

请注意,我计划将其转换为 jQuery 插件,因此我不能强制插件用户overflow设置为hidden. 该解决方案与viewportlefttopscroll widthheightwindow width/height属性有关,我稍后可以将其合并到插件中。


更新:

我想出了这个:

http://jsbin.com/upuref/14

但是,它非常非常hacky,并不是100%完美。我正在寻找更好的算法/解决方案。我已经看到很多悬停插件可以很好地做到这一点,但由于我不擅长这一点,所以我不能做得很好。例如,悬停缩放 Chrome 插件在根据大小在适当位置显示悬停图像方面做得很好。

4

4 回答 4

3

像这样:

html{overflow-x:hidden;}
html{overflow-y:hidden;}

您需要做的就是将这些定义添加到您的 CSS 中,然后您就完成了。

使用调整大小更新:这是用于在水平和垂直方向调整图片大小和重新定位图片的mouseenter代码。现在,无论 HOVER 图像出现在哪里,它的大小和位置都会被调整为始终完整显示且未剪切。就滚动条而言,如果您显示的缩略图多于页面无法容纳的数量,甚至在 HOVER 图像显示之前您就会有滚动条。

最终和工作更新:因为您专注于隐藏的滚动条,我认为您忽略了这样一个事实,即如果您放置的缩略图超过视口可以包含的数量,滚动条无论如何都会显示出来,因此,因为用户可以向下滚动文档,当你计算悬停图像的位置时,不仅需要考虑resize,还需要考虑scrollTop 位置!FINAL JSBIN HERE,无论scrollTop 在哪里,无论视口大小如何,所有图片都显示为RESIZED 和FULL。

$this.mouseenter(function () {

    dv = $('<div />')
          .attr('class', '__shidivbox__')
          .css({
            'display': 'none',
            'z-index': 9999,
            'position': 'absolute',
            'box-shadow': '0 0 1em #000',
            'border-radius': '5px'
          })
          .html('<img alt="" src="' + isrc + '" />')
          .appendTo(document.body);

    var DocuWidth = window.innerWidth;
    var DocuHeight = window.innerHeight;

    var DvImg = dv.find('img');

    var TheImage = new Image();
    TheImage.src = DvImg.attr("src");

    var DivWidth = TheImage.width;
    var DivHeight = TheImage.height;

    if (DivWidth > DocuWidth) {

        var WidthFactor = (DivWidth / DocuWidth) + 0.05;
        DivHeight = parseInt((DivHeight / WidthFactor), 10);
        DivWidth = parseInt((DivWidth / WidthFactor), 10);
    }

    var ThumbHeight = $this.height();
    var ThumbWidth = $this.width();
    var ThumbTop = $this.position().top;
    var ThumbLeft = $this.position().left;

    var SpaceAboveThumb = ThumbTop - $(document).scrollTop();
    var SpaceBelowThumb = DocuHeight - ThumbTop - ThumbHeight + $(document).scrollTop();

    var MaxHeight = Math.max(SpaceAboveThumb, SpaceBelowThumb);

    if (DivHeight > MaxHeight) {

        var HeightFactor = (DivHeight / MaxHeight) + 0.05;
        DivHeight = parseInt((DivHeight / HeightFactor), 10);
        DivWidth = parseInt((DivWidth / HeightFactor), 10);
    }

    var HoverImgLeft = 0;
    var HoverImgTop = 0;

    if (SpaceBelowThumb > SpaceAboveThumb) {
        HoverImgTop = ThumbTop + ThumbHeight;
    } else {
        HoverImgTop = ThumbTop - DivHeight;
    }

    HoverImgTop = (HoverImgTop < 0) ? 0 : HoverImgTop;

    HoverImgLeft = (DocuWidth - DivWidth) / 2;

    dv.find('img').css({
        'width': DivWidth,
        'height': DivHeight,
        'border-radius': '5px'
    });

    dv.css({
        'left': HoverImgLeft,
        'top': HoverImgTop
    });

    dv.fadeIn('fast');
});
于 2012-09-25T15:45:15.893 回答
1

您可以根据可用宽度定位图像:http: //jsbin.com/upuref/19/

该演示考虑了用于定位图像的可用空间(即窗口宽度减去图像宽度)。我还改进了事件顺序,只有在加载图像div弹出窗口才开始淡入。

于 2012-09-25T16:29:21.770 回答
1

我的回答也是(JSBin DEMO

$('.simplehover').each(function(){
        var $this = $(this);

        // make sure that element is really an image
        if (! $this.is('img')) return false;

        var isrc = $this[0].src, dv = null;

        if (! isrc) return false;

        $this.mouseenter(function(e){
            // mouse x position
            var initXPos = e.pageX;
            var initYPos = e.pageY+20-$(window).scrollTop();
            var windowWidth = $(window).width();
            var windowHeight = $(window).height();
            // load original image
            var $img = $('<img/>');
            $img.on('load',function(eload) {
                var widthImage = this.width;
                var heightImage = this.height;
                // set inline style for get sizes after (see problems webkit and cache)
                $(this).css('width',widthImage);
                $(this).css('height',heightImage);
                var ratio = widthImage/heightImage;

                var finalXPos = initXPos+widthImage>windowWidth? windowWidth-widthImage-5 : initXPos;
                var finalYPos = initYPos;

                var img = this;


                // resize image if is bigger than window
                if(finalXPos<0)  {
                    finalXPos = 0;
                    $img.css('width', windowWidth-10);
                    $img.css('height',(windowWidth-10)/ratio);
                }

                // If overflow Y

                if(finalYPos+getSize($img,'height')>windowHeight) {

                    // calculate where is more space (top or bottom?)
                    var showOnTop = (windowHeight-initYPos-10)<windowHeight/2;
                    if(showOnTop) {
                        if(initYPos<getSize($img,'height')) {
                            $img.height(initYPos-30);
                            $img.width(getSize($img,'height')*ratio);
                        }
                        finalYPos = 0;
                        finalXPos = initXPos+getSize($img,'width')>windowWidth? windowWidth-getSize($img,'width')-5 : initXPos;

                    }else {
                        // show on bottom
                        if(windowHeight-initYPos<getSize($img,'height')) {
                            $img.height(windowHeight-initYPos-10);
                            $img.width(getSize($img,'height')*ratio);

                        }
                        finalXPos = initXPos+getSize($img,'width')>windowWidth? windowWidth-getSize($img,'width')-5 : initXPos;
                    }
                }
                dv = $('<div />')
                .attr('class', '__shidivbox__')
                .css({
                    display: 'none',
                    zIndex : 9999,
                    position: 'absolute',
                    MozBorderRadius : '5px',
                    WebkitBorderRadius : '5px',
                    borderRadius : '5px',
                    top: finalYPos+$(window).scrollTop(),
                    left: finalXPos
                }).append($img)
                .appendTo(document.body);           
            dv.fadeIn('fast');
            });
            // load the original image (now is the same, but I think is better optimize it)
            $img.attr("src",$this.attr("src"));

            function getSize($el,widthOrHeight) {
                // horrible but working trick :)
                return +$el.css(widthOrHeight).replace("px","");
            }
        })
        .mouseleave(function(){
            dv.fadeOut('fast');
        });         

    });

此脚本使图像适应窗口大小并在需要时调整 x 位置。

于 2012-09-25T22:26:10.043 回答
1

嗯,这看起来很有趣。无论如何,这是我的答案。我已经看了几天了,虽然我也会参与进来。以下将确保悬停的图像不会超出视口,并且如果图像的宽度大于可显示的可用空间,则图像的显示将被调整大小(您可以注释掉代码如果你不想要它就这样做。只需在代码中查找“resize”这个词)。

var $document = $(document);
$('.simplehover').each(function(){
    var $this = $(this);
    // make sure that element is really an image
    if (! $this.is('img')) return false;

    var isrc = $this[0].src, ibox = null;

    if (! isrc) return false;
    ibox = $('<img />')
            .attr('class', 'simpleimagehover__shidivbox__')
            .css({
                display: 'none',
                zIndex : 99,
                MozBoxShadow: '0 0 1em #000', 
                WebkitBoxShadow: '0 0 1em #000',
                boxShadow: '0 0 1em #000',
                position: 'absolute',
                MozBorderRadius : '10px',
                WebkitBorderRadius : '10px',
                borderRadius : '10px'
            })
            .attr('src', isrc)
            .appendTo(document.body);          

    $this.bind('mouseenter mousemove', function(e) {
        $('.simpleimagehover__shidivbox__').hide();

        var left = e.pageX + 5, 
            top = e.pageY + 5,
            ww = window.innerWidth,
            wh = window.innerHeight,
            w = ibox.width(),
            h = ibox.height(),
            overflowedW = 0,
            overflowedH = 0;

        // calucation to show element avoiding scrollbars as much as possible - not a great method though
        if ((left + w + $document.scrollLeft()) > ww)
        {
            overflowedW = ww - (left + w + $document.scrollLeft());
            if (overflowedW < 0)
            {
               left -= Math.abs(overflowedW);
            }
        }

        // 25 is just a constant I picked arbitrarily to compensate pre-existing scrollbar if the page itself is too long
        left -= 25;
        left = left < $document.scrollLeft() ? $document.scrollLeft() : left;

        // if it's still overflowing because of the size, resize it
        if (left + w > ww)
        {
            overflowedW = left + w - ww;
            ibox.width(w - overflowedW - 25);
        }


        if (top + h > wh + $document.scrollTop())
        {
            overflowedH = top + h - wh - $document.scrollTop();
            if (overflowedH > 0)
            {
                top -= overflowedH;
            }
        }

        top = top < $document.scrollTop() ? $document.scrollTop() : top;
        ibox.css({
            top: top,
            left: left
        });

        ibox.show();
    }); 


    $('.simpleimagehover__shidivbox__').mouseleave(function(){
        $('.simpleimagehover__shidivbox__').hide();
    });

    $document.click(function(e){
        $('.simpleimagehover__shidivbox__').hide();
    });

    $document.mousemove(function(e){
        if (e.target.nodeName.toLowerCase() === 'img') {
            return false;
        }

        $('.simpleimagehover__shidivbox__').hide();
    });
});

虽然我的解决方案本身并不完美,但您可能会在其中找到一些有用的东西来帮助您确定视口。此外,您可能需要考虑代码的性能。由于这是您正在构建的插件,因此您需要在将其公开之前进行一些优化。基本上,只要确保它不慢。

于 2012-09-26T14:28:47.473 回答