Transformer是基于Group创建的一个组件,主要负责拖拽、缩放、旋转,只需要自己把形状放到这个组里面进行操作。[官方文档]
接下来我们需要以下几步操作:点选形状、多选形状、取消选中、框选、全选、缩放、旋转。
1、点选形状:点击形状添加到group中
2、多选形状:可以通过shift + 点击 把形状添加group中
3、取消选中:如果已经添加到group中 就把他移出group
4、框选:可以用鼠标左键把框选的形状添加到group中
5、全选:可以通过ctrl + a 把所有的形状添加到group中
我们接着上一篇的代码的基础上加代码
1、创建Transformer
private _transformer: Konva.Transformer | undefined;
public get transformer(): Konva.Transformer {
if (this._transformer === undefined) {
this._transformer = new Konva.Transformer();
}
return this._transformer;
}
public set transformer(v: Konva.Transformer) {
this._transformer = v;
}
2、 添加点击选中和框选
setStage(){
// 1、在舞台添加监听点击事件
this.stage.on("click tap",(e)=>{
// 2、判断点击的是否是匹配的对象
if(e.target === this.stage){
// 如果是舞台就清空
this.transformer.nodes([]);
return;
}
if (this.transformer.children?.indexOf(e.target) !== -1) {
// 不能点击自身
return;
}
// 3、判断是否是多选
if (e.evt.shiftKey){
let nodes = this.transformer.nodes();
let index = nodes.indexOf(e.target);
// 判断是否添加到group中,用于取消选中
if (index != -1) {
let ns = nodes.filter((n) => n != e.target);
this.transformer.nodes(ns);
} else {
let ns = nodes.concat([e.target]);
this.transformer.nodes(ns);
}
}else{
this.transformer.nodes([e.target]);
}
})
// 5、框选
rect:{x:number,y:number,width:number,height:number} = {x:0,y:0,width:0,height:0}
this.stage.on("mousemove mousedown mouseup",(e)=>{
let offset = this.byOffset(e.evt.offsetX, e.evt.offsetY);
if (e.type === "mousedown") {
rect.x = offset.x
rect.y = offset.y
} else if (e.type === "mouseup") {
rect.width = offset.x - start.x
rect.height = offset.y - start.y
if (this.layer.children != undefined) {
let ns: any = [];
ns = this.layer.children.filter(
(n) => this.isRectOn(rect, n.getClientRect())
);
this.transformer.nodes(ns);
}
}
})
// 判断矩阵相交
isRectOn(rect1,rect2): boolean{
return !(
rect2.x + rect2.width < rect1.x ||
rect2.x > rect1.x + rect1.width ||
rect2.y + rect2.height < rect1.y ||
rect2.y > rect1.y + rect1.height
);
}
// 计算偏移量后的位置
byOffset(
x: number,
y: number
): {
x: number;
y: number;
} {
x = (x - this.stage.x()) / this.stage.scaleX();
y = (y - this.stage.y()) / this.stage.scaleY();
return { x, y };
}
}
3、添加全选功能
init(){
// 4、全选
document.onkeydown = (e) => {
if(e.key === "a" && (e.metaKey || e.ctrlKey)){
if (this.layer.children === undefined) {
return;
}
let all = this.layer.children.filter(
(e) => true
);
this.transformer.nodes(all);
this.transformer.moveToTop();
}
};
}
5、开始使用
this.layer.add(this.transformer)