I have been building a slideshow custom element using polymer and have been using the Animate.css library for slide transitions. When used Canary with "Experimental web platform" features turned on, the tag works as expected, but in the regular version of chrome with the experimental features turned off, the platform polyfill does not allow me to data-bind within style tags. As an example:

<polymer-element name="impress-slide" constructor="ImpressSlide" attributes="exit entrance">
    <template>
        <link rel="stylesheet" type="text/css" href="basic-animations.css">
        <style type="text/css">
            :host{
              position: relative;
              top: 0;
              left: 0;
              overflow: hidden;
              display: none;
              width: 100%;
              height: 100%;
              margin: 0;
              -webkit-box-sizing: border-box;
              -moz-box-sizing: border-box;
              box-sizing: border-box;   

              /* Animate.css */
              -webkit-animation: 1s both;
              animation: 1s both;
              -webkit-animation-name: {{ animation }} !important;
              animation-name: {{ animation }} !important; 

          }

            @-webkit-keyframes fadeOutRightBig {
              0% {
                opacity: 1;
                -webkit-transform: translateX(0);
                transform: translateX(0);
              }

              100% {
                opacity: 0;
                -webkit-transform: translateX(2000px);
                transform: translateX(2000px);
              }
            }

            @keyframes fadeOutRightBig {
              0% {
                opacity: 1;
                -webkit-transform: translateX(0);
                -ms-transform: translateX(0);
                transform: translateX(0);
              }

              100% {
                opacity: 0;
                -webkit-transform: translateX(2000px);
                -ms-transform: translateX(2000px);
                transform: translateX(2000px);
              }
            }

            @keyframes bounceIn {
              0% {
                opacity: 0;
                -webkit-transform: scale(.3);
                -ms-transform: scale(.3);
                transform: scale(.3);
              }

              50% {
                opacity: 1;
                -webkit-transform: scale(1.05);
                -ms-transform: scale(1.05);
                transform: scale(1.05);
              }

              70% {
                -webkit-transform: scale(.9);
                -ms-transform: scale(.9);
                transform: scale(.9);
              }

              100% {
                -webkit-transform: scale(1);
                -ms-transform: scale(1);
                transform: scale(1);
              }
            }

            :host(.past:host) {
              /*opacity: 0;*/
            }

            :host(.current:host) {
              display: block;
            }

            :host(.next:host) {
              pointer-events: none;
            }
        </style>
        <content></content>
    </template>
    <script type="text/javascript">
        (function() {
            Polymer('impress-slide', {
                entrance: 'bounceIn',
                exit: 'fadeOutRightBig',
                animation: "",

                animateIn: function() {
                    // this.opacity = 1;
                    this.animation = this.entrance;
                },

                animateOut: function() {
                    // this.opacity = 0;
                    this.animation = this.exit;
                },

                ready: function() {

                }
            })
        })();
    </script>
</polymer-element>

The animation-name: {{ animation }} !important; will remain unrendered in the polyfill version, evaluating simply to animation: 1s both;. I was wondering if anyone had any insight as to why this is and what I can do as a workaround?

有帮助吗?

解决方案

So after some digging, I found a discussion of the problem on the polymer github page: https://github.com/Polymer/polymer/issues/270.

Basically, this is an unsupported feature in the ShadowDOMPolyfill for the time being, and the authors are unsure whether or not they will implement this functionality for performance reasons. The programmer assigned to the issue suggests the following workaround:

<style>
      div {
        border: 1px solid black;
        width: {{width}}px;
      }
      /* polyfill specific rule */
      /* @polyfill-rule
        @host[id={{id}}] div {
          border: 1px solid black;
          width: {{width}}px;
        }
      */
</style>

...

<script type="text/javascript">
Polymer('x-foo', {

        ...

        registerCallback: function(declaration) {
          // add shimmedStyles to this instance
          if (window.ShadowDOMPolyfill) {
            var content = declaration.templateContent();
            content.insertBefore(content.shimmedStyle, content.firstChild);
          }
        }
      }); 
</script>

For whatever reason, my own implementation of this method failed. In lieu of this, I wrote a workaround that, while being a little ugly, works quite well in unsupported browsers:

<script type="text/javascript">
    (function() {
        Polymer('impress-slide', {
            entrance: 'bounceIn',
            exit: 'fadeOutRightBig',
            animation: "",

            animateIn: function() {
                this.animation = this.entrance;
                // Fallback for polyfill
                if (window.ShadowDOMPolyfill &&
                    ((this.style.animationName != this.entrance) || 
                    (this.style.webkitAnimationName != this.entrance))) {
                        this.style.webkitAnimation = 
                        this.style.animation = this.entrance + " 1s both";
                }                       
            },
            animateOut: function() {
                this.animation = this.entrance;
                // Fallback for polyfill
                if (window.ShadowDOMPolyfill &&
                    ((this.style.animationName != this.exit) || 
                    (this.style.webkitAnimationName != this.exit))) {
                        this.style.webkitAnimation = 
                        this.style.animation = this.exit;
                }                       
            },

            ready: function() {

            }
        })
    })();
</script>

Essentially, these modifications test the browser for the presence of the polyfill and for the incorrect assignment of the animation style properties. If these are found, the function will manually apply them to the slide using inline insertion (e.g. this.style.animation = this.entrance + " 1s both";).

The downsides of this approach are that it exposes the inner workings of the element to the end user in the event of the polyfill, undermining the goal of encapsulation within the custom element. However, under normal circumstances within a supported browser, the element will transition as expected, with the encapsulation intact.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top