123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451 |
- import { dataService } from "../Service/DataService.js";
- import { stateService } from "../Service/StateService.js";
- import { coordinate } from "../Coordinate.js";
- import Style from "@/graphic/CanvasStyle/index.js";
- import VectorType from "../enum/VectorType.js";
- import { mathUtil } from "../Util/MathUtil.js";
- import ElementEvents from "../enum/ElementEvents.js";
- import { elementService } from "../Service/ElementService.js";
- const help = {
- getVectorStyle(vector, geoType = vector.geoType) {
- const geoId = vector?.vectorId;
- if (!geoId) {
- return Style[geoType];
- }
- const itemsEntry = [
- [stateService.getSelectItem(), "Select"],
- [stateService.getDraggingItem(), "Dragging"],
- [stateService.getFocusItem(), "Focus"],
- ];
- return itemsEntry.reduce((prev, [item, attr]) => {
- if (
- item &&
- item.type === VectorType[geoType] &&
- geoId === item.vectorId
- ) {
- if (Style[attr] && Style[attr][geoType]) {
- return Style[attr][geoType];
- }
- }
- return prev;
- }, Style[geoType]);
- },
- setVectorStyle(ctx, vector, geoType = vector.geoType) {
- const styles = help.getVectorStyle(vector, geoType);
- for (const style in styles) {
- if (typeof styles[style] === "function") {
- styles[style](ctx, vector);
- } else {
- ctx[style] = styles[style];
- }
- }
- return styles;
- },
- transformCoves(lines) {
- return lines.map((line) =>
- line.map((line) => ({
- start: coordinate.getScreenXY(line.start),
- end: coordinate.getScreenXY(line.end),
- controls: line.controls.map(coordinate.getScreenXY.bind(coordinate)),
- }))
- );
- },
- drawCoves(ctx, coves) {
- for (const curve of coves) {
- ctx.beginPath();
- ctx.moveTo(curve.start.x, curve.start.y);
- if (curve.controls.length === 1) {
- ctx.quadraticCurveTo(
- curve.controls[0].x,
- curve.controls[0].y,
- curve.end.x,
- curve.end.y
- );
- } else {
- ctx.bezierCurveTo(
- curve.controls[0].x,
- curve.controls[0].y,
- curve.controls[1].x,
- curve.controls[1].y,
- curve.end.x,
- curve.end.y
- );
- }
- ctx.stroke();
- }
- },
- };
- export default class Draw {
- constructor() {
- this.context = null;
- }
- initContext(canvas) {
- if (canvas) {
- this.context = canvas.getContext("2d");
- } else {
- this.context = null;
- }
- }
- clear() {
- this.context.clearRect(
- 0,
- 0,
- this.context.canvas.width,
- this.context.canvas.height
- );
- }
- drawBackGroundImg(vector) {
- this.context.save();
- this.context.restore();
- }
- drawGrid(startX, startY, w, h, step1, step2) {
- this.context.save();
- this.context.beginPath();
- for (var x = startX; x <= w; x += step1) {
- this.context.moveTo(x, 0);
- this.context.lineTo(x, h);
- }
- for (var y = startY; y <= h; y += step1) {
- this.context.moveTo(0, y);
- this.context.lineTo(w, y);
- }
- this.context.strokeStyle = "rgba(0,0,0,0.1)";
- this.context.lineWidth = 0.5;
- this.context.stroke();
- this.context.beginPath();
- for (var x = startX; x <= w; x += step2) {
- this.context.moveTo(x, 0);
- this.context.lineTo(x, h);
- }
- for (var y = startY; y <= h; y += step2) {
- this.context.moveTo(0, y);
- this.context.lineTo(w, y);
- }
- this.context.strokeStyle = "rgba(0,0,0,0.2)";
- this.context.lineWidth = 1;
- this.context.stroke();
- this.context.restore();
- }
- drawRoad(vector, isTemp) {
- console.log(vector);
- if (!isTemp && vector.display && vector.way !== "oneWay") {
- const ctx = this.context;
- const draw = (midDivide) => {
- const startScreen = coordinate.getScreenXY(midDivide.start);
- const endScreen = coordinate.getScreenXY(midDivide.end);
- ctx.beginPath();
- ctx.moveTo(startScreen.x, startScreen.y);
- ctx.lineTo(endScreen.x, endScreen.y);
- ctx.stroke();
- };
- ctx.save();
- help.setVectorStyle(ctx, vector);
- vector.midDivide.leftMidDivide && draw(vector.midDivide.leftMidDivide);
- vector.midDivide.rightMidDivide && draw(vector.midDivide.rightMidDivide);
- ctx.restore();
- }
- if (import.meta.env.DEV && !isTemp) {
- const startReal = isTemp
- ? vector.start
- : dataService.getRoadPoint(vector.startId);
- const endReal = isTemp
- ? vector.end
- : dataService.getRoadPoint(vector.endId);
- this.drawText(
- { x: (startReal.x + endReal.x) / 2, y: (startReal.y + endReal.y) / 2 },
- vector.vectorId
- );
- }
- this.drawRoadEdge(vector, isTemp);
- vector.leftLanes && vector.leftLanes.forEach(this.drawLan.bind(this));
- vector.rightLanes && vector.rightLanes.forEach(this.drawLan.bind(this));
- }
- drawLan(lan) {
- const ctx = this.context;
- const start = coordinate.getScreenXY(lan.start);
- const end = coordinate.getScreenXY(lan.end);
- ctx.save();
- ctx.beginPath();
- help.setVectorStyle(ctx, null, "Lane");
- ctx.setLineDash(Style.Lane.dash);
- ctx.moveTo(start.x, start.y);
- ctx.lineTo(end.x, end.y);
- ctx.stroke();
- ctx.restore();
- if (import.meta.env.DEV) {
- this.drawPoint(lan.start);
- this.drawPoint(lan.end);
- }
- }
- drawRoadEdge(vector, isTemp) {
- //判断是否与road方向一致。角度足够小,路足够宽,有可能向量方向不一致
- const start = isTemp
- ? vector.start
- : dataService.getRoadPoint(vector.startId);
- const end = isTemp ? vector.end : dataService.getRoadPoint(vector.endId);
- const drawRoadEdgeChild = (edgeVector) => {
- const flag = mathUtil.isSameDirForVector(
- start,
- end,
- edgeVector.start,
- edgeVector.end
- );
- if (flag) {
- ctx.beginPath();
- const point1 = coordinate.getScreenXY(edgeVector.start);
- const point2 = coordinate.getScreenXY(edgeVector.end);
- ctx.moveTo(point1.x, point1.y);
- ctx.lineTo(point2.x, point2.y);
- ctx.stroke();
- }
- this.drawText(
- {
- x: (edgeVector.start.x + edgeVector.end.x) / 2,
- y: (edgeVector.start.y + edgeVector.end.y) / 2,
- },
- edgeVector.vectorId
- );
- };
- const leftEdge = isTemp
- ? vector.leftEdge
- : dataService.getRoadEdge(vector.leftEdgeId);
- const rightEdge = isTemp
- ? vector.rightEdge
- : dataService.getRoadEdge(vector.rightEdgeId);
- const ctx = this.context;
- ctx.save();
- isTemp && (ctx.globalAlpha = 0.3);
- help.setVectorStyle(ctx, leftEdge);
- drawRoadEdgeChild(leftEdge);
- help.setVectorStyle(ctx, rightEdge);
- drawRoadEdgeChild(rightEdge);
- ctx.restore();
- if (import.meta.env.DEV) {
- this.drawPoint(leftEdge.start);
- this.drawPoint(leftEdge.end);
- this.drawPoint(rightEdge.start);
- this.drawPoint(rightEdge.end);
- }
- }
- drawControlPoint(vector) {
- const start = coordinate.getScreenXY(
- dataService
- .getRoadEdge(vector.edgeInfo1.id)
- .getPosition(vector.edgeInfo1.dir)
- );
- const end = coordinate.getScreenXY(
- dataService
- .getRoadEdge(vector.edgeInfo2.id)
- .getPosition(vector.edgeInfo2.dir)
- );
- const pt2 = mathUtil.twoOrderBezier(
- 0.5,
- start,
- coordinate.getScreenXY({ x: vector.x, y: vector.y }),
- end
- );
- const pt = mathUtil.twoOrderBezier2(0.5, start, pt2, end);
- const ctx = this.context;
- ctx.save();
- ctx.beginPath();
- ctx.arc(
- pt.x,
- pt.y,
- Style.ControlPoint.radius * coordinate.ratio,
- 0,
- Math.PI * 2,
- true
- );
- ctx.stroke();
- ctx.fill();
- ctx.restore();
- ctx.save();
- ctx.beginPath();
- help.setVectorStyle(ctx, null, "RoadEdge");
- //曲线
- ctx.moveTo(start.x, start.y);
- ctx.quadraticCurveTo(pt.x, pt.y, end.x, end.y);
- ctx.stroke();
- ctx.restore();
- }
- drawCurveRoad(vector) {
- if (vector.display && vector.midDivide) {
- const covesArray = help.transformCoves([
- vector.midDivide.leftMidDivideCurves,
- vector.midDivide.rightMidDivideCurves,
- ]);
- const ctx = this.context;
- ctx.save();
- help.setVectorStyle(ctx, vector);
- for (let coves of covesArray) {
- help.drawCoves(ctx, coves);
- }
- ctx.restore();
- }
- this.drawCurveRoadEdge(dataService.getCurveRoadEdge(vector.rightEdgeId));
- this.drawCurveRoadEdge(dataService.getCurveRoadEdge(vector.leftEdgeId));
- vector.leftLanesCurves &&
- vector.leftLanesCurves.forEach(this.drawCurveLan.bind(this));
- vector.rightLanesCurves &&
- vector.rightLanesCurves.forEach(this.drawCurveLan.bind(this));
- if (import.meta.env.DEV) {
- vector.points.forEach(this.drawPoint.bind(this));
- }
- }
- drawCurveRoadEdge(vector, isTemp) {
- const [coves] = help.transformCoves([vector.curves]);
- const ctx = this.context;
- ctx.save();
- help.setVectorStyle(ctx, vector);
- help.drawCoves(ctx, coves);
- ctx.restore();
- if (import.meta.env.DEV) {
- vector.points.forEach(this.drawPoint.bind(this));
- }
- }
- drawCurveLan(lines) {
- const [coves] = help.transformCoves([lines]);
- const ctx = this.context;
- ctx.save();
- help.setVectorStyle(ctx, null, "CurveLan");
- ctx.setLineDash(Style.Lane.dash);
- help.drawCoves(ctx, coves);
- ctx.restore();
- if (import.meta.env.DEV) {
- lines.map((line) => {
- this.drawPoint(line.start);
- this.drawPoint(line.end);
- });
- }
- }
- drawRoadPoint(vector) {
- this.drawPoint(vector);
- }
- drawCircle(element) {
- this.drawPoint({
- ...element.center,
- radius: element.radius,
- geoType: element.geoType,
- });
- }
- drawPoint(vector) {
- const pt = coordinate.getScreenXY({ x: vector.x, y: vector.y });
- const ctx = this.context;
- const style = help.setVectorStyle(ctx, vector, vector.geoType || "Point");
- const radius = (vector.radius || style.radius) * coordinate.ratio;
- ctx.save();
- ctx.beginPath();
- ctx.arc(pt.x, pt.y, radius, 0, Math.PI * 2, true);
- ctx.stroke();
- ctx.fill();
- ctx.restore();
- if (import.meta.env.DEV) {
- if (vector.vectorId) {
- this.drawText(vector, vector.vectorId);
- }
- }
- }
- // 文字
- drawText(position, txt, angle) {
- const ctx = this.context;
- ctx.save();
- help.setVectorStyle(ctx, null, "Text");
- const pt = coordinate.getScreenXY(position);
- if (angle) {
- ctx.translate(pt.x, pt.y);
- ctx.rotate(angle);
- ctx.fillText(txt, 0, 0);
- } else {
- ctx.fillText(txt, pt.x, pt.y);
- }
- ctx.restore();
- }
- drawLine(vector) {
- let start = dataService.getPoint(vector.startId);
- start = coordinate.getScreenXY(start);
- let end = dataService.getPoint(vector.endId);
- end = coordinate.getScreenXY(end);
- this.context.save();
- const style = help.setVectorStyle(
- this.context,
- vector,
- vector.category || vector.geoType
- );
- if (style.dash) {
- this.context.setLineDash(style.dash);
- }
- this.context.beginPath();
- this.context.moveTo(start.x, start.y);
- this.context.lineTo(end.x, end.y);
- this.context.stroke();
- this.context.restore();
- }
- drawElementLine(element) {
- let start = elementService.getPoint(element.startId);
- start = coordinate.getScreenXY(start);
- let end = elementService.getPoint(element.endId);
- end = coordinate.getScreenXY(end);
- this.context.save();
- const style = help.setVectorStyle(
- this.context,
- element,
- element.category || element.geoType
- );
- if (style.dash) {
- this.context.setLineDash(style.dash);
- }
- this.context.beginPath();
- this.context.moveTo(start.x, start.y);
- this.context.lineTo(end.x, end.y);
- this.context.stroke();
- this.context.restore();
- }
- }
- const draw = new Draw();
- export { draw };
|