如何根据鼠标位置偏移元素?

How do I offset an element based on my mouse position?

我在 SVG 中有一个包含多个 <rect> 元素的网格。我正在尝试根据鼠标的位置偏移元素。所以当我的鼠标在元素的一定范围内时,元素就会远离我的鼠标。

靠近鼠标的项目应该比外部范围内的元素移动得更远。

到目前为止,我已经成功地使用以下 if/else 语句将矩形定位在鼠标的特定范围内:

if((mouseX > coordX && mouseX < (coordX + 50) || mouseX < coordX && mouseX > (coordX - 50)) 
    && (mouseY > coordY && mouseY < (coordY + 50) || mouseY < coordY && mouseY > (coordY - 50)))

此语句可能需要一些改进。

下一步是根据我的鼠标位置更改 <rect> 元素的位置。影响最靠近鼠标的元素最强。

else 语句应该将元素恢复到原来的位置。当鼠标离开目标范围时触发此语句。

此刻我卡在了需要根据鼠标位置偏移<rect>元素的部分。

FIDDLE

您只需要计算指针到每个方块的距离,然后根据距离指针的距离使用transform将方块从指针移开。

$('rect').each(function(){
    var position = $(this).position();
    var widthMod = $(this).attr('width')/2;
    var heightMod = $(this).attr('height')/2;
    //console.log(widthMod);
    var coordX = position.left+widthMod;
    var coordY = position.top+heightMod;
    // dx and dy are the vextor from the mouse to the rect
    var dx = coordX - mouseX;
    var dy = coordY - mouseY;
    // distance from the mouse
    var distanceSquared = (dx * dx + dy * dy);
    var tx = 0, ty = 0;
    // if the rect is within range...
    // Note that we are comparing the squared values to avoid unnecessary sqrt() calls
    if (distanceSquared < theRangeSquared && distanceSquared != 0)
    {
        $(this).attr('fill','#000000');
        // Calculate shift scale (inverse of distance)
        var shift = maxOffset * (theRangeSquared - distanceSquared) / theRangeSquared;
        // Now calculate the translation vector.
        // We normalise the dx,dy vector by dividing by its length (distance),
        // then we multiply it by the shift scale
        var distance = Math.sqrt(distanceSquared);
        tx = shift * dx / distance;
        ty = shift * dy / distance;
    }else{
        $(this).attr('fill','#A4131C');
    }
    // Set a transform on the rect to translate it by our vector tx,ty
    $(this).attr('transform', "translate(" + tx + " " + ty + ")");
});

$( "svg" ).mousemove(function( event ) {    
    var mouseX = event.pageX;
    var mouseY = event.pageY;
    var theRangeSquared = 75 * 75;
    var maxOffset = 20;
    
    $('rect').each(function(){
        var position = $(this).position();
        var widthMod = $(this).attr('width')/2;
        var heightMod = $(this).attr('height')/2;
        //console.log(widthMod);
        var coordX = position.left+widthMod;
        var coordY = position.top+heightMod;
        // distance from mouse
        var dx = coordX - mouseX;
        var dy = coordY - mouseY;
        var distanceSquared = (dx * dx + dy * dy);
        var tx = 0, ty = 0;
        if (distanceSquared < theRangeSquared && distanceSquared != 0)
        {
            $(this).attr('fill','#000000');
            // Calculate shift scale (inverse of distance)
            var shift = maxOffset * (theRangeSquared - distanceSquared) / theRangeSquared;
            var distance = Math.sqrt(distanceSquared);
            tx = shift * dx / distance;
            ty = shift * dy / distance;
        }else{
            $(this).attr('fill','#A4131C');
        }
        $(this).attr('transform', "translate(" + tx + " " + ty + ")");
    });
    
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg version="1.1" baseProfile="tiny" id="Laag_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
  x="0px" y="0px" width="380.098px" height="369.383px" viewBox="0 0 380.098 369.383" xml:space="preserve">
<rect x="14.172" y="14.177" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="60.004" y="14.177" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.929" height="30.93"/>
<rect x="105.836" y="14.177" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="151.668" y="14.177" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="197.5" y="14.177" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="243.331" y="14.177" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="289.163" y="14.177" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="334.995" y="14.177" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="14.172" y="58.477" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="60.004" y="58.477" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.929" height="30.93"/>
<rect x="105.836" y="58.477" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="151.668" y="58.477" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="197.5" y="58.477" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="243.331" y="58.477" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="289.163" y="58.477" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="334.995" y="58.477" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="14.172" y="102.777" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="60.004" y="102.777" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.929" height="30.93"/>
<rect x="105.836" y="102.777" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="151.668" y="102.777" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="197.5" y="102.777" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="243.331" y="102.777" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="289.163" y="102.777" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="334.995" y="102.777" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="14.172" y="147.077" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="60.004" y="147.077" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.929" height="30.93"/>
<rect x="105.836" y="147.077" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="151.668" y="147.077" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="197.5" y="147.077" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="243.331" y="147.077" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="289.163" y="147.077" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="334.995" y="147.077" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="14.172" y="191.376" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.929"/>
<rect x="60.004" y="191.376" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.929" height="30.929"/>
<rect x="105.836" y="191.376" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.929"/>
<rect x="151.668" y="191.376" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.929"/>
<rect x="197.5" y="191.376" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.929"/>
<rect x="243.331" y="191.376" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.929"/>
<rect x="289.163" y="191.376" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.929"/>
<rect x="334.995" y="191.376" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.929"/>
<rect x="14.172" y="235.676" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="60.004" y="235.676" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.929" height="30.93"/>
<rect x="105.836" y="235.676" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="151.668" y="235.676" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="197.5" y="235.676" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="243.331" y="235.676" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="289.163" y="235.676" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="334.995" y="235.676" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="14.172" y="279.976" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="60.004" y="279.976" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.929" height="30.93"/>
<rect x="105.836" y="279.976" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="151.668" y="279.976" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="197.5" y="279.976" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="243.331" y="279.976" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="289.163" y="279.976" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="334.995" y="279.976" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="14.172" y="324.276" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="60.004" y="324.276" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.929" height="30.93"/>
<rect x="105.836" y="324.276" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="151.668" y="324.276" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="197.5" y="324.276" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="243.331" y="324.276" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="289.163" y="324.276" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
<rect x="334.995" y="324.276" fill="#A4131C" stroke="#000000" stroke-width="0.2182" stroke-miterlimit="10" width="30.93" height="30.93"/>
</svg>