jtopo 教程

在这里插入代码片

前言
一、安装

  1. 直接引用(上手推荐)
  2. npm方式(仓库里版本滞后)
    二、第一个程序(Helloword)
    三、基础讲解
    3.1 顶层对象(Stage)
    3.2 层对象(Layer)
    3.3 节点对象(Node)
    3.4 连线对象(Link)
    3.5 外观样式(Style)
    3.6 事件处理(鼠标交互)
    四、布局
    4.1 网格布局(GridLayout)
    4.2 树形布局(GridLayout)
    4.2 圆形布局(CircleLayout)
    4.3 自动边界布局(AutoBoundLayout)
    4.4 斥力布局(ForceDirectLayout)
    四、中级进阶
    4.1 文本和定位
    4.2 容器
    4.3 连接点
    4.4 自定义属性
    4.5 自定义节点
    4.6 自定义连线
    五、高级功能
    5.1 位置计算
    5.2 性能优化
    5.3 辅助绘图
    六、其它
    6.1 图片导出
    jtopo开发教程 下载PDF格式

前言
本教程假设读者已经对javaScript、html有所了解。

一、安装

  1. 直接引用(上手推荐)
    新建一个文本文件,命名为 helloword.html,文件内容:
2. npm方式(仓库里版本滞后) npm install -D jtopo2 二、第一个程序(Helloword) 完整的helloworld.html文件内容如下(可以复制粘贴到你的编辑器中):
<!DOCTYPE html>
<html>
<head>
    <script src="http://www.jtopo.com/download/jtopo-0.9.9_trial-min.umd.js"></script>
</head>
<body>
    <!-- 用于渲染显示的div -->
    <div id="divId" style="height:600px;width:600px;"></div>

    <script>
        var stage = new jtopo.Stage('divId');
        var layer = new jtopo.Layer('default');
        stage.addChild(layer);

        var fromNode = new jtopo.Node('From', 200, 200, 40, 40);
        var toNode   = new jtopo.Node('To',   400, 200, 40, 40);

        // 设置节点填充颜色
        fromNode.setStyles('fillStyle', 'orange');
        toNode.setStyles('fillStyle', 'blue');

        var link = new jtopo.Link('Link',fromNode,toNode);
        layer.addChild(link);

        layer.addChild(fromNode);
        layer.addChild(toNode);

        stage.show();
    </script>
</body>
</html>

用浏览器打开该完整的helloworld.html,查看运行效果如下:

参考:在线入门Demo

三、基础讲解
jtopo的核心对象有Stage、Layer、Canvas、Node、Link, 关系如下图:

Stage、Layer和Node关系

3.1 顶层对象(Stage)
jtopo的核心对象之间存在层级结构,最顶层的为Stage,管理一个或者多个Layer,可以对Layer进行管理:添加、移除。

提供一些常规性的交互功能,比如:鼠标缩放、视图模式变换(普通、框选、拖拽、编辑、锁定);

显示控制:按画布居中、1:1显示 导出图片等功能。

代码示例:

var stage = new jtopo.Stage(“divId”);
stage.show(); // 显示出来

详细的:Stage-API参考

3.2 层对象(Layer)
Layer 是一个抽象对象,默认是完全透明的,上层对象为Stage.

一个Layer下面可以有多个Node、Link对象,Node、Link对象只有放入Layer后才可能被绘制出来。

Layer 可以被平移、缩放,用户可以通过鼠标在画布上的拖拽 和 鼠标滚轮完成,也可以通过API来修改Layer的x、y坐标和缩放系数scaleX和scaleY实现同等效果。

一个Layer对象对应一个Canvas,多个Layer常用于画面逻辑分层,比如有的层绘制速度较慢,有的层绘制速度较快,有的层作为背景层,有的作为动画层。

代码示例:

var stage = new jtopo.Stage();
var layer = new jtopo.Layer(“layer-1”);
stage.addChild(layer); // 放入Stage
//…
stage.show(); // 显示出来

详细的:Layer-API参考

3.3 节点对象(Node)
用户操作的核心两个对象Node 、Link之一。

