분류 javascript

Fancy Exploding Button

컨텐츠 정보

  • 조회 264 (작성일 )

본문

https://codepen.io/takaneichinose/pen/jONdGxM 


HTML : 


<div id="app">

  <ti-button-splatter text="PRESS ME"></ti-button-splatter>

</div>



CSS : 


@import url("https://fonts.googleapis.com/css?family=Open+Sans:400,400i,700");


html, body {

  width: 100%;

  height: 100%;

}


#app {

  font-family: 'Open Sans', sans-serif;

  font-size: 24px;

  background-image: linear-gradient(to bottom right,

    #ff4e4e 0 15%, #f8ff64 40% 60%, #00ce1a 85% 100%);

  width: 100%;

  height: 100%;

  display: flex;

  align-items: center;

  justify-content: center;

}


.btn-splatter {

  color: #ffffff;

  font-family: inherit;

  font-weight: bold;

  background-color: #4487ed;

  width: 12em;

  height: 4em;

  border: 0;

  outline: 0;

  padding: 0;

  margin: 0;

  position: relative;

  border-radius: 0.9em;

  box-shadow: 0 0.6em 0.9em rgba(0, 0, 0, 0.6);

  user-select: none; /* Thanks to @SplittyDev */

  transform: translateY(-0.5em);

  transition:

    background-color 300ms cubic-bezier(0.18, 0.89, 0.32, 1.28),

    box-shadow 300ms cubic-bezier(0.18, 0.89, 0.32, 1.28),

    transform 300ms cubic-bezier(0.18, 0.89, 0.32, 1.28);

}


.btn-splatter:focus {

  outline: 0;

}


.btn-splatter:active {

  background-color: #2770df;

  box-shadow: 0 0 0 rgba(0, 0, 0, 0.5);

  transform: translateY(0em) scale(0.9);

  transition:

    background-color 150ms ease-out,

    box-shadow 150ms ease-out,

    transform 150ms ease-out;

}


.splatter {

  position: absolute;

  top: 0;

  left: 0;

}


.splatter-round, .splatter-ring, .splatter-star {

  position: absolute;

}


.splatter-round {

  width: 1em;

  height: 1em;

  background-color: #1da5ff;

  border-radius: 50%;

}


.splatter-ring {

  width: 0.8em;

  height: 0.8em;

  border: solid 0.35em #0099e6;

  border-radius: 50%;

}


.splatter-star {

  width: 1.8em;

  height: 1.8em;

  background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" fill="%23006dd0" viewBox="0 0 24 24"%3E%3Cpath%20d%3D%22M12%2C17.27L18.18%2C21L16.54%2C13.97L22%2C9.24L14.81%2C8.62L12%2C2L9.19%2C8.62L2%2C9.24L7.45%2C13.97L5.82%2C21L12%2C17.27Z%22%3E%3C%2Fpath%3E%3C/svg%3E');

}




Javascript : 


Vue.component('ti-button-splatter', {

  props: ['text'],

  data: function () {

    return {

      splatters: [] };


  },

  template: `

<button

  class="btn-splatter"

  v-on:click="makeSplatter(event)"

>

  {{text}}

  <div

    v-for="splatter, i in splatters"

    v-bind:class="splatter.type"

    v-bind:style="splatter.style"

    v-bind:ref="createRef(i)"

  ></div>

</button>

`,

  methods: {

    createRef: function (i) {

      return 'splatter-' + i;

    },

    getSizeEm: function (s) {

      if (s === 0) {

        return 1 / 2 + 'em';

      } else if (s === 1) {

        return 1.5 / 2 + 'em';

      } else if (s === 2) {

        return 1.8 / 2 + 'em';

      } else {

        return 0;

      }

    },

    createToXPos: function (tb, w, h, s) {

      let positionStyle = { style: {} };

      let randomPosition = Math.floor(Math.random() * w);

      let fixedPosition = tb === 0 ? h : 0;


      positionStyle.style.top = 'calc(' + fixedPosition + 'px - ' + s + ')';

      positionStyle.style.left = 'calc(' + randomPosition + 'px - ' + s + ')';


      return positionStyle;

    },

    createToYPos: function (lr, w, h, s) {

      let positionStyle = { style: {} };

      let randomPosition = Math.floor(Math.random() * h);

      let fixedPosition = lr === 0 ? w : 0;


      positionStyle.style.left = 'calc(' + fixedPosition + 'px - ' + s + ')';

      positionStyle.style.top = 'calc(' + randomPosition + 'px - ' + s + ')';


      return positionStyle;

    },

    createsplatter: function (el, count, types, w, h) {

      for (let i = 0; i < count; i++) {if (window.CP.shouldStopExecution(0)) break;

        let type = Math.floor(Math.random() * 3);

        let xOrY = Math.round(Math.random());

        let tblr = Math.round(Math.random());

        let splt = null;

        let sz = Math.random() + 0.5;


        if (xOrY === 0) {

          splt = this.createToXPos(tblr, w, h, this.getSizeEm(type));

        } else {

          splt = this.createToYPos(tblr, w, h, this.getSizeEm(type));

        }


        splt.type = types[type];

        splt.scale = sz;


        splt.style.display = 'none';

        splt.style.transform = 'scale(' + sz + ')';


        if (splt !== null) {

          this.splatters.push(splt);

        }

      }window.CP.exitedLoop(0);

    },

    explodeSplatter: function () {

      for (var i = 0; i < this.splatters.length; i++) {if (window.CP.shouldStopExecution(1)) break;

        if (this.splatters[i].animationEnd === true) {

          continue;

        }


        if (typeof this.splatters[i].moving === 'undefined') {

          let el = this.$refs['splatter-' + i];

          let an = Math.floor(Math.random() * 359) + 1;


          this.splatters[i].style.display = 'block';


          this.splatters[i].moving = true;


          let psY = Math.sin(an) * 3 + 'em';

          let psX = Math.cos(an) * 3 + 'em';

          let scl = this.splatters[i].scale;


          TweenLite.to(el, 0.8, {

            transform:

            'translate(' + psX + ', ' + psY + ') rotate(720deg) scale(0)' }).

          eventCallback('onComplete', () => {

            el.dataset.animationEnd = true;

          });

        }

      }window.CP.exitedLoop(1);

    },

    makeSplatter: function (e) {

      let el = e.target;

      let count = Math.floor(Math.random() * 4) + 5;

      let types = ['splatter-round', 'splatter-ring', 'splatter-star'];

      let w = el.clientWidth;

      let h = el.clientHeight;


      this.createsplatter(el, count, types, w, h);

    } },


  watch: {

    splatters: function (newData, oldData) {

      setTimeout(() => {

        this.explodeSplatter();

      }, 1);

    } } });




// -----


var app = new Vue({

  el: '#app' });