0

我正在尝试根据 fabric.canvas.object 中的属性动态生成一个 div。

以下是我的代码的摘录。

class Polymer2FabricEdit extends Polymer.Element {
  static get is() { return 'polymer-2-fabric-edit' }
  static get config() {
    return {
      properties: {
        canvas: {
          type: Object,
          value: null
        },
        ctx: {
          type: Object,
          value: null
        },
        canvasWidth: {
          type: Number,
          value: 300
        },
        canvasHeight: {
          type: Number,
          value: 300
        },
        topProperty: {
          type: Number,
          value: 0,
          notify: true
        },
      observers: [
       ]
    }
  }
  constructor() {
    super();
    console.log('created');
  }
  connectedCallback() {
    super.connectedCallback();
    console.log('attached');
  }
  ready() {
    super.ready();
    this.canvas = new fabric.Canvas(this.$.c, {isDrawingMode: false});
    console.log(this.canvas);
    this.ctx = this.canvas.getContext('2d');
    this.addEventListener('click', (e)=>this.handleClick(e));
    this.addEventListener('change', (e)=>this.handleChange(e));
    this.$.dropTargetDiv.addEventListener("dragover", (e)=>this.preventEventDefault(e));
    this.$.dropTargetDiv.addEventListener("drop", (e)=>this.loadObject(e));
    this.$.imageLoader.addEventListener("change", (e)=>this.readURL(e));
    this.$.backgroundImageLoader.addEventListener("change", (e)=>this.readBackgroundURL(e));
    this.$.textureImageLoader.addEventListener("change", (e)=>this.readTextureURL(e));
    console.log('ready');
  }

  generateEditView(obj) {

    console.log("generateEditView");
    console.log(obj);
    var html = "<br/><br/><b>Edit Properties</b><br/><br/>";
    for(var key in obj) {
      if(key === "stateProperties") {
        console.log(key, obj[key]);
        var o = obj[key];
          for(var k in o) {
            console.log(o[k], obj[o[k]]);
            switch(o[k]) {
            case 'top':
                console.log("setting top from:", this.topProperty);
                this.topProperty = obj[o[k]];
                html += '<input type="number" value="{{topProperty}}" min="0" max="150" id="topProperty">';
                html += '<input type="range" value="{{topProperty}}" min="0" max="150" id="topPropertyRange">';
                html += '<br/>';
                console.log("set to: " + this.topProperty);
                break;
           case ‘…’:
            break;
default;
    }
    console.log("adding: " + html);
    this.$.editView.innerHTML = html;
  }


  handleClick(e) {
    console.log("hamdleClick: " + e.type);
    console.log("click: " + e.currentTarget.tagName);
    console.log(e);
    var id = e.path[0].id;
    console.log("id: " + id);
    switch(id) {
        case '':
          console.log("No ID - This is mostlike a selet of an object");
          var target = e.target;
          var obj = this.canvas.getActiveObject();
          console.log("target:" + target);
          console.log("selected Object:" + obj);
          console.log("selected Menu: " + this.selectedMenu);
          if(this.selectedMenu === "control") {
            this.generateEditView(this.canvas.getActiveObject());
          }
          break;
        break;
        case 'topProperty':
          console.log("Change TopProperty", this.$.topProperty);
          this.topProperty = this.$.topProperty;
          break;
      default:
    }
  }

这不起作用我收到以下运行时错误 polymer-2-edit.html:1979 The specified value "{{topProperty}}" is not a valid number。该值必须与以下正则表达式匹配:-?(\d+|\d+.\d+|.\d+)([eE][-+]?\d+)? 生成的代码似乎没有获取绑定。

如果我将代码更改为以下 div 将正确显示。html += ''; html += ''

但是当我阅读 this,$.topProperty 或 this.$.topPropertyRange 时我得到了 undefined 我也尝试在后两者上添加 onchange=changeProperty(this) 并且我在调试器中得到 changeProperty is undefined 消息。

我怀疑它期望该功能在聚合物之外,但我需要它在聚合物内部来设置对象属性。

是否有添加动态输入字段和处理所做更改的示例?

4

1 回答 1

0

我仍然没有成功地让动态 html 生成的代码工作。我尝试使用 dom:if 重写代码,但它没有按照我想要的方式工作。

也就是说,我已经通过编写静态代码并使用 css 隐藏不需要的选择并显示我需要的部分来实现我的目标。

我添加了这个 CSS 类

.hide {
    display: none;
    visibility: hidden;
}

然后我为每个元素创建了一个 div 并将“Edit”附加到 div id 的属性名称

<div id="topEdit">
    <label for="top">Top:</label>
    <input type="number" value="{{top::input}}" min="0" max="150" id="top">
    <input type="range" value="{{top::input}}" min="0" max="150" id="topRange">
    <br/>
</div>
<div id="leftEdit">
    <label for="left">Left:</label>
    <input type="number" value="{{left::input}}" min="0" max="150" id="left" onchange="{{Change}}">
    <input type="range" value="{{left::input}}" min="0" max="150" id="leftRange">
    <br/>
</div>
<div id="widthEdit">
    <label for="width">Width:</label>
    <input type="number" value="{{width::input}}" min="0" max="150" id="width">
    <input type="range" value="{{width::input}}" min="0" max="150" id="widtnRange">
    <br/>
</div>

我使用这个函数来隐藏所有id为“Edit”的元素</p>

clearView() {
    // hide the Edit Elements
    var elements = this.$;
    for(var key in elements) {
        var element = elements[key];
        var elementId = element.id;
        if(!!elementId.match(/.*Edit$/)) {
            element.classList.add('hide');
        }
    }
}

然后原始代码循环遍历活动对象并从欣赏元素中删除 css 隐藏类。由于选择的某些 html 元素不直接对应于 objects 元素,因此修改了这种方法,并且我决定不想为每个属性提供字段。修改后的代码基于选定的对象类型,我利用了一个字段数组

当用户单击一个对象时,我执行类似于以下示例的代码。

此示例适用于文本或 iText 对象。

var fields = [
    "fontWeight", //  normal, bold
    "fontStyle", //  normal, italic, oblique, ''
    "textDecoration", //  underline, linethrough, overline
    "fontFamily",
    "textAlign",
    "stroke",
    "backgroundColor",
    "textBackgroundColor",
    "strokeWidth",
    "fontSize",
    "lineHeight",
    "charSpacing",
    "shadow", //  shadowColor, shadowBlur, shadowOffsetX, shadowOffsetY
    "shadowColor",
    "shadowBlur",
    "shadowOffsetX",
    "shadowOffsetY",
    "text",
    "addText"
];

以下代码删除 css hide 类并显示适当的元素。

for(var key in fields) {
    var id = fields[key] + "Edit";
    var element = this.$[id];
    if(element) {
        element.classList.remove('hide');
    }
}

这种方法对我来说效果很好,并为所选元素提供了完整的两种方式绑定。

于 2016-12-07T14:41:21.923 回答