昨天经理下班前要求我实现拖拽布局,那最基本的就要用JS来实现一个元素的拖拽效果,并且可以通过<input>标签来定义各种属性。设计思路,首先要实现元素的拖拽。

一、定义一个HTML

因为需要绑定未来元素,所以把DIV放到了一个共有的DIV中。

<div class="vb-move-container">
        <div class="vb-container vb-can-do" style="top:10px">
            <div class="vb-demo" style="background: #f60;"></div>
            <div class="vb-option">
                X轴<input type="text" class="vb-x">
                y轴<input type="text" class="vb-y">
                宽<input type="text" class="vb-width">
                高<input type="text" class="vb-height">
    </div>

二、拖拽代码的实现

通过Jquery的on方法实现未来元素绑定,给所有vb-container增加“mousedown”(鼠标按下)事件。

$(function(){
    $(".vb-move-container").on("mousedown",".vb-container",function(e){
})



然后我们需要让通过鼠标在点击的时候,移动的距离clientX和clientY得到应该给当前div位移的距离

$(function(){
    $(".vb-move-container").on("mousedown",".vb-container",function(e){
        var ele = $(this);
        ele.css('position','absolute');
        var disX = e.clientX-ele.position().left;
        var disY = e.clientY-ele.position().top;
        $(document).on("mousemove",function(e){
            ele.css("left",e.clientX-disX);
            ele.css("top",e.clientY-disY);
            getXY(ele);
            changeDivTB(ele);
        $(document).on("mouseup",function(){
            $(document).off();
})



到这里,DIV就可以开始移动了,并且如果你添加一个DIV

<button οnclick="add()">添加</button>
function add(){
    let str = `
    <div class="vb-container" style="top:50%;left:45%;">
        <div class="vb-demo" style="background: #f60;"></div>
        <div class="vb-option vb-option-top vb-option-right">
            X轴<input type="text" class="vb-x">
            y轴<input type="text" class="vb-y">
            宽<input type="text" class="vb-width">
            高<input type="text" class="vb-height">
    </div>`;
    $(".vb-move-container").append(str);
}

就可以实现新增的DIV来移动了。

三、增加<input>改变div属性(位置和大小)的功能

1、我们需要在DIV初始化出现的时候,就要获取到对应的值,首先定义一个方法,我这里用的getXY,因为宽高属性是后来才加进去的。方法名不太合适。

function getXY(ele){
    var div = ele.children(".vb-demo");
    var option = ele.children(".vb-option");
    option.children(".vb-x").val(ele.position().left);    //距离左侧距离
    option.children(".vb-y").val(ele.position().top);    //距离顶部距离
    option.children(".vb-height").val(div.height());    //高度
    option.children(".vb-width").val(div.width());        //
}

这里的ele是一个“vb-container”的JQuery对象。


2、我们需要给这些<input>绑定change方法,我们继续在初始化写mousedown的后面添加一些方法绑定,因为这些元素也都可能是未来元素:

$(".vb-move-container").on("change",".vb-x",function(){
        changeDiv(this,"left");
    $(".vb-move-container").on("change",".vb-y",function(){
        changeDiv(this,"top");
    $(".vb-move-container").on("change",".vb-height",function(){
        changeDiv(this,"height","body");
    $(".vb-move-container").on("change",".vb-width",function(){
        changeDiv(this,"width","body");
    $(".vb-container").each(function(){        //调用上面的方法,给一开始就在页面中的div赋值
        getXY($(this));
    });

他们全部调用了一个changeDiv的方法,这个方法是根据传入的参数,给div赋值。因为左右的距离是给container赋值的(所有都要跟着它一起走),而宽、高是要给真正显示的div(“vb-demo”)赋值的,所以我们需要再传入一个body,来确定到底是给谁赋值。而changeDiv的方法如下:

function changeDiv(ele,type,option){
    let div;
    if(option == "body"){
        div = $(ele).parent().prev();
    }else{
        div = $(ele).parent().parent();
    div.css(type,$(ele).val()+"px");
}

这样修改数据的工作就完成了。当然,我们还需要在移动的时候,输入框中单数据也要对应修改,就只需要在mousemove中也调用getXY方法即可。

四、vb-option(设置栏)不可以出界

当拖动数据栏的时候,会出现数据栏出界的情况,导致无法修改数据。解决办法是通过判断“数据栏”边界的位置,来调换数据栏的位置。

首先我们设置了四种css

.vb-option-top{
            bottom:-70px;
        .vb-option-bottom{
            top:140px;
        .vb-option-left{
            left:-120px;
        .vb-option-right{
            left:120px;
        }

然后给div中的vb-option后面再添加vb-option-top、vb-option-right(表示在右上角,也可以根据自己喜好添加)

<div class="vb-option vb-option-top vb-option-right">
                X轴<input type="text" class="vb-x">
                y轴<input type="text" class="vb-y">
                宽<input type="text" class="vb-width">
                高<input type="text" class="vb-height">
            </div>

然后就是在鼠标移动(mousemove)方法里增加一下判断。因为代码较多,所以我又单独写了一个方法

$(document).on("mousemove",function(e){
            ele.css("left",e.clientX-disX);
            ele.css("top",e.clientY-disY);
            getXY(ele);        //随着移动获取数据
            changeDivTB(ele);    //判断option的位置
        })
function changeDivTB(ele){
    var opt = ele.children(".vb-option");
    var top = ele.position().top + opt.position().top;
    var left = ele.position().left+opt.position().left;
    var bodyWidth = $(window).width();
    var bodyHeight = $(window).height();
    if(top<0){    //判断上边界
        opt.removeClass("vb-option-top");
        opt.removeClass("vb-option-bottom");
        opt.addClass("vb-option-bottom");
    if((top+opt.height())>bodyHeight){    //判断右边是否超出
        opt.removeClass("vb-option-top");
        opt.removeClass("vb-option-bottom");
        opt.addClass("vb-option-top");
    if(left<0){    //判断左边界
        opt.removeClass("vb-option-left");
        opt.removeClass("vb-option-right");
        opt.addClass("vb-option-right");
    if((left+opt.width())>bodyWidth){    //判断右边界
        opt.removeClass("vb-option-left");
        opt.removeClass("vb-option-right");
        opt.addClass("vb-option-left");
}

这样,我们元素拖拽的功能就实现了。因为第一次写博客,思路可能比较混乱,写的不太好。最后贴上完整代码:

HTML:

<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="node_modules/jquery/dist/jquery.min.js"></script>
    <script src="js/main.js"></script>
    <style>
        .vb-container{
            position: absolute;
            cursor: move;
        .vb-demo{
            position: absolute;
            border-radius: 50%;
            width:200px;
            height: 200px;
        .vb-option{
            position: absolute;
            width: 200px;
        .vb-option-top{
            bottom:-70px;
        .vb-option-bottom{
            top:140px;
        .vb-option-left{
            left:-120px;
        .vb-option-right{
            left:120px;
    </style>
</head>
    <button οnclick="add">添加</button>
    <div class="vb-move-container">
        <div class="vb-container vb-can-do" style="top:10px">
            <div class="vb-demo" style="background: #f60;"></div>
            <div class="vb-option vb-option-top vb-option-right">
                X轴<input type="text" class="vb-x">
                y轴<input type="text" class="vb-y">
                宽<input type="text" class="vb-width">
                高<input type="text" class="vb-height">
</body>
</html>

javascript:

$(function(){
    $(".vb-move-container").on("mousedown",".vb-container",function(e){
        var ele = $(this);
        ele.css('position','absolute');
        var disX = e.clientX-ele.position().left;
        var disY = e.clientY-ele.position().top;
        $(document).on("mousemove",function(e){
            ele.css("left",e.clientX-disX);
            ele.css("top",e.clientY-disY);
            getXY(ele);
            changeDivTB(ele);
        $(document).on("mouseup",function(){
            $(document).off();
    $(".vb-move-container").on("change",".vb-x",function(){
        changeDiv(this,"left");
    $(".vb-move-container").on("change",".vb-y",function(){
        changeDiv(this,"top");
    $(".vb-move-container").on("change",".vb-height",function(){
        changeDiv(this,"height","body");
    $(".vb-move-container").on("change",".vb-width",function(){
        changeDiv(this,"width","body");
    $(".vb-container").each(function(){
        getXY($(this));
function getXY(ele){
    var div = ele.children(".vb-demo");
    var option = ele.children(".vb-option");
    option.children(".vb-x").val(ele.position().left);
    option.children(".vb-y").val(ele.position().top);
    option.children(".vb-height").val(div.height());
    option.children(".vb-width").val(div.width());
function changeDiv(ele,type,option){
    let div;
    if(option){
        div = $(ele).parent().prev();
    }else{
        div = $(ele).parent().parent();
    div.css(type,$(ele).val()+"px");
function changeDivTB(ele){
    var opt = ele.children(".vb-option");
    var top = ele.position().top + opt.position().top;
    var left = ele.position().left+opt.position().left;
    var bodyWidth = $(window).width();
    var bodyHeight = $(window).height();
    if(top<0){
        opt.removeClass("vb-option-top");
        opt.removeClass("vb-option-bottom");
        opt.addClass("vb-option-bottom");
    if((top+opt.height())>bodyHeight){
        opt.removeClass("vb-option-top");
        opt.removeClass("vb-option-bottom");
        opt.addClass("vb-option-top");
    if(left<0){
        opt.removeClass("vb-option-left");
        opt.removeClass("vb-option-right");
        opt.addClass("vb-option-right");
    if((left+opt.height())>bodyWidth){
        opt.removeClass("vb-option-left");
        opt.removeClass("vb-option-right");
        opt.addClass("vb-option-left");
function add(){
    let str = `
    <div class="vb-container" style="top:50%;left:45%;">
        <div class="vb-demo" style="background: #f60;"></div>
        <div class="vb-option vb-option-top vb-option-right">
            X轴<input type="text" class="vb-x">
            y轴<input type="text" class="vb-y">
            宽<input type="text" class="vb-width">
            高<input type="text" class="vb-height">
    </div>`;
    $(".vb-move-container").append(str);
    $(".vb-container").each(function(){
        getXY($(this));
                            
android可拖拽view android可拖拽的悬浮窗

项目中需要实现一个状态显示的悬浮框,要求可以设置两种模式:拖动模式和不可拖动模式。实现效果图如下:实现步骤:1.首先要设置该悬浮框的基本属性:/** * 显示弹出框 * @param context @SuppressWarnings("WrongConstant") public static void showPopupWind