【问题标题】:jQuery - drag div css backgroundjQuery - 拖动 div css 背景
【发布时间】:2012-07-01 13:41:38
【问题描述】:

我希望能够在 div 内按住鼠标并移动它的背景。在google上搜索了很多,没有找到我想要的。

这是目标(显示的地图是要拖动的对象):http://pontografico.net/pvt/gamemap/

有什么建议吗?

干杯!

【问题讨论】:

  • 只是勾勒出一些东西,我会 onmousedown 设置一个 onmousemove 处理程序来检测和注册移动并重置 divbackground-image-position 设置,然后 unbind @987654328 @onmouseup。看起来合理吗?
  • 自从我写了这个问题以来,我就是这样做的:)
  • 如果你得到了一些有用的东西,请将其发布为答案。我很想看看jsfiddle.net 工作演示。 :)
  • 搞定了,可以查看问题链接。我现在有一个问题,如何将鼠标轴转换为合理的鼠标移动模拟?大概算出地图容器的位置,减去数值?
  • 在设置 mousemove 之前注册位置并将其用作原点。我认为,也可以标记与元素相关的位置,但我必须研究一下。

标签: jquery css background draggable


【解决方案1】:

好的,让它工作;我想我已经解决了所有问题:

带有边界限制的最终 jQuery

$(document).ready(function(){
    var $bg = $('.bg-img'),
        elbounds = {
            w: parseInt($bg.width()),
            h: parseInt($bg.height())
        },
        bounds = {w: 2350 - elbounds.w, h: 1750 - elbounds.h},
        origin = {x: 0, y: 0},
        start = {x: 0, y: 0},
        movecontinue = false;

    function move (e){
        var inbounds = {x: false, y: false},
            offset = {
                x: start.x - (origin.x - e.clientX),
                y: start.y - (origin.y - e.clientY)
            };

        inbounds.x = offset.x < 0 && (offset.x * -1) < bounds.w;
        inbounds.y = offset.y < 0 && (offset.y * -1) < bounds.h;

        if (movecontinue && inbounds.x && inbounds.y) {
            start.x = offset.x;
            start.y = offset.y;

            $(this).css('background-position', start.x + 'px ' + start.y + 'px');
        }

        origin.x = e.clientX;
        origin.y = e.clientY;

        e.stopPropagation();
        return false;
    }

    function handle (e){
        movecontinue = false;
        $bg.unbind('mousemove', move);

        if (e.type == 'mousedown') {
            origin.x = e.clientX;
            origin.y = e.clientY;
            movecontinue = true;
            $bg.bind('mousemove', move);
        } else {
            $(document.body).focus();
        }

        e.stopPropagation();
        return false;
    }

    function reset (){
        start = {x: 0, y: 0};
        $(this).css('backgroundPosition', '0 0');
    }

    $bg.bind('mousedown mouseup mouseleave', handle);
    $bg.bind('dblclick', reset);
});

http://jsfiddle.net/userdude/q6r8f/4/


原答案

HTML

<div class="bg-img"></div>

CSS

