• fabic.js Stickman应用》》元素关联设置/拓扑图


    需求:canvas画布上绘制多个圆形,并添加连接线,图形移动,线自动跟随移动。类似于拓扑关系。

    查看fabic文档,Stickman火柴人demo完美适应。官网具体代码如下:

    1. (function() {
    2. var canvas = this.__canvas = new fabric.Canvas('c', { selection: false });
    3. fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';
    4. function makeCircle(left, top, line1, line2, line3, line4) {
    5. var c = new fabric.Circle({
    6. left: left,
    7. top: top,
    8. strokeWidth: 5,
    9. radius: 12,
    10. fill: '#fff',
    11. stroke: '#666'
    12. });
    13. c.hasControls = c.hasBorders = false;
    14. c.line1 = line1;
    15. c.line2 = line2;
    16. c.line3 = line3;
    17. c.line4 = line4;
    18. return c;
    19. }
    20. function makeLine(coords) {
    21. return new fabric.Line(coords, {
    22. fill: 'red',
    23. stroke: 'red',
    24. strokeWidth: 5,
    25. selectable: false,
    26. evented: false,
    27. });
    28. }
    29. var line = makeLine([ 250, 125, 250, 175 ]),
    30. line2 = makeLine([ 250, 175, 250, 250 ]),
    31. line3 = makeLine([ 250, 250, 300, 350]),
    32. line4 = makeLine([ 250, 250, 200, 350]),
    33. line5 = makeLine([ 250, 175, 175, 225 ]),
    34. line6 = makeLine([ 250, 175, 325, 225 ]);
    35. canvas.add(line, line2, line3, line4, line5, line6);
    36. canvas.add(
    37. makeCircle(line.get('x1'), line.get('y1'), null, line),
    38. makeCircle(line.get('x2'), line.get('y2'), line, line2, line5, line6),
    39. makeCircle(line2.get('x2'), line2.get('y2'), line2, line3, line4),
    40. makeCircle(line3.get('x2'), line3.get('y2'), line3),
    41. makeCircle(line4.get('x2'), line4.get('y2'), line4),
    42. makeCircle(line5.get('x2'), line5.get('y2'), line5),
    43. makeCircle(line6.get('x2'), line6.get('y2'), line6)
    44. );
    45. canvas.on('object:moving', function(e) {
    46. var p = e.target;
    47. p.line1 && p.line1.set({ 'x2': p.left, 'y2': p.top });
    48. p.line2 && p.line2.set({ 'x1': p.left, 'y1': p.top });
    49. p.line3 && p.line3.set({ 'x1': p.left, 'y1': p.top });
    50. p.line4 && p.line4.set({ 'x1': p.left, 'y1': p.top });
    51. canvas.renderAll();
    52. });
    53. })();

    我在vue项目中使用,变形如下:

    1. <script>
    2. import { mapGetters } from 'vuex'
    3. import { getMapList } from '@/api/table'
    4. // import fabric from 'fabric'
    5. let canvas = ''
    6. export default {
    7. name: 'Dashboard',
    8. computed: {
    9. ...mapGetters([
    10. 'name'
    11. ])
    12. },
    13. data () {
    14. return {
    15. width: window.innerWidth,
    16. height: window.innerHeight,
    17. activeEl: {}// 获取当前点击元素
    18. }
    19. },
    20. mounted () {
    21. canvas = new fabric.Canvas('editorCanvas', {
    22. width: this.width,
    23. height: this.height,
    24. selection: false,
    25. backgroundColor: '#ffffff',
    26. transparentCorners: false,
    27. fireRightClick: true, // 启用右键,button的数字为3
    28. stopContextMenu: true // 禁止默认右键菜单
    29. })
    30. var line = this.makeLine([250, 125, 250, 175])
    31. var line2 = this.makeLine([250, 175, 250, 250])
    32. var line3 = this.makeLine([250, 250, 300, 350])
    33. var line4 = this.makeLine([250, 250, 200, 350])
    34. var line5 = this.makeLine([250, 175, 175, 225])
    35. var line6 = this.makeLine([250, 175, 325, 225])
    36. canvas.add(line, line2, line3, line4, line5, line6)
    37. canvas.add(
    38. this.makeCircle(line.get('x1'), line.get('y1'), null, line),
    39. this.makeCircle(line.get('x2'), line.get('y2'), line, line2, line5, line6),
    40. this.makeCircle(line2.get('x2'), line2.get('y2'), line2, line3, line4),
    41. this.makeCircle(line3.get('x2'), line3.get('y2'), line3),
    42. this.makeCircle(line4.get('x2'), line4.get('y2'), line4),
    43. this.makeCircle(line5.get('x2'), line5.get('y2'), line5),
    44. this.makeCircle(line6.get('x2'), line6.get('y2'), line6)
    45. )
    46. canvas.on('object:moving', function (e) {
    47. var p = e.target
    48. p.line1 && p.line1.set({ 'x2': p.left, 'y2': p.top })
    49. p.line2 && p.line2.set({ 'x1': p.left, 'y1': p.top })
    50. p.line3 && p.line3.set({ 'x1': p.left, 'y1': p.top })
    51. p.line4 && p.line4.set({ 'x1': p.left, 'y1': p.top })
    52. canvas.renderAll()
    53. })
    54. },
    55. methods: {
    56. makeCircle (left, top, line1, line2, line3, line4) {
    57. var c = new fabric.Circle({
    58. left: left,
    59. top: top,
    60. strokeWidth: 5,
    61. radius: 12,
    62. fill: '#fff',
    63. stroke: '#666',
    64. originX: 'center',
    65. originY: 'center'
    66. })
    67. c.hasControls = c.hasBorders = false
    68. c.line1 = line1
    69. c.line2 = line2
    70. c.line3 = line3
    71. c.line4 = line4
    72. return c
    73. },
    74. makeLine (coords) {
    75. return new fabric.Line(coords, {
    76. fill: 'red',
    77. stroke: 'red',
    78. strokeWidth: 5,
    79. selectable: false,
    80. evented: false, originX: 'center',
    81. originY: 'center'
    82. })
    83. }
    84. }
    85. }
    86. script>
    87. <style lang="scss" scoped>
    88. style>

    效果如图(随便拖动一点移动,关联线自动跟随):

    分析:最核心代码为set({ 'x2': p.left, 'y2': p.top }),通过为canvas添加元素移动判定canvas.on('object:moving',根据移动重新设定线段的绘制坐标。

    变形使用:(仅为逻辑,请自行编写判定逻辑)

    1. canvas.on('object:moving', function (e) {
    2. var p = e.target
    3. if (....) { /* 判定我移动的元素是点 ,即是移动会改变关联的元素*/
    4. canvas.forEachObject(function (object) {
    5. if(....){ /* 定位到关联的线 */
    6. object.set({ 'x1': p.left, 'y1': p.top })
    7. }
    8. })
    9. }
    10. })

  • 相关阅读:
    Java八股文总结(二)
    如何使用 ABAP 创建包含不同字体大小的 Word 文档
    JAVA计算机毕业设计医院设备管理系统Mybatis+源码+数据库+lw文档+系统+调试部署
    i.MX 6ULL 驱动开发 二十:RTC
    vue3 编写.netcore可视组件
    C#__资源访问冲突和死锁问题
    力扣之二分法
    Java泛型详解,史上最全图文详解!
    pywintypes.error: (6, ‘SetClipboardData‘, ‘句柄无效。‘)
    【最新鸿蒙应开发】——HarmonyOS沙箱目录
  • 原文地址:https://blog.csdn.net/Thea12138/article/details/133028548