Javascript 角度:样式或类别绑定,座位地图

Javascript 角度:样式或类别绑定,座位地图,javascript,css,angular,typescript,Javascript,Css,Angular,Typescript,我正在为我的研究生学习项目而奋斗。我需要使互动座位地图的角度与最大选择9个座位。在浏览了我以前的课程之后,我能够在JS中创造一些魔力,但没有max selection(下面链接到codepen) HTML代码包含巨大的SVG图形-您可以在下面附带的代码笔中找到它 CSS Javascript const buttonArray = document.querySelectorAll("#seats path"); console.log("query", typeof buttonArray);

我正在为我的研究生学习项目而奋斗。我需要使互动座位地图的角度与最大选择9个座位。在浏览了我以前的课程之后,我能够在JS中创造一些魔力,但没有max selection(下面链接到codepen)

HTML代码包含巨大的SVG图形-您可以在下面附带的代码笔中找到它

CSS

Javascript

const buttonArray = document.querySelectorAll("#seats path");
console.log("query", typeof buttonArray);


var myArray = Array.from(buttonArray);
console.log(myArray);

for (let i = 0; i < myArray.length; i++) {
    myArray[i].setAttribute("id", `seat_${i + 1}`);

    document.getElementById(`seat_${i + 1}`).addEventListener("click", function() {
        if (document.getElementById(this.id).getAttribute("class") == "occupied") {
            document.getElementById(this.id).removeAttribute("style");
            document.getElementById(this.id).setAttribute("class", "free");
        } else {
            document.getElementById(this.id).removeAttribute("style");
            document.getElementById(this.id).setAttribute("class", "occupied");
        }
    });
}
const buttonArray=document.queryselectoral(“座位路径”);
console.log(“查询”,按钮数组的类型);
var myArray=Array.from(buttonArray);
log(myArray);
for(设i=0;i

我不知道如何将其实现为Angular,或者如何使其更简单。 当然,如何最大限度地选择9个座位

我将非常感谢你的任何建议和帮助


您可以将onClick函数添加到path=seats

<g id="seats"  (click)="onClick($event)">
为什么不使用角呢

我们将定义一个指令,但是如果修改svg以将座椅分组(而不是将字母和背景分开),我们需要做的第一件事是

一个座位就变成这样了

   <g seat id="26F" >
        <path #background class="st121" d="M285.8,1126.1h-17c-0.6,0-1-0.4-1-1v-22c0-0.6,0.4-1,1-1h17c0.6,0,1,0.4,1,1v22
            C286.8,1125.7,286.3,1126.1,285.8,1126.1z "/>
      <path #letter class="st122" d="M275.8,1115.2v-6.4h4.2v1.2h-2.9v1.7h2.6v1.1h-2.6v2.5L275.8,1115.2L275.8,1115.2z"></path>
   </g>

注意不要在一个“组”中放置两条路径

我写
。是属性指令。还可以看到,我们使用了两个参考变量,一个用于背景,另一个用于字母

指令变得像

@Directive({
  selector: '[seat]',
  exportAs: 'seat'
})
export class SeatDirective {
  @ContentChild('background') background:ElementRef //<--reference to background
  @ContentChild('letter') letter:ElementRef  //<--reference to letter

  @HostListener('click', ['$event.target'])  //<--a HostListener
  onClick()                                  //when click
  {
    this.seatmap.seatClick(this) //call to a funcion of the "seatmap"
  }
  checked:boolean=false  //a variable that store if checked or not


  constructor(public el:ElementRef,@Host() private seatmap:SeatmapComponent ){}
}
@指令({
选择器:“[座位]”,
exportAs:'座位'
})
出口级定向{
@ContentChild('background')背景:ElementRef//x.checked)
.map(x=>x.el.nativeElement.getAttribute('id'))
}

另一种方法是“动态”创建座位,使用数组放置位置,并在svg中使用rect和文本

如果我们有一个行数组

  filas = [
    { y: 250, x: [0, 0, 0, 195.5, 175.2, 154.8] },
    { y: 281.9, x: [285.8, 265.5, 245.1, 195.5, 175.2, 154.8] },
    { y: 313.9, x: [285.8, 265.5, 245.1, 195.5, 175.2, 154.8] },
    { y: 345.9, x: [285.8, 265.5, 245.1, 195.5, 175.2, 154.8] },
        ...
    ]
我们可以动态创建svg,如果我们使用0作为coordenate,就不要创建座位

<svg version="1.1" id="whole_x5F_plane" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
     y="0px" viewBox="0 0 425 1467.9" style="enable-background:new 0 0 425 1467.9;" xml:space="preserve">
<style type="text/css">
  .st0{clip-path:url(#SVGID_15_);}
  .st1{clip-path:url(#SVGID_24_);}
    ...
  .free{fill:#FFFFFF;stroke:#050404;stroke-width:0.25;stroke-miterlimit:10;}
  .booked{fill:#8E8E8E;stroke:#050404;stroke-width:0.25;stroke-miterlimit:10;}
  .selected{fill:#FFFF00;stroke:#050404;stroke-width:0.25;stroke-miterlimit:10;}
</style>
...
<ng-container *ngFor="let fila of filas;let i=index">
    <ng-container *ngFor="let x of fila.x;let j=index">
        <!--if x==0 don't create the seat-->
        <g style="cursor:pointer" *ngIf="x" (click)="click(i,j)">
           <!--a rectangle-->
            <rect [ngClass]="status[i][j]" [attr.x]="x-18" [attr.y]="fila.y-22" width="20" height="20" rx="2"
                ry="2" />
            <!--and the text-->
            <text [attr.x]="x-16" [attr.y]="fila.y-8" font-family="Verdana" 
                font-size="11" stroke="transparent"
                fill="#333">
                {{this.letras[j]}}
            </text>
        </g>
    </ng-container>
</ng-container>
</svg>

.st0{clip path:url(#SVGID_15)}
.st1{剪辑路径:url(#SVGID_24)}
...
.free{fill:#FFFFFF;笔划:#050404;笔划宽度:0.25;笔划斜接限制:10;}
.booked{fill:#8E8E8E;笔划:#050404;笔划宽度:0.25;笔划斜接限制:10;}
.所选{填充:#FFFF00;笔划:#050404;笔划宽度:0.25;笔划斜接限制:10;}
...
{{this.letras[j]}
因为我们在svg中有预订、免费、选择的类,点击变得很容易,记住我们使用数组数组来存储座位的“类”

  status = this.filas.map(x => [
    "free",
    "free",
    "free",
    "free",
    "free",
    "free"
  ]);

  click(fila, column) {

    if (this.status[fila][column] == "free" && this.count() < 3) //here check the maximum
      this.status[fila][column] = "selected";
    else {
      if (this.status[fila][column] == "selected")
        this.status[fila][column] = "free";
    }
  }

  count() {
    return this.status
      .map(x => x.filter(s => s == "selected").length)
      .reduce((a, b) => a + b);
  }
status=this.filas.map(x=>[
“免费”,
“免费”,
“免费”,
“免费”,
“免费”,
“免费”
]);
单击(fila,列){
如果(this.status[fila][column]=“free”&&this.count()<3)//此处检查最大值
此.status[fila][column]=“已选定”;
否则{
如果(此状态[fila][column]=“已选定”)
此.status[fila][column]=“free”;
}
}
计数(){
返回此状态
.map(x=>x.filter(s=>s==“选定”).length)
.减少((a,b)=>a+b);
}


注意:我对数组的选择真的不是很满意,也许最好用行、字母、x、y和状态定义一个对象数组。但这是一个必须要做的事情

天哪!非常感谢你!哇,当你写的时候,它变得简单易懂了。现在我可以开始处理max selection;)您知道如何将最大选择数9添加到您的解决方案中吗?这一切都很好,但我有几个问题。第一个:
如果(!seat){return;}
如果我错了,请更正。如果有人点击了与座位不同的东西,这是一种预防措施吗?第二个:
const res=seat.getAttribute(“class”).split(“”).indexOf(“”)占用为什么在这里使用
split(“”)
,没有它代码仍然有效?1。第一个:如果(!seat){return;}如果我错了,请更正。如果有人点击了与座位不同的东西,这是一种预防措施吗?是的,你说得对。2.第二个:const res=seat.getAttribute(“class”).split(“”).indexOf(“”)占用;你为什么在这里使用split(“”),没有它代码仍然有效这是我的错。您不必使用split。我忘了我们也可以使用带字符串的拆分。这远远超过了我在课堂上学到的。关于开始时的分组问题,
class=“st122”
指的是那些灰色字段,它们不是座位,更像是座位之间的空间。我不想把座位和字母的路径分组,因为我真的不知道哪个路径是哪个座位的->它们在代码中是随机定位的。@cichebonki,我回答了另一个问题,那就是创建“动态”座位,我希望能帮到你
<svg version="1.1" id="whole_x5F_plane" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
     y="0px" viewBox="0 0 425 1467.9" style="enable-background:new 0 0 425 1467.9;" xml:space="preserve">
<style type="text/css">
  .st0{clip-path:url(#SVGID_15_);}
  .st1{clip-path:url(#SVGID_24_);}
    ...
  .free{fill:#FFFFFF;stroke:#050404;stroke-width:0.25;stroke-miterlimit:10;}
  .booked{fill:#8E8E8E;stroke:#050404;stroke-width:0.25;stroke-miterlimit:10;}
  .selected{fill:#FFFF00;stroke:#050404;stroke-width:0.25;stroke-miterlimit:10;}
</style>
...
<ng-container *ngFor="let fila of filas;let i=index">
    <ng-container *ngFor="let x of fila.x;let j=index">
        <!--if x==0 don't create the seat-->
        <g style="cursor:pointer" *ngIf="x" (click)="click(i,j)">
           <!--a rectangle-->
            <rect [ngClass]="status[i][j]" [attr.x]="x-18" [attr.y]="fila.y-22" width="20" height="20" rx="2"
                ry="2" />
            <!--and the text-->
            <text [attr.x]="x-16" [attr.y]="fila.y-8" font-family="Verdana" 
                font-size="11" stroke="transparent"
                fill="#333">
                {{this.letras[j]}}
            </text>
        </g>
    </ng-container>
</ng-container>
</svg>
  status = this.filas.map(x => [
    "free",
    "free",
    "free",
    "free",
    "free",
    "free"
  ]);

  click(fila, column) {

    if (this.status[fila][column] == "free" && this.count() < 3) //here check the maximum
      this.status[fila][column] = "selected";
    else {
      if (this.status[fila][column] == "selected")
        this.status[fila][column] = "free";
    }
  }

  count() {
    return this.status
      .map(x => x.filter(s => s == "selected").length)
      .reduce((a, b) => a + b);
  }