将CodePen babel和手写笔转换为Angular 5和scss

时间:2018-02-19 13:13:49

标签: angular babeljs stylus

我发现了这个整洁的CodePen动画按钮组:

https://codepen.io/Zaku/pen/reGRBg

我正试图将它实施到我的角色5项目中。

我对此非常了解。我可以看到svg发生的事情,但它并没有过渡,而且它是一个黑色阴影:

enter image description here

以下是我所做的更改:

mycomponent.ts

import {Component, ElementRef, OnInit} from '@angular/core';

@Component({
  selector: 'app-mycomponent',
  templateUrl: './mycomponent.html',
  styleUrls: ['./mycomponent.scss']
})
export class myComponent implements OnInit {

  pathLength = 68 * 2 + 200;
  group;
  buttons;
  svg;
  path;
  currentPath;
  currentIndex;

  constructor(private elRef:ElementRef) {}

  ngOnInit() {
    this.group = this.elRef.nativeElement.querySelector('.btn-group');
    this.buttons = Array.prototype.slice.call(
      this.group.querySelectorAll(".btn")
    );
    console.log(this.buttons);
    this.svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
    this.svg.setAttribute(
      "viewbox",
      `-1 -1 ${160 * this.buttons.length + 2} 42`
    );
    this.path = document.createElementNS("http://www.w3.org/2000/svg", "path");
    this.currentPath = "M -80, 40";
    this.currentIndex = -1;
    this.activateIndex(
      this.buttons.indexOf(this.group.querySelector(".active"))
    );
    this.group.appendChild(this.svg);
    this.svg.appendChild(this.path);
    this.refreshPath();
  }

  onClick(e) {
    const index = this.buttons.indexOf(e.srcElement || e.target);
    this.activateIndex(index);
  }

  refreshPath() {
    this.path.setAttributeNS(null, "d", this.currentPath);
    this.path.style.strokeDashoffset =
      (-this.path.getTotalLength() + this.pathLength) * 0.9965;
  }

  center(index) {
    return index * 160 + 80;
  }

  removeClass(str) {
    if (this.buttons[this.currentIndex]) {
      this.buttons[this.currentIndex].classList.remove(str);
    }
  }

  addClass(str) {
    if (this.buttons[this.currentIndex]) {
      this.buttons[this.currentIndex].classList.add(str);
    }
  }

  activateIndex(index) {
    const lastCenter = this.center(this.currentIndex);
    const nextCenter = this.center(index);
    const offset = index < this.currentIndex ? -50 : 50;
    const curve = index < this.currentIndex ? -30 : 30;
    this.currentPath += `
    L ${lastCenter + offset}, 40
    C ${lastCenter + offset + curve}, 40
      ${lastCenter + offset + curve},  0
      ${lastCenter + offset},  0
    L ${lastCenter - offset},  0
    C ${lastCenter - offset - curve},  0
      ${lastCenter - offset - curve}, 40
      ${lastCenter - offset}, 40
    L ${nextCenter + offset}, 40
    C ${nextCenter + offset + curve}, 40
      ${nextCenter + offset + curve},  0
      ${nextCenter + offset},  0
    L ${nextCenter - offset},  0
    C ${nextCenter - offset - curve},  0
      ${nextCenter - offset - curve}, 40
      ${nextCenter - offset}, 40
    L ${nextCenter}, 40`;
    this.removeClass("active");
    this.currentIndex = index;
    this.addClass("active");
    this.refreshPath();
  }
}

mycomponent.html :(您会注意到我添加了角度点击观察者来代替处理这些操作)

<div class="container">
  <div class="btn-group">
    <div (click)="onClick($event)" class="btn">First</div>
    <div (click)="onClick($event)" class="btn active">Middle</div>
    <div (click)="onClick($event)" class="btn">Last</div>
  </div>
</div>

mycomponent.scss

$easing: cubic-bezier(0, 0.8, 0.2, 1);
$duration: 1s;

  .container {
    color: #19cc95;
    text-align: center;
  }

  .btn-group {
    position: relative;
    display: inline-block;
    .btn {
      cursor: pointer;
      float: left;
      height: 40px;
      width: 160px;
      line-height: 40px;
      text-align: center;
      -webkit-user-select: none;
      transition: font-size 0.3s ease;
      &:active {
        font-size: 0.8em;
      }
    }
    svg {
      z-index: -1;
      top: 0;
      left: 0;
      position: absolute;
      width: 100%;
      height: 100%;
      overflow: visible;
    }
    path {
      fill: none;
      stroke: #19cc95;
      stroke-dasharray: 334.9, 99999;
      transition: stroke-dashoffset 1s cubic-bezier(0, 0.8, 0.2, 1);
      stroke-width: 1;
    }
  }

以上并非一半不好。活跃的&#39;正在根据点击正确设置类。并且svg黑色阴影改变了。

显然svg应该叠加在菜单上并且不会发生。

我错过了什么?

1 个答案:

答案 0 :(得分:1)

由于 svg 元素是动态创建的,因此您必须在动态创建svg的组件上使用encapsulation: ViewEncapsulation.None以确保 .component.scss <的样式/ em>适用于所有内容。

我复制了你的代码并成功运行,但稍作修改。

component.html

<div class="container">
  <div #btnGroup class="btn-group">
    <div class="btn" (click)="onClick($event)">First</div>
    <div class="btn active" (click)="onClick($event)">Middle</div>
    <div class="btn" (click)="onClick($event)">Last</div>
  </div>
</div>

component.ts

import {Component, ElementRef, OnInit, ViewChild, ViewEncapsulation} from '@angular/core';

@Component({
  selector: 'app-svg-buttons',
  templateUrl: './svg-buttons.component.html',
  styleUrls: ['./svg-buttons.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class SvgButtonsComponent implements OnInit, AfterViewInit {
  @ViewChild('btnGroup') btnGroup: ElementRef;

  pathLength = 68 * 2 + 200;
  group;
  buttons;
  svg;
  path;
  currentPath;
  currentIndex;

  constructor(private elementRef: ElementRef) {
  }

  ngOnInit() {
  }

  ngAfterViewInit() {
    this.initializeGroup(this.btnGroup.nativeElement);
  }

  initializeGroup(group) {
    this.group = group;

    this.buttons = Array.prototype.slice.call(
      this.group.querySelectorAll('.btn')
    );

    this.svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
    this.svg.setAttribute('viewbox',
      `-1 -1 ${160 * this.buttons.length + 2} 42`
    );
    this.path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    this.currentPath = 'M -80, 40';
    this.currentIndex = -1;
    this.activateIndex(
      this.buttons.indexOf(
        this.group.querySelector('.active')
      )
    );
    this.group.appendChild(this.svg);
    this.svg.appendChild(this.path);
    this.refreshPath();
  }

  onClick(e) {
    const index = this.buttons.indexOf(e.srcElement || e.target);
    this.activateIndex(index);
  }

  refreshPath() {
    this.path.setAttributeNS(null, 'd', this.currentPath);
    this.path.style.strokeDashoffset = (-this.path.getTotalLength() + this.pathLength) * 0.9965;
  }

  center(index) {
    return index * 160 + 80;
  }

  removeClass(str) {
    if (this.buttons[this.currentIndex]) {
      this.buttons[this.currentIndex].classList.remove(str);
    }
  }

  addClass(str) {
    if (this.buttons[this.currentIndex]) {
      this.buttons[this.currentIndex].classList.add(str);
    }
  }

  activateIndex(index) {
    const lastCenter = this.center(this.currentIndex);
    const nextCenter = this.center(index);
    const offset = index < this.currentIndex ? -50 : 50;
    const curve = index < this.currentIndex ? -30 : 30;
    this.currentPath += `
      L ${lastCenter + offset        }, 40
      C ${lastCenter + offset + curve}, 40
        ${lastCenter + offset + curve},  0
        ${lastCenter + offset        },  0
      L ${lastCenter - offset        },  0
      C ${lastCenter - offset - curve},  0
        ${lastCenter - offset - curve}, 40
        ${lastCenter - offset        }, 40
      L ${nextCenter + offset        }, 40
      C ${nextCenter + offset + curve}, 40
        ${nextCenter + offset + curve},  0
        ${nextCenter + offset        },  0
      L ${nextCenter - offset        },  0
      C ${nextCenter - offset - curve},  0
        ${nextCenter - offset - curve}, 40
        ${nextCenter - offset        }, 40
      L ${nextCenter                 }, 40
    `;
    this.removeClass('active');
    this.currentIndex = index;
    this.addClass('active');
    this.refreshPath();
  }
};