Анимация Polymer 3 не работает для элементов shadow dom - PullRequest
0 голосов
/ 23 сентября 2019

Я пытаюсь обновить проект Polymer 2, чтобы использовать Polymer 3, и я на 90%, но не могу получить анимацию для добавления новых элементов для правильной работы.Артефакты добавляются через теневой дом, и кажется, что даже если имя класса добавлено, анимация не работает.

Я пытался изменить способ добавления ключевых кадров в файл javascript, а также поместить классы анимации в ": host" вместо ": host :: slotted"

index.html

<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">

        <title>masonry-layout demo</title>

        <script src="../node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>

        <script type="module">
            import '@polymer/iron-demo-helpers/demo-pages-shared-styles';
            import '@polymer/iron-demo-helpers/demo-snippet';
        </script>
        <script>
        function addBelow() {
            let newArticle = document.createElement('article');
            newArticle.innerHTML = 'added below';
            document.getElementById('masonry').appendChild(newArticle);
        }
        function addAbove() {
            let newArticle = document.createElement('article');
            let masonry = document.getElementById('masonry');
            newArticle.innerHTML = 'added above';
            document.getElementById('masonry').prependChild(newArticle);
        }
    </script>
        <script type="module" src="../masonry-layout.js"></script>

    <custom-style>
        <style is="custom-style" include="demo-pages-shared-styles">
        </style>
        <style>
        article {
            background: #36abcc;
            width: 29%;
            height: 200px;
            margin: 2%;
            color: #fff;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        grain-masonry {
            background: #ccc;
        }
    </style>
    </custom-style>
</head>
<body>
    <div class="vertical-section-container centered">
        <h3>Basic masonry-layout demo</h3>
        <button onclick="addBelow();">add below</button>
    <button onclick="addAbove();">add above</button>
        <demo-snippet>
            <template>
                <masonry-layout id="masonry">
                    <article>
                        Power
                    </article>
                    <article style="height: 100px;">
                        To
                    </article>
                    <article style="height: 190px;">
                        The
                    </article>
                    <article style="height: 310px;">
                        People
                    </article>
                    <article>
                        Power
                    </article>
                    <article style="height: 140px;">
                        To
                    </article>
                    <article style="height: 210px;">
                        The
                    </article>
                    <article style="height: 230px;">
                        People
                    </article>
                </masonry-layout>
            </template>
        </demo-snippet>
    </div>
</body>
</html>

masonry-layout.js

import {html, PolymerElement} from '@polymer/polymer/polymer-element.js';
import {afterNextRender} from '@polymer/polymer/lib/utils/render-status.js';
import { FlattenedNodesObserver } from '@polymer/polymer/lib/utils/flattened-nodes-observer.js';
import './masonry.pkgd.min.js';
/**
 * `masonry-layout`
 * Polymer 3 wrapper for masonry javascript library
 *
 * @customElement
 * @polymer
 * @demo demo/index.html
 */
class MasonryLayout extends PolymerElement {

    static get is() {
        return 'masonry-layout'
    }

    static get properties() {
        return {
            itemSelector: {
                type: String,
                reflectToAttribute: true,
                value: 'article'
            },
            transitionDuration: {
                type: Number,
                reflectToAttribute: true,
                value: 0
            }
        };
    }

    static get template() {
        return html`
      <style>

        @keyframes containerMasonryMoveToOrigin {
        from {
                    opacity: 0;
                }
        to { transform: translateY(0); opacity: 1; }
    }

        :host {
          display: block;
          width: 100%;
        }

        :host .masonry-layout-animate-move-up) {
                        transform: translateY(200px);
                        opacity: 0;
                        animation: containerMasonryMoveToOrigin 5s ease forwards;
                    }
        .masonry-layout-animate-move-down) {
                        transform: translateY(-200px);
                        opacity: 0;
                        animation: containerMasonryMoveToOrigin 0.65s ease forwards;
                    }

      </style>

      <slot id="slot"></slot>

    `;
    }

    init() {
        this.raw = new Masonry(this, {
            itemSelector: this.itemSelector,
            transitionDuration: this.transitionDuration,
            initLayout: false
        });
        afterNextRender(this, function () {
            this.layout();
        });
    }
    connectedCallback() {
        super.connectedCallback();
        this.init();
        this._loadObserver = function (event) {
            let target = event.target;
            if (target.tagName === 'IMG') {
                this.layout();
            }
        }.bind(this);
        this.addEventListener('load', this._loadObserver, true);
        this.toggleSlotObsever = false;
        this._slotObserver = new FlattenedNodesObserver(this.$.slot, (info) => {
            if (this.toggleSlotObsever) {
                let addedElements = info.addedNodes.filter((node) => {
                    return (node.nodeType === Node.ELEMENT_NODE && node.nodeName === this.itemSelector.toUpperCase())
                });
                let removedElements = info.removedNodes.filter((node) => {
                    return (node.nodeType === Node.ELEMENT_NODE && node.nodeName === this.itemSelector.toUpperCase())
                });
                if (addedElements.length > 0 || removedElements.length > 0) {
                    this.reInit();
                }
            }
            this.toggleSlotObsever = true;
        });
    }
    disconnectedCallback() {
        this._slotObserver.disconnect();
        this.removeEventListener('load', this._loadObserver);
    }
    layout() {
        this.raw.layout();
    }
    reInit() {
        this.raw.destroy();
        this.init();
    }
    appendChild(element) {
        this.toggleSlotObsever = false;
        element.classList.add('masonry-layout-animate-move-up');
        element.addEventListener('animationend', function (event) {
            //event.target.classList.remove('masonry-layout-animate-move-up');
        });
        super.appendChild(element);
        this.raw.addItems(element);
        afterNextRender(this, function () {
            this.layout();
            this.toggleSlotObsever = true;
        });
    }
    appendChildren(elements) {
        for (let element of elements) {
            this.appendChild(element);
        }
    }
    prependChild(element) {
        this.insertBefore(element, this.children[0]);
    }
    prependChildren(elements) {
        for (let element of elements) {
            this.prependChild(element);
        }
    }
    insertBefore(element, before) {
        if (element.nodeName === '#document-fragment') {
            element = element.querySelector(this.itemSelector);
        }
        this.toggleSlotObsever = false;
        element.classList.add('masonry-layout-animate-move-down');
        element.addEventListener('animationend', function (event) {
            //event.target.classList.remove('masonry-layout-animate-move-down');
        });
        super.insertBefore(element, before);
        this.raw.prepended(element);
        afterNextRender(this, function () {
            this.layout();
            this.toggleSlotObsever = true;
        });
    }
}

window.customElements.define('masonry-layout', MasonryLayout);
...