Fabricjs 无法获取单选按钮来设置结构对象更改

Fabricjs trouble getting radio button to set fabric object change

我无法让我的单选按钮在单击时更改添加到结构 canvas 的对象。每次更改单选按钮时,新图标颜色仍为绿色,它应该更改为 selected 颜色。

我正在寻找的行为是,当您 select 绿色、黄色或红色单选按钮时,放置在 canvas 上的下一个图标应该变成 selected颜色.

有什么想法吗?

function iconSet() {
  var canvas = new fabric.Canvas('c');
  if (document.getElementById("green").checked == true) {
    var iconGreen = new fabric.Triangle({
      width: 62.5,
      height: 50,
      originX: 'center',
      originY: 'center',
      fill: 'green'
    });

    canvas.add(iconGreen);

    canvas.on('mouse:move', function(obj) {
      iconGreen.top = obj.e.y - 30;
      iconGreen.left = obj.e.x - 10;
      canvas.renderAll()
    })
    canvas.on('mouse:out', function(obj) {
      iconGreen.top = -100;
      iconGreen.left = -100;
      canvas.renderAll()
    })
    canvas.on('mouse:up', function(obj) {
      canvas.add(iconGreen.clone());
      canvas.renderAll();
    })
  } else if (document.getElementById("yellow").checked == true) {
    var iconYellow = new fabric.Triangle({
      width: 62.5,
      height: 50,
      originX: 'center',
      originY: 'center',
      fill: 'yellow'
    });

    canvas.add(iconYellow);

    canvas.on('mouse:move', function(obj) {
      iconYellow.top = obj.e.y - 30;
      iconYellow.left = obj.e.x - 10;
      canvas.renderAll()
    })

    canvas.on('mouse:out', function(obj) {
      iconYellow.top = -100;
      iconYellow.left = -100;
      canvas.renderAll()
    })

    canvas.on('mouse:up', function(obj) {
      canvas.add(iconYellow.clone());
      canvas.renderAll();
    })
  } else if (document.getElementById("red").checked == true) {
    var iconRed = new fabric.Triangle({
      width: 62.5,
      height: 50,
      originX: 'center',
      originY: 'center',
      fill: 'red'
    });

    canvas.add(iconRed);

    canvas.on('mouse:move', function(obj) {
      iconRed.top = obj.e.y - 30;
      iconRed.left = obj.e.x - 10;
      canvas.renderAll()
    })

    canvas.on('mouse:out', function(obj) {
      iconRed.top = -100;
      iconRed.left = -100;
      canvas.renderAll()
    })

    canvas.on('mouse:up', function(obj) {
      canvas.add(iconRed.clone());
      canvas.renderAll();
    })
  }
}
canvas {
  border: 1px solid #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.3/fabric.js"></script>


Green<input name="iconType" type="radio" id="green" onclick="iconSet()" /> Yellow

<input name="iconType" type="radio" id="yellow" onclick="iconSet()" /> Red

<input name="iconType" type="radio" id="red" onclick="iconSet()" />

<canvas id="c" width="600" height="600"></canvas>

尝试全局声明 canvas 和 obejct 变量,并在更改单选按钮时更改对象的填充 属性 和 canvas 的触发方法

icon.setFill("yellow");
canvas.renderAll();  
canvas.trigger('object:modified', {target: icon});

例子

var canvas = new fabric.Canvas('c');
var iconTriangle = new fabric.Triangle({
    width: 62.5,
    height: 50,
    originX: 'center',
    originY: 'center',
    fill:"green"
});
canvas.add(iconTriangle);

canvas.on('mouse:move', function(obj) {
    iconTriangle.top = obj.e.y - 30;
    iconTriangle.left = obj.e.x - 10;
    canvas.renderAll()
});
canvas.on('mouse:out', function(obj) {
    iconTriangle.top = -100;
    iconTriangle.left = -100;
    canvas.renderAll()
});
canvas.on('mouse:up', function(obj) {
    canvas.add(iconTriangle.clone());
    canvas.renderAll();
});

function iconSet() {
    if (document.getElementById("green").checked == true) {
        iconTriangle.setFill("green");
        canvas.renderAll();
    } 
    else if (document.getElementById("yellow").checked == true) {
        iconTriangle.setFill("yellow");
        canvas.renderAll();
   }
   else if (document.getElementById("red").checked == true) {
        iconTriangle.setFill("red");
        canvas.renderAll();
    }
}
canvas {
  border: 1px solid #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.3/fabric.js"></script>

Green<input name="iconType" type="radio" id="green" onclick="iconSet()" /> Yellow
<input name="iconType" type="radio" id="yellow" onclick="iconSet()" /> Red
<input name="iconType" type="radio" id="red" onclick="iconSet()" />
<canvas id="c" width="300" height="300"></canvas>

问题是您在 function 中创建了 canvas 和要添加到其中的图标,之后您就找不到它们了。在函数内部定义一个变量是没有问题的,但是你需要有一个保证以后能够引用到它。 var 变量是 function 范围的,这意味着您将无法从 function 调用之外访问这些变量,即使您再次调用 function 也是如此。此外,您重新创建了这些对象,但您需要确保能够跟踪您打算使用的变量,而不是重新创建 canvas 对象。此处提供快速修复:

var canvas = new fabric.Canvas('c');
var icons = {
    green: null,
    yellow: null,
    red: null
};
function iconSet() {
  for (var ic in icons)
    if (icons[ic]) {
      canvas.remove(icons[ic]);
      icons[ic] = null;
    }
  if (document.getElementById("green").checked == true) {
    var iconGreen = new fabric.Triangle({
      width: 62.5,
      height: 50,
      originX: 'center',
      originY: 'center',
      fill: 'green'
    });

    canvas.add(icons.green = iconGreen);

    canvas.on('mouse:move', function(obj) {
      iconGreen.top = obj.e.y - 30;
      iconGreen.left = obj.e.x - 10;
      canvas.renderAll()
    })
    canvas.on('mouse:out', function(obj) {
      iconGreen.top = -100;
      iconGreen.left = -100;
      canvas.renderAll()
    })
    canvas.on('mouse:up', function(obj) {
      canvas.add(iconGreen.clone());
      canvas.renderAll();
    })
  } else if (document.getElementById("yellow").checked == true) {
    var iconYellow = new fabric.Triangle({
      width: 62.5,
      height: 50,
      originX: 'center',
      originY: 'center',
      fill: 'yellow'
    });

    canvas.add(icons.yellow = iconYellow);

    canvas.on('mouse:move', function(obj) {
      iconYellow.top = obj.e.y - 30;
      iconYellow.left = obj.e.x - 10;
      canvas.renderAll()
    })

    canvas.on('mouse:out', function(obj) {
      iconYellow.top = -100;
      iconYellow.left = -100;
      canvas.renderAll()
    })

    canvas.on('mouse:up', function(obj) {
      canvas.add(iconYellow.clone());
      canvas.renderAll();
    })
  } else if (document.getElementById("red").checked == true) {
    var iconRed = new fabric.Triangle({
      width: 62.5,
      height: 50,
      originX: 'center',
      originY: 'center',
      fill: 'red'
    });

    canvas.add(icons.red = iconRed);

    canvas.on('mouse:move', function(obj) {
      iconRed.top = obj.e.y - 30;
      iconRed.left = obj.e.x - 10;
      canvas.renderAll()
    })

    canvas.on('mouse:out', function(obj) {
      iconRed.top = -100;
      iconRed.left = -100;
      canvas.renderAll()
    })

    canvas.on('mouse:up', function(obj) {
      canvas.add(iconRed.clone());
      canvas.renderAll();
    })
  }
}

顺着我解释的思路,看Fiddle。您可能想进一步重构它,但这是一个好的开始。

因为你每次都创建 new fabric.Triangle instead of that you can create once and when radio button values changed, just will update color of existing fabricTriangle by using fabricTriangle.setFill() 方法。

见下面的代码片段

document.getElementById('green').checked = true;

var canvas = new fabric.Canvas('c'),
  fabricTriangle = getfabricTriangle('green');

canvas.on('mouse:move', function(obj) {
  fabricTriangle.top = obj.e.y - 30;
  fabricTriangle.left = obj.e.x - 10;
  canvas.renderAll()
});

canvas.on('mouse:out', function(obj) {
  fabricTriangle.top = -100;
  fabricTriangle.left = -100;
  canvas.renderAll()
});

canvas.on('mouse:up', function(obj) {
  canvas.add(fabricTriangle.clone());
  canvas.renderAll();
});

canvas.add(fabricTriangle)

function getfabricTriangle(color) {
  if (!fabricTriangle) {
  //If it is not created then first will create and return..
     return new fabric.Triangle({
      width: 62.5,
      height: 50,
      originX: 'center',
      originY: 'center',
      fill: color
    });
  } /*else {
  //just changing the color of exiting fabric.Triangle...
    fabricTriangle.setFill(color)
  }*/
}

function iconSet() {
  fabricTriangle.setFill(document.querySelector('input[type="radio"]:checked').value)
}
canvas {
  border: 1px solid #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.3/fabric.js"></script>


Green
<input name="iconType" type="radio" id="green" onclick="iconSet()" value="green" /> 

Yellow
<input name="iconType" type="radio" id="yellow" onclick="iconSet()" value="yellow" /> 

Red
<input name="iconType" type="radio" id="red" onclick="iconSet()" value="red" />

<canvas id="c" width="600" height="600"></canvas>

这可能就是您所需要的。我还清理了代码使其更短 JsFiddle:https://jsfiddle.net/96nceasu/3/

var canvas = new fabric.Canvas('c');
function iconSet(ele){
      var icon = new fabric.Triangle({
          width: 62.5,
          height: 50,
          originX: 'center',
          originY: 'center',
          fill: ele.id
        });
        canvas.add(icon);
        canvas.on('mouse:move', function(obj) {
          icon.fill = ele.id;
          icon.top = obj.e.y - 30;
          icon.left = obj.e.x - 10;
          canvas.renderAll()
        })
        canvas.on('mouse:out', function(obj) {
          icon.top = -100;
          icon.left = -100;
          canvas.renderAll()
        })
        canvas.on('mouse:up', function(obj) {
          canvas.add(icon.clone());
          canvas.renderAll();
        })
      
    }
canvas{
      border: 1px solid #ccc;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.3/fabric.js"></script>
    Green<input name="iconType" type="radio" id="green" onclick="iconSet(this)" /> Yellow
    <input name="iconType" type="radio" id="yellow" onclick="iconSet(this)" /> Red
    <input name="iconType" type="radio" id="red" onclick="iconSet(this)" />
    <canvas id="c" width="600" height="600"></canvas>