关于fabric:fabricjs-可以实现哪些功能-动图介绍
我是开源图形编辑器,vue-fabric-editor的作者,明天整顿了一下fabric.js 能够实现的性能,用动图的模式分享给大家,不便疾速理解fabric.js。 源码见链接 辅助线 曲线文字 垂直文字 3D联合 自定义文字条 缩略图 白板 自定义管制条 Gif展现 图表展现 多边形绘制 拼图 笔刷 多图生成 导入PDF 流动线条 拖入元素 开源利用
我是开源图形编辑器,vue-fabric-editor的作者,明天整顿了一下fabric.js 能够实现的性能,用动图的模式分享给大家,不便疾速理解fabric.js。 源码见链接 辅助线 曲线文字 垂直文字 3D联合 自定义文字条 缩略图 白板 自定义管制条 Gif展现 图表展现 多边形绘制 拼图 笔刷 多图生成 导入PDF 流动线条 拖入元素 开源利用
前言在上个试验 Hyperledger Fabric 多组织多排序节点部署在多个主机上 中,咱们曾经实现了多组织多排序节点部署在多个主机上,但到目前为止,咱们所有的试验都只是钻研了联盟链的网络配置办法(只管这的确是重难点),而没有思考具体的利用开发。本文将在后面试验的根底上,首先尝试应用 Go 语言开发了一个工作室联盟链的我的项目信息智能合约,并胜利将其部署至联盟链上;而后根据官网示例,应用 fabric-gateway 模块实现了一个可能治理我的项目信息智能合约的客户端;之后比照了 fabric-gateway 模块和 fabric-sdk- 模块各自的优缺点,剖析官网示例源码实现了通过 fabric-sdk- 模块治理整个联盟链网络。个别语境下,本文默认智能合约等于链码。 工作筹备本文工作以三组织三排序节点的形式启动 Hyperledger Fabric 网络,试验共蕴含四个组织—— council 、 soft 、 web 、 hard , 其中 council 组织为网络提供 TLS-CA 服务,并且运行保护着三个 orderer 服务;其余每个组织都运行保护着一个 peer 节点、一个 admin 用户和一个 user 用户。网络结构为(试验代码已上传至:https://github.com/wefantasy/FabricLearn 的 6_ContractGatewayAndSDK 下): 项运行端口阐明council.ifantasy.net7050council 组织的 CA 服务, 为联盟链网络提供 TLS-CA 服务orderer1.council.ifantasy.net7051council 组织的 orderer1 服务orderer1.council.ifantasy.net7052council 组织的 orderer1 服务的 admin 服务orderer2.council.ifantasy.net7054council 组织的 orderer2 服务orderer2.council.ifantasy.net7055council 组织的 orderer2 服务的 admin 服务orderer3.council.ifantasy.net7057council 组织的 orderer3 服务orderer3.council.ifantasy.net7058council 组织的 orderer3 服务的 admin 服务soft.ifantasy.net7250soft 组织的 CA 服务, 蕴含成员: peer1 、 admin1 、user1peer1.soft.ifantasy.net7251soft 组织的 peer1 成员节点web.ifantasy.net7350web 组织的 CA 服务, 蕴含成员: peer1 、 admin1 、user1peer1.web.ifantasy.net7351web 组织的 peer1 成员节点hard.ifantasy.net7450hard 组织的 CA 服务, 蕴含成员: peer1 、 admin1 、user1peer1.hard.ifantasy.net7451hard 组织的 peer1 成员节点试验筹备本文网络结构间接将 Hyperledger Fabric无排序组织以Raft协定启动多个Orderer服务、TLS组织运行保护Orderer服务 中创立的 4-2_RunOrdererByCouncil 复制为 6_ContractGatewayAndSDK 并批改(倡议间接将本案例仓库 FabricLearn 下的 6_ContractGatewayAndSDK 目录拷贝到本地运行),文中大部分命令在 Hyperledger Fabric定制联盟链网络工程实际 中已有介绍因而不会具体阐明。默认状况下,所有命令皆在 6_ContractGatewayAndSDK 根目录下执行,在开始前面的试验前依照以下命令启动根底试验网络: ...
1、需要实现Canvas绘制多边形。 2、成果 3、代码官网Demo是HTML版本的,我改写了React版本。 // Copyright 2021 zhaoardenimport React, { useState,useCallback } from 'react';import { fabric } from "fabric";import { Button } from 'antd';class Polygon extends React.Component { constructor(props) { super(props); this.state={ canvas:{} } } componentDidMount(){ console.log('componentDidMount'); const canvas = new fabric.Canvas('c'); console.log('canvas',canvas); this.setState({canvas:canvas}) // console.log('state-canvas',this.state.canvas); var points = [{ x: 3, y: 4 }, { x: 16, y: 3 }, { x: 30, y: 5 }, { x: 25, y: 55 }, { x: 19, y: 44 }, { x: 15, y: 30 }, { x: 15, y: 55 }, { x: 9, y: 55 }, { x: 6, y: 53 }, { x: -2, y: 55 }, { x: -4, y: 40 }, { x: 0, y: 20 }] var polygon = new fabric.Polygon(points, { left: 100, top: 50, fill: '#D81B60', strokeWidth: 4, stroke: 'green', scaleX: 4, scaleY: 4, objectCaching: false, transparentCorners: false, cornerColor: 'blue', }); canvas.viewportTransform = [0.7, 0, 0, 0.7, -50, 50]; canvas.add(polygon); } render() { const controls={ display: 'inline-block' }; const {canvas}=this.state // define a function that can locate the controls. // this function will be used both for drawing and for interaction. function polygonPositionHandler(dim, finalMatrix, fabricObject) { var x = (fabricObject.points[this.pointIndex].x - fabricObject.pathOffset.x), y = (fabricObject.points[this.pointIndex].y - fabricObject.pathOffset.y); return fabric.util.transformPoint( { x: x, y: y }, fabric.util.multiplyTransformMatrices( fabricObject.canvas.viewportTransform, fabricObject.calcTransformMatrix() ) ); } // define a function that will define what the control does // this function will be called on every mouse move after a control has been // clicked and is being dragged. // The function receive as argument the mouse event, the current trasnform object // and the current position in canvas coordinate // transform.target is a reference to the current object being transformed, function actionHandler(eventData, transform, x, y) { var polygon = transform.target, currentControl = polygon.controls[polygon.__corner], mouseLocalPosition = polygon.toLocalPoint(new fabric.Point(x, y), 'center', 'center'), polygonBaseSize = polygon._getNonTransformedDimensions(), size = polygon._getTransformedDimensions(0, 0), finalPointPosition = { x: mouseLocalPosition.x * polygonBaseSize.x / size.x + polygon.pathOffset.x, y: mouseLocalPosition.y * polygonBaseSize.y / size.y + polygon.pathOffset.y }; polygon.points[currentControl.pointIndex] = finalPointPosition; return true; } // define a function that can keep the polygon in the same position when we change its // width/height/top/left. function anchorWrapper(anchorIndex, fn) { return function (eventData, transform, x, y) { var fabricObject = transform.target, absolutePoint = fabric.util.transformPoint({ x: (fabricObject.points[anchorIndex].x - fabricObject.pathOffset.x), y: (fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y), }, fabricObject.calcTransformMatrix()), actionPerformed = fn(eventData, transform, x, y), newDim = fabricObject._setPositionDimensions({}), polygonBaseSize = fabricObject._getNonTransformedDimensions(), newX = (fabricObject.points[anchorIndex].x - fabricObject.pathOffset.x) / polygonBaseSize.x, newY = (fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y) / polygonBaseSize.y; fabricObject.setPositionByOrigin(absolutePoint, newX + 0.5, newY + 0.5); return actionPerformed; } } function Edit() { console.log('canvas',canvas); console.log('Edit'); // clone what are you copying since you // may want copy and paste on different moment. // and you do not want the changes happened // later to reflect on the copy. var poly = canvas.getObjects()[0]; canvas.setActiveObject(poly); poly.edit = !poly.edit; if (poly.edit) { var lastControl = poly.points.length - 1; poly.cornerStyle = 'circle'; poly.cornerColor = 'rgba(0,0,255,0.5)'; poly.controls = poly.points.reduce(function (acc, point, index) { acc['p' + index] = new fabric.Control({ positionHandler: polygonPositionHandler, actionHandler: anchorWrapper(index > 0 ? index - 1 : lastControl, actionHandler), actionName: 'modifyPolygon', pointIndex: index }); return acc; }, {}); } else { poly.cornerColor = 'blue'; poly.cornerStyle = 'rect'; poly.controls = fabric.Object.prototype.controls; } poly.hasBorders = !poly.edit; canvas.requestRenderAll(); } return <div> <h1>Learn, {this.props.name}</h1> <div className={controls}> <p> <Button id="edit" onClick={Edit}>Toggle editing polygon</Button> </p> </div> <canvas id="c" width="500" height="400" style={{border:'1px solid #ccc'}}></canvas> </div>; }}export default Polygon;参考文档http://fabricjs.com/docs/fabr... ...
1、即便没有人为你鼓掌,也要优雅的谢幕,感激本人的认真付出。 2、只有小孩子才问你为什么不理我,成年人都是心领神会地互相疏远。 3、不要向任何人诉苦,因为20%的人不关怀,还有80%的人听到后很快乐。 4、遇见的人多了,你才会明确哪些人值得用生命去珍惜,哪些人只适宜绕道而行。 5、有时候,咱们必须闭上嘴,放下自豪,抵赖是本人错了。这不是认输,而是成长。 6、该扔的就扔,该放弃就放弃,从今天起,余生做个俗人,以本人最好的姿势生存。 7、生存有一百种过法,他人的故事再好,始终容不下你。活成什么样子,本人决定。 8、生存就是这样,痛并高兴着。好的坏的咱们都收下吧,而后一声不响,持续生存。 9、凡是能说透的货色,根本也就是释怀了,要晓得,心结,是说不清楚的,甚至说不出口。 10、凶恶要有底线,慷慨要有准则。不分青红皂白,只晓得对人好,那会辜负本人的一片善意。 11、无论这个世界对你怎么,都请你判若两人的致力,人生是一场一个人的旅程,无人可代替。 12、别总因为迁就他人就冤屈本人,弯腰的工夫久了,只会让人习惯于你的低姿态,你的不重要。 13、难熬的日子总会过来,不信你回头看看,你都曾经在人不知;鬼不觉中,熬过了很多苦难,很棒吧。 14、这世界上除了生命,其实没什么货色让你迷失本人,学会笑着接受,笑着说:没什么了不起! 15、你长大了,你须要的,是一个可能爱护你爱护你的人,而不是一个只晓得让你付出和惆怅的人。 16、有时候疏远不是厌恶,而是太喜爱又很无奈,我不想抱着冀望期待落空,只好伪装慷慨本人先走。 17、大多数时候,耗费你能量的都不是工作,而是工作中遇到的人。干活自身是不累的,均衡情绪最累。 18、不要到处鼓吹你的心田,这世上不止你一个人有故事;也不要到处宣泄你的苦楚,没人会感同身受。 19、没有人会活得一无是处,也没有人能活得了无遗憾;美妙的生存,并不是没有瑕疵,而是懂得取舍。 20、任何人都是这样,解决他人的事件总是大刀阔斧一把抓住问题,轮到本人却沉迷在细枝末节不肯撒手。 21、茶凉了,就别再续了,再续也不是原来的滋味了;人走了,就别再留了,再留下也不是原来的感觉了。 22、能笑的时候就开心大笑,感觉累了痛了就纵情地哭。每个人在这世上都是惟一,做就做最实在的本人。 23、累的时候抱抱本人,哭的时候哄哄本人,身边不可能无时无刻有一个人陪着你宠着你,要学会本人疼本人。 24、小时候认为流血了,就是很重大的事件,不论痛不痛,先哭再说,长大当前才发现,原来流泪,比流血还要疼。 25、看淡一点,再致力一点,越致力越侥幸,这世上没有谁活得比谁容易,只是有人在呼天喊地,有人在静默坚守。 26、当你下定决定做一件事,那就去尽力做,给本人一个期限,不必通知所有人,也不要犹豫,直到你真的尽力为止。 27、抓不紧的就放掉,得不到的就放弃,这并不是没有毅力,而是智慧的抉择。切记不要浪费时间在得不到后果的人和事上。
<script>export default { data () { return { setColor: ['#FF0000', '#F2C94C', '#EBFF00', '#9B51E0', '#6FCF97', '#F2F2F2', '#00FFF0', '#33FF00', '#00A3FF', '#FF00C7', '#FF7A00', '#0075FF'] } }, mounted () { }, methods: { oCoords (w, h, x2, y2, reg) { return { tl: this.rotatoNi(x2 - w / 2, y2 - h / 2, x2, y2, reg), tr: this.rotatoNi(x2 + w / 2, y2 - h / 2, x2, y2, reg), bl: this.rotatoNi(x2 - w / 2, y2 + h / 2, x2, y2, reg), br: this.rotatoNi(x2 + w / 2, y2 + h / 2, x2, y2, reg) } }, rotatoNi (x1, y1, x2, y2, reg) { // 在平面坐标上,任意点P(x1,y1),绕一个坐标点Q(x2,y2)逆时针旋转角度后,新的坐标设为(x, y)的计算公式: // x= (x1 - x2)*cos() - (y1 - y2)*sin() + x2 ; // y= (x1 - x2)*sin() + (y1 - y2)*cos() + y2 ; let x = parseInt((x1 - x2) * Math.cos(Math.PI * reg / 180) - (y1 - y2) * Math.sin(Math.PI * reg / 180) + x2); let y = parseInt((x1 - x2) * Math.sin(Math.PI * reg / 180) + (y1 - y2) * Math.cos(Math.PI * reg / 180) + y2); return { x: x, y: y } //旋转后的坐标(x,y) }, rotatoNi2 (x1, y1, x2, y2, reg) { let x = ((x1 - x2) * Math.cos(Math.PI * reg / 180) - (y1 - y2) * Math.sin(Math.PI * reg / 180) + x2); let y = ((x1 - x2) * Math.sin(Math.PI * reg / 180) + (y1 - y2) * Math.cos(Math.PI * reg / 180) + y2); return { x: x, y: y } //旋转后的坐标(x,y) }, //左上角直角三角形 creatPath (list, i, type) { //console.log('以后箱体左上角直角三角形数据', list, i, type) let wc = 0 let x1 = list.x - list.width / 2 + wc let y1 = list.y - list.height / 2 + wc let prot = this.rotatoNi(x1, y1, list.x, list.y, list.rotationAngle) let x = prot.x let y = prot.y let u = 'M ' + x + ' ' + y + ' L ' + (x + 10) + ' ' + y + ' L ' + x + ' ' + (y + 10) + ' z' var path = new fabric.Path(u); //console.log(i + '三角形的坐标点', x, y) return path.set({ angle: list.rotationAngle, left: x, //间隔画布上边的间隔 top: y, //间隔画布左侧的间隔,单位是像素 fill: '#FFFFFF', //填充的色彩 selectable: false, stroke: '#FFFFFF', // 边框色彩 opacity: 0.3, strokeWidth: 1, id: list.id, networkPort: list.networkPort, operateType: type, }); }, //创立中心点 makeCircle2 (list) { var circle = new fabric.Circle({ originX: "center", originY: "center", left: list.x, //间隔画布上边的间隔 top: list.y, //间隔画布左侧的间隔,单位是像素 radius: 4, //圆形半径 fill: '#000', //填充的色彩 stroke: this.setColor[list.portId % 12] ? this.setColor[list.portId % 12] : '#fff', // 边框色彩 selectable: false, evented: false, id: list.id, networkPort: list.networkPort, index: list.index, hoverCursor: "pointer",//鼠标指针形式 strokeWidth: 2 // 边框大小 }); return circle }, //创立文本 makeText (t, list, i, type) { let x1 = list.x - list.width / 2 let y1 = list.y - list.height / 2 let prot = this.rotatoNi(x1, y1, list.x, list.y, list.rotationAngle) let x = (prot.x - list.x) / 1.5 + list.x let y = (prot.y - list.y) / 1.5 + list.y //console.log(i + '文本的坐标点', x, y) var textBox = new fabric.Textbox(t, { /* originX: "left", originY: "top", */ originX: "center", originY: "center", left: x, top: y, centeredRotation: true, //核心旋转 fontSize: 12, selectable: false, evented: false, networkPort: list.networkPort, fill: '#fff', id: list.id, operateType: type, }); return textBox }, //创立矩形 makeRect (left, top, ids, width, height, angle, groupId, boxId, boxFileId) { let rect = new fabric.Rect({ //rx: 4, //圆角半径 // ry: 4, //圆角半径 angle: angle, left: left, top: top, originX: "center", //绝对于坐标点地位 originY: "center", //绝对于坐标点地位 width: width, height: height, //hoverCursor: "pointer", fill: "rgba(0,153,255,0.20)",//"#1C445E", stroke: '#136094', // 边框色彩 strokeWidth: 2, // 边框大小 borderColor: "#0099FF", //选中边框色 cornerStyle: "circle", // 手柄形态 正方形 rect||圆 circle cornerColor: "#0099FF", //手柄背景色 cornerStrokeColor: "#0099FF", //手柄框边框 hasControls: true, //手柄 hasBorders: true, //手柄线 visible: true, //是否可见 selectable: true, //是否可抉择的对象 evented: true, //是否拖动 centeredRotation: true, //核心旋转 centeredScaling: true, //居中缩放 transparentCorners: false, //选中框通明角 preserveObjectStacking: true, // opacity: 0.5, networkPort: ids.networkPort,//网口 index: ids.index,//序号 groupId: groupId, id: boxId ? boxId : null, boxFileId: boxFileId, //lockRotation: true,//锁定对象旋转 }); rect.setControlsVisibility({ mt: false, mb: false, bl: false, br: false, tl: false, tr: false, mr: false, ml: false, mtr: true, }); return rect; }, //创立线段 /* coords 坐标 list 以后对象 arr虚线 jt, 虚线箭头 */ makeLine (coords, list, arr, jt, startId, endId) { //console.log('list.networkPort', list.networkPort) return new fabric.Line(coords, { fill: this.setColor[list && list.portId % 12] ? this.setColor[list && list.portId % 12] : '#fff', stroke: this.setColor[list && list.portId % 12] ? this.setColor[list && list.portId % 12] : '#fff', strokeWidth: 2, originX: "center", originY: "center", selectable: false, evented: false, hasControls: false, hasBorders: false, hasRotatingPoint: false, hoverCursor: "default", index: list.index, networkPort: list && list.networkPort, jt: jt || '', id: list && list.id, startId, endId, //myJoker: arr, strokeDashArray: arr || [], huadongbs: list.huadongbs || false }); }, //创立连线上的实体三角形箭头 createArrowHead (x1, y1, x2, y2, width, height, list, type, startId, endId) { return new fabric.Triangle({ angle: this.getAngle(x1, y1, x2, y2), fill: "white", top: y2, left: x2, width: width, height: height, originX: "center", originY: "center", selectable: false, evented: false, id: list.id, index: list.index, networkPort: list.networkPort, startId, endId, huadongbs: list.huadongbs || false }); }, /* 绘制箭头函数 ------->-------- fromX, fromY:终点坐标(也能够换成p1,只不过它是一个数组) toX, toY:起点坐标 (也能够换成p2,只不过它是一个数组) theta:三角斜边一直线夹角 headlen:三角斜边长度 width:箭头线宽度 color:箭头色彩 */ drawArrow (canvas, fromX, fromY, toX, toY, theta, headlen, width, color) { width = 1;//箭头宽度设置为1 var theta = theta || 30, headlen = headlen || 10, width = width || 1, color = color || '#000', angle = Math.atan2(fromY - toY, fromX - toX) * 180 / Math.PI, angle1 = (angle + theta) * Math.PI / 180, angle2 = (angle - theta) * Math.PI / 180, topX = headlen * Math.cos(angle1), topY = headlen * Math.sin(angle1), botX = headlen * Math.cos(angle2), botY = headlen * Math.sin(angle2); var arrowX, arrowY; arrowX = toX + topX; //箭头结尾右边坐标 arrowY = toY + topY; canvas.add(this.makeLine([arrowX, arrowY, toX, toY], '', [], 'jt')); //ctx.moveTo(arrowX, arrowY); //ctx.lineTo(toX, toY); //箭头开始坐标 arrowX = toX + botX; //箭头结尾左边坐标 arrowY = toY + botY; canvas.add(this.makeLine([arrowX, arrowY, toX, toY], '', [], 'jt')); // ctx.lineTo(arrowX, arrowY); }, //三角形角度计算 getAngle (x1, y1, x2, y2) { var dx = x2 - x1, dy = y2 - y1, angle = Math.atan2(dy, dx); angle *= 180 / Math.PI; angle += 90; return angle; }, // //扭转画布大小 // zoomIt (factor) { // factor: 比例 // let cWidth = canvas.width; // canvas.setWidth(cWidth * factor); // canvas.setHeight(cWidth * factor); // if (canvas.backgroundImage) { // var bi = canvas.backgroundImage; // bi.width = bi.width * factor; // bi.height = bi.height * factor; // } // var objects = canvas.getObjects(); // for (var i in objects) { // var scaleX = objects[i].scaleX; // var scaleY = objects[i].scaleY; // var left = objects[i].left; // var top = objects[i].top; // var tempScaleX = scaleX * factor; // var tempScaleY = scaleY * factor; // var tempLeft = left * factor; // var tempTop = top * factor; // objects[i].scaleX = tempScaleX; // objects[i].scaleY = tempScaleY; // objects[i].left = tempLeft; // objects[i].top = tempTop; // objects[i].setCoords(); // } // canvas.renderAll(); // canvas.calcOffset(); // }, //阻止右键默认行为 preventYj () { $(document).contextmenu(function (ev) { if (ev.preventDefault) { ev.preventDefault(); } else { window.event.returnValue = false; } }) }, getTanDeg (tan) { var result = Math.atan(tan) / (Math.PI / 180); result = parseInt(result); return result; }, //自定义批改序号从新排序 setArrIndex (str, end, list) { for (var i = 0; i < list.length; i++) { if (end.index > list[i].index && list[i].index > str.index) { list[i].index = list[i].index + 1 } if (end.id == list[i].id) { list[i].index = str.index + 1 } } list = list.sort((a, b) => { return a.index - b.index }); return list; }, //自定义批改序号从新排序 setArrIndex2 (str, end, list) { //序号2和4 理论就是3和4调换地位 if (str.index < end.index) { list[str.index] = list.splice(end.index - 1, 1, list[str.index])[0]; for (var i = 0; i < list.length; i++) { list[i].index = i + 1 } } else { list[end.index - 1].index = str.index for (var i = 0; i < list.length; i++) { if (str.index > list[i].index && list[i].index > end.index) { list[i].index = list[i].index - 1 } } list[str.index - 1].index = str.index - 1 list = list.sort((a, b) => { return a.index - b.index }); } return list; }, compare (pro) { return function (obj1, obj2) { var val1 = obj1[pro]; var val2 = obj2[pro]; if (val1 < val2) { //正序 return 1; } else if (val1 > val2) { return -1; } else { return 0; } } }, isMouseoeut (x, y) { let that = this var a = -15 let cdiv = document.getElementById("canvasZone") var X1 = that.getOffsetLeft(cdiv) - a var Y1 = that.getOffsetTop(cdiv) - a var X2 = that.getOffsetLeft(cdiv) + cdiv.offsetWidth + a var Y2 = that.getOffsetTop(cdiv) + cdiv.offsetHeight + a if (x < X2 && x > X1 && y < Y2 && y > Y1) { return true } else { return false } }, groupAdd (list, canvas) { //console.log('旧式分组') /* x.y示意左上角点 */ var x1 = -50, y1 = -50, width = 100, height = 100; let x = list.x - list.width / 2 let y = list.y - list.height / 2 let u = 'M ' + x + ' ' + y + ' L ' + (x + 10) + ' ' + y + ' L ' + x + ' ' + (y + 10) + ' z' var path2 = new fabric.Path(u); //左上角三角形 path2.set({ left: this.face == true ? (-(list.width / 2)) : (list.width / 2), left: this.showFace == true ? (-(list.width / 2)) : (list.width / 2), top: -(list.height / 2), fill: '#dadcdb', //填充的色彩 opacity: list.boxStatus == 1 ? 0.3 : 1, strokeWidth: 1, angle: this.face == true ? 0 : 90, angle: this.showFace == true ? 0 : 90, }) var t = list.index == 0 ? '' : (list.slotId ? list.slotId : 0) + "_" + (list.portId ? list.portId : 0) + "_" + list.index //文字 // console.log(this.face); var text2 = new fabric.Text(t, { angle: -list.rotationAngle, fontSize: 12, originX: 'center', originY: 'center', fill: '#fff', left: this.face == true ? (-(list.width / 2) + 20) : (list.width / 2 - 20), left: this.showFace == true ? (-(list.width / 2) + 20) : (list.width / 2 - 20), top: -(list.height / 2) + 20, }); //中心点 var circle2 = new fabric.Circle({ originX: "center", originY: "center", radius: 4, //圆形半径 fill: '#000', //填充的色彩 stroke: this.setColor[list.portId] ? this.setColor[list.portId] : '#fff', // 边框色彩 selectable: false, evented: false, hoverCursor: "pointer",//鼠标指针形式 strokeWidth: 2 // 边框大小 }); //矩形 var rect2 = new fabric.Rect({ width: list.width, height: list.height, originX: 'center', originY: 'center', fill: "rgba(0,153,255,0.20)",//"#1C445E", stroke: '#136094', // 边框色彩 strokeWidth: 2, // 边框大小 borderColor: "#0099FF", //选中边框色 cornerStyle: "circle", // 手柄形态 正方形 rect||圆 circle cornerColor: "#0099FF", //手柄背景色 cornerStrokeColor: "#0099FF", //手柄框边框 centeredRotation: true, portId: list.portId, slotId: list.slotId, isSwitch: list.isSwitch, }); var group2 = new fabric.Group([rect2, circle2, text2, path2], { left: list.x, top: list.y, width: list.width, height: list.height, originX: 'center', originY: 'center', isCheckTo: true, //有这个字段示意单选,没有多选 networkPort: list.networkPort,//网口 index: list.index,//序号 groupId: 'box', groupIdd: list.groupId, id: list.id, angle: list.rotationAngle, centeredRotation: true, fill: "#0099FF",//"#1C445E", stroke: '#0099FF', // 边框色彩 strokeWidth: 2, // 边框大小 borderColor: "#0099FF", //选中边框色 cornerStyle: "circle", // 手柄形态 正方形 rect||圆 circle cornerColor: "#0099FF", //手柄背景色 cornerStrokeColor: "#0099FF", //手柄框边框 huadongbs: list.huadongbs || false, boxFileId: list.boxFileId, portId: list.portId, slotId: list.slotId, isSwitch: list.isSwitch, //scaleX: this.canvasZoom, //scaleY: this.canvasZoom }); return group2 } },};</script>
本文不会在从0开始搭建这个那个网络,咱们会在<<Hyperledger Fabric 2.0 手动生成CA证书搭建Fabric网络-Raft协定>>的根底上来改良,有上文中单orderer节点改成多节点共识。 本次将orderer改为三个节点, 本人须要更多节点的能够本人依据机会状况进行减少,步骤和办法雷同。 一、orderer节点用户注册(TLS)在向TLS注册用户是,有以前注册单用户改成注册多用户(三个节点、orderer1-org0,orderer2-org0,orderer3-org0)https://0.0.0.0:7052为TLS CA 地址, fabric-ca-client register -d --id.name orderer1-org0 --id.secret ordererPW --id.type orderer-u https://0.0.0.0:7052 --tls.certfiles /tmp/hyperledger/fabric-ca-tls/crypto/ca-cert.pemfabric-ca-client register -d --id.name orderer2-org0 --id.secret ordererPW --id.type orderer -u https://0.0.0.0:7052 --tls.certfiles /tmp/hyperledger/fabric-ca-tls/crypto/ca-cert.pemfabric-ca-client register -d --id.name orderer3-org0 --id.secret ordererPW --id.type orderer -u https://0.0.0.0:7052 --tls.certfiles /tmp/hyperledger/fabric-ca-tls/crypto/ca-cert.pem二、org0注册用户同样须要注册三个节点用户 export FABRIC_CA_CLIENT_TLS_CERTFILES=/data/hyperledger/org0/ca/crypto/ca-cert.pemexport FABRIC_CA_CLIENT_HOME=/data/hyperledger/org0/ca/adminfabric-ca-client enroll -d -u https://org0-admin:org0-adminpw@0.0.0.0:7053 --tls.certfiles /tmp/hyperledger/org0/ca/crypto/ca-cert.pem#注册order1用户fabric-ca-client register -d --id.name orderer1-org0 --id.secret ordererpw --id.type orderer --id.attrs '"hf.Registrar.Roles=orderer"' -u https://0.0.0.0:7053 --tls.certfiles /tmp/hyperledger/org0/ca/crypto/ca-cert.pem#注册order2用户fabric-ca-client register -d --id.name orderer2-org0 --id.secret ordererpw --id.type orderer --id.attrs '"hf.Registrar.Roles=orderer"' -u https://0.0.0.0:7053 --tls.certfiles /tmp/hyperledger/org0/ca/crypto/ca-cert.pem#注册order3用户fabric-ca-client register -d --id.name orderer3-org0 --id.secret ordererpw --id.type orderer --id.attrs '"hf.Registrar.Roles=orderer"' -u https://0.0.0.0:7053 --tls.certfiles /tmp/hyperledger/org0/ca/crypto/ca-cert.pemfabric-ca-client register -d --id.name admin-org0 --id.secret org0adminpw --id.type admin --id.attrs "hf.Registrar.Roles=client,hf.Registrar.Attributes=*,hf.Revoker=true,hf.GenCRL=true,admin=true:ecert,abac.init=true:ecert" -u https://0.0.0.0:7053 --tls.certfiles /tmp/hyperledger/org0/ca/crypto/ca-cert.pem三、生成oerders MSP证书mkdir -p /tmp/hyperledger/org0/orderers/assets/ca/cp /tmp/hyperledger/org0/ca/crypto/ca-cert.pem /tmp/hyperledger/org0/orderers/assets/ca/org0-ca-cert.pemexport FABRIC_CA_CLIENT_HOME=/tmp/hyperledger/org0/orderers/orderer1-org0#orderer1 msp证书export FABRIC_CA_CLIENT_TLS_CERTFILES=/tmp/hyperledger/org0/orderers/assets/ca/org0-ca-cert.pemexport FABRIC_CA_CLIENT_MSPDIR=mspfabric-ca-client enroll -u https://orderer1-org0:ordererpw@0.0.0.0:7053 -M /tmp/hyperledger/org0/orderers/orderer1-org0/msp --csr.hosts orderer1-org0 --tls.certfiles /tmp/hyperledger/org0/ca/crypto/ca-cert.pem#orderer2 msp证书export FABRIC_CA_CLIENT_HOME=/tmp/hyperledger/org0/orderers/orderer2-org0export FABRIC_CA_CLIENT_TLS_CERTFILES=/tmp/hyperledger/org0/orderers/assets/ca/org0-ca-cert.pemexport FABRIC_CA_CLIENT_MSPDIR=mspfabric-ca-client enroll -u https://orderer2-org0:ordererpw@0.0.0.0:7053 -M /tmp/hyperledger/org0/orderers/orderer2-org0/msp --csr.hosts orderer2-org0 --tls.certfiles /tmp/hyperledger/org0/ca/crypto/ca-cert.pem#orderer3 msp证书export FABRIC_CA_CLIENT_HOME=/tmp/hyperledger/org0/orderers/orderer3-org0export FABRIC_CA_CLIENT_TLS_CERTFILES=/tmp/hyperledger/org0/orderers/assets/ca/org0-ca-cert.pemexport FABRIC_CA_CLIENT_MSPDIR=mspfabric-ca-client enroll -u https://orderer3-org0:ordererpw@0.0.0.0:7053 -M /tmp/hyperledger/org0/orderers/orderer3-org0/msp --csr.hosts orderer3-org0 --tls.certfiles /tmp/hyperledger/org0/ca/crypto/ca-cert.pem#admin msp证书export FABRIC_CA_CLIENT_HOME=/tmp/hyperledger/org0/adminexport FABRIC_CA_CLIENT_TLS_CERTFILES=/tmp/hyperledger/org0/orderers/assets/ca/org0-ca-cert.pemexport FABRIC_CA_CLIENT_MSPDIR=mspfabric-ca-client enroll -d -u https://admin-org0:org0adminpw@0.0.0.0:7053 --tls.certfiles /tmp/hyperledger/org0/orderers/assets/ca/org0-ca-cert.pem四、生成oerders tls-ca证书mkdir /tmp/hyperledger/org0/orderers/assets/tls-ca/cp /tmp/hyperledger/fabric-ca-tls/crypto/ca-cert.pem /tmp/hyperledger/org0/orderers/assets/tls-ca/tls-ca-cert.pemexport FABRIC_CA_CLIENT_MSPDIR=tls-mspexport FABRIC_CA_CLIENT_TLS_CERTFILES=/tmp/hyperledger/org0/orderers/assets/tls-ca/tls-ca-cert.pemfabric-ca-client enroll -u https://orderer1-org0:ordererPW@0.0.0.0:7052 -M /tmp/hyperledger/org0/orderers/orderer1-org0/tls-msp --enrollment.profile tls --csr.hosts orderer1-org0 --tls.certfiles /data/hyperledger/org0/orderers/tls-ca-cert.pemfabric-ca-client enroll -u https://orderer2-org0:ordererPW@0.0.0.0:7052 -M /tmp/hyperledger/org0/orderers/orderer2-org0/tls-msp --enrollment.profile tls --csr.hosts orderer2-org0 --tls.certfiles /data/hyperledger/org0/orderers/tls-ca-cert.pemfabric-ca-client enroll -u https://orderer3-org0:ordererPW@0.0.0.0:7052 -M /tmp/hyperledger/org0/orderers/orderer3-org0/tls-msp --enrollment.profile tls --csr.hosts orderer3-org0 --tls.certfiles /data/hyperledger/org0/orderers/tls-ca-cert.pem#批改keystore名称mv /tmp/hyperledger/org0/orderers/orderer1-org0/tls-msp/keystore/*_sk /tmp/hyperledger/org0/orderers/orderer1-org0/tls-msp/keystore/key.pemmv /tmp/hyperledger/org0/orderers/orderer2-org0/tls-msp/keystore/*_sk /tmp/hyperledger/org0/orderers/orderer2-org0/tls-msp/keystore/key.pemmv /tmp/hyperledger/org0/orderers/orderer3-org0/tls-msp/keystore/*_sk /tmp/hyperledger/org0/orderers/orderer3-org0/tls-msp/keystore/key.pem#生成admincerts目录mkdir /tmp/hyperledger/org0/orderers/orderer1-org0/msp/admincertscp /tmp/hyperledger/org0/admin/msp/signcerts/cert.pem /data/hyperledger/org0/orderers/orderer1-org0/msp/admincerts/orderer-admin-cert.pemmkdir /tmp/hyperledger/org0/orderers/orderer2-org0/msp/admincertscp /tmp/hyperledger/org0/admin/msp/signcerts/cert.pem /data/hyperledger/org0/orderers/orderer2-org0/msp/admincerts/orderer-admin-cert.pemmkdir /tmp/hyperledger/org0/orderers/orderer3-org0/msp/admincertscp /tmp/hyperledger/org0/admin/msp/signcerts/cert.pem /data/hyperledger/org0/orderers/orderer3-org0/msp/admincerts/orderer-admin-cert.pem⚠️: 同理在每个orderer节点msp上面增加config.yaml文件 ...