Javascript 避免滚动条的jQuery图像视口计算算法

Javascript 避免滚动条的jQuery图像视口计算算法,javascript,jquery,css,Javascript,Jquery,Css,我正在创建一个图像悬停效果,但我有问题。当我将鼠标悬停在某些图像上时,会出现我想要避免但不知道如何避免的滚动条。我相信这与视口和计算有关,但不确定如何做到这一点 代码如下: $('.simplehover').each(function(){ var $this = $(this); var isrc = $this[0].src, dv = null; $this.mouseenter(functio

我正在创建一个图像悬停效果,但我有问题。当我将鼠标悬停在某些图像上时,会出现我想要避免但不知道如何避免的滚动条。我相信这与视口和计算有关,但不确定如何做到这一点

代码如下:

$('.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');
    });         

});
$('.simplehover')。每个(函数(){
var$this=$(this);
var isrc=$this[0]。src,dv=null;
$this.mouseenter(函数(e){
dv=$('')
.attr('class','u\u shidivbox')
.css({
显示:“无”,
zIndex:9999,
位置:'绝对',
顶部:e.pageY+20,
左:e.pageX+20
})
.html(“”)
.附录(文件正文);
dv.fadeIn(“快速”);
})
.mouseleave(函数(){
dv.fadeOut(“快速”);
});         
});
有人能帮我吗?我该如何使悬停的图像出现在滚动条不出现的地方?(当然,如果图像大小非常大,我们无法避免滚动条)

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

请注意我计划将其转换为jQuery插件,因此我不能强制插件用户将
溢出设置为
隐藏
。该解决方案与视口滚动宽度高度窗口宽度/高度属性有关,我以后可以将这些属性合并到插件中


更新: 我想到了这个:

然而,它是非常非常黑客和不是100%完美。我正在寻找更好的算法/解决方案。我见过很多hover插件都能很好地做到这一点,但由于我不太擅长这一点,所以我不能很好地做到这一点。例如,根据悬停图像的大小在适当的位置显示悬停图像,这项工作非常出色。

如下:

html{overflow-x:hidden;}
html{overflow-y:hidden;}
您所需要做的就是将这些定义添加到CSS中,就完成了

使用调整大小更新:这是用于调整图片大小和重新定位图片的鼠标输入代码水平和垂直方向。现在,无论悬停图像显示在何处,它的大小和位置都将始终以完整和未剪切的形式显示。就滚动条而言,如果您显示的缩略图超过页面所能容纳的数量,那么即使在悬停图像显示之前,您也会有滚动条

最终和工作更新:因为您关注的是隐藏的滚动条,我认为您忽略了一个事实,即如果您放置的缩略图超过了视口所能包含的数量,滚动条无论如何都会显示出来,因此,当您计算悬停图像的位置时,用户可以向下滚动文档,您不仅需要考虑调整大小,还需要考虑scrollTop位置,所有图片都显示已调整大小的完整图片,无论滚动顶在何处,也不管视口大小如何

$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');
});
$this.mouseenter(函数(){
dv=$('')
.attr('class','u\u shidivbox')
.css({
“显示”:“无”,
“z指数”:9999,
'位置':'绝对',
“长方体阴影”:“0 0 1em#000”,
“边界半径”:“5px”
})
.html(“”)
.附录(文件正文);
var DocuWidth=window.innerWidth;
var DocuHeight=窗内高度;
var DvImg=dv.find('img');
var TheImage=新图像();
TheImage.src=DvImg.attr(“src”);
var DivWidth=图像宽度;
var DivHeight=图像高度;
如果(DivWidth>DocuWidth){
var宽度因子=(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 thumbleet=$this.position().left;
var spaceoverthumb=ThumbTop-$(document.scrollTop();
var SpaceBelowThumb=DocuHeight-ThumbTop-ThumbHeight+$(document.scrollTop();
var MaxHeight=Math.max(spaceoverthumb,SpaceBelowThumb);
如果(DivHeight>MaxHeight){
变量高度因子=(DivHeight/MaxHeight)+0.05;
DivHeight=parseInt((DivHeight/HeightFactor),10);
DivWidth=parseInt((DivWidth/HeightFactor),10);
}
var HoverImgLeft=0;
var HoverImgTop=0;
if(SpaceBelowThumb>spacebeloverthumb){
HoverImgTop=拇指顶部+拇指高度;
}否则{
HoverImgTop=拇指顶-DivHeight;
}
HoverImgTop=(HoverImgTop<0)?0:HoverImgTop;
HoverImgLeft=(DocuWidth-DivWidth)/2;
dv.find('img').css({
“宽度”:DivWidth,
“高度”:高度,
“边界半径”:“5px”
});
dv.css({
“左”:HoverImgLeft,
“顶部”:HoverImgTop
});
dv.fadeIn(“快速”);
});

您可以根据可用宽度定位图像:

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

$('.simplehover')。每个(函数(){
var$this=$(this);
//确保该元素实际上是一个图像
如果(!$this.is('img'))返回false;
var isrc=$this[0]。src,dv=null;
如果(!isrc)返回false;
$this.mouseenter(函数(e){
//鼠标x位置
var initXPos=e.pageX;
var initYPos=e.pageY+20-$(窗口)。滚动到
$('.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');
        });         

    });
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();
    });
});