博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HT for Web列表和3D拓扑组件的拖拽应用
阅读量:6818 次
发布时间:2019-06-26

本文共 7923 字,大约阅读时间需要 26 分钟。

非常多可视化编辑器都或多或少有一些拖拽功能。比方从一个中拖拽一个节点到拓扑组件上进行建模,而且在拖拽的过程中鼠标位置下会附带一个被拖拽节点的缩略图,那么今天我们就来实现这种拖拽效果。

 

首先我们须要创建一个,在列表中增加图片信息,让List列表不那么单调,先来看看效果图。

 

 

接下来我们一步一步来是想这个,先来解决下数据,在这里我就列举一两个:

 

var products = [    {        ProductId : 1,        ProductName : "Chai",        QuantityPerUnit : "10 boxes x 20 bags",        UnitPrice : 18.00,        Description : "Soft drinks, coffees, teas, beers, and ales"    },    {        ProductId : 2,        ProductName : "Chang",        QuantityPerUnit : "24 - 12 oz bottles",        UnitPrice : 19.00,        Description : "Soft drinks, coffees, teas, beers, and ales"    },    ……];

 

有了数据,我们就能够来创建ListView组件了:

 

var listView = new ht.widget.ListView();var view = listView.getView();document.body.appendChild(view);

 

这时我们创建的是一个空的ListView组件,在浏览器上看不到不论什么东西,那么接下来我们就该把我们定义的数据加入到上了:

 

products.forEach(function(product){    var data = new ht.Data();    data.a(product);    listView.dm().add(data);});

 

数据的加入是不是非常easy,可是上显示的内容默认是Data的name属性或displayName属性,在创建Data时,并没有对Data设置displayName或者name属性,所以这个时候在页面上看到的还是一个空的List组件,别急,我们能够在不设置displayName或name属性的情况下让组件显示效果图上的文本内容,请看:

 

listView.getLabel = function(data){    return data.a('ProductName') + ' - $' + data.a('UnitPrice').toFixed(2);};

 

嘿嘿,提供了getLabel方法供用户重载来实现自己定义显示文本内容,这下应该就能够显示文本内容了吧~

 

oh no~还是什么都没有,是不是还少了点什么呢~对了,忘记给ListView组件加入铺满浏览器的样式了。将厦门的样式加入到head标签中:

 

 

接下来指定view的className属性:

 

view.className = 'main';

 

噢~总算出来了~

 

 

行高太小了。背景也太单调了,向效果图看齐:

 

listView.setRowHeight(50);listView.drawRowBackground = function(g, data, selected, x, y, width, height){    if(this.isSelected(data)){        g.fillStyle = '#87A6CB';    }    else if(this.getRowIndex(data) % 2 === 0){        g.fillStyle = '#F1F4F7';    }    else{        g.fillStyle = '#FAFAFA';    }    g.beginPath();    g.rect(x, y, width, height);    g.fill();};

 

通过setRowHeight()方法设置行高,通过重载drawRowBackground()方法绘制交叉背景。

 

 

嘿,有点样子了,和效果图越来越近了~那么就差图标了呢。

 

