9 changed files with 342 additions and 498 deletions
@ -0,0 +1,68 @@ |
|||||||
|
import { Graphics, Sprite, Text } from "pixi.js"; |
||||||
|
import { WorkingAreaComponent } from "../working-area.component"; |
||||||
|
import { AxArrowConnector } from "./axArrowConnector"; |
||||||
|
import { AxImageShape } from "./axImageShape"; |
||||||
|
import { AxShape } from "./axShape"; |
||||||
|
import { MultipointIcon } from "./multipointIcon"; |
||||||
|
import { PolygonIcon } from "./polygonIcon"; |
||||||
|
|
||||||
|
|
||||||
|
export class Legend extends AxShape{ |
||||||
|
background: Graphics = null; |
||||||
|
data:Map<string,string> = new Map<string,string>() |
||||||
|
/** |
||||||
|
* |
||||||
|
*/ |
||||||
|
constructor(workingArea: WorkingAreaComponent) { |
||||||
|
super(null, workingArea); |
||||||
|
this.draw(); |
||||||
|
} |
||||||
|
|
||||||
|
getData() { |
||||||
|
this.workingArea.backgroundImage.children.forEach(item => { |
||||||
|
if (item instanceof AxImageShape|| item instanceof AxArrowConnector || item instanceof PolygonIcon || item instanceof MultipointIcon) { |
||||||
|
if (!this.data.has(item.assetData.Name)) { |
||||||
|
this.data[item.assetData.Name] = item.assetData.ImageUrl; |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
draw() { |
||||||
|
this.getData(); |
||||||
|
this.background = new Graphics(); |
||||||
|
this.background.lineStyle(1, 0xff0000); |
||||||
|
this.background.beginFill(0xffffff); |
||||||
|
this.background.drawRect(0, 0, 200, 300); |
||||||
|
this.background.endFill(); |
||||||
|
this.background.x = -(this.parent.width/2/ this.parent.scale.x); |
||||||
|
this.background.y = -(this.parent.height/2/ this.parent.scale.x); |
||||||
|
this.addChild(this.background); |
||||||
|
var showName: Text = new Text('图例'); |
||||||
|
showName.x = 0; |
||||||
|
showName.y = 0; |
||||||
|
this.background.addChild(showName); |
||||||
|
var showDescrption: Text = new Text('说明') |
||||||
|
showDescrption.x = 100; |
||||||
|
showDescrption.y = 0; |
||||||
|
this.background.addChild(showDescrption); |
||||||
|
let index = 1; |
||||||
|
this.data.forEach((value, key) => { |
||||||
|
var image: Sprite = Sprite.from(value); |
||||||
|
image.width = 32; |
||||||
|
image.height = 32; |
||||||
|
image.x = 0; |
||||||
|
image.y = index * 32; |
||||||
|
this.background.addChild(image); |
||||||
|
var description = new Text(key); |
||||||
|
description.x = 100; |
||||||
|
description.y = index * 32; |
||||||
|
this.background.addChild(description); |
||||||
|
index++; |
||||||
|
}) |
||||||
|
} |
||||||
|
redraw() { |
||||||
|
this.background.destroy(); |
||||||
|
this.draw(); |
||||||
|
} |
||||||
|
} |
@ -1,328 +0,0 @@ |
|||||||
import { WorkingAreaComponent } from '../working-area.component'; |
|
||||||
import * as PIXI from 'pixi.js'; |
|
||||||
import { AxShape } from './axShape'; |
|
||||||
|
|
||||||
/** |
|
||||||
* 管线 |
|
||||||
*/ |
|
||||||
export class Pipeline extends AxShape { |
|
||||||
public line: PIXI.Graphics = new PIXI.Graphics(); |
|
||||||
constructor(assetData: any, workingArea: WorkingAreaComponent) { |
|
||||||
super(assetData, workingArea); |
|
||||||
this.name = this.assetData.Id; |
|
||||||
this.moveable = false; |
|
||||||
this.x = this.assetData.Point.x; |
|
||||||
this.y = this.assetData.Point.y; |
|
||||||
this.workingArea.backgroundImage.addChild(this); |
|
||||||
this.addChild(this.line); |
|
||||||
// 画线图标
|
|
||||||
this.refresh(); |
|
||||||
this.interactive = true; |
|
||||||
this.on('mousedown', event => { |
|
||||||
event.stopPropagation(); |
|
||||||
this.workingArea.selection.selectOne(this); |
|
||||||
}); |
|
||||||
} |
|
||||||
/** |
|
||||||
* 刷新 |
|
||||||
*/ |
|
||||||
public refresh() { |
|
||||||
|
|
||||||
const strokeWidth = 1; |
|
||||||
const startWidth = 30 + strokeWidth; |
|
||||||
const endWidth = 30 + strokeWidth; |
|
||||||
const edgeWidth = 10; |
|
||||||
const openEnded = false; |
|
||||||
const markerStart = false; |
|
||||||
const markerEnd = true; |
|
||||||
const spacing = (openEnded) ? 0 : 0 + strokeWidth / 2; |
|
||||||
const startSize = 30 + strokeWidth; |
|
||||||
const endSize = 30 + strokeWidth; |
|
||||||
const isRounded = true; |
|
||||||
const pts = this.assetData.MultiPoint; |
|
||||||
const c = this.line; |
|
||||||
if (pts.length < 2) { return; } |
|
||||||
// Base vector (between first points)
|
|
||||||
const pe = pts[pts.length - 1]; |
|
||||||
|
|
||||||
// Finds first non-overlapping point
|
|
||||||
let i0 = 1; |
|
||||||
|
|
||||||
while (i0 < pts.length - 1 && pts[i0].x === pts[0].x && pts[i0].y === pts[0].y) { |
|
||||||
i0++; |
|
||||||
} |
|
||||||
|
|
||||||
const dx = pts[i0].x - pts[0].x; |
|
||||||
const dy = pts[i0].y - pts[0].y; |
|
||||||
const dist = Math.sqrt(dx * dx + dy * dy); |
|
||||||
|
|
||||||
if (dist === 0) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
// Computes the norm and the inverse norm
|
|
||||||
let nx = dx / dist; |
|
||||||
let nx1 = nx; |
|
||||||
let nx2 = nx; |
|
||||||
let ny = dy / dist; |
|
||||||
let ny2 = ny; |
|
||||||
let ny1 = ny; |
|
||||||
let orthx = edgeWidth * ny; |
|
||||||
let orthy = -edgeWidth * nx; |
|
||||||
|
|
||||||
// Stores the inbound function calls in reverse order in fns
|
|
||||||
const fns = []; |
|
||||||
|
|
||||||
// if (isRounded) {
|
|
||||||
// // c.setLineJoin('round');
|
|
||||||
// c.lineTextureStyle({ join: PIXI.LINE_JOIN.ROUND });
|
|
||||||
// } else if (pts.length > 2) {
|
|
||||||
// // Only mitre if there are waypoints
|
|
||||||
// // c.setMiterLimit(1.42);
|
|
||||||
// c.lineTextureStyle({ miterLimit: 1.42 });
|
|
||||||
// }
|
|
||||||
// c.lineStyle(1, 0x000000, 1);
|
|
||||||
c.clear(); |
|
||||||
c.lineTextureStyle({ width: 1, color: 0x00000, join: PIXI.LINE_JOIN.ROUND }); |
|
||||||
// c.begin();
|
|
||||||
c.beginFill(0xffffff); |
|
||||||
const startNx = nx; |
|
||||||
const startNy = ny; |
|
||||||
|
|
||||||
if (markerStart && !openEnded) { |
|
||||||
this.paintMarker(c, pts[0].x, pts[0].y, nx, ny, startSize, startWidth, edgeWidth, spacing, true); |
|
||||||
} else { |
|
||||||
const outStartX = pts[0].x + orthx / 2 + spacing * nx; |
|
||||||
const outStartY = pts[0].y + orthy / 2 + spacing * ny; |
|
||||||
const inEndX = pts[0].x - orthx / 2 + spacing * nx; |
|
||||||
const inEndY = pts[0].y - orthy / 2 + spacing * ny; |
|
||||||
|
|
||||||
if (openEnded) { |
|
||||||
c.moveTo(outStartX, outStartY); |
|
||||||
fns.push( () => { |
|
||||||
c.lineTo(inEndX, inEndY); |
|
||||||
}); |
|
||||||
} else { |
|
||||||
c.moveTo(inEndX, inEndY); |
|
||||||
c.lineTo(outStartX, outStartY); |
|
||||||
} |
|
||||||
} |
|
||||||
let dx1 = 0; |
|
||||||
let dy1 = 0; |
|
||||||
let dist1 = 0; |
|
||||||
|
|
||||||
for (let i = 0; i < pts.length - 2; i++) { |
|
||||||
// Work out in which direction the line is bending
|
|
||||||
const pos = this.relativeCcw(pts[i].x, pts[i].y, pts[i + 1].x, pts[i + 1].y, pts[i + 2].x, pts[i + 2].y); |
|
||||||
|
|
||||||
dx1 = pts[i + 2].x - pts[i + 1].x; |
|
||||||
dy1 = pts[i + 2].y - pts[i + 1].y; |
|
||||||
|
|
||||||
dist1 = Math.sqrt(dx1 * dx1 + dy1 * dy1); |
|
||||||
|
|
||||||
if (dist1 !== 0) { |
|
||||||
nx1 = dx1 / dist1; |
|
||||||
ny1 = dy1 / dist1; |
|
||||||
|
|
||||||
const tmp1 = nx * nx1 + ny * ny1; |
|
||||||
const tmp = Math.max(Math.sqrt((tmp1 + 1) / 2), 0.04); |
|
||||||
|
|
||||||
// Work out the normal orthogonal to the line through the control point and the edge sides intersection
|
|
||||||
nx2 = (nx + nx1); |
|
||||||
ny2 = (ny + ny1); |
|
||||||
|
|
||||||
const dist2 = Math.sqrt(nx2 * nx2 + ny2 * ny2); |
|
||||||
|
|
||||||
if (dist2 !== 0) { |
|
||||||
nx2 = nx2 / dist2; |
|
||||||
ny2 = ny2 / dist2; |
|
||||||
|
|
||||||
// Higher strokewidths require a larger minimum bend, 0.35 covers all but the most extreme cases
|
|
||||||
const strokeWidthFactor = Math.max(tmp, Math.min(1 / 200 + 0.04, 0.35)); |
|
||||||
const angleFactor = (pos !== 0 && isRounded) ? Math.max(0.1, strokeWidthFactor) : Math.max(tmp, 0.06); |
|
||||||
|
|
||||||
const outX = pts[i + 1].x + ny2 * edgeWidth / 2 / angleFactor; |
|
||||||
const outY = pts[i + 1].y - nx2 * edgeWidth / 2 / angleFactor; |
|
||||||
const inX = pts[i + 1].x - ny2 * edgeWidth / 2 / angleFactor; |
|
||||||
const inY = pts[i + 1].y + nx2 * edgeWidth / 2 / angleFactor; |
|
||||||
|
|
||||||
if (pos === 0 || !isRounded) { |
|
||||||
// If the two segments are aligned, or if we're not drawing curved sections between segments
|
|
||||||
// just draw straight to the intersection point
|
|
||||||
c.lineTo(outX, outY); |
|
||||||
|
|
||||||
((x, y) => { |
|
||||||
fns.push(() => { |
|
||||||
c.lineTo(x, y); |
|
||||||
}); |
|
||||||
})(inX, inY); |
|
||||||
} else if (pos === -1) { |
|
||||||
const c1x = inX + ny * edgeWidth; |
|
||||||
const c1y = inY - nx * edgeWidth; |
|
||||||
const c2x = inX + ny1 * edgeWidth; |
|
||||||
const c2y = inY - nx1 * edgeWidth; |
|
||||||
c.lineTo(c1x, c1y); |
|
||||||
if (isRounded) { |
|
||||||
c.quadraticCurveTo(outX, outY, c2x, c2y); // 圆角
|
|
||||||
} else { |
|
||||||
c.lineTo(outX, outY); |
|
||||||
} |
|
||||||
((x, y) => { |
|
||||||
fns.push(() => { |
|
||||||
c.lineTo(x, y); |
|
||||||
}); |
|
||||||
})(inX, inY); |
|
||||||
} else { |
|
||||||
c.lineTo(outX, outY); |
|
||||||
|
|
||||||
((x, y) => { |
|
||||||
const c1x = outX - ny * edgeWidth; |
|
||||||
const c1y = outY + nx * edgeWidth; |
|
||||||
const c2x = outX - ny1 * edgeWidth; |
|
||||||
const c2y = outY + nx1 * edgeWidth; |
|
||||||
|
|
||||||
fns.push(() => { |
|
||||||
if (isRounded) { |
|
||||||
c.quadraticCurveTo(x, y, c1x, c1y); |
|
||||||
} else { |
|
||||||
c.lineTo(x, y); |
|
||||||
} |
|
||||||
}); |
|
||||||
fns.push(() => { |
|
||||||
c.lineTo(c2x, c2y); |
|
||||||
}); |
|
||||||
})(inX, inY); |
|
||||||
} |
|
||||||
|
|
||||||
nx = nx1; |
|
||||||
ny = ny1; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
orthx = edgeWidth * ny1; |
|
||||||
orthy = - edgeWidth * nx1; |
|
||||||
|
|
||||||
if (markerEnd && !openEnded) { |
|
||||||
this.paintMarker(c, pe.x, pe.y, -nx, -ny, endSize, endWidth, edgeWidth, spacing, false); |
|
||||||
} else { |
|
||||||
c.lineTo(pe.x - spacing * nx1 + orthx / 2, pe.y - spacing * ny1 + orthy / 2); |
|
||||||
|
|
||||||
const inStartX = pe.x - spacing * nx1 - orthx / 2; |
|
||||||
const inStartY = pe.y - spacing * ny1 - orthy / 2; |
|
||||||
|
|
||||||
if (!openEnded) { |
|
||||||
c.lineTo(inStartX, inStartY); |
|
||||||
} else { |
|
||||||
c.moveTo(inStartX, inStartY); |
|
||||||
|
|
||||||
fns.splice(0, 0, () => { |
|
||||||
c.moveTo(inStartX, inStartY); |
|
||||||
}); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
for (let i = fns.length - 1; i >= 0; i--) { |
|
||||||
fns[i](); |
|
||||||
} |
|
||||||
c.closePath(); |
|
||||||
c.endFill(); |
|
||||||
// if (openEnded)
|
|
||||||
// {
|
|
||||||
// c.end();
|
|
||||||
// c.stroke();
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// c.close();
|
|
||||||
// c.fillAndStroke();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Workaround for shadow on top of base arrow
|
|
||||||
// c.setShadow(false);
|
|
||||||
|
|
||||||
// Need to redraw the markers without the low miter limit
|
|
||||||
// c.setMiterLimit(4);
|
|
||||||
|
|
||||||
// if (isRounded)
|
|
||||||
// {
|
|
||||||
// c.setLineJoin('flat');
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (pts.length > 2) {
|
|
||||||
// // Only to repaint markers if no waypoints
|
|
||||||
// // Need to redraw the markers without the low miter limit
|
|
||||||
// // c.setMiterLimit(4);
|
|
||||||
// c.lineTextureStyle({ width: 1, color: 0x00000, miterLimit: 4 });
|
|
||||||
// if (markerStart && !openEnded) {
|
|
||||||
// // c.begin();
|
|
||||||
// this.paintMarker(c, pts[0].x, pts[0].y, startNx, startNy, startSize, startWidth, edgeWidth, spacing, true);
|
|
||||||
// // c.stroke();
|
|
||||||
// // c.end();
|
|
||||||
// // c.closePath();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (markerEnd && !openEnded) {
|
|
||||||
// // c.begin();
|
|
||||||
// this.paintMarker(c, pe.x, pe.y, -nx, -ny, endSize, endWidth, edgeWidth, spacing, true);
|
|
||||||
// // c.stroke();
|
|
||||||
// // c.end();
|
|
||||||
// // c.closePath();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
} |
|
||||||
/** |
|
||||||
* 画箭头 |
|
||||||
* @param c |
|
||||||
* @param ptX |
|
||||||
* @param ptY |
|
||||||
* @param nx |
|
||||||
* @param ny |
|
||||||
* @param size |
|
||||||
* @param arrowWidth |
|
||||||
* @param edgeWidth |
|
||||||
* @param spacing |
|
||||||
* @param initialMove |
|
||||||
*/ |
|
||||||
paintMarker(c: PIXI.Graphics, ptX: number, ptY: number, nx: number, ny: number, |
|
||||||
size: number, arrowWidth: number, edgeWidth: number, spacing: number, initialMove: boolean) { |
|
||||||
const widthArrowRatio = edgeWidth / arrowWidth; |
|
||||||
const orthx = edgeWidth * ny / 2; |
|
||||||
const orthy = -edgeWidth * nx / 2; |
|
||||||
|
|
||||||
const spaceX = (spacing + size) * nx; |
|
||||||
const spaceY = (spacing + size) * ny; |
|
||||||
|
|
||||||
if (initialMove) { |
|
||||||
c.moveTo(ptX - orthx + spaceX, ptY - orthy + spaceY); |
|
||||||
} else { |
|
||||||
c.lineTo(ptX - orthx + spaceX, ptY - orthy + spaceY); |
|
||||||
} |
|
||||||
c.lineTo(ptX - orthx / widthArrowRatio + spaceX, ptY - orthy / widthArrowRatio + spaceY); |
|
||||||
c.lineTo(ptX + spacing * nx, ptY + spacing * ny); |
|
||||||
c.lineTo(ptX + orthx / widthArrowRatio + spaceX, ptY + orthy / widthArrowRatio + spaceY); |
|
||||||
c.lineTo(ptX + orthx + spaceX, ptY + orthy + spaceY); |
|
||||||
} |
|
||||||
|
|
||||||
relativeCcw(x1: number, y1: number, x2: number, y2: number, px: number, py: number) { |
|
||||||
x2 -= x1; |
|
||||||
y2 -= y1; |
|
||||||
px -= x1; |
|
||||||
py -= y1; |
|
||||||
let ccw = px * y2 - py * x2; |
|
||||||
|
|
||||||
if (ccw === 0.0) { |
|
||||||
ccw = px * x2 + py * y2; |
|
||||||
|
|
||||||
if (ccw > 0.0) { |
|
||||||
px -= x2; |
|
||||||
py -= y2; |
|
||||||
ccw = px * x2 + py * y2; |
|
||||||
|
|
||||||
if (ccw < 0.0) { |
|
||||||
ccw = 0.0; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return (ccw < 0.0) ? -1 : ((ccw > 0.0) ? 1 : 0); |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue