我发现了这个整洁的CodePen动画按钮组:
https://codepen.io/Zaku/pen/reGRBg
我正试图将它实施到我的角色5项目中。
我对此非常了解。我可以看到svg发生的事情,但它并没有过渡,而且它是一个黑色阴影:
以下是我所做的更改:
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应该叠加在菜单上并且不会发生。
我错过了什么?
答案 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();
}
};