简体   繁体   中英

ionic ts part to can't correctly put JavaScript

I'm try to create like this example animated for my Ionic mobile application, I have small issue , actually this animated part not working for me, anyone know know how to put that script part correctly for Ionic, Please help me to fix that issue Thanks

this is my code sample my live code part without animated

this is my code

html

<div class="claps">
  <button id="clap" class="clap">
  <span>
    <!--  SVG Created by Luis Durazo from the Noun Project  -->
    <svg id="clap--icon" xmlns="http://www.w3.org/2000/svg" viewBox="-549 338 100.1 125">
  <path d="M-471.2 366.8c1.2 1.1 1.9 2.6 2.3 4.1.4-.3.8-.5 1.2-.7 1-1.9.7-4.3-1-5.9-2-1.9-5.2-1.9-7.2.1l-.2.2c1.8.1 3.6.9 4.9 2.2zm-28.8 14c.4.9.7 1.9.8 3.1l16.5-16.9c.6-.6 1.4-1.1 2.1-1.5 1-1.9.7-4.4-.9-6-2-1.9-5.2-1.9-7.2.1l-15.5 15.9c2.3 2.2 3.1 3 4.2 5.3zm-38.9 39.7c-.1-8.9 3.2-17.2 9.4-23.6l18.6-19c.7-2 .5-4.1-.1-5.3-.8-1.8-1.3-2.3-3.6-4.5l-20.9 21.4c-10.6 10.8-11.2 27.6-2.3 39.3-.6-2.6-1-5.4-1.1-8.3z"/>
  <path d="M-527.2 399.1l20.9-21.4c2.2 2.2 2.7 2.6 3.5 4.5.8 1.8 1 5.4-1.6 8l-11.8 12.2c-.5.5-.4 1.2 0 1.7.5.5 1.2.5 1.7 0l34-35c1.9-2 5.2-2.1 7.2-.1 2 1.9 2 5.2.1 7.2l-24.7 25.3c-.5.5-.4 1.2 0 1.7.5.5 1.2.5 1.7 0l28.5-29.3c2-2 5.2-2 7.1-.1 2 1.9 2 5.1.1 7.1l-28.5 29.3c-.5.5-.4 1.2 0 1.7.5.5 1.2.4 1.7 0l24.7-25.3c1.9-2 5.1-2.1 7.1-.1 2 1.9 2 5.2.1 7.2l-24.7 25.3c-.5.5-.4 1.2 0 1.7.5.5 1.2.5 1.7 0l14.6-15c2-2 5.2-2 7.2-.1 2 2 2.1 5.2.1 7.2l-27.6 28.4c-11.6 11.9-30.6 12.2-42.5.6-12-11.7-12.2-30.8-.6-42.7m18.1-48.4l-.7 4.9-2.2-4.4m7.6.9l-3.7 3.4 1.2-4.8m5.5 4.7l-4.8 1.6 3.1-3.9"/>
</svg>
  </span>
  <span id="clap--count" class="clap--count"></span>
  <span id="clap--count-total" class="clap--count-total"></span>
</button>
  </div>

css

  $btn-dimension: 80px;
    $primary-color: rgba(189,195,199 ,1);
    $secondary-color: rgba(39,174,96 ,1);
    @mixin debug {
      outline: 1px solid red;
    }



    /*========================
        BASIC styles
      =======================*/
    * {
      box-sizing: border-box
    }
    .claps {margin-top: 10rem;margin-left: 5rem;}
    /*========================
        BUTTON styles
      =======================*/
    .clap {
      position: relative;
      outline: 1px solid transparent;
      border-radius: 50%;
      border: 1px solid $primary-color;
      width: $btn-dimension;
      height: $btn-dimension; 
      background: none;
      &:after {
        content: "";
        position: absolute;
        top: 0;
        left: 0;
        display: block;
        border-radius: 50%;
        //border: 1px solid $primary-color;
        width: $btn-dimension - 1px;
        height: $btn-dimension - 1px;
      }
      &:hover {
       cursor: pointer;
       border: 1px solid $secondary-color;
       transition: border-color 0.3s ease-in;
        &:after {
          animation: shockwave 1s ease-in infinite;
        } 
      }
      svg {
        width: 40px;
        fill: none;
        stroke: $secondary-color;
        stroke-width: 2px;
        &.checked {
          fill: $secondary-color;
          stroke: #fff;
          stroke-width: 1px;
        }
      }
      .clap--count {
        position: absolute;
        top: -$btn-dimension/1.6;
        left: $btn-dimension/4;
        font-size: 0.8rem;
        color: white;
        background: $secondary-color;
        border-radius: 50%;
        height: $btn-dimension/2;
        width: $btn-dimension/2;
        line-height: $btn-dimension/2;
      }
      .clap--count-total {
        position: absolute;
        font-size: 0.8rem;
        width: $btn-dimension;
        text-align: center;
        left: 0;
        top: -$btn-dimension/3.5;
        color: $primary-color; 
      }
    }



    /*====================
            Message
    ======================*/
    #message {
      position: absolute;
      bottom: 20px;
      color: $secondary-color;
      line-height: 1.52rem;
      padding: 1rem;
      font-size: 0.9rem;
      a {
        color: $primary-color
      }
    }
@keyframes shockwave {
  0% {
    transform: scale(1);
    box-shadow: 0 0 2px $secondary-color;
    opacity: 1;
  }

  100% {
    transform: scale(1);
    opacity: 0;
    box-shadow: 0 0 50px darken($secondary-color, 20%), inset 0 0 10px $secondary-color;
  }
}

I want to know how to put this part correctly for Ionic

const clap = document.getElementById('clap')
const clapIcon = document.getElementById('clap--icon')
const clapCount = document.getElementById('clap--count')
const clapTotalCount = document.getElementById('clap--count-total')
const initialNumberOfClaps = generateRandomNumber(500, 10000);
const btnDimension = 80
const tlDuration = 300
let numberOfClaps = 0
let clapHold;

const triangleBurst = new mojs.Burst({
  parent: clap,
  radius: {50:95},
  count: 5,
  angle: 30,
  children: {
    shape: 'polygon',
    radius: {6: 0},
    scale: 1,
    stroke: 'rgba(211,84,0 ,0.5)',
    strokeWidth: 2,
    angle: 210,
    delay: 30,
    speed: 0.2,
    easing: mojs.easing.bezier(0.1, 1, 0.3 ,1),
    duration: tlDuration
  } 
})
const circleBurst = new mojs.Burst({
  parent: clap,
  radius: {50:75},
  angle: 25,
  duration: tlDuration,
  children: {
    shape: 'circle',
    fill: 'rgba(149,165,166 ,0.5)',
    delay: 30,
    speed: 0.2,
    radius: {3: 0},
    easing: mojs.easing.bezier(0.1, 1, 0.3, 1),
  }
})
const countAnimation = new mojs.Html({
  el: '#clap--count',
  isShowStart: false,
  isShowEnd: true,
  y: {0: -30},
  opacity: {0:1},
  duration: tlDuration
}).then({
  opacity: {1:0},
  y: -80,
  delay: tlDuration/2
})
const countTotalAnimation = new mojs.Html({
  el: '#clap--count-total',
  isShowStart: false,
  isShowEnd: true,
  opacity: {0:1},
  delay: 3*(tlDuration)/2,
  duration: tlDuration,
  y: {0: -3}
})
const scaleButton = new mojs.Html({
  el: '#clap',
  duration: tlDuration,
  scale: {1.3: 1},
  easing: mojs.easing.out
})
clap.style.transform = "scale(1, 1)" /*Bug1 fix*/

const animationTimeline = new mojs.Timeline()
animationTimeline.add([
  triangleBurst,
  circleBurst,
  countAnimation,
  countTotalAnimation,
  scaleButton
])


clap.addEventListener('click', function() {
   repeatClapping();
})

clap.addEventListener('mousedown', function() {
   clapHold = setInterval(function() {
   repeatClapping();
   }, 400)
})

clap.addEventListener('mouseup', function() {
 clearInterval(clapHold);
})


function repeatClapping() {
 updateNumberOfClaps()
 animationTimeline.replay()
 clapIcon.classList.add('checked')
}

function updateNumberOfClaps() {
  numberOfClaps < 50 ? numberOfClaps++ : null
  clapCount.innerHTML = "+" + numberOfClaps
  clapTotalCount.innerHTML = initialNumberOfClaps + numberOfClaps
}

function generateRandomNumber(min, max) {
  return Math.floor(Math.random()*(max-min+1)+min);
}

I would create dedicated component like clap

But first you need to add mojs to your page

<script src="https://cdnjs.cloudflare.com/ajax/libs/mo-js/0.288.1/mo.min.js"></scrip>

Since we don't have typings for mojs you can just define it as any :

declare let mojs: any;

(Note: you can create typings something like How to extend js class from outside library in TypeScript / Using mojs in TypeScript if you want)

Now it's time to create our custom component.

