jQuery - CSS的“transform:scale”会影响jQuery的“.offset()”吗?

16

我正在尝试使用jQuery进行验证。

blur事件发生后,通过检查给定的input是否为空,会产生错误。基于此,它将在该input旁边创建一个<div class="errdiv">,其中将具有特定的错误信息。我使用.offset获取该特定input的位置来将.errdiv定位到相应的位置。

CSS:

.inpt {
    width:500px;
    height:50px;
    background:#eee;
    color:#444;
    border:2px solid #ddd;
    padding:5px;
    transition: all ease 1s;
    border-radius:5px;
    outline:none;
}
.inpt:focus {
    background:#fff;
    color:#222;
    border:2px solid #000;
}
.err {
    background:pink;
    border:2px solid #f00;
    color:#a00;
}
.errdiv {
    position:absolute;
    top:0px;
    left:0px;
    height:30px;
    display:inline-block;
    padding:5px;
    border-radius:5px;
    background:#a00;
    border:1px solid #a44;
    color:#fff;
    text-align:center;    
    font-weight:bolder;
    visibility:visible;
    opacity:0;
}

JS:

$(document).ready(function(){
    $(".inpt").blur(function(){
        // Check Input for validation.
        $(".errdiv").remove(); //Remove Any Previous Error.
        var vl=$(this).val();
        var vl1=vl.split(" ").join("");
        if(vl==""||vl1==""){
            // Input is Empty Mark It red.
            $(this).addClass("err");
        }
    });
    $(".inpt").focus(function(){
        //Check Whether Input is marked Red or Not (hasClass) err?
        $(".errdiv").remove(); //Remove Any Previous Error.
        if($(this).hasClass("err")){
        // Input is Marked!
        $(this).removeClass("err");
        var tp=$(this).offset().top+12;
        var lf=$(this).offset().left+$(this).width()+12;
         // Add Error Div and appropriate Message.
        $("body").append("<div class='errdiv' style='position:absolute;top:"+tp+"px;left:"+lf+"px;'>*This is Required.</div>");
        $(".errdiv").animate({
            "visibility":"visible",
            "opacity":"1"
        },1000); //Show What is The Error?
    });
});

HTML:

<center>Hello Every One!</center>
<hr>    
<center>
<input class="inpt" placeholder="name" type="text" /><br />
<input class="inpt" placeholder="email" type="text" /><br />
<input class="inpt" placeholder="password" type="password" /><br />
 </center>
 <center>
Just Try Focusing and Bluring the Inputs
</center>

它能正常工作。你可以在这里测试它。

正如你所见,它创建了错误的<div>并将其显示如下:

"Actual and Expected Output"


实际问题

当我尝试使用 scale(zoom) 来为视力受损和/或使用非常大屏幕显示器的用户缩放页面时,出现了问题:

body{
    /*mozilla hack*/
    -moz-transform: scale(1.25,1.25);
    /* Chrome and Safari */
   -webkit-transform: scale(1.25,1.25);
    /*IE */
    -ms-transform:scale(1.25,1.25);
    /*Opera*/
    -o-transform:scale(1.25,1.25);
    /*Others*/
    transform:scale(1.25,1.25);
} 

然后我不知道发生了什么事情。但是情况变得非常糟糕,.offset() 似乎无法正常工作。你可以在这里看到。

div的错误现在被定位为: Error After Zoom


请问有人可以告诉我如何在 scaling 页面后正确地定位那个 .errdiv 吗?

我做错了什么吗?

欢迎任何建议或想法。希望大家能尽快帮助我。先谢谢了 :).


PS:

transform-origin: 0 0;

没有帮助我,我不想在HTML中使用<table><td>或写

,而是想要动态添加。

修改奖金

我已经接受的解决方案可以用于验证部分,但现在我正在尝试使用ajax实现它,其中内容将动态添加到div中,并且我必须将 transition: all ease 2.0s 添加到的CSS中,以使某些东西看起来很棒。 但是添加trasition会影响到已被解决方案改变的transform的特性(transform也会得到动画效果),而且它并没有解决定位问题。是否有更好的方法来满足需求?能否请任何人提供跨浏览器的解决方案?

3个回答

14

你的问题在于jQuery没有返回你元素的正确尺寸($(this).width())。

尝试使用 getBoundingClientRect 函数来获取一个包围你元素的矩形对象。

你可以这样在你的函数中使用它:

var lf=$(this).offset().left+$(this)[0].getBoundingClientRect().width+12;

尝试这种解决方法

http://jsfiddle.net/H5sW9/10/

获取当前比例在matches[1](scaleX)和matches[2](scaleY)中

var matrixRegex = /matrix\((-?\d*\.?\d+),\s*0,\s*0,\s*(-?\d*\.?\d+),\s*0,\s*0\)/;
var matches =$("body").css('transform').match(matrixRegex);

在添加之前将缩放比例设置为100%

$("body").css('transform', 'scale(' + '1' + ')');

在添加了

恢复
后将其调整为125%。

 $("body").css('transform', 'scale(' + matches[1] + ')');

我只使用了transform而没有使用-webkit-transition、-moz-transform等,你应该使用它们。

要对不同的因素x和y进行缩放,你应该使用

$("body").css('transform', 'scale(' + '1' +','  +'1' + ')');

谢谢,伙计。但是它没有帮助到我 :(。 - Vedant Terkar
为什么不呢?矩形总是在同一位置吗? - faby
感谢您抽出时间。以下是两个fiddles链接:带缩放不带缩放 - Vedant Terkar
太完美了!谢谢你一直以来的帮助 :). 感谢你的一切。+1 接受这个答案。 - Vedant Terkar
2
不错的解决方案。我有点担心这会导致闪烁。也许只会在移动设备上出现图形密集的页面时才会出现。您认为这种担忧是否有任何合理性? - Gattster

1
这是一个有效的解决方案。
CSS
.inpt:focus {
    background:#fff;
    color:#222;
    border:2px solid #000;
}
.err {
    background:pink;
    border:2px solid #f00;
    color:#a00;
}
.errdiv {
    position:absolute;    
    height:30px;
    display:inline-block;
    padding:5px;
    border-radius:5px;
    background:#a00;
    border:1px solid #a44;
    color:#fff;
    text-align:center;    
    font-weight:bolder;
    visibility:visible;
    opacity:0;
}

HTML

<center>Hello Every One!</center>
<hr>    
<center>
    <input class="inpt" placeholder="name" type="text" /><br />
    <input class="inpt" placeholder="email" type="text" /><br />
    <input class="inpt" placeholder="password" type="password" /><br />
</center>
<center>
    Just Try Focusing and Bluring the Inputs
</center>

JavaScript(JavaScript)
$(document).ready(function() {
    $(".inpt").blur(function() {
        // Check Input for validation.
        $(".errdiv").remove(); //Remove Any Previous Error.
        var vl = $(this).val();
        var vl1 = vl.split(" ").join("");
        if (vl == "" || vl1 == "") {
            // Input is Empty Mark It red.
            $(this).addClass("err");
        }
    });
    $(".inpt").focus(function() {
        //Check Whether Input is marked Red or Not (hasClass) err?
        // $(".errdiv").remove(); //Remove Any Previous Error.
        if ($(this).hasClass("err")) {
            // Input is Marked!
            $(this).removeClass("err");
//            var tp=$(this).offset().top+12;// not needed 
//            var lf=$(this).offset().left+$(this).width()+12;// not needed
//             // Add Error Div and appropriate Message.
            $('<div class="errdiv">*This is Required.</div>').insertAfter(this);

            $(".errdiv").animate({
                "visibility": "visible",
                "opacity": "1"
            }, 1000); //Show What is The Error?
        }
    });
});

只需要进行一点修改

从你的 .errdiv 类中删除 top 和 left 属性,并在元素后动态添加 div。


不错的解决方案,伙计。+1。但这只是一个简单的例子,让人们理解问题。在我的实际页面中,DOM树中有几个元素相互嵌套,所以我不能在那里使用这种方法。这就是为什么我需要.top.left。顺便说一句,感谢你花时间帮忙。 - Vedant Terkar
我知道这只是一个示例,你的应用程序肯定更加复杂。但是你尝试过在你的应用程序中使用这个解决方案吗?我在一个稍微复杂一点的场景中测试了这段代码,它对我来说是有效的。所以如果你还没有尝试过,可以试一下。 - Deepak Kumar
在你想要添加div元素的元素后面添加position:relative - Deepak Kumar

0
我遇到了一个非常相似的问题,但问题是当我尝试调用.offset时,JS没有完全加载。
添加一个
$(document).ready(function() {
    //Do the offset thing here
}

问题已解决。

我希望这个解决方案可以帮助到一些路过的人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接