聚合物就绪函数只调用一次

时间:2015-11-28 04:05:31

标签: javascript html5 html5-canvas polymer web-component

我正在测试Polymer开发一个我想在html中重复使用多次的组件(见下图)。我开发了以下元素:

<link rel="import" href="bower_components/polymer/polymer.html">
<script src="js/fabric.js"></script>

<dom-module id="tooth-element">
  <template>
    <style>
      #labelWrapper {
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 35px;
        font-weight: bold;
        height: 40PX;
      }
    </style>

    <div id="toothWrapper">
      <div id="upperRootWrapper">
        <canvas id="upperRoot" />
      </div>

      <div>
        <canvas id="tooth" />
      </div>

      <div id="lowerRootWrapper">
        <canvas id="lowerRoot" />
      </div>

      <div id="labelWrapper">
        <p>{{toothLabel}}</p>
      </div>
    </div>
  </template>

  <script>
  var TOOTH_SIZE = 50;
  var TOOTH_GAP = 5;

  var UPPERROOTID = 'upperRoot';
  var LOWERROOTID = 'lowerRoot';
  var TOOTHID = 'tooth';

  Polymer({
    is: "tooth-element",
    properties: {
      // declare the owner property
      showUpperRoot: {
        type: Boolean,
        value: true
      },
      showLowerRoot: {
        type: Boolean,
        value: true
      },
      toothLabel: {
        type: String,
        value: 30
      }
    },
    ready: function() {
      drawUpperRoot(this.showUpperRoot);
      drawTooth();
      drawLowerRoot(this.showLowerRoot);
      initLabel(this.toothLabel);
    }
  });

  function initLabel (label) {
    document.getElementById("labelWrapper").style.width = new String(3*TOOTH_SIZE)+'px';
  }

  function drawUpperRoot (isVisible) {
    var canvas = new fabric.Canvas(UPPERROOTID);
    if (isVisible) {
      canvas.setHeight(TOOTH_SIZE+TOOTH_GAP);
      canvas.setWidth(TOOTH_SIZE*3+TOOTH_GAP);
      canvas.renderAll();
      canvas.add(drawFace(1));
    } else {
      document.getElementById("upperRootWrapper").style.display = "none";
    }
  }

  function drawTooth () {
    var canvas = new fabric.Canvas(TOOTHID);
    canvas.setHeight(TOOTH_SIZE*3+TOOTH_GAP*2);
    canvas.setWidth(TOOTH_SIZE*3+TOOTH_GAP*2);
    canvas.renderAll();
    canvas.add(drawFace(2));
    canvas.add(drawFace(3));
    canvas.add(drawFace(4));
    canvas.add(drawFace(5));
    canvas.add(drawFace(6));
    //canvas.add(drawFace(7));
  }

  function drawLowerRoot (isVisible) {
    var canvas = new fabric.Canvas(LOWERROOTID);
    if (isVisible) {
      canvas.setHeight(TOOTH_SIZE+TOOTH_GAP*2);
      canvas.setWidth(TOOTH_SIZE*3+TOOTH_GAP*2);
      canvas.renderAll();
      canvas.add(drawFace(7));
    } else {
      document.getElementById("lowerRootWrapper").style.display = "none";;
    }
  }

  function drawFace(face) {
    var coordinates;
    switch (face) {
      case 1:
      coordinates = getFace1Coordinates();
      break;
      case 2:
      coordinates = getFace2Coordinates();
      break;
      case 3:
      coordinates = getFace3Coordinates();
      break;
      case 4:
      coordinates = getFace4Coordinates();
      break;
      case 5:
      coordinates = getFace5Coordinates();
      break
      case 6:
      coordinates = getFace6Coordinates();
      break;
      case 7:
      coordinates = getFace7Coordinates();
      break;
      default:
      coorddinates = null;
    }

    face = new fabric.Polygon(coordinates, {
      fill: '#E1E1E1',
      selectable: false,
      stroke: 'green'
    });
    face.on('mousedown', function () {
      if (face.fill == '#E1E1E1') {
        face.fill = '#878787';
      } else {
        face.fill = '#E1E1E1';
      }
    });
    return face;
  }

  function getFace1Coordinates() {
    return [{x: TOOTH_SIZE, y: 0}, {x: TOOTH_SIZE*2+TOOTH_GAP, y: 0}, {x: TOOTH_SIZE*3+TOOTH_GAP, y: TOOTH_SIZE}, {x: 0, y: TOOTH_SIZE}];
  }

  function getFace2Coordinates() {
    return [{x: 0, y: TOOTH_GAP}, {x: TOOTH_SIZE, y: TOOTH_SIZE+TOOTH_GAP}, {x: TOOTH_SIZE, y: TOOTH_SIZE*2+TOOTH_GAP}, {x: 0, y: TOOTH_SIZE*3}];
  }

  function getFace3Coordinates() {
    return [{x: 0, y: 0}, {x: TOOTH_SIZE, y: TOOTH_SIZE}, {x: TOOTH_SIZE*2, y: TOOTH_SIZE}, {x: TOOTH_SIZE*3, y: 0}];
  }

  function getFace4Coordinates() {
    return [{x: TOOTH_SIZE*3+TOOTH_GAP, y: 0}, {x: TOOTH_SIZE*2+TOOTH_GAP, y: TOOTH_SIZE}, {x: TOOTH_SIZE*2+TOOTH_GAP, y: TOOTH_SIZE*2+TOOTH_GAP}, {x: TOOTH_SIZE*3+TOOTH_GAP, y: TOOTH_SIZE*3}];
  }

  function getFace5Coordinates() {
    return [{x: 0, y: TOOTH_SIZE*3+TOOTH_GAP}, {x: TOOTH_SIZE+TOOTH_GAP, y: TOOTH_SIZE*2+TOOTH_GAP}, {x: TOOTH_SIZE*2, y: TOOTH_SIZE*2+TOOTH_GAP}, {x: TOOTH_SIZE*3+TOOTH_GAP, y: TOOTH_SIZE*3+TOOTH_GAP}];
  }

  function getFace6Coordinates() {
    return [{x: TOOTH_SIZE+TOOTH_GAP, y: TOOTH_SIZE+TOOTH_GAP}, {x: TOOTH_SIZE*2, y: TOOTH_SIZE+TOOTH_GAP}, {x: TOOTH_SIZE*2, y: TOOTH_SIZE*2}, {x: TOOTH_SIZE+TOOTH_GAP, y: TOOTH_SIZE*2}];
  }

  function getFace7Coordinates() {
    return [{x: 0, y: 0}, {x: TOOTH_SIZE, y: TOOTH_SIZE}, {x: TOOTH_SIZE*2, y: TOOTH_SIZE}, {x: TOOTH_SIZE*3, y: 0}];
  }
  </script>
