真正的原生js写的拖拽来了
来源:互联网 发布:微软雅黑bold for mac 编辑:程序博客网 时间:2024/06/06 11:02
前几次的拖拽都是基于HTML5的拖拽API写的,在项目中我发现我自己写的只支持谷歌浏览器,火狐和IE都不支持,这就很尴尬了,当时的我内心是崩溃的。。。不过思路是有了,还是原来的思路,但是就是拖拽的时候不好弄,我也试着引用基于jquery的插件,但是不行,老是冲突,我在这里的意思不是说HTML5的拖拽API兼容性不好,应该是我自己的代码有问题,我真的是,一股傲气冲上头顶,老子要写纯原生的,于是我就上网查找资料,用mousedown、mousemove、mouseup事件配合来进行拖拽,基于以前拖拽的思路,做出了流程图,比1.0版本还要好,拖动起来还要唯美,还要舒服,下面上2.0版本的代码
<!DOCTYPE html><html lang="en" onselectstart='return false'><head> <meta charset="UTF-8"> <title>Document</title> <style type="text/css"> #d1{ width: 800px; height:800px; border:1px solid #ccc; background: #fafafa; position: relative; } #d1 .drawContent div{ width:130px; height:30px; border: 1px solid #ccc; background: #fff; border-radius: 8px; position: absolute; text-align: center; line-height: 30px; z-index: 2; cursor:move; } #d1 .drawContent div span{ display: inline-block; width: 130px; height: 20px; line-height: 20px; cursor: move; } #d1 .drawContent div i{ display: inline-block; width: 10px; height:10px; background: #fff; border-radius: 50%; position: absolute; top:-7px; left:46%; border:1px solid #ccc; cursor: default; } #d1 .drawContent div s{ display: inline-block; width: 10px; height:10px; background: #fff; border-radius: 50%; position: absolute; bottom:-7px; left:46%; border:1px solid #ccc; cursor: crosshair; } #d1 .drawContent div u{ position: absolute; display: inline-block; border:6px solid transparent; border-top:6px solid #ccc; top:0px; left:58px; } #d1 .drawContent div s:hover{ background: #F8BC06; } #d1 svg{ width: 100%; height:100%; position: absolute; z-index: 1; } #d2{ width: 300px; height:2000px; } ul li{ cursor: default; } </style></head><body> <ul> <li data-name = 'xiangjiao'> <span>香蕉</span> </li> <li data-name = 'pingguo'> <span>苹果</span> </li> <li data-name = 'liulian'> <span>榴莲</span> </li> <li data-name = 'xigua'> <span>西瓜</span> </li> <li data-name = 'xihongshi'> <span>西红柿</span> </li> </ul> <div id = 'd1'> <div class = "drawContent"> </div> <svg></svg> </div> <div id = 'd2'></div> <script type="text/x-handlebars-template" id = "content"> {{#each this}} <div class = "{{name}}" data-id = '{{id}}' data-inx = '{{inx}}' data-iny = '{{iny}}'style = "top:{{y}}px;left:{{x}}px"> <i title = "输入" style = "display:{{circle}}"></i> <u style = "display:{{arrow}}"></u> <span class = "label">{{label}}</span> <s title = "输出"></s> </div> <ul class = "clickMenu" style = "top:{{mTop}}px;left:{{mLeft}}px;display:{{menuShow}}"> <li>重命名</li> <li class = "delete">删除</li> <li>全部运行</li> <li>运行到此处</li> <li>运行该节点</li> <li>从此节点运行</li> <li>查看数据</li> <li>查看日志</li> </ul> {{/each}} </script> <script type="text/x-handlebars-template" id = "line"> {{#each this}} {{#each link}} <g class = "{{name}}"> <path d = "M{{../outx}} {{../outy}} Q{{mx1}} {{my1}} {{mx2}} {{my2}} T{{dx}} {{dy}}" stroke = "#CCCCCC" fill = "none" style = "stroke-width: 1px;"/> </g> {{/each}} {{/each}} </script> <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> <script type="text/javascript" src = 'js/handlebars-v4.0.10 .js'></script> <script type="text/javascript"> var element; // 获得容器的宽度 var dWidth = Number($('#d1').css('width').slice(0,-2)); // 获得容器的高度 var dHeight = Number($('#d1').css('height').slice(0,-2)); var dragData = [ { id:0, name:'xiangjiao', label:'香蕉', draw:false, link:[], linked:[], outx:268, outy:430, dx:0, dy:0, inx:265, iny:399, x:200, y:400, arrow:"none", circle:"inline-block", },{ id:1, name:'pingguo', draw:false, label:'苹果', link:[], linked:[], outx:468, outy:230, dx:0, dy:0, inx:465, iny:199, x:400, y:200, arrow:"none", circle:"inline-block", }, ] function reload(){ var myTemplate = Handlebars.compile($("#content").html()); $('#d1 .drawContent').html(myTemplate(dragData)); var myLine = Handlebars.compile($("#line").html()); $('#d1 svg').html(myLine(dragData)); } reload(); //按下列表创建虚像 $('ul li ').mousedown(function(e){ var span = document.createElement('span'); span.innerHTML = $(this).text(); span.setAttribute('data-name',$(this).data('name')); span.style.opacity = 0.6; span.style.position = 'absolute'; span.style.top = (e.pageY-8) + 'px'; span.style.left = (e.pageX-8) + 'px'; span.style.zIndex = 5; $(this).append(span); element = $(this).children('span:last-child'); console.log('element',element); }) // 文档鼠标抬起时判断在不在容器内,创建元素 $(document).mouseup(function(e){ console.log('e.target',e.target); $('#d1').unbind('mousemove'); if(element){ if(e.pageY > $('#d1').offset().top && e.pageX > $('#d1').offset().left){ console.log('e.offsetY',e.offsetY,'e.offsetX',e.offsetX); console.log(element); var x = e.pageX - $('#d1').offset().left - e.offsetX; var y = e.pageY - $('#d1').offset().top - e.offsetY; //判断x if((x >= 0 && x <= dWidth - 132)){ x = x; }else if(x < 0){ x = 1; }else if(x > dWidth - 132){ x = dWidth - 132 } //判断y if((y >= 0 && y <= dHeight - 32)){ y = y; }else if(y < 0){ y = 1; }else if(y > dHeight - 32){ y = dHeight - 32 } dragData.push({ id:dragData.length, name:element.data('name'), draw:false, label:element.text(), x:x, y:y, outx:x + 68, outy:y + 30, inx:x +65, iny:y - 1, link:[], linked:[], dx:0, dy:0, arrow:"none", circle:"inline-block" }) reload(); element.remove(); element = undefined; }else{ element.remove(); element = undefined; } } }) //拖动虚像在文档中进行移动 $(document).mousemove(function(e){ //console.log('x',e.pageX,'y',e.pageY); if(element){ element.css({'top':(e.pageY - 8) + 'px','left':(e.pageX - 8)}); } }) //给创建的新的组件加上mousedown事件 var waitElement; $('#d1 > .drawContent').on('mousedown','div',function(e){ waitElement = $(this); console.log(waitElement); var dx = e.offsetX var dy = e.offsetY console.log('e.offsetX',e.offsetX) console.log('e.offsetY',e.offsetY) //容器的mousemove事件 $('#d1').mousemove(function(e){ if(waitElement){ waitElement.css({top:(e.pageY - $('#d1').offset().top - dy) + 'px',left:(e.pageX - $('#d1').offset().left - dx) + 'px'}); console.log(waitElement.data('id')); var id = waitElement.data('id') var x = e.pageX - $('#d1').offset().left - dx; var y = e.pageY - $('#d1').offset().top - dy; //判断x if((x >= 0 && x <= dWidth - 132)){ x = x; }else if(x < 0){ x = 1; }else if(x > dWidth - 132){ x = dWidth - 132 } //判断y if((y >= 0 && y <= dHeight - 32)){ y = y; }else if(y < 0){ y = 1; }else if(y > dHeight - 32){ y = dHeight - 32 } for(var i = 0; i < dragData.length; i++){ if(id == dragData[i].id){ console.log(dragData[i]); dragData[i].x = x; dragData[i].outx = dragData[i].x + 68; dragData[i].inx = dragData[i].x + 65; dragData[i].y = y; dragData[i].outy = dragData[i].y + 30; dragData[i].iny = dragData[i].y - 1; console.log('要开始了') for(let j = 0; j < dragData[i].link.length;j++){ dragData[i].link[j].linkId = parseFloat(dragData[i].link[j].name.split("|")[1]); } for(var k = 0 ; k < dragData[i].linked.length;k++){ console.log('dragData[i].linked[k]',dragData[i].linked[k]); for(let j = 0; j < dragData.length;j++){ if(dragData[i].linked[k].linkedNum == dragData[j].id){ console.log('ID一样了啊'); for(let m = 0; m < dragData[j].link.length; m++){ if(dragData[i].linked[k].name == dragData[j].link[m].name){ console.log("名字一样了啊"); dragData[j].link[m].dx = dragData[i].inx; dragData[j].link[m].dy = dragData[i].iny; dragData[j].link[m].mx1 = dragData[j].outx; dragData[j].link[m].my1 = dragData[j].link[m].dy > dragData[j].outy?dragData[j].outy + (dragData[j].link[m].dy-dragData[j].outy)/4:dragData[j].outy - (dragData[j].link[m].dy-dragData[j].outy)/4; dragData[j].link[m].mx2 = dragData[j].outx + (dragData[j].link[m].dx-dragData[j].outx)/2, dragData[j].link[m].my2 = dragData[j].outy +(dragData[j].link[m].dy-dragData[j].outy)/2 } } } } } reload(); if(dragData[i].link.length > 0){ for(var j = 0; j < dragData[i].link.length;j++){ dragData[i].link[j].mx1 = dragData[i].outx; dragData[i].link[j].my1 = dragData[i].link[j].dy > dragData[i].outy?dragData[i].outy + (dragData[i].link[j].dy-dragData[i].outy)/4:dragData[i].outy - (dragData[i].link[j].dy-dragData[i].outy)/4; dragData[i].link[j].mx2 = dragData[i].outx + (dragData[i].link[j].dx-dragData[i].outx)/2, dragData[i].link[j].my2 = dragData[i].outy +(dragData[i].link[j].dy-dragData[i].outy)/2 } } reload(); } } console.log(dragData); reload(); } }) }) //给创建的新的组件加上mouseup事件 $('#d1 > .drawContent > div').mouseup(function(){ waitElement = undefined; console.log(waitElement); }) //容器的mouseup事件 $('#d1').mouseup(function(e){ console.log('我抬起了'); waitElement = undefined; $('#d1').unbind('mousemove'); if(waitElement){ waitElement.css({top:e.pageY - $('#d1').offset().top,left:e.pageX - $('#d1').offset().left}) } }) //给组件的输出圆圈加入mouseenter事件使组件不能拖拽 $('#d1 > .drawContent').on('mouseenter','div>s',function(){ console.log('进入了输出'); waitElement = undefined; $('#d1').unbind('mousemove'); $('svg').unbind('mousemove'); $('#d1 > .drawContent').off('mousedown','div'); }) //先给组件的输出源加入mousedown事件,先创建连线 $('#d1 > .drawContent').on('mousedown','div>s',function(){ //先创建连线的数据 console.log($(this).parent()); var parent = $(this).parent(); var id = parent.data('id'); console.log('idididid',id); for(var i = 0; i < dragData.length; i++){ if(dragData[i].id == id){ dragData[i].draw = true; dragData[i].link.push({ name:id + parent.attr('class'), dx:0, dy:0, mx1:0, my1:0, mx2:0, my2:0 }); console.log('dragData哈哈哈哈',dragData); $('body').on('mouseup',function(e){ for(var j = 0; j < dragData.length; j++){ if(id == dragData[j].id){ console.log('页面抬起了'); dragData[j].draw = false; if(e.target.title){ if(e.target.title == "输入"){ $('svg').unbind('mousemove'); dragData[j].link[dragData[j].link.length - 1].name = dragData[j].link[dragData[j].link.length - 1].name + "|" + e.target.parentNode.dataset.id + e.target.parentNode.className; dragData[j].link[dragData[j].link.length - 1].dx = Number(e.target.parentNode.dataset.inx); dragData[j].link[dragData[j].link.length - 1].dy = Number(e.target.parentNode.dataset.iny); for(let i = 0; i < dragData.length; i++){ if(e.target.parentNode.dataset.id == dragData[i].id){ dragData[i].linked.push({ name: dragData[j].link[dragData[j].link.length - 1].name, linkedNum:parseFloat(dragData[j].link[dragData[j].link.length - 1].name) }) dragData[i].circle = "none"; dragData[i].arrow = "inline-block"; } } }else{ dragData[j].link.splice(dragData[j].link.length-1,1); $('svg').unbind('mousemove'); reload(); } }else{ dragData[j].link.splice(dragData[j].link.length-1,1); $('svg').unbind('mousemove'); } reload(); } } $('body').unbind('mouseup'); }) } } }) //给输出圆圈添加mouseup事件 $('#d1 > .drawContent').on('mouseup','div>s',function(){ var parent = $(this).parent(); for(var i = 0; i < dragData.length;i++){ if(parent.data('id') == dragData[i].id){ dragData[i].draw = false; console.log(dragData[i]); } } }) //给组件的输出源加入mouseleave事件使组件继续能够拖拽 $('#d1 > .drawContent').on('mouseleave','div>s',function(){ console.log('离开了了输出'); console.log($(this).parent()); waitElement = $(this).parent(); var id = waitElement.data('id') //重新赋值使选中组件能够进行拖拽 $('#d1 > .drawContent').on('mousedown','div',function(e){ waitElement = $(this); console.log(waitElement); var dx = e.offsetX var dy = e.offsetY console.log('e.offsetX',e.offsetX) console.log('e.offsetY',e.offsetY) //容器的mousemove事件 $('#d1').mousemove(function(e){ if(waitElement){ waitElement.css({top:(e.pageY - $('#d1').offset().top - dy) + 'px',left:(e.pageX - $('#d1').offset().left - dx) + 'px'}); console.log(waitElement.data('id')); var id = waitElement.data('id') var x = e.pageX - $('#d1').offset().left - dx; var y = e.pageY - $('#d1').offset().top - dy; //判断x if((x >= 0 && x <= dWidth - 132)){ x = x; }else if(x < 0){ x = 1; }else if(x > dWidth - 132){ x = dWidth - 132 } //判断y if((y >= 0 && y <= dHeight - 32)){ y = y; }else if(y < 0){ y = 1; }else if(y > dHeight - 32){ y = dHeight - 32 } for(var i = 0; i < dragData.length; i++){ if(id == dragData[i].id){ console.log(dragData[i]); dragData[i].x = x; dragData[i].outx = dragData[i].x + 68; dragData[i].inx = dragData[i].x + 65; dragData[i].y = y; dragData[i].outy = dragData[i].y + 30; dragData[i].iny = dragData[i].y - 1; console.log('要开始了') for(let j = 0; j < dragData[i].link.length;j++){ dragData[i].link[j].linkId = parseFloat(dragData[i].link[j].name.split("|")[1]); } for(var k = 0 ; k < dragData[i].linked.length;k++){ console.log('dragData[i].linked[k]',dragData[i].linked[k]); for(let j = 0; j < dragData.length;j++){ if(dragData[i].linked[k].linkedNum == dragData[j].id){ console.log('ID一样了啊'); for(let m = 0; m < dragData[j].link.length; m++){ if(dragData[i].linked[k].name == dragData[j].link[m].name){ console.log("名字一样了啊"); dragData[j].link[m].dx = dragData[i].inx; dragData[j].link[m].dy = dragData[i].iny; dragData[j].link[m].mx1 = dragData[j].outx; dragData[j].link[m].my1 = dragData[j].link[m].dy > dragData[j].outy?dragData[j].outy + (dragData[j].link[m].dy-dragData[j].outy)/4:dragData[j].outy - (dragData[j].link[m].dy-dragData[j].outy)/4; dragData[j].link[m].mx2 = dragData[j].outx + (dragData[j].link[m].dx-dragData[j].outx)/2, dragData[j].link[m].my2 = dragData[j].outy +(dragData[j].link[m].dy-dragData[j].outy)/2 } } } } } reload(); if(dragData[i].link.length > 0){ for(var j = 0; j < dragData[i].link.length;j++){ dragData[i].link[j].mx1 = dragData[i].outx; dragData[i].link[j].my1 = dragData[i].link[j].dy > dragData[i].outy?dragData[i].outy + (dragData[i].link[j].dy-dragData[i].outy)/4:dragData[i].outy - (dragData[i].link[j].dy-dragData[i].outy)/4; dragData[i].link[j].mx2 = dragData[i].outx + (dragData[i].link[j].dx-dragData[i].outx)/2, dragData[i].link[j].my2 = dragData[i].outy +(dragData[i].link[j].dy-dragData[i].outy)/2 } } reload(); } } console.log(dragData); reload(); } }) }) //给svg加mousemove事件 for(var i = 0; i < dragData.length;i++){ if(id == dragData[i].id){ if(dragData[i].draw == true){ $('svg').mousemove(function(e){ for(var i = 0; i < dragData.length;i++){ if(id == dragData[i].id){ console.log(dragData[i]); if(dragData[i].link[dragData[i].link.length-1]){ dragData[i].link[dragData[i].link.length-1].dx = e.offsetX; dragData[i].link[dragData[i].link.length-1].dy = e.offsetY; dragData[i].link[dragData[i].link.length-1].mx1 = dragData[i].outx; dragData[i].link[dragData[i].link.length-1].my1 = dragData[i].dy > dragData[i].outy?dragData[i].outy + (dragData[i].dy-dragData[i].outy)/4:dragData[i].outy - (dragData[i].dy-dragData[i].outy)/4; dragData[i].link[dragData[i].link.length-1].mx2 = dragData[i].outx + (dragData[i].dx-dragData[i].outx)/2, dragData[i].link[dragData[i].link.length-1].my2 = dragData[i].outy +(dragData[i].dy-dragData[i].outy)/2 } ////////////////////////////////////////////// dragData[i].dx = e.offsetX; dragData[i].dy = e.offsetY; dragData[i].mx1 = dragData[i].outx; if(dragData[i].dy > dragData[i].outy){ dragData[i].my1 = dragData[i].outy + (dragData[i].dy-dragData[i].outy)/4; }else{ dragData[i].my1 = dragData[i].outy - (dragData[i].dy-dragData[i].outy)/4; } dragData[i].mx2 = dragData[i].outx + (dragData[i].dx-dragData[i].outx)/2 dragData[i].my2 = dragData[i].outy +(dragData[i].dy-dragData[i].outy)/2 } } reload(); console.log(2333); }) }else{ $('svg').unbind('mousemove'); } } } }) //给svg添加mouseup事件 $('svg').mouseup(function(e){ console.log(e.target); $('svg').unbind('mousemove'); for(var i = 0; i < dragData.length;i++){ dragData[i].draw = false; } console.log('起来了'); }) </script></body></html>
这里要提一嘴,因为没有用到angular,用了一套基于jquery的一个模版插件,可以对数据进行双向数据绑定,叫Handlebars.js,下面有教程链接,是一个大神的博客,冒昧的引用一下他的链接
http://www.cnblogs.com/iyangyuan/archive/2013/12/12/3471227.html
我的主要思路还是先操作数组对象,然后再利用这个js模版引擎画到DOM中去,来两张效果图
当然我这里只是写的一个demo,具体应用到项目中去,还要根据相对定位的父元素来计算出鼠标的实际坐标,我这里默认的相对定位的父元素是body,不过我已经应用到项目中去了,肯定没问题的,ok,今天就到这里吧,终于拖拽可以消停了,哈哈哈哈哈哈!!!!!
阅读全文
0 0
- 真正的原生js写的拖拽来了
- js定时器,原生js写的时钟
- 用JS写原生的选项卡
- 原生js写的tab切换
- 原生js写的简单心电图
- 原生JS写Ajax的请求函数
- 原生JS写Ajax的请求函数
- 原生js写的斗鱼弹幕
- 自己写的原生js轮播图插件
- 会不会把原生的JS忘记了
- js插件--基于原生js写的autoComplete插件
- 原生js写的贪吃蛇网页版游戏
- 原生js写的一个下拉框功能插件
- 原生js写的slider_up与slider_down效果
- 使用原生js写一个日期的倒计时
- 原生 JS 写的手机端上下拉
- 原生Js的bind
- 原生JS的ajax
- 开启我的Java之旅(不甘心再做一个小白)
- 二进制枚举子集
- 双十一还没到,EasyRecovery降价风暴已来到!
- java 泛型之 通配符的限定 之 super 的实例
- 上传下载加分页
- 真正的原生js写的拖拽来了
- 参考教程地址
- i++与++i是一样的吗?
- 软件工程作业--03 黄金点游戏
- Java发展史
- uva170
- 解决symbol(s) not found for architecture x86_64报错
- centos 6.8 下python2.6 升级python2.7,安装pip工具
- Unity相机自身围绕(第一人称视角)