收藏
回答

使用canvas实现类似流程节点的图,在真机调试和预览时 安卓手机样式乱了?

,请问这个问题该怎么解决?

回答关注问题邀请回答
收藏

2 个回答

  • Jerry
    Jerry
    2023-11-10

    贴代码

    2023-11-10
    有用 1
    回复 7
    • 529
      529
      2023-11-10
      贴在楼下了
      2023-11-10
      回复
    • 529
      529
      2023-11-10
      nodes静态的没有问题,在请求后再赋值的出现这个问题的
      2023-11-10
      回复
    • Jerry
      Jerry
      2023-11-10回复529
      你先不要画连接线,只画节点看看正常不
      2023-11-10
      回复
    • Jerry
      Jerry
      2023-11-10
      另外,你用的还是旧版画布接口吗? 新版ctx.draw()已经不用了
      2023-11-10
      回复
    • 529
      529
      2023-11-10
      单独话节点也是一样的有问题,旧的画布,但是官网说的从基础库 2.9.0 开始,接口停止维护,我用的时2.33.0
      2023-11-10
      回复
    查看更多(2)
  • 529
    529
    2023-11-10
    const wxapi =require("../../utils/httpApi.js")
    Page({
        data: {
            kxgwId:'',
            canvasWidth: 0,//画布宽
            canvasHeight: 0,//画布高
            corridorArr:[0,0,0],//计算甬道的宽存储(对应左,中,右)
            clickNode:{},//当前点击的节点
            gkTypeObj:{
                "41":{
                    text:"个人关卡",
                    image:'../images/kcview/icon_gr.png'
                },
                "42":{
                    text:"团队关卡",
                    image:'../images/kcview/icon_td.png'
                },
                "43":{
                    text:"考试关卡",
                    image:'../images/kcview/icon_ks.png'
                },
                "44":{
                    text:"教师授课",
                    image:'../images/kcview/icon_sk.png'
                },
                "45":{
                    text:"评价模板",
                    image:'../images/kcview/icon_pj.png'
                },
                "51":{
                    text:"升级关卡",
                    image:'../images/kcview/icon_sj.png'
                }
            },
            ztColorObj:{
                "0":"#BFC1C1",
                "1":"#5c89ff",
                "2":"#5c89ff",
                "3":"#44BB8C",
            },
            nodes: [
                
            ],
            connections: [
               
            ]
        },
      
      
      
        onLoad: function (option) {
            this.setData({
                kxgwId:option.kxgwId
            })
        },
      
        onShow: function () {
            this.setColumnData();
            setTimeout(() => {
                this.getKxgwView();
            }, 1000);
        },
    
    
        //获取课程的详情
        getKxgwView:function(){
            var _that =this;
            var userid = wx.getStorageSync('userid');
            var data={
                kxgwId:_that.data.kxgwId,
                studentid:userid
            };
            wxapi.requestHandling('POST', "/tgjhApi/getKxgwViewV1.do", data, true,"课程加载中...", (res) => {
                var nodes=[];
                var connections=[];
                if(res && res.graph){
                    //节点构建
                    var nodeList = res.graph.nodeList;
                    var newNodeList =[];
                    var wcztMap ={};
                    nodeList.forEach(node => {
                        wcztMap[node.id]=node.xsgkzt;
                        var topY = node.position.top;
                        let top = parseFloat(topY);
                        var leftX = node.position.left;
                        let left = parseFloat(leftX);
                        var newLeft =0;
                        if(left==25){
                            newLeft=_that.data.corridorArr[0];
                        }else if(left==225){
                            newLeft=_that.data.corridorArr[1];
                        }else{
                            newLeft=_that.data.corridorArr[2];
                        }
                        var text = node.data.stageTitle;
                        if(node.config.type=="51"){
                            text = node.data.glzcName;
                        }
                        newNodeList.push({ 
                            id: node.id, 
                            text:text,
                            x: newLeft, 
                            y: top+40,
                            width: 80, 
                            height: 50, 
                            xsgkid:node.xsgkid,
                            zt:node.xsgkzt,
                            cq: node.cq, 
                            type:node.config.type
                        });
                    });
                    nodes=newNodeList;
                    //连接线构建
                    var connList = res.graph.conList;
                    var newConList =[];
                    connList.forEach(element => {
                        var sourceZt = 0;
                        if(wcztMap[element.sourceId]){
                            sourceZt = wcztMap[element.sourceId];
                        }
                        var targetZt = 0;
                        if(wcztMap[element.targetId]){
                            targetZt = wcztMap[element.targetId];
                        }
                        newConList.push({ source: element.sourceId, target: element.targetId,sourceZt:sourceZt,targetZt:targetZt });
                    });
                    connections=newConList;
                }
                _that.setData({
                    nodes:nodes,
                    connections:connections
                })
                this.setCanvasSize();
            })
        },
    
    
        //设置列的宽,用于对齐甬道
        setColumnData:function(){
            var _that =this;
            wx.createSelectorQuery().select('#left-column').fields({ size: true }, rect => {
              var left =(rect.width-80)/2;
              var center =left+rect.width;
              var right =center+rect.width;
              var corridorArr=[left,center,right];
              _that.setData({
                corridorArr:corridorArr
              });
            }).exec();
        },
      
        //设置画布的高宽,实现超出可滚动
        setCanvasSize:function(){
          // 计算canvas的实际大小
          let maxX = 0;
          let maxY = 0;
          this.data.nodes.forEach(node => {
            const nodeRight = node.x + node.width;
            const nodeBottom = node.y + node.height;
            if (nodeRight > maxX) {
              maxX = nodeRight;
            }
            if (nodeBottom > maxY) {
              maxY = nodeBottom;
            }
          });
          this.setData({
            canvasWidth: maxX + 20, // 加上一些额外空间
            canvasHeight: maxY + 20
          });
          this.drawGraph();
        },
      
        drawGraph: function () {
          const ctx = wx.createCanvasContext('myCanvas');
      
          // 绘制连接线
          this.data.connections.forEach(conn => {
            const sourceNode = this.data.nodes.find(node => node.id === conn.source);
            const targetNode = this.data.nodes.find(node => node.id === conn.target);
            this.drawConnection(ctx, sourceNode, targetNode,conn.sourceZt,conn.targetZt);
          });
      
          // 绘制节点
          this.data.nodes.forEach(node => {
            this.drawNode(ctx, node);
          });
      
          ctx.draw();
        },
      
        drawNode: function (ctx, node) {
          //获取
          var typeObj = this.data.gkTypeObj[node.type];
          var color = this.data.ztColorObj[node.zt];
    
    
          const x = node.x;
          const y = node.y;
          const width = node.width;
          const height = node.height;
          const radius = 10;
      
          // 绘制节点的圆角长方形
          ctx.beginPath();
          ctx.moveTo(x + radius, y);
          ctx.lineTo(x + width - radius, y);
          ctx.arcTo(x + width, y, x + width, y + radius, radius);
          ctx.lineTo(x + width, y + height - radius);
          ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius);
          ctx.lineTo(x + radius, y + height);
          ctx.arcTo(x, y + height, x, y + height - radius, radius);
          ctx.lineTo(x, y + radius);
          ctx.arcTo(x, y, x + radius, y, radius);
          ctx.closePath();
          ctx.fillStyle = color;
          ctx.fill();
      
          // 绘制节点中的图片
          const image = typeObj.image;
          const imageX = x + width / 2 - 10; // 图片的左上角x坐标
          const imageY = y + 5; // 图片的左上角y坐标
          ctx.drawImage(image, imageX, imageY, 20, 20);
      
          // 绘制节点中的文字
          const text = typeObj.text;
          ctx.font = '14px Arial';
          ctx.fillStyle = '#ffffff';
          ctx.textAlign = 'center';
          ctx.fillText(text, x + width / 2, y + height - 10);
        },
      
        
        drawConnection: function (ctx, sourceNode, targetNode, sourceZt, targetZt) {
            const sourceX = sourceNode.x + sourceNode.width / 2;
            const sourceY = sourceNode.y + sourceNode.height / 2;
            const targetX = targetNode.x + targetNode.width / 2;
            const targetY = targetNode.y + targetNode.height / 2;
        
            // 计算转折点的位置
            const midX = (sourceX + targetX) / 2;
            const midY = (sourceY + targetY) / 2;
          
            var color = "#dcdcdc";
            if (sourceZt == 0 || targetZt == 0) {
              ctx.setLineDash([5, 5]); //虚线
              color = "#dcdcdc";
            } else {
              ctx.setLineDash([]); //实现
              color = "#333";
            }
          
    
    
            // 绘制连接线
            ctx.beginPath();
            ctx.moveTo(sourceX, sourceY);
            ctx.bezierCurveTo(sourceX, midY, targetX, midY, targetX, targetY);
            ctx.lineTo(targetX, targetY);
            ctx.strokeStyle = color;
            ctx.lineWidth = 2;
            ctx.stroke();
        
          
            // 绘制箭头
            const angle = Math.atan2(targetY - midY, targetX - midX);
            const arrowSize = 10;
            const arrowStartX = targetX - Math.cos(angle) * 20; // 计算箭头起始点的 x 坐标
            const arrowStartY = targetY - Math.sin(angle) * 20; // 计算箭头起始点的 y 坐标
            ctx.save();
            ctx.beginPath();
            ctx.translate(arrowStartX, arrowStartY);
            ctx.rotate(angle);
            ctx.moveTo(0, 0);
            ctx.lineTo(-arrowSize, arrowSize / 2);
            ctx.lineTo(-arrowSize, -arrowSize / 2);
            ctx.closePath();
            ctx.fillStyle = color;
            ctx.fill();
            ctx.restore();
          }
      })
      
    
    2023-11-10
    有用
    回复 1
    • 529
      529
      2023-11-10
      2023-11-10
      回复
登录 后发表内容