很多可视化编辑器都或多或少有一些拖拽功能,比如从一个List列表中拖拽一个节点到拓扑组件上进行建模,并且在拖拽的过程中鼠标位置下会附带一个被拖拽节点的缩略图,那么今天我们就来实现这样的拖拽效果。
首先我们需要创建一个ListView列表,在列表中加入图片信息,让List列表不那么单调,先来看看效果图。
接下来我们一步一步来是想这个ListView列表,先来解决下数据,在这里我就列举一两个:
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组件,在浏览器上看不到任何东西,那么接下来我们就该把我们定义的数据添加到ListView组件上了:
products.forEach(function(product){ var data = new ht.Data(); data.a(product); listView.dm().add(data); });
数据的添加是不是很简单,但是ListView组件上显示的内容默认是Data的name属性或displayName属性,在创建Data时,并没有对Data设置displayName或者name属性,所以这个时候在页面上看到的还是一个空的List组件,别急,我们可以在不设置displayName或name属性的情况下让组件显示效果图上的文本内容,请看:
listView.getLabel = function(data){ return data.a('ProductName') + ' - $' + data.a('UnitPrice').toFixed(2); };
嘿嘿,ListView组件提供了getLabel方法供用户重载来实现自定义显示文本内容,这下应该就可以显示文本内容了吧~
oh no~还是什么都没有,是不是还少了点什么呢~对了,忘记给ListView组件添加铺满浏览器的样式了,将厦门的样式添加到head标签中:
<style> html, body { padding: 0px; margin: 0px; } .main { margin: 0px; padding: 0px; position: absolute; top: 0px; bottom: 0px; left: 0px; right: 0px; } </style>
接下来指定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,重载ListView的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属性定义裁切区域,效果就是超出该裁切区域外的内容将被隐藏。现在矢量定义好了,我们只需要在ListView的getIcon()方法中返回我们定义的矢量名称就可以实现圆形图标了:
listView.getIcon = function(data){ return 'productIcon'; };
到这里,和效果图的效果就一模一样了~那么接下来我们就该创建3D拓扑组件了,来看看效果图:
很简单,就在3D拓扑中放两个正方体:
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和3D拓扑是两个独立的组件,我们该如何将这两个组件组合在一起呢?这时候,我想到了BorderPane组件,将List组件放在左边,将3D拓扑组件放在右边:
var borderPane = new ht.widget.BorderPane(); borderPane.setLeftView(listView, 350); borderPane.setCenterView(g3d);
看,成功将两个组件合并在一起了,离成功不远了。接下来就是今天的重头戏了,该如何实现拖拽List上的节点到3D拓扑上,并实现节点的图标吸附到3D拓扑的图元上呢,我给大家细细道来。
首先先来了解下ListView的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; } } };
如此在拖拽ListView节点时就能够看到有一个小图标一直跟着鼠标在移动。
OK,接下来该解决图元吸附功能,当鼠标拖拽ListView节点到3D拓扑上的图元是,将该节点的图标设置为图元当前面的贴图。
思路是这样子的:
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; } } };
今天就到这吧,将的内容有点多,涉及到HT for Web的知识点也比较多,下面附上本次Demo的源代码,感兴趣的朋友可以载下来看看,同时也欢迎大家留言质询。
相关推荐
1. 分析 `htForWeb3D.html` 的结构,理解如何引入HT for Web库和其他资源。 2. 查看 `js` 文件夹中的脚本,了解数据模型的构建和3D场景的初始化过程。 3. 深入研究 `img` 文件夹中的图片资源,理解它们在3D场景中的...
HT for Web是基于HTML5标准的企业应用图形界面一站式解决方案, 其包含通用组件、拓扑组件和3D渲染引擎等丰富的图形界面开发类库,提供了完全基于HTML5的矢量编辑器、拓扑编辑器及 3D场景编辑器等多套可视化设计工具...
HT for Web,通常简称为 HT,这是一个基于 JavaScript 开发的 WebGL 引擎。可用于 2D/3D 可视化开发,其核心文件只有一个,就是 ”ht.js”。在 index.html 中使用 script 标签进入后便可使用。 完全版本效果:...
6. **事件处理与交互**:HT for Web支持丰富的事件监听和处理机制,包括节点点击、拖拽、缩放等,使得用户交互功能的实现变得简单。 7. **动画效果**:内置的动画引擎使得HT for Web可以创建流畅的动态效果,无论是...
一直在找苦苦寻找一个Box2D的物理引擎javascript整合例子,发现 http://www.hightopo.com/blog/275.html 这篇文章的例子效果非常棒,通过HT for Web的3D引擎直观的呈现Box2D物理碰撞的实时运行效果,这么强大的3D...
【ht-for-web】是一款专为前端开发者设计的框架,主要用于创建和管理拓扑图以及页面布局。这个框架的强大之处在于它的灵活性和可定制性,使得开发者可以轻松地构建出复杂且交互性强的可视化应用。 在拓扑图制作方面...
HT for Web是一款基于HTML5的2D/3D图形和交互开发工具,广泛应用于数据可视化、模拟仿真、工业互联网等领域。通过这个标题,我们可以推测文章将探讨如何利用HT框架创建基本的Web动画效果。 【描述】虽然描述部分为...
HT for Web(Hierarchical Timeline for Web)是迪吉多科技公司(Digipede Technologies)开发的一个强大的Web可视化工具,它基于HTML5和JavaScript,提供了一种高效的方式来构建交互式和实时的Web应用。HT for Web...
HT for Web是一款强大的Web可视化工具,它允许开发者通过矢量图形来构建交互式的Web应用程序。在HTML5中,File API提供了处理文件和数据的能力,包括读取本地文件、监控文件上传进度等功能。 这篇博客(博文链接:...
HT FOR WEB 一套强大的基于 WebGL 技术的 3D 图形引擎,编辑器下,左边菜单可自定义控制多个不同的菜单操作。
上回我们用 ht.widget....HT for Web 提供了工具条组件类 ht.widget.Toolbar,工具条上的元素可为原生的 html 元素, 也支持 ht 提供的如 ht-form.js 的表单插件中的组件,并内置提供了按钮、单选按钮、复选框等组件。
HT-for-web 的概述、开发类库、开发工具、运行环境、函数简写、模型、设计模式、类包层次、工具类、数据类型、数据容器、选择模型、组件、配置、图片、动画、属性组件、列表组件、树形组件、表格组件、工具条组件、...
Hightopo Master,简称HT for Web,是一个强大的图形界面组件库,旨在帮助开发者轻松创建桌面和移动终端上的企业级应用。它以HTML5为基础,无需担心跨平台兼容性问题,同时处理触屏手势交互等复杂功能,极大地简化了...
ht.js开发实例最新版本,通过这个版本开发html5工业设计智慧平台,经过在网上寻找发现 http://www.hightopo.com/blog/275.html 这篇文章的例子效果非常棒,通过HT for Web的3D引擎直观的呈现Box2D物理碰撞的实时运行...
这些工具通常包含一系列的绘图组件,如线条、形状、文字等,帮助用户轻松构建和编辑拓扑结构。例如,JTopo 就是一个流行的选择,它是一个开源的 JavaScript 库,专门用于创建网络拓扑图。JTopo 提供了丰富的API和...
此外,HT 提供了一系列预定义的图形组件和交互模式,如节点、连接线、拖放、缩放和平移等,开发者无需从零开始编写图形代码,只需配置相应的属性和事件即可。这极大地提高了开发效率,降低了学习曲线。 在电信领域...
本资料包包含了与HT1622相关的两个实例程序(HT1622.c和HT1622_2.c)以及一份详尽的应用笔记(ht1622应用笔记.pdf),旨在为初学者提供实用的参考和指导。 HT1622是一款8位并行接口的LCD驱动器,能够驱动多达40x4或...
此外,ht.js可能是一个用于构建3D场景的JavaScript库,它为开发者提供了更高级的工具和函数,简化了WebGL的编程复杂性。通过这个库,开发者可以轻松地添加交互式元素,如点击某个货位获取详细信息,或者拖放货物进行...
【标题】"hightopo.zip" 是一个包含 HT for Web 库相关资源的压缩文件,这个库是一个专注于 HTML5 的图形界面组件...通过深入学习和应用这些组件和库,开发者能够提升项目开发的效率,同时保证应用的质量和用户体验。