`
xhload3d
  • 浏览: 201327 次
社区版块
存档分类
最新评论

HT for Web列表和3D拓扑组件的拖拽应用

阅读更多

很多可视化编辑器都或多或少有一些拖拽功能,比如从一个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的源代码,感兴趣的朋友可以载下来看看,同时也欢迎大家留言质询。

 

  • 大小: 91.9 KB
  • 大小: 43.6 KB
  • 大小: 52 KB
  • 大小: 95.8 KB
  • 大小: 86.9 KB
  • 大小: 183.7 KB
  • 大小: 182.2 KB
  • 大小: 249.7 KB
4
2
分享到:
评论

相关推荐

    HT for Web 入门手册

    HT for Web是基于HTML5标准的企业应用图形界面一站式解决方案, 其包含通用组件、拓扑组件和3D渲染引擎等丰富的图形界面开发类库,提供了完全基于HTML5的矢量编辑器、拓扑编辑器及 3D场景编辑器等多套可视化设计工具...

    HT for Web Demo

    https://blog.csdn.net/shenjuntao520/article/details/100155817#comments_15044861 文章相关素材

    HT FOR WEB 自定义图标菜单

    HT FOR WEB 一套强大的基于 WebGL 技术的 3D 图形引擎,编辑器下,左边菜单可自定义控制多个不同的菜单操作。

    HT for Web - Box2d

    一直在找苦苦寻找一个Box2D的物理引擎javascript整合例子,发现 http://www.hightopo.com/blog/275.html 这篇文章的例子效果非常棒,通过HT for Web的3D引擎直观的呈现Box2D物理碰撞的实时运行效果,这么强大的3D...

    HT for Web基础动画介绍

    NULL 博文链接:https://xhload3d.iteye.com/blog/2232348

    HT for Web 3d引擎示例加api说明文档

    HT for Web,通常简称为 HT,这是一个基于 JavaScript 开发的 WebGL 引擎。可用于 2D/3D 可视化开发,其核心文件只有一个,就是 ”ht.js”。在 index.html 中使用 script 标签进入后便可使用。 完全版本效果:...

    基于HT for Web矢量实现HTML5上传文件进度条

    NULL 博文链接:https://xhload3d.iteye.com/blog/2217955

    基于HT for Web矢量实现HTML5文件上传进度条

    NULL 博文链接:https://xhload3d.iteye.com/blog/2217934

    ht-for-web

    前端框架:ht-for-web,专用于拓扑图制作和页面布局。

    快速开发基于 HTML5 网络拓扑图应用--入门篇(四)

    上回我们用 ht.widget....HT for Web 提供了工具条组件类 ht.widget.Toolbar,工具条上的元素可为原生的 html 元素, 也支持 ht 提供的如 ht-form.js 的表单插件中的组件,并内置提供了按钮、单选按钮、复选框等组件。

    hightopo HT for Web(hightopo.zip)

    HT for Web 您可以轻松构建现代化的,跨桌面和移动终端的企业应用,无需担忧跨平台兼容性,及触屏手势交互等棘手问题

    ht.js html5 canvas2d3d教程手册

    ht.js开发实例最新版本,通过这个版本开发html5工业设计智慧平台,经过在网上寻找发现 http://www.hightopo.com/blog/275.html 这篇文章的例子效果非常棒,通过HT for Web的3D引擎直观的呈现Box2D物理碰撞的实时运行...

    HT1622应用程序+应用笔记

    HT1622 LCD驱动芯片2个实例程序附加一个通用程序,基于NXP芯片MC9S08DZ60配置,其他MCU做必要基础配置即可,相信对初次使用者定有很大帮助!

    基于 HTML5 快速构建拓扑图1

    电信网管的网络拓扑图、电力的电网拓扑图、工业控制的监控图、工作流程图、思维脑图等等都可以用 HTML5 的图形化界面来完成,所有这些简称为拓扑图。使用 HT 会让你的开发变得更加快速,快来玩玩吧!

    HTML5 WebGL 3D 仓储管理系统

    基于HTML5 WebGL 3D仓储系统Demo,使用范围还很广!ht.js评论留言邮箱地址,看到留言会发送至邮箱

    ht.rar_3D HT_3d heat_3d heat _fdm 3d_heat fdm

    3D heat transfer using FDM

    HT1621程序应用实例

    HT1621程序应用实例,模块化 程序 HT1621 程序 应用 实例 代码

    HT 手册-07311656.pdf

    ht-for-web 开发支持手册

    HT6015 HT7038三相方案原理图

    HT7038原理图

Global site tag (gtag.js) - Google Analytics