Node给人的形象是一个矩形,有坐标(x,y) 和 宽高尺寸(width、heigh)。

可以指定一个文本字符串,默认显示在中矩形的下面。

Node对象的外观可以通过setStyles方法设置,核心的外观属性有:边框颜色、填充颜色、字体颜色、字体(大小、加粗等CSS Font支持的都可以)、圆角。

代码示例:

var stage = new jtopo.Stage();
var layer = new jtopo.Layer(“layer-1”);
stage.addChild(layer); // 放入Stage

var node = new jtopo.Node(“Node-1”);
layer.addChild(node); // 放入Layer

stage.show(); // 显示出来

各种Node效果如下:

参考:Node演示

详细的:Node-API参考

3.4 连线对象(Link)
用户操作的核心两个对象之一。

Link给人的形象是连线,有起始点和结束点,一般用来表示关系、流向等。

可以指定一个文本字符串,默认显示在连线的中间。

Link对象的外观可以通过setStyles方法设置,核心的外观属性有:颜色、线条粗细、字体颜色、字体(大小、加粗等CSS Font支持的都可以)。

代码示例:

var link = new jtopo.Link('Link',fromNode,toNode);
layer.addChild(link);

各种Link效果如下:

参考:Link演示 详细的:Link-API参考

3.5 外观样式(Style)
样式大部分属性命名和效果都遵循和参考了Html5-Canvas的绘图定义。

var stage = new jtopo.Stage(‘divId’);
var layer = new jtopo.Layer(‘default’);
stage.addChild(layer);

// 全局样式
layer.setStyles({
// 字体,格式CSS-FONT
‘font’: ‘bold 12px 仿宋’
});

var circleNode = new jtopo.CircleNode(‘选中样式’, 400, 200, 60);

// 节点样式
circleNode.setStyles({
// 画笔颜色(即边框)
‘strokeStyle’: ‘red’,

// 画笔粗细
'lineWidth': 9,

// 填充颜色
'fillStyle': 'orange',

// 字体颜色
'fontColor': 'black',

// 节点中间
'textPosition': 'center',

// 左右居中
'textAlign': 'center',

// 上下居中
'textBaseline': 'middle'

});

// 被选中的状态样式
// 选中的样式会在绘制图元的形状之前被应用
circleNode.selectedStyle = new jtopo.Style({
// 阴影颜色
‘shadowColor’: ‘orange’,

// 阴影的模糊级数
'shadowBlur': 7,

// 阴影的偏移(这里3和3表示右下方向了)
'shadowOffsetX' : 3,
'shadowOffsetY' : 3,

// 甚至可以改变字体
'font': 'bold 18px 仿宋'

});

layer.addChild(circleNode);

stage.show();
效果:

参考:样式演示

详细的:Style-API参考

3.6 事件处理(鼠标交互)
jtopo封装了鼠标行为,可以在Node或者Link对象上增加事件监听,代码示例:

var stage = new jtopo.Stage(‘divId’);
var layer = new jtopo.Layer(‘default’);
stage.addChild(layer);

var fromNode = new jtopo.Node(‘From’, 200, 150, 40, 40);
fromNode.setImage(‘./demo/img/laptop.png’, true);
layer.addChild(fromNode);

// 鼠标点击
fromNode.on(‘click’, function(event) {
fromNode.text = ‘click’;
console.log(‘click’);
});

// 鼠标双击
fromNode.on(‘dblclick’, function(event) {
console.log(‘dblclick’);
fromNode.text = ‘dblclick’;
});

// 鼠标进入
fromNode.on(‘mouseenter’, function(event) {
console.log(‘mouseenter’);
fromNode.text = ‘mouseenter’;
});

// 鼠标移动
fromNode.on(‘mousemove’, function(event) {
console.log(‘mousemove’);
fromNode.text = ‘mousemove’;
});

// 鼠标离开
fromNode.on(‘mouseout’, function(event) {
fromNode.text = ‘mouseout’;
console.log(‘mouseout’);
});