We're going to use ViewChild instead of document.getElementById to hold of reference to DOM element. For that we need to put template references on elements ( <button #clap ). We will use that references instead of selectors like el: '#clap--count-total', so our component will be scope safed

Also we won't listen to dom events through .addEventListener but rather via element output events like (click)

So here's the code

clap.component.html

<button #clap class="clap"
     (click)="repeatClapping()" 
     (mousedown)="onClapMouseDown()" 
     (mouseup)="onClapMouseUp()">
  <span>
    <svg [class.checked]="clapIconChecked" ...>
      ...
    </svg>
  </span>
  <span #clapCount class="clap--count">+{{currentClaps}}</span>
  <span #clapCountTotal class="clap--count-total">{{claps}}</span>
</button>

clap.component.ts

import { Component, ElementRef, Input, OnInit, ViewChild, EventEmitter, Output } from '@angular/core';

declare let mojs: any;

@Component({
  selector: 'clap',
  templateUrl: './clap.component.html',
  styleUrls: ['./clap.component.css']
})
export class ClapComponent implements OnInit {

  @Input() claps = 0;

  @Input() tlDuration = 300;

  @Output() clapsChange = new EventEmitter();

  @ViewChild('clap') clapEl: ElementRef;

  @ViewChild('clapCount') clapCountEl: ElementRef;

  @ViewChild('clapCountTotal') clapCountTotalEl: ElementRef;

  currentClaps: number = 0;

  clapIconChecked = false;

  private animationTimeline: any;

  private clapHold: any;

  ngOnInit() {
    const triangleBurst = new mojs.Burst({
      parent: this.clapEl.nativeElement,
      radius: {50: 95},
      count: 5,
      angle: 30,
      children: {
        shape: 'polygon',
        radius: {6: 0},
        scale: 1,
        stroke: 'rgba(211,84,0 ,0.5)',
        strokeWidth: 2,
        angle: 210,
        delay: 30,
        speed: 0.2,
        easing: mojs.easing.bezier(0.1, 1, 0.3, 1),
        duration: this.tlDuration
      }
    });

    const circleBurst = new mojs.Burst({
      parent: this.clapEl.nativeElement,
      radius: {50: 75},
      angle: 25,
      duration: this.tlDuration,
      children: {
        shape: 'circle',
        fill: 'rgba(149,165,166 ,0.5)',
        delay: 30,
        speed: 0.2,
        radius: {3: 0},
        easing: mojs.easing.bezier(0.1, 1, 0.3, 1),
      }
    });

    const countAnimation = new mojs.Html({
      el: this.clapCountEl.nativeElement,
      isShowStart: false,
      isShowEnd: true,
      y: {0: -30},
      opacity: {0: 1},
      duration: this.tlDuration
    }).then({
      opacity: {1: 0},
      y: -80,
      delay: this.tlDuration / 2
    });

    const countTotalAnimation = new mojs.Html({
      el: this.clapCountTotalEl.nativeElement,
      isShowStart: false,
      isShowEnd: true,
      opacity: {0: 1},
      delay: 3 * (this.tlDuration) / 2,
      duration: this.tlDuration,
      y: {0: -3}
    });

    const scaleButton = new mojs.Html({
      el: this.clapEl.nativeElement,
      duration: this.tlDuration,
      scale: {1.3: 1},
      easing: mojs.easing.out
    });

    this.clapEl.nativeElement.style.transform = 'scale(1, 1)';

    this.animationTimeline = new mojs.Timeline();
    this.animationTimeline.add([
      triangleBurst,
      circleBurst,
      countAnimation,
      countTotalAnimation,
      scaleButton
    ]);
  } 

  repeatClapping() {
    if (this.currentClaps > 49) {
      alert('Limit 50 claps');
      return;
    }

    this.currentClaps++;
    this.claps++;
    this.clapsChange.emit(this.claps);

    this.animationTimeline.replay();
    this.clapIconChecked = true;
  }

  onClapMouseDown() {
    this.clapHold = setInterval(() => {
      this.repeatClapping();
    }, 400);
  }

  onClapMouseUp() {
    clearInterval(this.clapHold);
  }
}

As you can see there is no magic here. It's simple component with two-way binding that we can use anywhere as follows:

home.html

<clap [(claps)]="claps"></clap>

home.ts

export class HomePage {
  claps = generateRandomNumber(500, 10000);
}

function generateRandomNumber(min, max) {
  return Math.floor(Math.random() * (max - min + 1) + min);
}

在此处输入图片说明

Try it out Example

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM