Используйте несколько экземпляров одного и того же полимерного пользовательского элемента

У меня проблема с использованием полимера (1.3.1) для определения пользовательского элемента, который является кнопкой svg для веб-приложения Portal.

Вот код моего пользовательского элемента:

<link rel="import" href="../../lib/polymer/1.3.1/polymer.html">

<dom-module id="portal-button">
  <link rel="import" type="css" href="portal-button.css">
  <template>
    <svg id="hexagon-button" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="200" height="187">
      <a xlink:href="#dummy" xlink:href$="{{url}}">
        <defs>
          <pattern id="dashed-line" height="9" width="9" patternUnits="userSpaceOnUse">
            <rect x="0" y="0" width="9" height="9" fill="rgb(245,245,245)" />
            <line x1="1" y1="9" x2="9" y2="1" stroke="rgb(187,187,187)" stroke-dasharray="2" />
          </pattern>
          <pattern id="logo" width="100%" height="100%" viewBox="0 0 135 133">
            <image id="buttonlogo" width="135" height="133" xlink:href="#dummy" xlink:href$="{{src}}" />
          </pattern>
          <pattern id="text" width="100%" height="100%" viewBox="0 0 590 76">
            <image id="buttontext" width="590" height="76" xlink:href="#dummy" xlink:href$="{{text}}" />
          </pattern>
        </defs>
        <g class="button">
          <g class="back">
            <path d="M 150,13 L 50,13 0,100 50,187 150,187 200,100 z M 140,31 L 60,31 20,100 60,169 140,169 180,100 z" fill-rule="evenodd" fill="url(#dashed-line)" />
            <polygon points="140,31 60,31 20,100 60,169 140,169 180,100" fill="rgb(88,151,162)" />
            <polygon points="140,31 60,31 20,100 60,169 140,169 180,100" fill="url(#logo)" />
          </g>
          <g class="front">
            <polygon points="19,100 25,90 175,90 181,100 175,110 25,110" fill="url(#dashed-line)" />
            <polygon points="19,100 25,90 175,90 181,100 175,110 25,110" fill="url(#text)" />
          </g>
        </g>
      </a>
    </svg>
  </template>
</dom-module>

<script>
  Polymer({
    is: 'portal-button',

    properties: {
      text: String,
      url: String,
      src: String
    }
  });
</script>

Немного CSS для отображения/скрытия переднего элемента svg

.back {
	fill-opacity: 0.5;
}

.front {
	fill-opacity: 0.1;
}

.button:hover > * {
	fill-opacity: 1;
}

index.html с объявлением двух экземпляров моего пользовательского элемента

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Izakiel's Lair</title>
  <link rel="icon" href="chaos_symbol.png">
  <!-- include polymer html5 polyfill library -->
  <script src="lib/webcomponentsjs/0.7.21/webcomponents-lite.js"></script>
  <link rel="import" href="components/portal-button/portal-button.html">
</head>

<body>
  <portal-button id="virtualmin" url="http://localhost:8080/portal" src="img/virtualmin-logo.svg" text="img/virtualmin-titles.svg"></portal-button>
  <portal-button id="jenkins" url="http://localhost:8080/portal" src="img/jenkins-logo.svg" text="img/jenkins-titles.svg"></portal-button>
</body>

</html>

Когда страница загружена, рендеринг в полном порядке.

страница загружена

Когда я навожу курсор на кнопку, непрозрачность устанавливается на 1 css, заставляя браузер перерисовывать кнопку. Когда кнопка повторно отображается, вся информация для изображения svg отображается с последним объявленным элементом (т.е. данными кнопки jenkins в этом примере), но все данные в DOM совершенно хороши, что, на мой взгляд, странно.

после наведения

Кто-нибудь знает, почему браузер установил рендеринг всех пользовательских элементов с последним рендерингом элемента или это ошибка?

Мой предыдущий тест был сделан с Chrome, когда я пытаюсь с Firefox, это еще хуже, все элементы имеют рендеринг первого элемента, но данные в DOM хорошие. Я что-то пропустил ?

пример firefox


person izakiel    schedule 17.03.2016    source источник


Ответы (1)


Я думаю, ваша проблема в том, что шаблоны являются глобальными, а не ограниченными теневым корнем. Я пробовал это как с теневым DOM, так и с собственным теневым корнем, с теми же результатами.

Вот частичное обходное решение, которое устраняет насущную проблему как в Chrome, так и в Firefox: создайте уникальный идентификатор для каждого шаблона:

<pattern id="logo-{{id}}" width="100%" height="100%" viewBox="0 0 135 133">
  <image id="buttonlogo" width="135" height="133" xlink:href="#dummy" xlink:href$="{{src}}" />
</pattern>

Примените узор следующим образом:

<polygon points="140,31 60,31 20,100 60,169 140,169 180,100" fill$="[[_computeFill('#logo', id)]]" />

Я обнаружил, что здесь мне нужна вычисляемая привязка - я думаю, что скобки в url( arg перепутали систему привязки, но, возможно, я просто что-то неправильно понял. YMMV. В любом случае, вычислительная функция может выглядеть так:

_computeFill: function(name, id) {
  return 'url('+ name + '-' + id + ')';
}

Вы могли бы сделать это немного более элегантным, но это должно заставить вас работать.

Это частичное обходное решение, потому что если вы повторно используете идентификатор, вы вернетесь к исходной проблеме замены изображений.

Если вы хотите избежать этого, вы можете определить отдельную библиотеку шаблонов, идентифицируемых по идентификатору (например, iron-iconset-svg для значков). Или, как более простое решение, вы можете вычислить уникальный идентификатор из имени файла SVG.

Надеюсь это поможет.

person DocDude    schedule 18.03.2016
comment
Большое спасибо за вашу помощь, по крайней мере, это не сложное «исправление» :), как вы думаете, мне следует открыть проблему в репозитории Polymer Github? - person izakiel; 19.03.2016
comment
Мне удалось воспроизвести эту проблему (или ее близкий вариант) без использования Polymer, а только с общими API-интерфейсами веб-компонентов. Посоветовавшись с некоторыми людьми из команды Chrome, я решил, что это ошибка Chrome, и я сообщил об этом здесь: выпуск 579080. - person DocDude; 23.03.2016