// 鼠标按下
fromNode.on(‘mousedown’, function(event) {
console.log(‘mousedown’);
fromNode.text = ‘mousedown’;
});

// 鼠标松开
fromNode.on(‘mouseup’, function(event) {
console.log(‘mouseup’);
fromNode.text = ‘mouseup’;
});

// 鼠标拖拽
fromNode.on(‘mousedrag’, function(event) {
console.log(‘mousedrag’);
fromNode.text = ‘mousedrag’;
});

stage.show();
参考:事件处理演示

四、布局
布局功能允许用户把Node和Link按照一定形式调整相对坐标

4.1 网格布局(GridLayout)
网格布局是较为简单的一种布局,把Node对象按照行、列的方式摆放

// 存放要布局的节点数组
var nodes = [];

// 生成9个节点
for(var i=0; i<9; i++){
var node = new jtopo.Node(‘’+i, 0,0,32,32);
nodes.push(node);
}

// 网格式布局,3行3列
var rows = 3;
var cols = 3;
var gridLayout = new jtopo.GridLayout(rows, cols);

// 执行布局,节点水平和垂直的间距为 20, 20
gridLayout.doLayout(nodes, 20, 20);
效果:

参考:网格布局演示

详细的:GridLayout-API参考

4.2 树形布局(GridLayout)
树形布局根据Node和Link的关系自动找到根节点,然后递归式的逐级布局为一棵树的形状。 可以指定树的朝向。

var nodes = […];

// 方向: up、down、left、right

// 左右间隔量 40, 上下间隔量 80
var treeLayout = new jtopo.TreeLayout(‘down’, 40, 78);
treeLayout.doLayout(nodes);
效果:

参考:树形布局演示

详细的:Layer-API参考

4.2 圆形布局(CircleLayout)
圆形布局将多个节点以一个节点为圆心进行布局。

var layout = new jtopo.CircleLayout({
minRadius: 200 // 圆最小半径
});

layout.doLayout(rootNode, nodes);
效果:

参考:圆形布局演示

详细的:CircleLayout-API参考

4.3 自动边界布局(AutoBoundLayout)
容器的边界和尺寸会随着多个子节点而自动变化

var autoBoundLayout = new jtopo.AutoBoundLayout();
autoBoundLayout.doLayout(group);
效果:

参考:自动边界布局演示

详细的:AutoBoundLayout-API参考

4.4 斥力布局(ForceDirectLayout)
模拟斥物理性质(质量,斥力和张力), 各个节点在力的相互作用下不断运动,直至最终达到力的平衡,完成自动布局.

var layout = new ForceDirectLayout(rootNode, stage.width, stage.height);

// 斥力布局需要多次调用applyForce迭代
layout.applyForce();
效果:

参考:斥力布局演示

详细的:ForceDirectLayout-API参考

四、中级进阶
4.1 文本和定位
文本在节点上的位置可以调整。

文字定位由三个核心属性控制:1. 位置 2. 文本对齐方式 2. 文本基线

位置表示如下图:

灰色矩形区域代表节点,节点文本的位置默认在下面中间(cb)的位置。

文本对齐方式如下图:

文本基线如下图:

自定义偏移量 除上述三种方式,还可以通过设置:textOffsetX 和 textOffsetY 属性来设置文本的水平和垂直偏移量。
下面的代码展示了不同位置和对齐方式的组合:

var Stage = jtopo.Stage;
var Layer = jtopo.Layer;
var Node = jtopo.Node;
var GridLayout = jtopo.GridLayout;

var stage = new jtopo.Stage(‘divId’);
var layer = new jtopo.Layer(‘default’);

stage.addChild(layer);
// 全局样式
layer.setStyles({
‘lineWidth’: 5, // 边框粗细
‘strokeStyle’: ‘#E1E1E1’,
‘font’: ‘bold 12px arial’
});

