|
@@ -0,0 +1,198 @@
|
|
|
+import { SelectCtrl } from ".";
|
|
|
+import { ObjsContainer } from "./ObjsContainer";
|
|
|
+import { CompObject } from "./compObj";
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * 吸附功能实现
|
|
|
+ */
|
|
|
+export class AssistMagnetCtrl {
|
|
|
+ ctrl: SelectCtrl
|
|
|
+
|
|
|
+ constructor(ctrl: SelectCtrl) {
|
|
|
+ this.ctrl = ctrl;
|
|
|
+ }
|
|
|
+
|
|
|
+ rulerYs:number[]= [];
|
|
|
+ rulerXs:number[]= [];
|
|
|
+
|
|
|
+ clientX = 0;
|
|
|
+ clientY = 0;
|
|
|
+ currRefYs:number[] = [];
|
|
|
+ currRefXs:number[] = []
|
|
|
+ otherSlides : CompObject[] = [];
|
|
|
+
|
|
|
+ getMinValues(srcYs:number[], refYs: number[]) {
|
|
|
+ //找出最近的参考线
|
|
|
+ let n = srcYs.length;
|
|
|
+ let out :{min: number, v:number, o:number}[] = [];
|
|
|
+ while(n--) {
|
|
|
+ const srcY = srcYs[n];
|
|
|
+ let k = refYs.length;
|
|
|
+ let currMinY = 10000;
|
|
|
+ let currMinRefY = -10000;
|
|
|
+ let lastOffset = 0;
|
|
|
+ for (let i=0; i<k; i++) {
|
|
|
+ const o = srcY - refYs[i]
|
|
|
+ if (Math.abs(o) <= currMinY) {
|
|
|
+ currMinY = Math.abs(o);
|
|
|
+ currMinRefY = refYs[i]
|
|
|
+ lastOffset = o;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ break
|
|
|
+ }
|
|
|
+ out.push({min: currMinY, v: currMinRefY, o: lastOffset})
|
|
|
+ }
|
|
|
+ out = out.sort((a, b)=>(a.min-b.min))
|
|
|
+
|
|
|
+ let min = out[0].min;
|
|
|
+ const sames = [out[0].v];
|
|
|
+ let m = out.length;
|
|
|
+ for(let i=1; i<m; i++) {
|
|
|
+ if (Math.abs(out[i].min- min) < 1) {
|
|
|
+ sames.push(out[i].v);
|
|
|
+ } else {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return {offset: out[0].o, min: min, values: sames};
|
|
|
+ }
|
|
|
+
|
|
|
+ test(e:MouseEvent) {
|
|
|
+
|
|
|
+ this.clientX = e.clientX;
|
|
|
+ this.clientY = e.clientY;
|
|
|
+
|
|
|
+ const eps = 6;
|
|
|
+ const Objc = this.ctrl.objContainer as ObjsContainer
|
|
|
+ const bund = Objc.getBound();
|
|
|
+ const box = this.ctrl.getCurrCardBox();
|
|
|
+
|
|
|
+ //包围盒的上 中 下 三条横线
|
|
|
+ const srcY1 = (bund.y + box.top)*2.0
|
|
|
+ const srcYs = [srcY1, srcY1 + bund.height, srcY1 + bund.height*2];
|
|
|
+ if (this.rulerYs.length < 1) {
|
|
|
+ this.rulerYs.push(box.top *2.0) //card上边线
|
|
|
+ this.rulerYs.push(box.top *2.0 + box.height )//中线
|
|
|
+ this.rulerYs.push((box.top + box.height) * 2.0) //下边线
|
|
|
+
|
|
|
+ //所有参考线
|
|
|
+ const rulers = this.ctrl.assistRuler?.rulers || [];
|
|
|
+ let n = rulers.length;
|
|
|
+ while(n--) {
|
|
|
+ if (rulers[n].horz != undefined)
|
|
|
+ this.rulerYs.push(box.top *2 + (rulers[n].horz as number));
|
|
|
+ }
|
|
|
+ //添加card内的其他对象
|
|
|
+ this.otherSlides = this.ctrl.getUnSelectChilds();
|
|
|
+
|
|
|
+ this.otherSlides.forEach(item=>{
|
|
|
+ const b = item.getBox();
|
|
|
+ const y = (b.y + box.top) *2.0
|
|
|
+ if (this.rulerYs.indexOf(y) == -1) {
|
|
|
+ this.rulerYs.push(y)
|
|
|
+ }
|
|
|
+ const y1 = y + b.h
|
|
|
+ if (this.rulerYs.indexOf(y1) == -1) {
|
|
|
+ this.rulerYs.push(y1)
|
|
|
+ }
|
|
|
+ const y2 = y + b.h *2
|
|
|
+ if (this.rulerYs.indexOf(y2) == -1) {
|
|
|
+ this.rulerYs.push(y2)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ this.rulerYs = this.rulerYs.sort((a,b)=>a-b)
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ this.currRefYs = [];
|
|
|
+ const {offset, min, values} = this.getMinValues(srcYs, this.rulerYs)
|
|
|
+ if (min < eps) {//找到了最近点,进行磁铁吸附
|
|
|
+ this.clientY = e.clientY - offset / 2.0;
|
|
|
+ this.currRefYs = values;
|
|
|
+ }
|
|
|
+
|
|
|
+ //包围盒的左 中 右三条横线
|
|
|
+ const srcX1 = (bund.x + box.left)*2.0
|
|
|
+ const srcXs = [srcX1, srcX1 + bund.width, srcX1 + bund.width*2];
|
|
|
+ if (this.rulerXs.length < 1) {
|
|
|
+ this.rulerXs.push(box.left *2.0) //card上边线
|
|
|
+ this.rulerXs.push(box.left *2.0 + box.width )//中线
|
|
|
+ this.rulerXs.push((box.left + box.width) * 2.0) //下边线
|
|
|
+
|
|
|
+ //所有参考线
|
|
|
+ const rulers = this.ctrl.assistRuler?.rulers || [];
|
|
|
+ let n = rulers.length;
|
|
|
+ while(n--) {
|
|
|
+ if (rulers[n].verz != undefined)
|
|
|
+ this.rulerXs.push(box.left *2 + (rulers[n].verz as number));
|
|
|
+ }
|
|
|
+
|
|
|
+ //添加card内的其他对象
|
|
|
+ this.otherSlides.forEach(item=>{
|
|
|
+ const b = item.getBox();
|
|
|
+ const x = (b.x + box.left) *2.0
|
|
|
+ if (this.rulerXs.indexOf(x) == -1) {
|
|
|
+ this.rulerXs.push(x)
|
|
|
+ }
|
|
|
+ const x1 = x + b.w
|
|
|
+ if (this.rulerXs.indexOf(x1) == -1) {
|
|
|
+ this.rulerXs.push(x1)
|
|
|
+ }
|
|
|
+ const x2 = x + b.w *2
|
|
|
+ if (this.rulerXs.indexOf(x2) == -1) {
|
|
|
+ this.rulerXs.push(x2)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ this.rulerXs = this.rulerXs.sort((a,b)=>a-b)
|
|
|
+ }
|
|
|
+
|
|
|
+ this.currRefXs = [];
|
|
|
+ const ret = this.getMinValues(srcXs, this.rulerXs)
|
|
|
+ if (ret.min < eps) {//找到了最近点,进行磁铁吸附
|
|
|
+ this.clientX = e.clientX - ret.offset / 2.0;
|
|
|
+ this.currRefXs = ret.values;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ onMouseUp() {
|
|
|
+ this.rulerYs = [];
|
|
|
+ this.rulerXs = [];
|
|
|
+ this.currRefXs = [];
|
|
|
+ this.currRefYs = [];
|
|
|
+ }
|
|
|
+
|
|
|
+ draw() {
|
|
|
+ if ( !(this.currRefXs.length > 0 || this.currRefYs.length > 0) ) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const ctx = this.ctrl._selCtx;
|
|
|
+ let n = this.currRefXs.length;
|
|
|
+ ctx.lineWidth = 2;
|
|
|
+ ctx.strokeStyle = "orange";
|
|
|
+ // 清除虚线样式
|
|
|
+ // ctx.setLineDash([]);
|
|
|
+
|
|
|
+ while(n--) {
|
|
|
+ let x = this.currRefXs[n]
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.moveTo(x, 0)
|
|
|
+ ctx.lineTo(x, this.ctrl._selCanvaseSize.h);
|
|
|
+ ctx.stroke();
|
|
|
+ ctx.closePath();
|
|
|
+ }
|
|
|
+
|
|
|
+ const box = this.ctrl.getViewPortBox();
|
|
|
+ n = this.currRefYs.length;
|
|
|
+ while(n--) {
|
|
|
+ let y = this.currRefYs[n]
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.moveTo(box.left*2, y)
|
|
|
+ ctx.lineTo(box.right*2, y);
|
|
|
+ ctx.stroke();
|
|
|
+ ctx.closePath();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|