Blockly 自定义Field

506 阅读1分钟

Blockly中的field是用来在block中显示和编辑特定值的组件。例如,你可以使用field来创建一个下拉菜单、一个文本框或一个滑块等。

要自定义一个field,你需要创建一个新的field类,并指定它的行为和样式。下面是一个示例代码,它创建了一个自定义field,用来输入时间(小时和分钟):

// 定义自定义field类
Blockly.FieldTime = function(hour, minute, opt_validator) {
  // 调用父类构造函数
  Blockly.FieldTime.superClass_.constructor.call(this, hour + ':' + minute, opt_validator);
  // 初始化属性
  this.hour_ = hour;
  this.minute_ = minute;
};
// 继承Blockly.Field类
Blockly.utils.object.inherits(Blockly.FieldTime, Blockly.Field);

// 设置field的行为
Blockly.FieldTime.prototype.showEditor_ = function() {
  // 创建HTML元素并添加到页面中
  var htmlInput = document.createElement('input');
  htmlInput.setAttribute('type', 'time');
  htmlInput.setAttribute('value', this.hour_ + ':' + this.minute_);
  htmlInput.style.height = '25px';
  htmlInput.style.width = '60px';
  htmlInput.style.border = '1px solid #ccc';
  var div = Blockly.DropDownDiv.getContentDiv();
  div.appendChild(htmlInput);

  // 添加事件监听器来更新field的值
  var thisField = this;
  htmlInput.addEventListener('input', function() {
    var newValue = htmlInput.value;
    if (newValue != thisField.getValue()) {
      thisField.setValue(newValue);
      Blockly.DropDownDiv.hide();
    }
  });

  // 计算field的位置并显示下拉菜单
  var viewportBBox = Blockly.utils.getViewportBBox();
  var anchorBBox = this.getScaledBBox_();
  Blockly.DropDownDiv.showPositionedByField(this, div, viewportBBox);
};

// 设置field的样式
Blockly.FieldTime.prototype.render_ = function() {
  // 调用父类渲染方法
  Blockly.FieldTime.superClass_.render_.call(this);

  // 根据当前值更新field的样式
  var border = '1px solid #ddd';
  var color = '#444';
  if (!this.sourceBlock_.isEnabled()) {
    border = '1px dotted #ccc';
    color = '#ccc';
  }
  this.textElement_.style.border = border;
  this.textElement_.style.color = color;
};

// 设置field的取值和赋值方法
Blockly.FieldTime.prototype.getValue = function() {
  return this.hour_ + ':' + this.minute_;
};
Blockly.FieldTime.prototype.setValue = function(newValue) {
  var match = /^(\d+):(\d+)$/.exec(newValue);
  if (match) {
    this.hour_ = match[1];
    this.minute_ = match[2];
    this.setText(newValue);
  }
};
Blockly.fieldRegistry.register("field_time", Blockly.FieldTime);
// 添加样式
Blockly.Css.register(
     `
     .xxx {
          padding: 4px;
        }
     `
  );

在上述代码中,我们创建了一个名为 Blockly.FieldTime 的新field类,并继承了Blockly.Field类。我们定义了它的行为和样式,并指定了它的取值和赋值方法。

使用

{
  "type": "my_block",
  "message0": "My Block %1",
  "args0": [
    {
      "type": "field_time",
      "name": "ABC",
    }
  ],
}