/*

  • 位置表示: 水平(left-center-right) 垂直(top-middle-bottom)

  • lt : left-top 左上

  • ct : center-top 正上

  • rt : right-top 右上

  • lm : left-middle 左中

  • center : center 正中-中心

  • rm : right-bottom 右中

  • lb : left-bottom 左下

  • cb : center-bottom 正下

  • rb : right-bottom 右下

*/
var positions = [
‘lt’, ‘ct’, ‘rt’,
‘lm’, ‘center’, ‘rm’,
‘lb’, ‘cb’, ‘rb’];

var textAligns = [‘center’, ‘left’, ‘right’];

var textBaselines = [‘top’, ‘middle’, ‘bottom’];

var count = 0;

for (var i = 0; i < positions.length; i++) {
for (var a = 0; a < textAligns.length; a++) {
for (var b = 0; b < textBaselines.length; b++) {

        var node = new Node('T', 0,0, 30, 30);

        node.setStyles({
              'fillStyle': jtopo.randomColor(),
            textPosition: positions[i],
            textAlign: textAligns[a],
            textBaseline: textBaselines[b],
            fontColor: 'black',
        });

        // 更细致的控制:水平和垂直方向的偏移量。
          //node.textOffsetX = 5;
       // node.textOffsetY = 5;

        // 开始不好记忆,没关系
        // 可以把本例子当做字典,需要定位时,找一个满意的 'T' 所在的节点
        // 点击节点,查看具体的设置
        node.on('click', function () {
            var msg = 'textPosition: ' + this.getStyle('textPosition') + '\n' +
                'textAlign:      ' + this.getStyle('textAlign') + '\n' +
                'textBaseline: ' + this.getStyle('textBaseline');
            alert(msg);
        });

        layer.addChild(node);
    }
}

}

// 9 x 9 的网格
var gridLayout = new GridLayout(9, 9);

var hGap = 20; // 节点左右间距
var vGap = 20; // 节点上下间距
gridLayout.doLayout(layer.children, hGap, vGap);

stage.translateToCenter();
stage.show();
执行结果:

4.2 容器
jtopo拥有强大的组合能力,每个Node都可以作为容器使用。

容器内的左上角,对于子元素来说就是子元素的原点(0,0)。

var Layer = jtopo.Layer;
var Node = jtopo.Node;
var CircleNode = jtopo.CircleNode;
var FoldLink = jtopo.FoldLink;

var stage = new jtopo.Stage(‘divId’);
var layer = new Layer(‘default’);
stage.addChild(layer);

// 全局样式
layer.style.setStyles({
‘lineWidth’: 2,
‘font’: ‘12px arial’,
‘strokeStyle’: ‘red’
});

var container1 = new Node(‘最底层’, 150, 150, 500, 400);
var container2 = new Node(null, 80, 80, 400, 300);
var container3 = new Node(‘最上层’, 160, 160, 200, 100);

container1.setStyles({
‘fillStyle’: ‘#3586E3’,
‘lineWidth’: 12
});
container2.setStyles({
‘fillStyle’: ‘#FDD163’,
‘strokeStyle’: ‘black’
});
container3.setStyles({
‘fillStyle’: ‘#D73417’,
‘strokeStyle’: ‘black’
});
container3.textOffsetY = 8;

layer.addChild(container1);
container1.addChild(container2);
container2.addChild(container3);

var toNode = new Node(‘在第二层’, 30, 30, 40, 40);
toNode.setStyles(‘fontColor’, ‘white’);
toNode.setImage(‘./demo/img/laptop.png’);
container2.addChild(toNode);