div.bg-img {
    background-image: url(http://upload.wikimedia.org/wikipedia/commons/9/91/Flexopecten_ponticus_2008_G1.jpg);
    background-position: 0 0;
    background-repeat: no-repeat;
    background-color: blue;
    border: 1px solid #aaa;
    width: 250px;
    height: 250px;
    margin: 25px auto;
}

jQuery

$(document).ready(function(){
    var $bg = $('.bg-img'),
        origin = {x: 0, y: 0},
        start = {x: 0, y: 0},
        movecontinue = false;

    function move (e){
        var moveby = {
            x: origin.x - e.clientX,
            y: origin.y - e.clientY
        };

        if (movecontinue === true) {
            start.x = start.x - moveby.x;
            start.y = start.y - moveby.y;

            $(this).css('background-position', start.x + 'px ' + start.y + 'px');
        }

        origin.x = e.clientX;
        origin.y = e.clientY;

        e.stopPropagation();
        return false;
    }

    function handle (e){
        movecontinue = false;
        $bg.unbind('mousemove', move);

        if (e.type == 'mousedown') {
            origin.x = e.clientX;
            origin.y = e.clientY;
            movecontinue = true;
            $bg.bind('mousemove', move);
        } else {
            $(document.body).focus();
        }

        e.stopPropagation();
        return false;
    }

    function reset (){
        start = {x: 0, y: 0};
        $(this).css('backgroundPosition', '0 0');
    }

    $bg.bind('mousedown mouseup mouseleave', handle);
    $bg.bind('dblclick', reset);
});

http://jsfiddle.net/userdude/q6r8f/2/

【讨论】:

  • 干得好!最后一件事:如何限制运动以仅匹配背景尺寸?
  • @yoda - 好的,这是边界版本:jsfiddle.net/userdude/q6r8f/4 你可能想要一个策略来获得background-imagewidthheight,因为你赢了'不能直接拿到我不信;您可能希望将其加载到一个虚拟的 $('&lt;img&gt;').attr('src', bgurl); 中,当 load() 触发时,使用该信息设置边界。
  • @DexterHuinda - 我知道看看我能否让它工作比仅仅依靠 UI 方法更有趣。结果并没有那么困难,而且很有趣。 :)
  • @yoda,IKR,铁杆程序员很难取悦:D
  • @yoda - 使用分离的x, y 拖动逻辑效果明显更好。否则,运动会突然停止在边缘,您实际上必须至少转 90 度才能继续运动。
【解决方案2】:

来自 ui 可拖动演示:

拖动 DOM 元素很简单,无需重新发明轮子。

<style>
#draggable { width: 150px; height: 150px; padding: 0.5em; }
</style>
<script>
    $(function() {
        $( "#draggable" ).draggable();
    });
</script>



<div class="demo">

<div id="draggable" class="ui-widget-content">
    <p>Drag me around</p>
</div>

</div><!-- End demo -->



<div class="demo-description" style="display: none; ">
<p>Enable draggable functionality on any DOM element. Move the draggable object by clicking on it with the mouse and dragging it anywhere within the viewport.</p>
</div><!-- End demo-description -->

http://jqueryui.com/demos/draggable/

编辑: div 内的可拖动背景也是可能的。在这里看小提琴:http://jsfiddle.net/FyFZA/

【讨论】:

  • 这是针对对象的,而不是 CSS 背景。
  • @yoda 适用于所有 DOM 元素,可能是 div、p、span 或其他。您的背景包含在 DOM 元素中,因此当您移动 div 时,您也移动了其中包含的背景。
  • 你没有关注尤达正在做的事情;他正在操作元素(背景图像)的属性,而不是元素本身。
  • 尽管没有回答,但这篇文章让我意识到,可能我需要在#gamemapz-index 内部设置一个内部容器并使其成为导航控制器.. 听起来怎么样?
  • @yoda - 这是我目前所拥有的,它有几个问题(我的数学有点落后,mouseup 并不总是处理解除绑定):jsfiddle.net/userdude/q6r8f
【解决方案3】:

这篇文章是我的问题的一个很好的起点。我结合了上面的答案和另一个与获取背景图像的原始尺寸有关的答案 (SO:How do I get background image size in jQuery?)

在我的特定设置中,我使用了background-size:cover,因此我必须确定背景图像的高度/宽度比率,并将其与容器的高度/宽度比率进行比较。这意味着每个图像只允许在一维上滑动。

这里有两个你可能不需要的额外内容。我为当前正在操作的元素添加了一个边框,只是为了让它易于查看,完成后将其删除。我还用偏移值更新了输入,因此我可以将它们发送到服务器。

我的 cmets 往往非常冗长,所以有点冗长,但我希望它对某人有所帮助。

<script>
$(document).ready(function(){

    function reset (){
        start = {x: 0, y: 0};
        $(this).css('backgroundPosition', '0 0');
    }

    $(".bg-img").bind('dblclick', reset);

    //my jquery
$(".bg-img").on('mousedown mouseup', function(e){

    //declare some vars
    var start = {x: 0, y: 0};
    var move = {x: 0, y: 0};
    var id = $(this).attr('id');

    //pointer coordinates on mousedown
    var origin = {x: 0, y: 0};

    //container dimensions
    var container = {w: $(this).width(), h: $(this).height()};

    //container ratio
    var containerRatio = container.h / container.w;

    //background image dimensions, note: this gets dimensions of unscaled image
    var img = new Image;
    img.src = $(this).css('background-image').replace(/url\(|\)$/ig, "");
    var background = {w: img.width, h: img.height};

    //background ratio
    var backgroundRatio = background.h / background.w;

    //max x and y position, aka boundary
    var min = {x: 0, y: 0};
    var max = {x: 0, y: 0};

    //move x
    if(backgroundRatio < containerRatio){
        min.y = 0;
        min.x = -((container.h * (1/backgroundRatio)) - container.w);
    }

    //move y
    else if (backgroundRatio > containerRatio){
        min.x = 0;
        min.y = -((container.w * backgroundRatio) - container.h);
    }

    //ratios are equal, don't move anything
    else{
        min.x = 0;
        min.y = 0;
    }

    //activate
    if(e.type == 'mousedown'){

        //add border so it's easier to visualize
        $(this).css('border', '1px solid #000000');

        //get current position of mouse pointer
        origin.x = e.clientX;
        origin.y = e.clientY;

        //get current background image starting position
        var temp = $(this).css('background-position').split(" ");
        start.x = parseInt(temp[0]);
        start.y = parseInt(temp[1]);

        //mouse is dragged while mousedown
        $(this).mousemove(function(e){

            //move position
            move.x = start.x + (e.clientX - origin.x);
            move.y = start.y + (e.clientY - origin.y);

            //if it's in the bounds, move it
            if(move.x <= max.x && move.x >= min.x && move.y <= max.y && move.y >= min.y){

                console.log('both');

                //alter css
                $(this).css('background-position', move.x + 'px ' + move.y + 'px');

                //update input
                $("#" + id).val('x:' + move.x + ', y:' + move.y);
            }

            //in x bound,
            else if(move.x <= max.x && move.x >= min.x){

                console.log('x');

                //below min.y
                if(move.y < min.y){
                    $(this).css('background-position', move.x + 'px ' + min.y + 'px');

                    //update input
                    $("#" + id).val('x:' + move.x + ', y:' + min.y);
                }
                //above max.y
                else if(move.y > max.y){
                    $(this).css('background-position', move.x + 'px ' + max.y + 'px');

                    //update input
                    $("#" + id).val('x:' + move.x + ', y:' + max.y);
                }
            }

            //in y bound
            else if(move.y <= max.y && move.y >= min.y){

                console.log('y');

                //below min.x
                if(move.x < min.x){
                    $(this).css('background-position', min.x + 'px ' + move.y + 'px');

                    //update input
                    $("#" + id).val('x:' + min.x + ', y:' + move.y);            
                }

                //above max.x
                else if(move.x > max.x){
                    $(this).css('background-position', max.x + 'px ' + move.y + 'px');

                    //update input
                    $("#" + id).val('x:' + max.x + ', y:' + move.y);
                }
            }

            //out of both bounds
            else{
                console.log('problem');
            }
        });
    }

    //deactivate
    else{

        //remove border
        $(this).css('border', 'none');

        //remove mousemove
        $(this).off('mousemove');
        $(document.body).focus();
    }
});
});
</script>

【讨论】:

    【解决方案4】:

    我知道这是一篇旧帖子,但如果您使用 jQueryUI,另一种解决方案是在背景之上创建一个透明元素,然后使用拖动回调来更新原始节点的 backgroundPosition。这是一个例子:

    /* node is the element containing the background image */
    /* width/height variables are just there if your background image is a different width/height then the container */
    var transparent = $('<div></div>');
    transparent.css({
        position: 'absolute',
        zIndex: 10,
        left: node.offset().left,
        top: this.node.offset().top,
        width: width || node.width(),
        height: height || node.height(),
        backgroundColor: '#fff',
        opacity: 0.2
    });
    
    $('body').append(transparent);
    
    options.config.drag = function(event, ui) {
        node.css({ backgroundPosition: (ui.position.left - ui.originalPosition.left) + 'px ' + (ui.position.top - ui.originalPosition.top) + 'px' });
    };
    
    $(transparent).draggable(options.config);
    

    我特意留下了带有不透明度的白色背景颜色,以便您在测试时可以看到元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-03
      • 2011-11-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多