无法在 Angular 中为 svg 元素添加调整大小手柄



我正在尝试使用Angular构建一个基于web的绘画应用程序,我对web开发仍然有点陌生。我的应用程序使用svg元素来呈现几何形状,如圆形、矩形等但是我不能在我的应用程序中添加一个大小调整功能,我希望用户能够随意调整任何svg元素的大小。

这是我的代码

circle.component.html

<svg>
<circle *ngFor="let circle of circles; let i = index" 
(focus)="selectObject(i)" 
[attr.cx]="circle.x" 
[attr.cy]="circle.y" 
[attr.r]="circle.r" 
[attr.fill]="circle.color" 
stroke="black"
strokeWidth="3"
cdkDrag 
>
</circle>
</svg>

circle.component.ts


@Component({
selector: '[app-circle]',
templateUrl: './circle.component.html',
styleUrls: ['./circle.component.css'] 
})
export class CircleComponent implements OnInit {
isPressed = false;
selectedID = 1;
constructor() { }
ngOnInit(): void {
}
circles: Circle[] = [
{id:0, x: 50, y: 50, r: 40, color: 'red'},
{id:1, x: 100, y: 200, r: 50, color: 'green'},
{id:2, x: 200, y: 300, r: 60, color: 'blue'} 
];
selectObject(index: number){
this.selectedID = index;
console.log('select called with index ' + index);
}
}

我知道我可以简单地改变r值的圆圈,我想调整大小很容易,但我不知道如何添加处理到我的svg元素,以表明这是可能的,像这样:我想达到的目标

我试过把4个div元素作为子元素放在我的circle元素里面,把它变成一个小的调整大小的句柄,但事实证明我不能把div放在svg里面。

我也试过把基本的圆圈svg元素放在我的圆圈里,然后样式化它,但是angular没有渲染它们。

所有的"我已经看到了这些组件

<div class="resizable" [class.select]="selected"  [ngStyle]="style" >
<ng-content ></ng-content>
<div class="cell-top" ></div>
<div class="cell-border-top" ></div>
<div class="cell-border-bottom" ></div>
<div class="cell-border-left" ></div>
<div class="cell-border-right" ></div>
<div class="cell-top-right" ></div>
<div class="cell-bottom-right" ></div>
<div class="cell-top-left" ></div>
<div class="cell-bottom-left"></div>
</div>

然后,在mouseDown中检查元素的className到

  1. 定义拖动类型
  2. 订阅鼠标up
  3. 订阅MouseMove

当mouseUp被执行时,对mouseMove的订阅结束,当鼠标移动时,计算新的位置,宽度和高度。

merge(
fromEvent(this.elementRef.nativeElement, 'mousedown'),
fromEvent(this.elementRef.nativeElement, 'touchstart').pipe(map((event:TouchEvent)=>({
target:event.target,
screenX:event.touches[0].screenX,
screenY:event.touches[0].screenY
}))
))
.pipe(
filter((event: MouseEvent) => {
if (!this.selected)
return false;
const classs = (event.target as any).className;
if (classs && typeof classs === 'string') {
const className = classs.split(' ');
const inside:boolean=(className.indexOf('cell-top')>0)
if (inside)
{
this.selected=true;
}
return inside || this.classNames.indexOf(classs) >= 0;
}
return false;
})
)
.subscribe((event: MouseEvent) => {
this.origin =  { x: event.screenX, y: event.screenY };
const className = (event.target as any).className.split(' ');
this.typeDrag =
className.indexOf('cell-top') >= 0
? TypeDrag.Move
: (this.classNames.indexOf(className[0]) as TypeDrag);
this.incr =
this.typeDrag == TypeDrag.Move
? [1, 0, 1, 0]
: this.typeDrag == TypeDrag.Top
? [1, -1, 0, 0]
: this.typeDrag == TypeDrag.Bottom
? [0, 1, 0, 0]
: this.typeDrag == TypeDrag.Right
? [0, 0, 0, 1]
: this.typeDrag == TypeDrag.Left
? [0, 0, 1, -1]
: this.typeDrag == TypeDrag.TopRight
? [1, -1, 0, 1]
: this.typeDrag == TypeDrag.TopLeft
? [1, -1, 1, -1]
: this.typeDrag == TypeDrag.BottomRight
? [0, 1, 0, 1]
: [0, 1, 1, -1];

merge(fromEvent(document, 'mouseup'),
fromEvent(document,'touchend')
)
.pipe(take(1))
.subscribe(() => {
if (this.moveSubscription) {
this.moveSubscription.unsubscribe();
this.moveSubscription = undefined;
this.rectInit={...this.rect}
}
});
if (!this.moveSubscription) {
this.moveSubscription = merge(
fromEvent(document, 'mousemove'),
fromEvent(document, 'touchmove').pipe(map((event:TouchEvent)=>({
target:event.target,
screenX:event.touches[0].screenX,
screenY:event.touches[0].screenY
}))
))
.pipe(startWith({ screenY: this.origin.y, screenX: this.origin.x }))
.subscribe((moveEvent: MouseEvent) => {
const incrTop = moveEvent.screenY - this.origin.y;
const incrLeft = moveEvent.screenX - this.origin.x;
const width=this.rectInit.width + this.incr[3] * incrLeft;
const height=this.rectInit.height + this.incr[1] * incrTop;
this.rect={
width:width<15?15:width,
height:height<15?15:height,
left:this.rectInit.left+this.incr[2] * incrLeft,
top:this.rectInit.top+this.incr[0] * incrTop
}
this.style = {
width: this.rect.width + 'px',
height: this.rect.height + 'px',
left:this.rect.left+ 'px',
top:this.rect.top+ 'px'
};
});
}
});

我写了这个stackblitz。我希望能给你一个开始的线索或点

最新更新