var tip = new jtopo.TipNode(“第二层角标”);
tip.setStyles(‘fillStyle’, ‘#FDD163’);
tip.setStyles(‘fontColor’, ‘#D73417’);
tip.setStyles(‘strokeStyle’, ‘#3586E3’);
tip.translateTo(container2.width, 0);
tip.rotateTo(Math.PI / 4);
container2.addChild(tip);

var cantOutNode = new Node(‘出不去’, 30, 30, 40, 40);
cantOutNode.setImage(‘./demo/img/laptop.png’);
cantOutNode.setStyles(‘fontColor’, ‘white’);
// 增加一个限制:不允许拖拽出父节点
cantOutNode.on(‘mousedrag’, function (e) {
var p = this.parent;
if (this.x < 0) this.x = 0;
if (this.y < 0) this.y = 0;
if (this.x + this.width > p.width) {
this.x = p.width - this.width
}
if (this.y + this.height > p.height) {
this.y = p.height - this.height;
}
});

var link = new FoldLink(null, toNode, cantOutNode, ‘center’, ‘ct’);
link.setStyles({
‘lineWidth’: 5,
‘strokeStyle’: ‘black’
});

// 可以通过调整zIndex改变显示的先后顺序(同级别之间有效)
link.zIndex = 2;
container3.zIndex = 1;
toNode.zIndex = 3;
cantOutNode.zIndex = 3;

container2.addChild(link);
container3.addChild(cantOutNode);

stage.show();

基于容器的概念,为多个Node组装成复杂对象提供了很大便利。

4.3 连接点
连线可以连接到节点的不同位置上,节点默认有10个’连接点‘,通过 node.getPosition(name); 可以获取指定位置的坐标;

如图:灰色矩形代表节点,上面标注了9个连接点(和文本定位是一样的),另外还有一个动态的连接点:edge表示节点的边框,是随着对端节点的位置自动计算出来的。

/*

  • 位置表示: 水平(left-center-right) 垂直(top-middle-bottom)

  • lt : left-top 左上

  • ct : center-top 正上

  • rt : right-top 右上

  • lm : left-middle 左中

  • center : center 正中-中心

  • rm : right-bottom 右中

  • lb : left-bottom 左下

  • cb : center-bottom 正下

  • rb : right-bottom 右下

  • edge: 节点边框,不是固定的
    */

// 示例1
var position1 = ‘center’;
var position2 = ‘ct’;
var link = new Link(null, nodeA, nodeZ, position1, position2);
// 或者:
var link2 = new Link(null, nodeA, nodeZ, ‘center’, ‘rb’);
// …
///
参考:

参考:连接点演示

4.4 自定义属性
如果需要在节点或者连线上添加自定义的属性, 方法如下:

// 直接修改、读取属性 userData
node.userData = {...};

所有节点和连线,名字为 userData 的属性jtopo不会做任何改动

避免直接在对象上增加属性,这样避免了属性冲突和一些奇怪的问题,也便于以后升级

4.5 自定义节点
通过面向对象式的继承,实现draw(ctx)方法即可实现自定义节点:

var stage = new jtopo.Stage(‘divId’);
var layer = new jtopo.Layer();
stage.addChild(layer);

// 自定义节点: 重写Node对象的draw 方法即可.
class MyNode extends jtopo.Node {
constructor(text, x, y, w, h) {
super(text, x, y, w, h);
}

/**
 * 绘制图形
 * @param ctx Canvas.context
 */
draw(ctx) {
    // 填充个矩形
    ctx.beginPath();
    ctx.rect(0, 0, this.width, this.height);
    ctx.fill();

    // 鼠标拾取(固定模式,一般情况不需要修改)
    // 判断鼠标位置是否在上面填充的矩形内
    this.mousePickupPath(ctx);

    ctx.beginPath();
    ctx.fillStyle = 'green';
    ctx.rect(20, 20, this.width-40, 20);
    ctx.fill();

    // 文本
    this.paintText(ctx);
}

}

var myNode = new MyNode(‘自定义节点’, 300, 200, 100, 100);
// 节点样式
var nodeStyle = new jtopo.Style({
‘fillStyle’: ‘orange’,
‘font’: ‘bold 14px 仿宋’
});
myNode.style = nodeStyle;

layer.addChild(myNode);

stage.show();
执行结果:

4.6 自定义连线
通过面向对象式的继承,实现draw(ctx)方法即可实现自定义连线:

var Node = jtopo.Node;

var stage = new jtopo.Stage(‘divId’);
var layer = new jtopo.Layer();
stage.addChild(layer);

// 自定义连线: 重写Link对象的draw 方法即可.
class MyLink extends jtopo.Link {
/**
* 构造器
* @constructor
* @param {string} text 文本
* @param {Object} start 开始节点对象
* @param {Object} end 结束节点对象
* @param {string} beginPosition 开始节点对象的‘定位点’
* @param {string} endPosition 结束节点对象的‘定位点’
*/
constructor(text, start, end, beginPosition, endPosition) {
super(text, start, end, beginPosition, endPosition);
}

/**
 * 绘制图形
 * @param ctx Canvas.context
 */
draw(ctx) {
    // 起始点a 和 结束点z
    var a = this.getBeginPoint();
    var z = this.getEndPoint();

    // 绘制
    ctx.beginPath();
    ctx.moveTo(a.x, a.y);
    ctx.lineTo(a.x + 100, a.y);
    ctx.lineTo(a.x + 100, z.y);
    ctx.lineTo(z.x, z.y);
    ctx.stroke();

    // 文本位置
    var textPoint = {
        x:a.x + 100,
        y:a.y
    }

    // 文本旋转角度
    var angle = 0;
    this.paintText(ctx, angle, textPoint);

    // 鼠标拾取最后一次stroke的路径(固定模式,一般情况不需要修改)
    this.mousePickupStroke(ctx);
}

}

// 节点样式
var nodeStyle = new jtopo.Style({
‘strokeStyle’: ‘orange’,
‘font’: ‘bold 14px 仿宋’
});

var fromNode = new Node(‘A’, 300, 200, 60, 60);
fromNode.style = nodeStyle;

var toNode = new Node(‘Z’, 200, 300, 60, 60);
toNode.style = nodeStyle;

var link = new MyLink(‘Link’, fromNode, toNode);
link.setStyles({
‘lineWidth’: 2,
‘strokeStyle’: ‘green’
});
layer.addChild(link);
layer.addChild(fromNode);
layer.addChild(toNode);

stage.show();
执行结果:

五、高级功能
5.1 位置计算
Node 或 Link对象有一个getPoint(t)方法, t取值范围:[0-1],可以获取对象上某一点的坐标。

对于Node, t在0-1期间的轨迹为矩形的一周:可以获取节点边框上任意一点:

例如:t = 0.25的时候,取矩形右上角的坐标,t=0.5的时候表示右下角的坐标。

对于矩形,t=0 和 t=1 两个点是重叠的。

对于Link,t在0-1期间的轨迹为起点到终点。

例如:t = 0时表示起点,t = 1时表示终点, t = 0.5时表示中点。

var Node = jtopo.Node;
var CircleNode = jtopo.CircleNode;
var BezierLink = jtopo.BezierLink;
var stage = new jtopo.Stage(‘divId’);
var layer = new jtopo.Layer(‘default’);
stage.addChild(layer);

// 矩形节点 (圆形节点也可以)
var node = new jtopo.Node(‘Node’, 100, 100, 400, 400);
node.setStyles({
‘strokeStyle’: ‘gray’,
‘lineWidth’: 6
});
layer.addChild(node);

// 创建小球
function newBall(color, r) {
var ball = new jtopo.CircleNode(null, 0, 0, r);
ball.setStyles({
‘fillStyle’: color,
‘lineWidth’: 2
});
layer.addChild(ball);
return ball;
}

// 在方框上运动
var redBall = newBall(‘red’, 40);
var greenBall = newBall(‘green’, 20);

// 在link上运动
var blueBall = newBall(‘blue’, 20);

// 绕红色球运动
var ball4 = newBall(‘white’, 10);

// 连线
var link = new jtopo.CurveLink(null, redBall, greenBall);
link.setStyles({
‘lineWidth’: 2
});
layer.addChild(link);

stage.show();

// 动画
jtopo.Animation.circle(0, 1, 6000, function (t) {
// 红色小球
var p = node.getPoint(t/3);
redBall.text = ‘’ + t.toFixed(1);
redBall.translateCenterTo(p.x, p.y);

//绿色小球 1-t(与红色小球方向相反)
var p2 = node.getPoint(1 - t);
greenBall.translateCenterTo(p2.x, p2.y);

}).start().repeat(10);

jtopo.Animation.circle(0, 1, 3000, function (t) {
// 蓝色小球
var p3 = link.getPoint(t);
blueBall.translateCenterTo(p3.x, p3.y);

// 小小白球
var p4 = redBall.getPoint(t);
ball4.translateCenterTo(p4.x, p4.y);
stage.update();

}).start().repeat(10);
执行结果:

5.2 性能优化
尽量减少画布上显示的对象个数(效果极为明显); 数据量较多时可以考虑:滚动展示 + 搜索功能

减少文本信息,文字的渲染非常耗时; a) 允许的话,先把文字隐藏,鼠标指向时再显示(效果非常明显) b) 可以考虑事先用画图软件把文字绘制到节点图片上(效果非常明显)

可以使用SVG作为图片,但性能比较差; 事先把SVG转成png图片会更好

当画面不够流畅时,放弃阴影效果 也可以考虑预先制作好有阴影效果的png

5.3 辅助绘图
绘图时,可能会遇到复杂的坐标计算, jtopo提供了一个名为’Topo画家’的类来降低部分计算难度。

var stage = new jtopo.Stage(‘divId’);
var layer = new jtopo.Layer(‘default’);
stage.addChild(layer);

// 可以试着用笔在纸上体会绘制过程

// 确定两点
var a = {
x: 200,
y: 200
};
var z = {
x: 400,
y: 400
};

// 创建一个’Topo画家‘
var tp = new jtopo.TopoPainter();
tp.beginPath();

// 移动到点a,面向点z,前进100像素(划线)
tp.moveTo(a).faceTo(z).forward(100);

// 移动到点z,面向点a,前进100个像素(划线)
tp.moveTo(z).faceTo(a).forward(100);

// 移动到点a和z的中点,面向a, 向左转30度,绘制并记录下点位置
var angle = 30 / 180 * Math.PI;
tp.moveToMiddle(a, z).faceTo(a).turnLeft(angle).forward(40).mark(‘P1’);

// 移动到点a和z的中点, 面向z, 向右转30度,绘制并记录下点位置
tp.moveToMiddle(a, z).faceTo(a).turnRight(angle).forward(40).mark(‘P2’)

// 连接点 P1 和 P2
//tp.moveToMark(‘P1’).forwardToMark(‘P2’);

tp.stroke();
// 绘图完毕

// 生成canvas的绘制指令代码,可以复制粘贴到程序里
var code = tp.toCmd();
console.log(code);
/* 如下:
ctx.beginPath();
ctx.moveTo(200,200);
ctx.lineTo(270.71067811865476,270.71067811865476);
ctx.moveTo(400,400);
ctx.lineTo(329.28932188134524,329.28932188134524);
ctx.moveTo(300,300);
ctx.lineTo(261.36296694843725,289.64723819589915);
ctx.moveTo(300,300);
ctx.lineTo(289.64723819589915,261.36296694843725);
ctx.stroke();
*/

// 也可以直接编译成函数调用
var draw = tp.toFunction();
/*
等价于:
var draw = function(ctx) {
ctx.beginPath();
ctx.beginPath();
ctx.moveTo(200,200);
ctx.lineTo(270.71067811865476,270.71067811865476);
ctx.moveTo(400,400);
ctx.lineTo(329.28932188134524,329.28932188134524);
ctx.moveTo(300,300);
ctx.lineTo(261.36296694843725,289.64723819589915);
ctx.moveTo(300,300);
ctx.lineTo(289.64723819589915,261.36296694843725);
ctx.stroke();

ctx.stroke();
}
*/

// 用连线呈现出来
var link = new jtopo.Link(null, a, z);
link.setStyles({
‘lineWidth’: 5
});
link.draw = draw;

layer.addChild(link);

stage.show();
执行效果:

六、其它
6.1 图片导出
导出png透明的图片

stage.saveImageInfo();

课程
入门教程
中级进阶
高级应用

参考学习
Html5
Canvas
JavaScript

社区
CSDN
简书
联系我们
郑州集图软件科技有限公司.
Email: service@jitusoft.com
微信号: neng-duan

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值