基于html5二个div 连线
因为要实现拖拽连线研究了一下基于extjs 和html5的不同实现方法
extjs底层的画图引擎是svg 不知道在html5大潮即将袭来的前夕一贯走在技术前沿的extjs开发团队没有自己封装基于html5的画图引擎,而是选择了svg 。
下边是花了不到一天的时间实现的任意点连线和拖动功能,代码没有优化,稍微乱了点
如果单纯应用canvas进行画图,拖拽是非常麻烦的,我们往往要基于第三方的画图类库,这里实现是基于kineticjs
为了测试方便我使用了双击事件控制拖动还是划线 。
代码
- <!DOCTYPE HTML>
- <html>
- <head>
- <style>
- body {
- margin: 0px;
- padding: 0px;
- }
- canvas {
- border: 1px solid #9C9898;
- }
- </style>
- <script type="text/javascript" src="ext/bootstrap.js"></script>
- <!-- ENDLIBS -->
- <script type="text/javascript" src="ext/ext-all-debug.js"></script>
- <script src="js/kinetic-v3.10.2.min.js"></script>
- <script>
- Ext.onReady(function(){
- /**
- 自动判断顶点连线算法
- */
- var stage=new Kinetic.Stage({
- container:'container',
- width:1000,
- height:1000
- });
- var layer=new Kinetic.Layer();
- var flag=false;
- var imgArray=[];
- var lineArray=[];
- var tmpMoveImg=null;
- var loop=0;
- function Pos(x,y){
- this.x=x;
- this.y=y;
- };
- function LineImage(img,line){
- this.img=img;
- this.line=line;
- };
- function NewImage(img,opsArray){
- this.img=img;
- this.opsArray=opsArray;
- };
- var imgA= new Image();
- imgA.onload=function(){
- var imgObjA= createImage(imgA,100,100,100,100)
- var array=new Array();
- var na=new NewImage(imgObjA,array);
- imgArray.push(na);
- layer.add(imgObjA);
- stage.add(layer);
- }
- var imgB= new Image();
- imgB.onload=function(){
- var imgObjB= createImage(imgB,400,400,100,100)
- var array=new Array();
- var nb=new NewImage(imgObjB,array);
- imgArray.push(nb);
- layer.add(imgObjB);
- stage.add(layer);
- }
- var imgC= new Image();
- imgC.onload=function(){
- var imgObjC= createImage(imgC,700,100,100,100)
- var array=new Array();
- var nc=new NewImage(imgObjC,array);
- imgArray.push(nc);
- layer.add(imgObjC);
- stage.add(layer);
- }
- var rect=new Kinetic.Rect({
- x:0,
- y:0,
- width:1000,
- height:1000,
- fill:'white',
- storke:'red',
- storkeWidth:5
- });
- layer.add(rect);
- imgA.src='img/db.png';
- imgB.src='img/mj.png';
- imgC.src="img/kt1.png";
- rect.on('dblclick',function(){
- if(loop%2==0){
- flag=true;
- for(var i=0;i<imgArray.length;i++){
- imgArray[i].img.setDraggable(false);
- }
- }else{
- flag=false;
- for(var i=0;i<imgArray.length;i++){
- imgArray[i].img.setDraggable(true);
- imgArray[i].img.on('mouseover',function(){
- var p=new Pos(this.getX(),this.getY());
- tmpMoveImg=getImgByPos(p);
- })
- imgArray[i].img.on('dragmove',function(){
- for(var j=0;j<tmpMoveImg.opsArray.length;j++){
- var realPoints=[];
- calculateStartEndPos(tmpMoveImg.opsArray[j].img,this,realPoints);
- var line= createLine(realPoints);
- var oldLine=tmpMoveImg.opsArray[j].line;
- var p=new Pos(tmpMoveImg.opsArray[j].img.getX(),tmpMoveImg.opsArray[j].img.getY());
- var oppoImg= getImgByPos(p);
- replaceOppoLine(oppoImg,oldLine,line);
- layer.remove(tmpMoveImg.opsArray[j].line);
- tmpMoveImg.opsArray[j].line=line;
- layer.add(line);
- layer.draw();
- realPoints=[];
- }
- layer.draw();
- })
- }
- }
- loop++;
- for(var i=0;i<imgArray.length;i++){
- var innerFlag=false;
- var points=[];//标记性的点,为了获取img 使用
- var realPoints=[];//真正计算后合理的划线点
- imgArray[i].img.on('mousedown',function(){
- if(flag){
- var pos= stage.getMousePosition();
- points.push(this.getX());
- points.push(this.getY());
- innerFlag=true;
- }
- });
- imgArray[i].img.on('mouseup',function(){
- if(flag&&innerFlag){
- var pos= stage.getMousePosition();
- points.push(this.getX());
- points.push(this.getY());
- var p=new Pos(points[0],points[1]);
- var op=new Pos(points[2],points[3]);
- var opImg=getImgByPos(p);
- var owImg=getImgByPos(op);
- if(opImg!=owImg){
- calculateStartEndPos(opImg.img,owImg.img,realPoints);
- var line= createLine(realPoints);
- var opLine=new LineImage(opImg.img,line);
- var owLine=new LineImage(owImg.img,line);
- owImg.opsArray.push(opLine);
- opImg.opsArray.push(owLine);
- flag=false;
- innerFlag=false;
- points=[];
- realPoints=[];
- layer.add(line);
- layer.draw();
- }
- }
- });
- }
- })
- /**
- * 通过坐标获取Img对象
- */
- function getImgByPos(pos){
- for(var i=0;i<imgArray.length;i++){
- if(imgArray[i].img.getX()==pos.x&&imgArray[i].img.getY()==pos.y){
- return imgArray[i];
- }
- }
- }
- /**
- * 替换对方中line
- */
- function replaceOppoLine(imgObj,oldLine,newLine){
- for(var i=0;i<imgObj.opsArray.length;i++){
- if(imgObj.opsArray[i].line==oldLine){
- imgObj.opsArray[i].line=newLine;
- }
- }
- }
- /**
- 划线
- */
- function createLine(points){
- var line=new Kinetic.Line({
- points:points,
- stroke:'bule',
- strokeWidth:5,
- lineCap:'round',
- lineJoin:'round'
- });
- return line;
- }
- /**
- * 计算划线的开始坐标
- */
- function calculateStartEndPos(imgStart,imgEnd,realPoints){
- var realSx=0;
- var realSy=0;
- var realEx=0;
- var realEy=0;
- var sx=imgStart.getX();
- var sy=imgStart.getY();
- var swidth=imgStart.getWidth();
- var sheight=imgStart.getHeight();
- var ex=imgEnd.getX();
- var ey=imgEnd.getY();
- var ewidth=imgEnd.getWidth();
- var eheight=imgEnd.getHeight();
- var arrayx=calculateX(sx,swidth,ex,ewidth );
- var arrayy=calculateY(sy,sheight,ey,eheight );
- realPoints.push(arrayx[0]);
- realPoints.push(arrayy[0]);
- realPoints.push(arrayx[1]);
- realPoints.push(arrayy[1]);
- }
- /**
- 计算开始和结束节点x坐标
- */
- function calculateX(sx,swidth,ex,ewidth ){
- var arrayX=[];
- if(sx>ex){
- arrayX.push(sx);
- arrayX.push(ex+ewidth);
- }else if(sx==ex){
- arrayX.push(sx+(swidth/2));
- arrayX.push(sx+(ewidth/2));
- }else{
- arrayX.push(sx+swidth);
- arrayX.push(ex);
- }
- return arrayX;
- }
- /**
- 计算开始和结束节点y坐标
- */
- function calculateY(sy,sheight,ey,eheight ){
- var arrayY=[];
- if(sy>ey){
- arrayY.push(sy+(sheight/2));
- arrayY.push(ey+(eheight/2));
- }else if(sy==ey){
- arrayY.push(sy+(sheight/2));
- arrayY.push(sy+(eheight/2));
- }else{
- arrayY.push(sy+(sheight/2));
- arrayY.push(ey+(eheight/2));
- }
- return arrayY;
- }
- /**
- 画图
- */
- function createImage(img,x,y,width,height){
- var imgObj=new Kinetic.Image({
- x:x,
- y:y,
- width:width,
- height:height,
- draggable:true,
- image:img
- });
- imgObj.on("mouseover", function(){
- document.body.style.cursor = "pointer";
- });
- imgObj.on("mouseout", function(){
- document.body.style.cursor = "default";
- });
- return imgObj
- }
- });
- </script>
- </head>
- <body>
- <div id="container"></div>
- </body>
- </html>
- <img alt="" src="http://dl.iteye.com/upload/attachment/0070/8176/f9bb5503-b35b-3a45-abb1-0241a1495665.png">
- <img alt="" src="http://dl.iteye.com/upload/attachment/0070/8178/54c788d0-1395-3824-aea1-280b70b6f523.png">
效果如下
代码里还有一项基于extjs4 的实现和纯html5 canvas 的实现
基于html5二个div 连线的更多相关文章
- 基于Html5 Plus + Vue + Mui 移动App 开发(二)
基于Html5 Plus + Vue + Mui 移动App 开发(二) 界面效果: 本页面采用Html5 Plus + Vue + Mui 开发移动界面,本页面实现: 1.下拉刷新.上拉获取更多功能 ...
- HT for Web基于HTML5的图像操作(二)
上篇介绍了HT for Web采用HTML5 Canvas的getImageData和setImageData函数,通过颜色乘积实现的染色效果,本文将再次介绍另一种更为高效的实现方式,当然要实现的功能 ...
- 基于HTML5技术的电力3D监控应用(二)
上篇介绍了我们电力项目的基本情况,我们选用HTML5技术还是顶着很大压力,毕竟HTML5技术性能行不行,浏览器兼容性会不会有问题,这些在项目选型阶段还是充满疑惑,项目做到现在终于快收尾了我们才敢松口气 ...
- 使用PhoneGap开发基于Html5应用二:第一个PhoneGap应用:百度
上一篇博文使用PhoneGap开发基于Html5应用一:PhoneGap简单介绍 中我介绍了怎样从phonegap官网上下载源代码并启动第一个应用,今天我们把phonegap的应用略微改一下,让他实现 ...
- 基于 HTML5 WebGL 的发动机 3D 可视化系统
前言 工业机械产品大多体积庞大.运输成本高,在参加行业展会或向海外客户销售时,如果没有实物展示,仅凭静态.简单的图片说明书介绍,无法让客户全面了解产品,不仅工作人员制作麻烦,客户看得也费力.如 ...
- 基于HTML5实现3D热图Heatmap应用
Heatmap热图通过众多数据点信息,汇聚成直观可视化颜色效果,热图已广泛被应用于气象预报.医疗成像.机房温度监控等行业,甚至应用于竞技体育领域的数据分析. http://www.hightopo.c ...
- 基于HTML5 Canvas实现的图片马赛克模糊特效
效果请点击下面网址: http://hovertree.com/texiao/html5/1.htm 一.开门见山受美国肖像画家Chuck Close的启发,此脚本通过使用HTML5 canvas元素 ...
- 基于HTML5实现的Heatmap热图3D应用
Heatmap热图通过众多数据点信息,汇聚成直观可视化颜色效果,热图已广泛被应用于气象预报.医疗成像.机房温度监控等行业,甚至应用于竞技体育领域的数据分析. 已有众多文章分享了生成Heatmap热图原 ...
- 基于HTML5技术的电力3D监控应用(三)
继(一)和(二)之后不少,不少网友问我移动终端的使用问题,因为我们项目这次采用Android平板终端,所以我对这方面有点肤浅的研究,这篇分享些项目经验总结,希望对大家有所帮助. 电力3D项目去年底刚立 ...
随机推荐
- 二叉树中序遍历,先序遍历,后序遍历(递归栈,非递归栈,Morris Traversal)
例题 中序遍历94. Binary Tree Inorder Traversal 先序遍历144. Binary Tree Preorder Traversal 后序遍历145. Binary Tre ...
- 分布式远程获取配置文件config属性(修正)
1.采用springcloud 获取github上config配置文件属性需要注意的问题; 2.此时github下面的配置文件,命名要特别注意,否则会获取不到配置里面的属性而报错,报错是因为配置文件命 ...
- 使用RegisterPointerInputTarget时的一些注意事项
RegisterPointerInputTarget :允许调用者注册一个目标窗口,指定类型的所有指针输入都重定向到该窗口. 要使用它必须使 UIAccess = true,见下图 在设置完之后,需要 ...
- 多层for循环嵌套,如何能优化一点点,从运行时间维度
将循环次数多的放在最内层,循环次数最少的放在最外层 换句话说,按照循环次数从小到大依次嵌套
- C# 判断 List 是否存在某一个字段
foreach (var item in list_QuestionnaireSelect) { EntityQuestionnaireParticipantsReport _entityReport ...
- [SpringBoot] 通过spring.factory文件来加载第三方的bean
在springboot的开发过程中,我们经常需要加载一些bean,如果bean使我们自己写的类,那很好办,加个@Component注解就搞定了,然后过程启动会扫描启动类所在的包及其子包,如果我 ...
- 【知识】定时器setTimeout/setInterval执行时this指针指向问题
[问题描述] setTimetout/setInterval中this指针指向window,以下是一个小demo: var demoChange = { key: true, changeFun() ...
- mysql NULL函数 语法
mysql NULL函数 语法 作用:如果表中的某个列是可选的,那么我们可以在不向该列添加值的情况下插入新记录或更新已有的记录.这意味着该字段将以 NULL 值保存. 说明:NULL 值的处理方式与其 ...
- python 输出一个随机数
题目:输出一个随机数. 程序分析:使用 random 模块. #!/user/bin/env python #coding:utf-8 import random print random.rando ...
- java总结1
栈,堆,方法区.main和局部变量在栈,new 对象 在堆, 类和常量在方法区除了8大基础数据类型,其他都为引用变量局部变量在函数内或方法上声明,没有默认值,定义必须赋值一旦提供构造方法,就不会有默认 ...