ht.Default.setImage('1', 40, 40, 'data:image/jpeg;base64,...');ht.Default.setImage('2', 40, 40, ‘data:image/jpeg;base64,...');……listView.setIndent(60);listView.getIcon = function(data){    return data.a('ProductId');};

 

通过ht.Default.setImage()方法定义ProductId相应的图片资源,以ProductId作为图片的别名,然后接下来定义icon位置大小为60,重载的getIcon方法返回数据中定义的ProductId属性,如此就能够看到图标了。

 

 

还没完,效果图上显示的图片是圆形的,这该怎样是好呢?别急,我们有万能的,上么样的图形都难不倒我们:

 

ht.Default.setImage('productIcon', {    width: 50,    height: 50,    clip: function(g, width, height) {        g.beginPath();        g.arc(width/2, height/2, Math.min(width, height)/2-3, 0, Math.PI * 2, true);        g.clip();    },    comps: [        {            type: 'image',            stretch: 'uniform',            rect: [0, 0, 50, 50],            name: {func: function(data){return data.a('ProductId');}}        }    ]});

 

在代码中我们定义了一个名称为productIcon的矢量,在矢量中通过clip属性定义裁切区域,效果就是超出该裁切区域外的内容将被隐藏。

如今定义好了。我们仅仅须要在的getIcon()方法中返回我们定义的矢量名称就能够实现圆形图标了:

 

listView.getIcon = function(data){    return 'productIcon';};

 

到这里。和效果图的效果就一模一样了~那么接下来我们就该创建组件了。来看看效果图:

 

 

非常easy。就在中放两个正方体:

 

var g3d = new ht.graph3d.Graph3dView();var node = new ht.Node();node.s3(30, 30, 30);node.p3(-30, 15, 0);node.s('all.color', '#87A6CB');g3d.dm().add(node);node = new ht.Node();node.s3(30, 30, 30);node.p3(30, 15, 0);node.s('all.color', '#87A6CB');node.setElevation(15);g3d.dm().add(node);

 

这是你会发现并没有像效果图中显示的那么会有网格效果。而且视角也不正确。没事,待我加入几个属性:

 

g3d.setEye(-100, 100, 80);g3d.setGridVisible(true);g3d.setGridColor(‘#F1F4F7');

  

如此就和效果图一模一样了~

 

ListView和是两个独立的组件,我们该怎样将这两个组件组合在一起呢?这时候。我想到了BorderPane组件。将List组件放在左边,将3D拓扑组件放在右边:

 

var borderPane = new ht.widget.BorderPane();borderPane.setLeftView(listView, 350);borderPane.setCenterView(g3d);

 

看,成功将两个组件合并在一起了,离成功不远了。

接下来就是今天的重头戏了,该怎样实现拖拽List上的节点到3D拓扑上。并实现节点的图标吸附到的图元上呢,我给大家细细道来。

 

 

首先先来了解下的handleDragAndDrop()方法,draganddrop一共同拥有4个状态:prepare、begin、between和end,可更具这4个不同状态来做不同的业务处理。

 

第一步,我们来实现鼠标附带图标的效果,在拖拽ListView的节点时,在鼠标下方添加一个该节点的缩略图:

 

思路是这种:

1. 在prepare状态时获取当前拖拽节点的ProductId属性,并通过调用ht.Default.toCanvas()方法将当前拖拽节点结合矢量productIcon获得一个canvas对象;

2. 在begin状态时依据鼠标当前位置设置canvas对象的left和top属性,并将其加入到DOM树中;

3. 在between状态时,依据鼠标位置信息,又一次设置canvas对象的left和top属性。令canvas对象一直跟着鼠标在移动;

4. 在end状态时,将canvas对象移除DOM树。

 

var dragImage = null,    productId = null;listView.handleDragAndDrop = function(e, state) {    if (state === 'prepare') {        var data = listView.getDataAt(e);        listView.sm().ss(data);        if (dragImage && dragImage.parentNode) {            document.body.removeChild(dragImage);        }        dragImage = ht.Default.toCanvas('productIcon', 30, 30, 'uniform', data);        productId = data.a('ProductId');    }    else if (state === 'begin') {        if (dragImage) {            var pagePoint = ht.Default.getPagePoint(e);            dragImage.style.left = pagePoint.x - dragImage.width / 2 + 'px';            dragImage.style.top = pagePoint.y - dragImage.height / 2 + 'px';            document.body.appendChild(dragImage);        }    }    else if (state === 'between') {        if (dragImage) {            var pagePoint = ht.Default.getPagePoint(e);            dragImage.style.left = pagePoint.x - dragImage.width / 2 + 'px';            dragImage.style.top = pagePoint.y - dragImage.height / 2 + 'px';        }    }    else {        if (dragImage) {            if (dragImage.parentNode) {                document.body.removeChild(dragImage);            }            dragImage = null;            productId = null;        }    }};

 

如此在拖拽节点时就行看到有一个小图标一直跟着鼠标在移动。

 

 

OK,接下来该解决图元吸附功能。当鼠标拖拽ListView节点到上的图元是,将该节点的图标设置为图元当前面的贴图。

 

思路是这样子的:

1. 在between状态时,通过ht.Default.containedInView()方法推断殿前鼠标是否在3D拓扑组件上;

2. 若鼠标在3D拓扑上,则通过g3d.getHitFaceInfo()方法,依据鼠标当前信息获取当前鼠标下的图元表面信息;

3. 若当前鼠标在图元的某个表面上,则先保存该图元表面信息的贴图,然后设置当前图元表面的贴图为拖拽节点相应的图片,最后将当前图元表面信息缓存下来。当鼠标离开该表面时,还原图元的贴图。

4. 在end状态时,假设当前鼠标位置在某个图元表面时。就将当前拖拽节点的相应的图片做为当前图元表面的贴图。

 

那么接下来就须要对ListView组件的handleDragAndDrop()方法做些微的改动了。

 

listView.handleDragAndDrop = function(e, state) {    if (state === 'prepare') {        var data = listView.getDataAt(e);        listView.sm().ss(data);        if (dragImage && dragImage.parentNode) {            document.body.removeChild(dragImage);        }        dragImage = ht.Default.toCanvas('productIcon', 30, 30, 'uniform', data);        productId = data.a('ProductId');    }    else if (state === 'begin') {        if (dragImage) {            var pagePoint = ht.Default.getPagePoint(e);            dragImage.style.left = pagePoint.x - dragImage.width / 2 + 'px';            dragImage.style.top = pagePoint.y - dragImage.height / 2 + 'px';            document.body.appendChild(dragImage);        }    }    else if (state === 'between') {        if (dragImage) {            var pagePoint = ht.Default.getPagePoint(e);            dragImage.style.left = pagePoint.x - dragImage.width / 2 + 'px';            dragImage.style.top = pagePoint.y - dragImage.height / 2 + 'px';            if (ht.Default.containedInView(e, g3d)) {                if (lastFaceInfo) {                    lastFaceInfo.data.s(lastFaceInfo.face + '.image', lastFaceInfo.oldValue);                    lastFaceInfo = null;                }                var faceInfo = g3d.getHitFaceInfo(e);                if (faceInfo) {                    faceInfo.oldValue = faceInfo.data.s(faceInfo.face + '.image');                    faceInfo.data.s(faceInfo.face + '.image', productId);                    lastFaceInfo = faceInfo;                }            }        }    }    else {        if (dragImage) {            if (lastFaceInfo) {                lastFaceInfo.data.s(lastFaceInfo.face + '.image', lastFaceInfo.oldValue);                lastFaceInfo = null;            }            if (ht.Default.containedInView(e, g3d)) {                var faceInfo = g3d.getHitFaceInfo(e);                if (faceInfo) {                    faceInfo.data.s(faceInfo.face + '.image', productId);                }            }            if (dragImage.parentNode) {                document.body.removeChild(dragImage);            }            dragImage = null;            productId = null;        }    }};

 今天就到这吧,将的内容有点多,涉及到的知识点也比較多,以下附上本次Demo的源码。感兴趣的朋友能够载下来看看,同一时候也欢迎大家留言质询。

 

转载地址:http://tkpzl.baihongyu.com/

你可能感兴趣的文章
【VUE】@click加上v-bind绑定切换类名及动画事件
查看>>
Microsoft发布新一代主机:Xbox One
查看>>
运维经验分享:关于系统运维监控的几点建议
查看>>
jQuery渐隐渐现字体发虚的问题
查看>>
[SDOI2008]烧水问题
查看>>
杂项之rabbitmq
查看>>
【转】关于大型网站技术演进的思考(十)--网站静态化处理—动静整合方案(2)...
查看>>
jQuery练习题HTML文件
查看>>
SQL注入原理
查看>>
MySQL 锁(lock与latch)
查看>>
python
查看>>
DataTable数据存入指定路径的Excel文件
查看>>
JS 验证
查看>>
【Lua】特性和一些基础语法
查看>>
Jaxb2 实现JavaBean与xml互转
查看>>
easyui的 getSelections 与 getSelected 对比区别
查看>>
算法:街区最短路径问题
查看>>
Linux下Samba的配置
查看>>
如何取消IE“已限制此网页运行可以访问计算机的脚本或ActiveX控件”
查看>>
Android 所遇问题(一)
查看>>