</dom-module>

我正试图在index.html文件中导入它:

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" src="bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
        <link rel="import" href="tooth-element.html">
    </head>

    <body>
        <div id="line1">
            <tooth-element></tooth-element>
            <tooth-element></tooth-element>
        </div>
    </body>
</html>

当我在div line1中放置两个tooth-elements时会出现问题。永远不会显示第二个元素,因为从不为它调用ready函数。我不知道为了解决这个问题我应该做些什么。任何帮助将不胜感激

我想在html中重复的组件布局如下所示(我得到第一个牙齿元素的图像,但不是第二个牙齿元素):

Tooth Representation

(溶液) 我没有正确使用DOM(正如Neil John Ramal所解释的那样)。使用Glenn和Neil建议使用Poly.dom API我能够得到我想要的行为

2 个答案:

答案 0 :(得分:1)

在处理本地DOM(即document.getElementByIddocument.querySelector等)时,请避免使用常规DOM API。请改用Polymer.dom。请注意,当您将Polymer设置为使用Shadow DOM而不是Shady DOM时,您的代码可能会失败,因为常规DOM访问器无法穿透Shadow DOM(封装是其功能之一,Shady DOM尝试近似)。

代码中的一个问题是结果元素与某些全局对象紧密耦合(例如drawUpperRoot)。这实际上打破了元素封装,因为这个代码也将被该元素的其他实例使用,这样你就不会使用自己的范围,而是基本上使它们依赖于全局范围。

此代码:

function initLabel (label) {
  document.getElementById("labelWrapper").style.width = new String(3*TOOTH_SIZE)+'px';
}

意味着当你创建两个tooth-element时,第二个元素基本上会引用第一个元素labelWrapper而不是它自己的A

https://www.polymer-project.org/1.0/docs/devguide/local-dom.html

答案 1 :(得分:1)

document.querySelector()返回它在文档中找到的第一个元素,第二个元素被忽略。

将文档更改为此应解决问题。

document.querySelector('#labelWrapper') -> this.querySelector(#labelWrapper)

或者

document.querySelector('#labelWrapper') -> Polymer.dom(this).querySelector('#labelWrapper')