索引
HT
提供了基于WebGL的3D
技术的图形组件ht.graph3d.Graph3dView
,
WebGL
基于OpenGL ES 2.0图形接口,因此WebGL
属于底层的图形API
接口,
二次开发还是有很高的门槛,HT
的Graph3dView
组件通过对WebGL
底层技术的封装,与HT
其他组件一样,
基于HT
统一的DataModel
数据模型来驱动图形显示,极大降低了3D
图形技术开发的门槛,在熟悉HT
数据模型基础上,
一般程序员只需要1
个小时的学习即可上手3D
图形开发。
同时HT
提供了强大的完全基于HTML5
技术3D
图形建模设计器,用户无需编码即可快速可视化搭建各种3D
场景,
可以说HT
的3D
开发模式完全打破了传统3D
开发模式,绝大部分应用不再需要依赖精通3ds Max
或Maya的专业3D
设计师来建模,
也不需要整合Unity3d等引擎做图形渲染,HT
一站式的提供了从建模到渲染,包括和2D
组件呈现和数据融合的一站式解决方案。
WebGL
技术已被大部分最新浏览器支持,caniuse.com/webgl网站维护着最新桌面和移动浏览器对WebGL
支持情况。
通过get.webgl.org可检测访问的浏览器是否支持WebGL
。
目前Chrome
、Firefox
、Safari
和Opera
的桌面也移动终端版本都已经支持WebGL
标准,
采用iOS
系统需要iOS8
及以上版本,采用IE
浏览器须IE11
及以上版本才支持WebGL
,
不管选择哪种类型浏览器,我们建议尽量采用最新版本。
如果你一定要使用IE6
,IE7
和IE8
等老版IE浏览器,或者因采用HT for Web 3D
,而老机器无法升级到IE11
,则可以考虑安装
Google Chrome Frame插件,
在页面嵌入以下Tag
代码片段,该页面就会采用Chrome
来渲染。
<meta http-equiv="X-UA-Compatible" content="chrome=1">
使用Google Chrome Frame
还需要注意一下几点:
Google Chrome Frame
不支持直接从本地local file
方式打开页面,必须把页面部署到Web
服务器发布方式打开Google Chrome Frame
不支持64位的浏览器:Currently, 64-bit versions of IE are not supported. It's worth pointing out that 32-bit IE is the default on 64-bit Windows 7.Google Chrome Frame
不支持iframe
方式: At this point ChromeFrame only supports the meta tag detection on top level URLs.可采用嵌入OBJECT
元素的解决方案,绕开Google Chrome Frame
不支持iframe
的问题
<OBJECT ID="ChromeFrame" WIDTH=500 HEIGHT=500 CODEBASE="http://yourdomain/yourproject/"
CLASSID="CLSID:E0A900DF-9611-4446-86BD-4B1D47E7DB2A">
<PARAM NAME="src" VALUE="http://yourdomain/yourproject/">
<embed ID="ChromeFramePlugin" WIDTH=500 HEIGHT=500 NAME="ChromeFrame"
SRC="http://yourdomain/yourproject/" TYPE="application/chromeframe">
</embed>
</OBJECT>
Google Chrome Frame
将于2014
年1
月停止支持和更新,目前Google Chrome Frame
以发展到31
的版本,
这个版本已满足HT
的2D
和3D
所需的Canvas
功能,因此HT
的客户可以放心采用Google Chrome Frame
解决老IE
问题。
其他问题可参考Google Chrome Frame
的Developer Guide
和Troubleshooting
HT
的三维坐标系由x
,y
和z
三个轴线构成,x
轴正方向朝右,y
轴正方向朝上,z
轴正方向朝向屏幕外。
HT
系统的旋转采用右手螺旋法则。
Graph3dView
的3D
坐标系与GraphView
的2D
坐标系既有关联又有差异,2D
坐标系的x
轴与3D
坐标系的x
轴对应,
2D
坐标系的y
轴与3D
坐标系的z
轴对应,2D
坐标系的xy
屏幕面相当于3D
坐标系的xz
面。
例如Node#getPosition()
返回{x: 100, y: 200}
,则代表:
2D
坐标系x
轴为100
,y
轴为200
3D
坐标系x
轴为100
,z
轴为200
例如Node#getSize()
返回{width: 300, height: 400}
,则代表:
2D
坐标系x
轴上长度300
,y
轴上长度400
3D
坐标系x
轴上长度300
,z
轴上长度400
3D
坐标系的y
轴则是与2D
坐标系没有关联的新轴,ht.Node
上增加了getElevation()
和setElevation(elevation)
函数,
控制Node
图元中心位置所在3D
坐标系的y
轴位置。同时增加了getTall()
和setTall(tall)
函数,控制Node
图元在y
轴的长度。
为了避免2D
和3D
坐标系的混乱,以及设置3D
图元位置大小的方便,HT
为ht.Node
图元增加了以下新函数:
setPosition3d(x, y, z)|setPosition3d([x, y, z])
,可传入x, y, z
三个参数,或传入[x, y, z]
的数组getPosition3d()
的新函数,返回[x, y, z]
数组值,即[getPosition().x, getElevation(), getPosition().y]
setSize3d(x, y, z)|setSize3d([x, y, z])
,可传入x, y, z
三个参数,或传入[x, y, z]
的数组getSize3d()
的新函数,返回[x, y, z]
数组值,即[getWidth(), getTall(), getHeight()]
ht.Node
在2D
坐标系下由getRotation()
和setRotation(rotation)
函数控制旋转,该参数对应于3D
坐标系下沿y
轴的负旋转值。
同时3D
坐标系下增加了rotationX
和rotationZ
两个分别沿着x
轴和z
轴的新旋转变量,同时增加以下新函数:
setRotationY(y)
设置沿y
轴旋转弧度,相当于setRotation(-y)
getRotationY()
获取沿y
轴旋转弧度,相当于-getRotation()
setRotation3d(x, y, z)|setRotation3d([x, y, z])
,可传入x, y, z
三个参数,或传入[x, y, z]
的数组getRotation3d()
的新函数,返回[x, y, z]
数组值,即[getRotationX(), -getRotation(), getRotationZ()]
对于旋转还有个很重要的参数rotationMode
,该参数通过getRotationMode()|setRotationMode('xzy')
进行设置,
旋转的先后顺序会影响最终效果,该参数用于指定旋转的先后顺序,默认值为xzy
,用户可通过设置以下六种参数改变旋转顺序模式:
xyz
:先进行x
轴旋转,再进行y
轴旋转,最后进行z
轴旋转。xzy
:先进行x
轴旋转,再进行z
轴旋转,最后进行y
轴旋转。yxz
:先进行y
轴旋转,再进行x
轴旋转,最后进行z
轴旋转。yzx
:先进行y
轴旋转,再进行z
轴旋转,最后进行x
轴旋转。zxy
:先进行z
轴旋转,再进行x
轴旋转,最后进行y
轴旋转。zyx
:先进行z
轴旋转,再进行y
轴旋转,最后进行x
轴旋转。HT
对常用函数有不少简写方式,例如getDataModel()|dm()
,getSelectionModel()|sm()
等,同样3D
也有不少便捷的简写函数:
setPosition3d(x, y, z)|setPosition3d([x, y, z])
可简写为p3(x, y, z)|p3([x, y, z])
getPosition3d()
可简写为p3()
setSize3d(x, y, z)|setSize3d([x, y, z])
可简写为s3(x, y, z)|s3([x, y, z])
getSize3d()
可简写为s3()
setRotation3d(x, y, z)|setRotation3d([x, y, z])
可简写为r3(x, y, z)|r3([x, y, z])
getRotation3d()
可简写为r3()
3D投影是一种将三维空间的点映射到二维平面的算法,
既3D
空间的内容投影到2D
屏幕坐标的过程,不同的投影算法会最终产生不同的屏幕内容显示效果,
HT
支持透视投影Perspective Projection
和正交投影Orthographic Projection这两种最主常用的投影算法。
Graph3dView
组件默认采用透视投影,通过Graph3dView#setOrtho(true)
可切换到正交投影。
透视投影是为了获得接近真实三维物体的视觉效果而在二维的纸或者画布平面上绘图或者渲染的一种方法,它也称为透视图。 透视使得远的对象变小,近的对象变大,平行线会出现先交等更更接近人眼观察的视觉效果。
如上图所示,透视投影最终显示到屏幕上的内容只有截头锥体( View Frustum )部分的内容,
因此Graph3dView
提供了eye
, center
, up
, far
,near
,fovy
和aspect
参数来控制截头锥体的具体范围:
getEye()|setEye([x, y, z])
,决定眼睛(或Camera
)所在位置,默认值为[0, 300, 1000]
getCenter()|setCenter([x, y, z])
,决定目标中心点(或Target
)所在位置,默认值为[0, 0, 0]
getUp()|setUp([x, y, z])
,决定摄像头正上方向,该参数一般较少改动,默认值为[0, 1, 0]
getNear()|setNear(near)
,决定近端截面位置,默认值为10
getFar()|setFar(far)
,决定远端截面位置,默认值为10000
getFovy()|setFovy(fovy)
,fovy决定垂直方向的视觉张角弧度,默认值为Math.PI/4
getAspect()|setAspect(aspect)
,决定截头锥体的宽高比,该参数默认自动根据屏幕的宽高比决定,一般不需要设置。near
和far
虽可根据实际场景任意调节,但建议在可接受的范围内,尽量让near
和far
越接近越好,
有助于避免Z-fighting的精度问题。
正交投影也叫正交视图,在这种投影方式下,不管远近物体看起来都是同样大小,屏幕成像让人感觉与人眼观察效果不一样。 正交投影在建模过程很有用,它提供了对场景更“技术”的视觉,让它易于绘制和判断比例。
正交投影具有和透视投影一样的大部分参数,但没有fovy
参数,取而代之的是orthoWidth
参数:
isOrtho()|setOrtho(ortho)
,决定是否为正交投影,默认值为false
getOrthoWidth()|setOrthoWidth(orthoWidth)
,决定宽度,即left
和right
之间的距离,默认值为2000
HT
提供了多种基础形体类型供用户建模使用,不同于传统的3D建模方式,HT
的建模核心都是基于API
的接口方式,
通过HT
预定义的图元类型和参数接口,进行设置达到三维模型的构建,以下章节将介绍预定义的3D模型类型及设置参数,
另外可参考建模手册和
OBJ手册介绍的更多自定义扩展模型方式。
六面体是由六个面形成的立方体,是HT
系统中最常被使用的基本图元类型,默认当构建一个ht.Node
对象时显示的就是一个六面体,
六个面的整体参数可以通过style
属性的all.*
控制,例如all.color
设置为red
,那么所有六个面默认颜色都会变成红色,
如果需要具体面独立设置,则可以通过left.*|right.*|top.*|bottom.*|front.*|back.*
具体面参数控制,
例如left.color
设置为blue
,那么左侧面将显示为红色,如果left.color
设置为空,则HT
会采用all.color
的值。
all.light
:默认值为true
,六面是否受光线影响,受光线影响时正面看时最亮,侧面看时变暗all.visible
:默认值为true
,六面是否可见,该参数不会影响附属部件all.color
:默认值为#3498DB
,六面颜色all.image
:默认值为undefined
,六面贴图,优先级高于all.color
all.blend
:默认值为undefined
,六面染色颜色,优先级高于all.color
,如果有贴图时,则对贴图染色all.opacity
:默认值为undefined
,六面透明度,值范围0~1
,一般有透明度时需要将all.transparent
设置为true
all.reverse.flip
:默认值为false
,六面的反面是否显示正面的内容all.reverse.color
:默认值为#868686
,六面的反面颜色,即立方体内部面颜色all.reverse.cull
:默认值为false
,六面的反面是否可见,即立方体内部面是否显示,一般六面闭合立方体,可不显示以提高性能all.transparent
:默认值为false
,六面是否透明,若color|image|opacity
属性出现透明区域情况下,一般需设置为true
all.discard.selectable
:默认值为true
,代表贴图透明度低到被剔除的部分也能点击选中,可设置为false
则被剔除部分不可选中默认情况下贴图会将整个图片填充满对应的面,但很多情况下贴图需要偏移一定位置,有时地板砖需要Tile
方式平铺,有时贴图需要翻转,
甚至有时贴图的布局需要动态变化以达到流动等特效,这种情况下就需要定制UV Mapping,
通过uv
参数告诉HT
如何将图片根据需要自定义贴到面上:
all.uv.offset
:默认值为undefined
,六面贴图的uv
偏移,格式为[0.5, 0.5]
,分别为水平和垂直方向的偏移量all.uv.scale
:默认值为undefined
,六面贴图的uv
缩放,格式为[3, 2]
,分别为水平和垂直的贴图倍数all.uv
:默认值为undefined
,六面自定义uv
参数,下面为几种常见需求的自定义uv
参数供参考[0,0, 0,1, 1,1, 1,0]
90
度:[1,0, 0,0, 0,1, 1,1]
90
度:[0,1, 1,1, 1,0, 0,0]
180
度:[1,1, 1,0, 0,0, 0,1]
180
度:[0,1, 0,0, 1,0, 1,1]
[0,1, 0,0, 1,0, 1,1]
[1,0, 1,1, 0,1, 0,0]
HT
在GraphView
的2D
图形上,呈现各种图形是通过style
的shape
属性决定,类似的HT
在3D
上提供了shape3d
属性,
预定义了多种3D
的形体。shape3d
的默认值为undefined
,图元显示为上章节介绍的六面立体图形,当shape3d
指定值时,
则显示为shape3d
指定的形体,其余的具体参数通过shape3d.*
进行设置:
shape3d
:默认值为undefined
,为空时显示为六面立方体,其他可选值为:box
:立方体,不同于默认的六面体,立方体类型的六个面颜色和贴图只能相同,绘制性能比默认六面体高 sphere
:球体,可通过shape3d.side
分成多片,结合shape3d.side.from
和shape3d.side.to
可形成半球体等 cone
:锥体,可通过shape3d.side
形成三角锥、四角锥等形状torus
:圆环,可通过shape3d.side
分成多片,结合shape3d.side.from
和shape3d.side.to
可形成半圆环等cylinder
:圆柱,可通过shape3d.top.*
和shape3d.bottom.*
可控制顶面和底面的参数star
:星形体,可通过shape3d.top.*
和shape3d.bottom.*
可控制顶面和底面的参数rect
:矩形体,可通过shape3d.top.*
和shape3d.bottom.*
可控制顶面和底面的参数roundRect
:圆矩形体,可通过shape3d.top.*
和shape3d.bottom.*
可控制顶面和底面的参数triangle
:三角形体,可通过shape3d.top.*
和shape3d.bottom.*
可控制顶面和底面的参数rightTriangle
:直角三角形体,可通过shape3d.top.*
和shape3d.bottom.*
可控制顶面和底面的参数parallelogram
:平行四边形体,可通过shape3d.top.*
和shape3d.bottom.*
可控制顶面和底面的参数trapezoid
:梯形体,可通过shape3d.top.*
和shape3d.bottom.*
可控制顶面和底面的参数shape3d.color
:默认值为#3498DB
,3d
图形整体颜色shape3d.top.color
:默认值为undefined
,3d
图形顶面颜色shape3d.bottom.color
:默认值为undefined
,3d
图形底面颜色shape3d.from.color
:默认值为undefined
,3d
图形起始面颜色shape3d.to.color
:默认值为undefined
,3d
图形结束面颜色shape3d.image
:默认值为undefined
,3d
图形整体贴图shape3d.top.image
:默认值为undefined
,3d
图形顶面贴图shape3d.bottom.image
:默认值为undefined
,3d
图形底面贴图shape3d.from.image
:默认值为undefined
,3d
图形起始面贴图shape3d.to.image
:默认值为undefined
,3d
图形结束面贴图shape3d.light
:默认值为true
,3d
图形是否受光线影响shape3d.side
:默认值为0
,决定3d
图形显示为几边型,为0
时显示为平滑的曲面效果shape3d.side.from
:默认值为undefined
,决定3d
图形起始边位置shape3d.side.to
:默认值为undefined
,决定3d
图形结束边位置shape3d.visible
:默认值为true
,决定3d
图形是否可见,该参数不影响label
,note
和icons
等其他部分元素shape3d.from.visible
:默认值为true
,决定3d
图形起始面是否可见shape3d.to.visible
:默认值为true
,决定3d
图形结束面是否可见shape3d.top.visible
:默认值为true
,决定3d
图形顶面是否可见shape3d.bottom.visible
:默认值为true
,决定3d
图形底面是否可见shape3d.torus.radius
:默认值为0.17
,决定3d圆环形管半径shape3d.resolution
:默认值为24
,决定3d
图形精确度,和side
类似但决定不同的方向的分段,数值越大越均匀但影响性能shape3d.blend
:默认值为undefined
,决定3d
图形的染色shape3d.opacity
:默认值为undefined
,决定3d
图形的透明度,值范围0~1
shape3d.reverse.flip
:默认值为false
,决定3d
图形的反面是否显示正面的内容shape3d.reverse.color
:#868686
,决定3d
图形的反面颜色shape3d.reverse.cull
:默认值为false
,决定3d
图形的反面是否显示,隐藏背面可提高性能shape3d.transparent
:默认值为false
,决定3d
图形是否透明shape3d.uv.offset
:默认值为undefined
,决定3d
图形整体贴图的uv
偏移,格式为[0.5, 0.5]
shape3d.uv.scale
:默认值为undefined
,决定3d
图形整体贴图的uv
缩放,格式为[3, 2]
shape3d.top.uv.offset
:默认值为undefined
,决定3d
图形顶面贴图的uv
偏移,格式为[0.5, 0.5]
shape3d.top.uv.scale
:默认值为undefined
,决定3d
图形顶面贴图的uv
缩放,格式为[3, 2]
shape3d.bottom.uv.offset
:默认值为undefined
,决定3d
图形底面贴图的uv
偏移,格式为[0.5, 0.5]
shape3d.bottom.uv.scale
:默认值为undefined
,决定3d
图形底面贴图的uv
缩放,格式为[3, 2]
shape3d.from.uv.offset
:默认值为undefined
,决定3d
图形起始面贴图的uv
偏移,格式为[0.5, 0.5]
shape3d.from.uv.scale
:默认值为undefined
,决定3d
图形起始面贴图的uv
缩放,格式为[3, 2]
shape3d.to.uv.offset
:默认值为undefined
,决定3d
图形结束面贴图的uv
偏移,格式为[0.5, 0.5]
shape3d.to.uv.scale
:默认值为undefined
,决定3d
图形结束面贴图的uv
缩放,格式为[3, 2]
shape3d.discard.selectable
:默认值为true
,整体贴图透明度低到被剔除的部分也能选中,设为false
则被剔除部分不可选shape3d.top.discard.selectable
:默认值为true
,顶部贴图透明度低到被剔除的部分也能选中,设为false
则被剔除部分不可选shape3d.bottom.discard.selectable
:默认值为true
,底部贴图透明度低到被剔除的部分也能选中,设为false
则被剔除部分不可选shape3d.from.discard.selectable
:默认值为true
,起始面贴图透明度低到被剔除的部分也能选中,设为false
则被剔除部分不可选shape3d.to.discard.selectable
:默认值为true
,结束面贴图透明度低到被剔除的部分也能选中,设为false
则被剔除部分不可选ht.Edge
在GraphView
的拓扑组件中作为连接节点的连线是重要的图元类型,同样在Graph3dView
组件中依然具备2D
连线的展示功能,
并且实现空间的三维连线效果,同时也增加了些针对3D
的连线参数,连线在三维空间呈现默认是非立体方式,
通过设置style
为cylinder
可呈现为管状的立体线效果,构建连线的常用参数说明如下:
edge.color
:连线颜色edge.width
:连线宽度edge.gradient.color
:连线渐进色,目前仅在3D
上连线的非立体方式下支持,会在连线的target
端呈现此渐进色edge.source.t3
:连线source
端偏移,[tx, ty, tz]
格式,默认为空edge.target.t3
:连线target
端偏移,[tx, ty, tz]
格式,默认为空当edge.type
为points
类型时,设置到edge.points
的拐点参数兼容2D
的{x: 100, y: 100}
的JSON
格式,
同时3D
上引入新的参数e
代表elevation
的海拔高度,因此3D
支持{x: 10, y: 20, e: 30}
的拐点参数格式,
此拐点代表在x
轴10
,y
轴30
,z
轴20
的位置点。
当style
为cylinder
时连线呈现立体管线效果,这时候控制连线显示效果的参数都在shape3d.*
上,
同时增加了repeat.uv.length
参数,该参数默认为空,如果设置了长度值,则贴图会根据连线长度自动调节连线方向上的贴图倍数。
参见形状手册的空间管线章节
参见形状手册
brightness
:默认值为undefined
,整体图形在3D
下的亮度,大于1
代表更亮,小于1
代表更暗,1
则代表不变化opacity
:默认值为undefined
,整体图形在3D
下的透明度,值范围0~1
transparent.mask
:默认值为false
,该属性能使得图元不绘制显示在界面上,但依然可以点击选中2D
的label.*
文字属性对于3D
依然试用,3D
也支持内置的第二个label2.*
文字,同时增加了以下针对3D
空间摆放以及呈现特性的属性参数:
label.face
: 默认值为front
,文字在3D
下的朝向,可取值left|right|top|bottom|front|back|center
label.t3
: 默认值为undefined
,文字在3D
下的偏移,格式为[x,y,z]
label.r3
: 默认值为undefined
,文字在3D
下的旋转,格式为[rotationX,rotationY,rotationZ]
label.rotationMode
:默认值为xzy
,文字在3D
下的沿三个轴旋转先后顺序,可取值xyz|xzy|yxz|yzx|zxy|zyx
label.light
: 默认值为false
,文字在3D
下是否受光线影响label.blend
: 默认值为undefined
,文字在3D
下染色颜色label.opacity
: 默认值为undefined
,文字在3D
下的透明度,值范围0~1
label.reverse.flip
: 默认值为false
,文字在3D
下反面是否显示正面的内容label.reverse.color
: 默认值为#868686
,文字在3D
下反面的颜色label.reverse.cull
: 默认值为false
,文字在3D
下反面是否显示,隐藏背面可提高性能label.transparent
: 默认值为false
,文字在3D
下是否透明label.autorotate
: 默认值为false
,文字在3D
下是否自动朝向眼睛的方向,可设为true
或y
,y
代表沿着y
轴转动label.texture.scale
:默认值为2
,该值代表内存实际生成贴图的倍数,不宜设置过大否则影响性能,
参见位置手册例子2D
的note.*
标注属性对于3D
依然试用,3D
也支持内置的第二个note.*
标注,同时增加了以下针对3D
空间摆放以及呈现特性的属性参数:
note.face
:默认值为front
,标注在3D
下的朝向,可取值left|right|top|bottom|front|back|center
note.t3
:默认值为undefined
,标注在3D
下的偏移,格式为[x,y,z]
note.r3
:默认值为undefined
,标注在3D
下的旋转,格式为[rotationX,rotationY,rotationZ]
note.rotationMode
:默认值为xzy
,标注在3D
下的沿三个轴旋转先后顺序,可取值xyz|xzy|yxz|yzx|zxy|zyx
note.light
:默认值为false
,标注在3D
下是否受光线影响note.blend
:默认值为undefined
,标注在3D
下染色颜色note.opacity
:默认值为undefined
,标注在3D
下的透明度,值范围0~1
note.reverse.flip
:默认值为false
,标注在3D
下反面是否显示正面的内容note.reverse.color
:默认值为#868686
,标注在3D
下反面的颜色note.reverse.cull
:默认值为false
,标注在3D
下反面是否显示,隐藏背面可提高性能note.transparent
:默认值为false
,标注在3D
下是否透明note.autorotate
:默认值为false
,标注在3D
下是否自动朝向眼睛的方向,可设为true
或y
,y
代表沿着y
轴转动note.texture.scale
:默认值为2
,该值代表内存实际生成贴图的倍数,不宜设置过大否则影响性能,
参见位置手册例子icons
是HT
图元扩展上的一个非常有用的属性,利用其可以为图元增加任意多得图标附属部件。
icons
内容为style
上的icons
属性json对象,该对象的结构示例代码如下:
data.setStyle('icons', {
whateverName1: {
position: 17,
direction: 'north', // east, west, south, north
gap: 1,
names: ['icon1', 'icon2', 'icon3']
},
whateverName2: {
position: 20,
width: 16,
height: 16,
name: ['icon5']
},
whateverName3: ...
]);
icons
可分为很多组,其中whateverName*
可理解为组的名称,这个名称HT
没有显示也不用于界面呈现效果,用户可以根据自己需要进行命名管理。
直接设置icons对象会冲掉已经设置的图标的副作用,为此HT
提供了Data#addStyleIcon(name, json)
和Data#removeStyleIcon(name)
的函数,
便于控制管理图标增删,因此以上代码也可通过下面代码实现:
data.addStyleIcon('whateverName1', {
position: 17,
direction: 'north', // east, west, south, north
gap: 1,
names: ['icon1', 'icon2', 'icon3']
});
data.addStyleIcon('whateverName2', {
position: 20,
width: 16,
height: 16,
name: ['icon5']
});
从以上示例代码可发现每组图标可为单个图标如whateverName2
定义了icon5
图标,也可为多个图标的排列,
如whateverName1
的['icon1', 'icon2', 'icon3']
。而json
的其他参数为如何摆放和显示这些图标相关:
names
: 包含多个字符串的数组,每个字符串对应一张图片或矢量(通过ht.Default.setImage
注册)visible
:表示该组图片是否显示for3d
:代表该组图片仅用于Graph3dView
的组件显示,不显示于GraphView
组件direction
: 值为west
、east
、north
、south
之一,指定icons
的排列方向,默认值为east
keepOrien
: 旋转Edge
时,icons
会自动调整方向以保持最好的阅读效果(比如文字),此属性为true
表示禁止自动调整方向gap
: 指定同一组中得多个图标之间的距离width
: 指定每个icon
的宽度,默认根据注册图片时的宽度height
: 指定每个icon
的高度,默认根据注册图片时的高度face
:默认值为front
,图标在3D
下的朝向,可取值left|right|top|bottom|front|back|center
t3
:默认值为undefined
,图标在3D
下的偏移,格式为[x,y,z]
r3
:默认值为undefined
,图标在3D
下的旋转,格式为[rotationX,rotationY,rotationZ]
rotationMode
:默认值为xzy
,图标在3D
下的沿三个轴旋转先后顺序,可取值xyz|xzy|yxz|yzx|zxy|zyx
light
:如果shape3d
为空,则默认值为false
,否则默认为true
,图标在3D
下是否受光线影响blend
:默认值为undefined
,图标在3D
下染色颜色,opacity
:默认值为undefined
,图标在3D
下的透明度,值范围0~1
reverseFlip
:默认值为false
,图标在3D
下反面是否显示正面的内容reverseColor
:默认值为#868686
,图标在3D
下反面的颜色reverseCull
:默认值为false
,图标在3D
下反面是否显示,隐藏背面可提高性能transparent
:默认值为false
,图标在3D
下是否透明autorotate
:默认值为false
,图标在3D
下是否自动朝向眼睛的方向discardSelectable
:默认值为true
,代表贴图透明度低到被剔除的部分也能点击选中,可设置为false
则被剔除部分不可选中textureScale
:默认值为2
,该值代表内存实际生成贴图的倍数,不宜设置过大否则影响性能,
参见位置手册例子shape3d
:该属性指定显示为3d
模型的图标效果,如果设置了该属性则忽略names
、width
和height
属性,
参见位置手册例子position
: 指定icons
的位置,支持的枚举值对应位置如下:
34 35
1 | 2 38 3 39 4 | 5
----6-------40-----7-----41-------8----
9 | 10 42 11 43 12 | 13
| |
| 44 |
14 15 16 45 46 17 47 48 18 19 20
| 49 |
| |
21 | 22 50 23 51 24 | 25
----26------52-----27-----53------28---
29 | 30 54 31 55 32 | 33
36 37
吸附功能对于设计有层次关系的模型非常方便,例如设备面板吸附上设备机框,设备端口吸附上设备面板,这样从机框-面板-端口的层次关系吸附,
使得用户拖动整体机框时所有这个层次下的图元都会跟随移动。对于3D
的场景下,吸附的概念更进一步延伸,当机框在三维空间进行任意位置偏移
以及任意角度旋转时,所有吸附的相关图元都会正确的跟随平移,并做出相应位置对应的旋转,以达到整体设备各个图形部分保持物理相对位置一致。
Node#getHost()
和Node#setHost(node)
获取和设置吸附的图元对象Node#getAttaches()
返回目前吸附到该图元的所有对象,返回ht.List
链表对象,无吸附对象时返回空Node#isHostOn(node)
判断该图元是否吸附到指定图元对象上Node#isLoopedHostOn(node)
判断该图元是否与指定图元相互形成环状吸附,例如A
吸附B
,B
吸附C
,C
又吸附回A
,则A
,B
和C
图元相互环状吸附HT
显示3D
视图的组件为ht.graph3d.Graph3dView
,其中ht.graph3d
为和3D
组件相关的类包,Graph3dView
为呈现3D
视图的组件类。
可类比于2D
视图组件ht.graph.GraphView
,GraphView
和Graph3dView
两者可共享同一数据模型DataModel
,
在2D
和3D
的API设计上HT
保持了很多一致性。
Graph3dView
的界面DOM
结构是由最底层的DIV
元素,以及渲染层CANVAS
元素组合而成,通过getView()
可得到最底层的DIV
元素,
通过getCanvas()
可得到渲染层CANVAS
元素,HT
默认的交互事件都是添加在底层DIV
元素上,
用户做自定义交互扩展也可通过直接对getView()
返回的元素添加事件监听的方式。
颜色参数在HTML
领域是比较灵活,可为#F0F1F2
的十六进制格式,可为字符串名red
和black
等,可为rgb(255,128,32)
格式,
可为rgba(255,128,32,0.5)
包含透明度的格式。然而WebGL
的API接口对于颜色参数的格式,一般要求rgba四个参数的取值范围为0~1
的数字格式,
因此Graph3dView
组件上的颜色参数默认值为[r,g,b,a]数字数组格式,而考虑到DataModel
上的Data
数据与2D
兼容性,
HT
内部会自动对颜色参数进行转换,因此data.s('all.color','red')
与data.s('all.color',[1,0,0,1])
的方式都是一样的效果。
灯光和雾化等效果请参见灯光手册
为了提供三维空间的坐标参考,Graph3dView
预置了现实xz
面网格,x
、y
和z
三个方向轴,以及中心点位置的显示功能,
默认这些参数都是关闭不显示状态,可根据需要打开开关,并改变显示参数。
getGridSize()|setGridSize(40)
,指定网格行列数getGridGap()|setGridGap(20)
,指定网格线间距getGridColor()|setGridColor([0.4, 0.75, 0.85, 1.0])
,指定网格线颜色isGridVisible()|setGridVisible(true)
,指定是否显示网格isOriginAxisVisible()|setOriginAxisVisible(true)
,指定是否显示坐标原点[0,0,0]
轴线isCenterAxisVisible()|setCenterAxisVisible(true)
,指定是否显示目前中心点轴线getAxisXColor()|setAxisXColor([1.0, 0.0, 0.0, 1.0])
,指定x
轴线颜色getAxisYColor()|setAxisYColor([0.0, 1.0, 0.0, 1.0])
,指定y
轴线颜色getAxisZColor()|setAxisZColor([0.0, 0.0, 1.0, 1.0])
,指定z
轴线颜色3D
的交互与2D
有很大的区别,默认Graph3dView
提供的是围绕Graph3dView#getCenter()
中心点旋转的操作模式,
这种模式下进行Drag
操作时会改变Graph3dView#getEye()
的眼睛观察点位置,鼠标滚轮或触屏pinch
缩放的效果,
实质也是改变eye
位置,使其更接近或者更远离center
中心位置,最终达到视觉缩放或者走近和远离物体的效果。
drag
围绕中心旋转;按下shift
键则进行pan
方式的手抓图;滚轮进行走近和远离中心;
右键drag
时上下位置变化影响前进后退,左右位置变化影响左右平移。pinch
方式的缩放;三指头拖拽进行pan
方式平移。Graph3dView
还提供了第一人称的漫游交互模型,该模式同时改变eye
和center
的位置,
通过Graph3dView#setFirstPersonMode(true)
可切换为第一人称模式,这种模式下操作就行人或车在行进的效果:
shift
键则进行pan
方式的手抓图,即改变上下左右位置。滚轮则进行上下位置调节。drag
拖拽则进行pan
方式的手抓图,即改变上下左右位置。在第一人称模式下,还可设置Graph3dView#setMouseRoamable(true|false)
参数,该参数默认值为true
,如果设置为false
,
则鼠标左键右键都不支持前进后退的操作功能,但左键可拖拽编辑图元,右键可改变视角方向,采用这样的方式一般会结合键盘w|s|a|d
按键进行漫游操作。
HT
的交互函数一般都有是否起动画的参数anim
,该参数可为boolean
类型的简单true|false
,也可为json
对象,
当为json
对象时则代表启动动画,同时json
对象上的属性则用于控制动画相关的参数,以下示例代码片段供参考:
g3d.walk(distance, {
frames: 50,
interval: 30,
easing: function(t) {return t; },
finishFunc: function() {
forwardIndex += 1;
if (points.length - 2 > forwardIndex) {
g3d.setCenter([point2.x, 1600, point2.y]);
setTimeout(function() {
g3d.rotate(Math.PI / 2, 0, {
frames: 30,
interval: 30,
easing: function(t) {return t;},
finishFunc:function() {forward();}
});
}, 60);
} else {
var lastPoint = points[points.length - 1];
g3d.setCenter([lastPoint.x, 1400, lastPoint.y]);
setTimeout(function() {
g3d.rotate(-Math.PI / 2, 0, {
frames: 30,
interval: 30,
finishFunc: function() {
window.isAnimationRunning = false;
}
});
}, 60);
}
}
});
虽然3D
交互本质主要就是改变eye
和center
这两个位置参数,但直接操作三维坐标点还是太原始晦涩,
Graph3dView
提供了以下跟简单直观的函数操作方式:
setZoom(increment, anim)
:缩放操作,默认操作模式意味着eye
离center
的远近变化,increment
为步进的比例,
调用zoomIn(anim)
和zoomOut(anim)
,等同于调用了setZoom(1.3, anim)
和setZoom(1/1.3, anim)
。
如果在Graph3dView#isOrtho()
为true
的正交投影情况下,缩放意味着改变Graph3dView#setOrthoWidth(width)
的可视宽度范围。
pan(dx, dy, anim, firstPersonMode)
:上下左右四个方向的平移,本质为eye
和center
同时做四个方向的相同偏移量,
dx
左右偏移参数,dy
上下偏移参数,dx
和dy
一般代表屏幕移动像素,Graph3dView
自动会换算成合理的3D
空间逻辑坐标偏移量。
firstPersonMode
参数为空时则默认采用Graph3dView#isFirstPersonMode()
当前值,
如果为第一人称模式调用pan
操作,该函数会考虑Graph3dView#getBoundaries()
边界限制。
rotate(leftRight, upDown, anim, firstPersonMode)
:上下左右四个方位旋转一定角度,leftRight
水平旋转弧度,upDown
垂直旋转弧度,
firstPersonMode
参数为空时则默认采用Graph3dView#isFirstPersonMode()
当前值,该参数将影响旋转移动的参照标准,为默认非第一人称模式时,
旋转是以center
为中心进行旋转,也就是围绕中心物体旋转,当为第一人称时旋转以eye
为中心进行旋转,也就是旋转眼睛朝向方向。
walk(step, anim, firstPersonMode)
:该函数同时改变eye
和center
的位置,也就是eye
和center
在两点建立的矢量方向上同时移动相同的偏移量。
step
为偏移的矢量长度值。firstPersonMode
参数为空时则默认采用Graph3dView#isFirstPersonMode()
当前值,
如果为第一人称模式调用walk
操作,该函数会考虑Graph3dView#getBoundaries()
边界限制。
reset()
:复位函数,调用该函数将eye
、center
和up
三个变量设置为ht.Default
上对应的
graph3dViewCenter
、graph3dViewEye
和graph3dViewUp
初始默认值。
默认情况下以下参数都是开启状态,即可通过鼠标或键盘进行以下交互操作,可根据需求进行开关设置:
isRotatable()|setRotatable(true)
,控制是否可旋转 isZoomable()|setZoomable(true)
,控制是否可缩放 isPannable()|setPannable(true)
,控制是否可平移 isWalkable()|setWalkable(true)
,控制是否可进退 isResettable()|setResettable(true)
,控制是否可按空格键复位isRectSelectable()|setRectSelectable(true)
,控制是否可框选Graph3dView
预置了很多键盘操作功能
w
:前进,如果同时按下shift
键则为上移s
:后退,如果同时按下shift
键则为下移a
:左移d
:右移ctrl
或command
键:进行框选space
空格键:调用reset()
进行复位shift
键:按住shift
键盘时,默认操作变成pan
的平移效果Graph3dView
默认情况下移动图元是沿着xz
平面移动,当按住以下键时将改变移动模式:
shift
键,或者同时按下x
、y
和z
键时,则进行xyz
三维空间的移动x
和y
键时,则进行沿xy
平面的移动x
和z
键时,则进行沿xz
平面的移动y
和z
键时,则进行沿yz
平面的移动x
键时,则进行沿x
轴方向的移动y
键时,则进行沿y
轴方向的移动z
键时,则进行沿z
轴方向的移动通过键盘改变移动模式的默认实现逻辑在getMoveMode(event, data)
函数里,该函数默认实现逻辑如下,
如果最后选中的图元的style
属性3d.move.mode
指定了值,则不再考虑键盘状态而采用该设置值:
getMoveMode: function(event, data){
var movemode = data.s('3d.move.mode');
if(movemode){
return movemode;
}
var map = ht.Default.getCurrentKeyCodeMap(),
x = '88',
y = '89',
z = '90';
if(event.shiftKey || (map[x] && map[y] && map[z])) return 'xyz';
if(map[x] && map[y]) return 'xy';
if(map[x] && map[z]) return 'xz';
if(map[y] && map[z]) return 'yz';
if(map[x]) return 'x';
if(map[y]) return 'y';
if(map[z]) return 'z';
return 'xz';
},
可参考吸附章节例子中,将移动模式设置为沿xyz
三维空间移动的代码:
g3d.getMoveMode = function(event){
return 'xyz';
};
默认情况下图元在三维场景即可拖拽沿着xz
平面移动,或结合键盘实现任意空间方向移动,但结合键盘毕竟不够直观易用,
同时图元还有三个轴方向的旋转角度,三个轴方向的大小尺寸等参数需要可控,即需要修改p3
、s3
和r3
参数的编辑功能。
为此HT
提供了直观的解决方案,当Graph3dView#setEditable(true)
处于编辑状态时,最后一个选中的图元将呈现如下的,
由图元中心延伸出来的三个轴方向的标示条,每个轴方向的标示条又分为三段:
shift
键可同时同比例改变三个轴方向大小0
参见过滤器章节,控制图元是否允许移动、旋转和改变大小。
通过Graph3dView#addInteractorListener
可监听交互过程:
g3d.addInteractorListener(function(e){
console.log(e.kind);
});
其中回调事件e.kind
参数类型如下:
beginRotate
:开始旋转betweenRotate
:旋转过程endRotate
:结束旋转beginWalk
:开始行进betweenWalk
:行进过程endWalk
:结束行进beginZoom
:开始缩放betweenZoom
:缩放过程endZoom
:结束缩放beginPan
:开始平移betweenPan
:平移过程endPan
:结束平移beginPinch
:开始双指缩放betweenPinch
:双指缩放过程endPinch
:结束双指缩放toggleNote
:双击在note
上toggleNote2
:双击在note2
上clickData
:单击图元clickBackground
:单击背景doubleClickData
:双击图元doubleClickBackground
:双击背景beginEditRotation
: 开始编辑图元旋转角度betweenEditRotation
: 正在编辑图元旋转角度endEditRotation
: 结束编辑图元旋转角度beginEditSize
: 开始编辑图元大小betweenEditSize
: 正在编辑图元大小endEditSize
: 结束编辑图元大小beginMove
: 开始移动图元betweenMove
: 正在移动图元endMove
: 结束移动图元beginRectSelect
: 开始框选图元betweenRectSelect
: 正在框选图元endRectSelect
: 结束框选图元当单击或双击在图元上时,返回事件除了e.kind
外,还有e.part
参数提供了具体点击图元哪个部位的信息:
body
:图片的中心部分label
:图元文字标签label2
:图元第二个文字标签note
:图元冒泡标注label2
:图元第二个冒泡标注icons
上的key
:代表一组图标edit_tx
:编辑状态下,标示改变x
轴位置部分edit_ty
:编辑状态下,标示改变y
轴位置部分edit_tz
:编辑状态下,标示改变z
轴位置部分edit_rx
:编辑状态下,标示改变x
轴旋转部分edit_ry
:编辑状态下,标示改变y
轴旋转部分edit_rz
:编辑状态下,标示改变z
轴旋转部分edit_sx
:编辑状态下,标示改变x
轴大小部分edit_sy
:编辑状态下,标示改变y
轴大小部分edit_sz
:编辑状态下,标示改变z
轴大小部分HT
不但提供第一人称漫游交互模式,还支持漫游过程对墙面等阻挡物的碰撞检测功能。
通过碰撞检测可以限制第一人称漫游的允许范围。漫游操作一般沿着xz
平面进行,因此HT
提供了定义xz
平面上的多线,
用来描述不可超越的漫游边界。
通过Graph3dView#setBoundaries(boundaries)
可指定碰撞边界,boundaries
的格式如下:
g3d.setBoundaries([
[
p0.x, p0.y,
p1.x, p1.y,
p2.x, p2.y,
p3.x, p3.y
],
[
p4.x, p4.y,
p5.x, p5.y,
p6.x, p6.y
]
]);
以上代码设置了两条折线p0-p1-p2-p3
和p4-p5-p6
,每条折线由一个数组描述所有端点,数组的第一和第二元素表示起始点的x,z
坐标,
接下来依次是第二、第三等端点的x,z
坐标,可理解为第一个端点为MoveTo
其他图元依次进行LineTo
围成的边界。
以下示例代码用到了ht.Default.toBoundaries(data.getPoints(), data.getSegments())
的函数,
该函数可将不连续的曲线转化成微分的直线线段。代码利用GraphView#addTopPainter
,
将3D
的eye
和center
的位置方向信息实时绘制在2D
,以便直观理解当前第一人称所在位置和朝向。
Graph3dView
中被选中的图元会显示为较暗的状态,变暗系数是由图元style
的brightness
和select.brightness
属性决定,
select.brightness
属性默认值为0.7
,最终返回值大于1
变亮,小于1
变暗,等于1
或为空则不变化。
Graph3dView#getBrightness
函数控制最终图元亮度,因此也可以通过重载覆盖该函数自定义选中图元亮度,以下为默认逻辑:
getBrightness: function(data){
var brightness = data.s('brightness'),
selectBrightness = this.isSelected(data) ? data.s('select.brightness') : null;
if(brightness == null){
return selectBrightness;
}
if(selectBrightness == null){
return brightness;
}
return brightness * selectBrightness;
},
Graph3dView#getWireframe
函数用于定义图元立体线框效果,默认实现代码如下,
由实现代码可知通过控制wf.*
(wf
为wireframe
的简称)相关参数即可实现显示选中线框的效果。
getWireframe: function(data){
var visible = data.s('wf.visible');
if(visible === true || (visible === 'selected' && this.isSelected(data))){
return {
color: data.s('wf.color'),
width: data.s('wf.width'),
short: data.s('wf.short'),
mat: data.s('wf.mat')
};
}
},
wf.visible
:默认为false
代表不显示,可设置为selected
值代表选中时才显示,或true
值代表一直显示线框wf.color
:线框颜色wf.short
:默认值为false
代表显示封闭的立体线框,设置为true
则显示不封闭的短线框wf.width
:线框宽度,默认值为1
,有些系统下只能显示1
的效果,不同系统能显示的最大值也都有限制wf.mat
:默认值为空,可通过ht.Default.createMatrix
构建转换矩阵,参见 Unboxing 例子默认情况所有图元都是可选中,用户可通过设置选择过滤器取消部分图元的可选中功能,
可否选中的最终控制在SelectionModel
模型的filterFunc
过滤器上,也可通过重载GraphView
的isSelectable
函数,
或调用GraphView.setSelectableFunc(func)
的封装函数控制,示例代码如下:
graph3dView.setSelectableFunc(function(data){
return data.a('selectable');
});
默认情况图元都是可见,用户可通过设置可见过滤器隐藏部分图元,示例代码如下:
graph3dView.setVisibleFunc(function(data){
return data.s('all.transparent') === true;
});
该示例代码逻辑为:只显示all.transparent
为true
的图元。
Graph3dView#isVisible
函数最终决定图元是否可见,因此也可通过直接重载覆盖该函数自定义:
graph3dView.isVisible = function(data){
return data.s('all.transparent') === true;
};
默认情况图元都是可移动,用户可通过设置移动过滤器固定部分图元,示例代码如下:
graph3dView.setMovableFunc(function(data){
return movableItem.selected;
});
该示例代码逻辑为:当movableItem
的selected
为true
时图元才允许移动。
Graph3dView#isMovable
函数最终决定图元可否移动,因此也可通过直接重载覆盖该函数自定义:
graph3dView.isMovable = function(data){
return movableItem.selected;
};
当Graph3dView#setEditable(true)
设置为可编辑的情况下,默认选中图元允许旋转,可通过如下代码禁止部分图元旋转:
graph3dView.setRotationEditableFunc(function(data){
return data instanceof ht.Shape;
});
以上代码的逻辑为:只允许ht.Shape
类型的图元可以旋转。
Graph3dView#isRotationEditable
函数最终决定图元可否旋转,因此也可通过直接重载覆盖该函数自定义:
graph3dView.isRotationEditable: function(data){
return data instanceof ht.Shape;
},
当Graph3dView#setEditable(true)
设置为可编辑的情况下,默认选中图元允许改变大小,可通过如下代码禁止部分图元旋转:
graph3dView.setSizeEditableFunc(function(data){
return data instanceof ht.Shape;
});
以上代码的逻辑为:只允许ht.Shape
类型的图元可以改变大小。
Graph3dView#isSizeEditable
函数最终决定图元可否改变大小,因此也可通过直接重载覆盖该函数自定义:
graph3dView.isSizeEditable: function(data){
return data instanceof ht.Shape;
},
除在视图组件上设置过滤器外,GraphView
和Graph3dView
的内置过滤机制也参考了以下style
属性,用户可直接改变以下style
达到对单个图元的控制效果:
2d.visible
:默认值为true
,控制图元在GraphView
上是否可见2d.selectable
:默认值为true
,控制图元在GraphView
上是否可选中2d.movable
:默认值为true
,控制图元在GraphView
上是否可移动2d.editable
:默认值为true
,控制图元在GraphView
上是否可编辑2d.move.mode
:默认值为空,控制图元移动范围,可设置为如下参数: xy
:可在xy
平面移动 x
:仅沿x
轴移动 y
:仅沿y
轴移动 3d.visible
:默认值为true
,控制图元在Graph3dView
上是否可见3d.selectable
:默认值为true
,控制图元在Graph3dView
上是否可选中3d.movable
:默认值为true
,控制图元在Graph3dView
上是否可移动3d.editable
:默认值为true
,控制图元在Graph3dView
上是否可编辑3d.move.mode
:默认值为空,参见键盘操作,控制图元移动范围,可设置为如下参数:xyz
:可在三维空间移动xy
:仅在xy
平面移动 xz
:仅在xz
平面移动yz
:仅在yz
平面移动x
:仅沿x
轴移动 y
:仅沿y
轴移动 z
:仅沿z
轴移动 toCanvas(background)
:导出当前视图内容成一个Canvas
组件,background
为背景颜色toDataURL(background)
:导出当前视图内容为base64格式的字符串图片内容,background
为背景颜色导出例子片段:
{
label: 'Export Image',
action: function(){
var w = window.open();
w.document.open();
w.document.write("<img src='" + g3d.toDataURL(g3d.getView().style.background) + "'/>");
w.document.close();
}
}