324 lines
11 KiB
JavaScript
324 lines
11 KiB
JavaScript
import { Container, Graphics, Point, Color } from 'pixi.js';
|
|
import { JlGraphic, JlGraphicTemplate, GraphicIdGenerator, calculateMirrorPoint, VectorText } from 'jl-graphic';
|
|
import { getTrainConsts, EnumDiriveModel, EnumTrainType } from './TrainConfig.js';
|
|
|
|
class TrainHead extends Container {
|
|
arrow; // 列车箭头
|
|
pause; // 列车停止
|
|
train;
|
|
arrowColor;
|
|
pauseColor;
|
|
constructor(train) {
|
|
super();
|
|
this.arrow = new Graphics();
|
|
this.pause = new Graphics();
|
|
this.addChild(this.arrow);
|
|
this.addChild(this.pause);
|
|
this.train = train;
|
|
this.arrowColor = this.train.constDatas.arrowDefaultColor;
|
|
this.pauseColor = this.train.constDatas.pauseDefaultColor;
|
|
}
|
|
clear() {
|
|
this.arrow.clear();
|
|
this.pause.clear();
|
|
}
|
|
doRepaint() {
|
|
this.clear();
|
|
const trainConsts = this.train.constDatas;
|
|
const bodyWH = this.train.trainbody.getBodyWH();
|
|
const marginX = trainConsts.marginX;
|
|
const pauseW = trainConsts.pauseW;
|
|
const bodyWidth = bodyWH ? bodyWH.width : trainConsts.bodyWidth;
|
|
const bodyHeight = bodyWH ? bodyWH.height : trainConsts.bodyHeight;
|
|
let pauseTW = pauseW + marginX;
|
|
if (trainConsts.arrowPauseOnlyOne) {
|
|
pauseTW = 0;
|
|
}
|
|
let arrowPoint = [
|
|
-bodyHeight * 0.4 - marginX - pauseTW - bodyWidth / 2,
|
|
0,
|
|
-marginX - pauseTW - bodyWidth / 2,
|
|
bodyHeight / 2,
|
|
-marginX - pauseTW - bodyWidth / 2,
|
|
-bodyHeight / 2,
|
|
];
|
|
let pausePoint = [
|
|
-marginX - pauseW / 2 - bodyWidth / 2,
|
|
-bodyHeight / 2,
|
|
-marginX - pauseW / 2 - bodyWidth / 2,
|
|
bodyHeight / 2,
|
|
];
|
|
// 列车是向右或者向上
|
|
if (this.isRight()) {
|
|
const aP = [];
|
|
arrowPoint.forEach((item, index) => {
|
|
if (index % 2 == 1) {
|
|
const p = new Point(arrowPoint[index - 1], item);
|
|
const newP = calculateMirrorPoint(new Point(0, 0), p);
|
|
aP.push(newP.x, newP.y);
|
|
}
|
|
});
|
|
arrowPoint = aP;
|
|
const pP = [];
|
|
pausePoint.forEach((item, index) => {
|
|
if (index % 2 == 1) {
|
|
const p = new Point(pausePoint[index - 1], item);
|
|
const newP = calculateMirrorPoint(new Point(0, 0), p);
|
|
pP.push(newP.x, newP.y);
|
|
}
|
|
});
|
|
pausePoint = pP;
|
|
}
|
|
this.pause.lineStyle(pauseW, this.pauseColor, 1);
|
|
this.pause.moveTo(pausePoint[0], pausePoint[1]);
|
|
this.pause.lineTo(pausePoint[2], pausePoint[3]);
|
|
const arrow = this.arrow;
|
|
arrow.beginFill(this.arrowColor, 1);
|
|
arrow.drawPolygon(arrowPoint);
|
|
arrow.endFill();
|
|
}
|
|
isRight() {
|
|
let d = false;
|
|
if (this.train.isRightRoTop) {
|
|
d = true;
|
|
}
|
|
return d;
|
|
}
|
|
}
|
|
class TrainBody extends Container {
|
|
bodyRact;
|
|
codeAGraph = new VectorText(''); //识别号AA
|
|
codeBGraph = new VectorText(''); //识别号BBB
|
|
train;
|
|
codeAColor;
|
|
codeBColor;
|
|
codeAText;
|
|
codeBText;
|
|
constructor(train) {
|
|
super();
|
|
this.bodyRact = new Graphics();
|
|
this.addChild(this.bodyRact);
|
|
this.addChild(this.codeAGraph);
|
|
this.addChild(this.codeBGraph);
|
|
this.train = train;
|
|
this.codeAGraph.setVectorFontSize(this.train.constDatas.codeFontSize);
|
|
this.codeBGraph.setVectorFontSize(this.train.constDatas.codeFontSize);
|
|
this.codeAColor = this.train.constDatas.codeColor;
|
|
this.codeBColor = this.train.constDatas.codeColor;
|
|
this.codeAText = '';
|
|
this.codeBText = '';
|
|
}
|
|
clear() {
|
|
this.bodyRact.clear();
|
|
}
|
|
getBodyWH() {
|
|
const bodyAWH = this.codeAGraph.getLocalBounds();
|
|
const bodyBWH = this.codeBGraph.getLocalBounds();
|
|
return {
|
|
width: bodyAWH.width + bodyBWH.width + this.train.constDatas.bodyPadding * 2,
|
|
height: bodyAWH.height + this.train.constDatas.bodyPadding * 2,
|
|
};
|
|
}
|
|
doRepaint() {
|
|
this.clear();
|
|
const trainConsts = this.train.constDatas;
|
|
const codeAGraph = this.codeAGraph;
|
|
const codeBGraph = this.codeBGraph;
|
|
codeAGraph.text = this.codeAText;
|
|
codeBGraph.text = this.codeBText;
|
|
codeAGraph.anchor.set(0.5);
|
|
codeBGraph.anchor.set(0.5);
|
|
const styleA = {
|
|
fill: this.codeAColor,
|
|
fontSize: trainConsts.codeFontSize,
|
|
};
|
|
const styleB = {
|
|
fill: this.codeBColor,
|
|
fontSize: trainConsts.codeFontSize,
|
|
};
|
|
codeAGraph.style = styleA;
|
|
codeBGraph.style = styleB;
|
|
if (this.codeBText) {
|
|
const bodyAWH = codeAGraph.getLocalBounds();
|
|
const bodyBWH = codeBGraph.getLocalBounds();
|
|
codeAGraph.position.set(-bodyBWH.width / 2, 0);
|
|
codeBGraph.position.set(bodyAWH.width / 2, 0);
|
|
}
|
|
codeAGraph.updateOnScaled();
|
|
codeBGraph.updateOnScaled();
|
|
if (this.train.constDatas.hasBodyRact) {
|
|
const bodyRact = this.bodyRact;
|
|
const { width: bodyWidth, height: bodyHeight } = this.getBodyWH();
|
|
bodyRact.lineStyle(trainConsts.borderWidth, new Color(trainConsts.borderColor));
|
|
const bgColor = trainConsts.bodyBgColor;
|
|
bodyRact.beginFill(new Color(bgColor));
|
|
bodyRact.drawRect(-bodyWidth / 2, -bodyHeight / 2, bodyWidth, bodyHeight);
|
|
bodyRact.endFill();
|
|
}
|
|
}
|
|
}
|
|
class StatusText extends Container {
|
|
sText = new VectorText('');
|
|
train;
|
|
constructor(train) {
|
|
super();
|
|
this.train = train;
|
|
this.addChild(this.sText);
|
|
}
|
|
doRepaint(text, bodyWH) {
|
|
const trainConsts = this.train.constDatas;
|
|
let t = text;
|
|
if (trainConsts.statusTextTransform) {
|
|
t = trainConsts.statusTextTransform[text];
|
|
}
|
|
this.sText.text = t;
|
|
this.sText.anchor.set(0.5);
|
|
const c = trainConsts.statusTextColor[text] || trainConsts.statusTextColor.D;
|
|
const style = {
|
|
fill: c,
|
|
fontSize: trainConsts.textFontSize,
|
|
};
|
|
this.sText.style = style;
|
|
const { width: bodyWidth, height: bodyHeight } = bodyWH;
|
|
const { width: textHWidth, height: textHeight } = this.sText.getLocalBounds();
|
|
const num = trainConsts.statusTextList.length;
|
|
let index = trainConsts.statusTextList.findIndex((item) => {
|
|
return item == text;
|
|
});
|
|
if (index < 0) {
|
|
index = (num - 1) / 2; // 中间
|
|
}
|
|
const textMargin = (bodyWidth - textHWidth * num) / (num - 1);
|
|
this.sText.position.set(-bodyWidth / 2 + (textHWidth * (index * 2 + 1)) / 2 + textMargin * index, -bodyHeight / 2 - textHeight / 2 - trainConsts.textMarginY);
|
|
}
|
|
clear() {
|
|
this.sText.text = '';
|
|
}
|
|
}
|
|
/**
|
|
* 列车
|
|
*/
|
|
class Train extends JlGraphic {
|
|
static Type = 'Train';
|
|
trainHead;
|
|
trainbody;
|
|
statusTextMap = new Map();
|
|
isRightRoTop; // 方向是否向右或者向上
|
|
constDatas;
|
|
constructor(data) {
|
|
super(Train.Type);
|
|
this.isRightRoTop = false;
|
|
this.constDatas = getTrainConsts();
|
|
if (data) {
|
|
Object.assign(this.constDatas, data);
|
|
}
|
|
this.trainbody = new TrainBody(this);
|
|
this.trainHead = new TrainHead(this);
|
|
this.addChild(this.trainHead);
|
|
this.addChild(this.trainbody);
|
|
}
|
|
get datas() {
|
|
return this.getDatas();
|
|
}
|
|
doRepaint() {
|
|
this.trainbody.doRepaint();
|
|
this.trainHead.doRepaint();
|
|
}
|
|
// 设置列车箭头是否显示
|
|
setArrowVisible(v) {
|
|
this.trainHead.arrow.visible = v;
|
|
}
|
|
// 设置列车暂停是否显示
|
|
setPauseVisible(v) {
|
|
this.trainHead.pause.visible = v;
|
|
}
|
|
run() {
|
|
this.trainHead.arrow.visible = true;
|
|
this.trainHead.pause.visible = !this.constDatas.arrowPauseOnlyOne;
|
|
}
|
|
stop() {
|
|
this.trainHead.arrow.visible = false;
|
|
this.trainHead.pause.visible = true;
|
|
}
|
|
setCodeAText(v) {
|
|
this.trainbody.codeAText = v;
|
|
}
|
|
setCodeBText(v) {
|
|
this.trainbody.codeBText = v;
|
|
}
|
|
// 设置驾驶模式对应颜色
|
|
setDiriveModelColor(s) {
|
|
const aModelColorEnum = this.constDatas.arrowDiriveModelColorEnum;
|
|
const pModelColorEnum = this.constDatas.pauseDiriveModelColorEnum;
|
|
let aColor = aModelColorEnum.AM;
|
|
let pColor = pModelColorEnum.AM;
|
|
if (s == EnumDiriveModel.SM) {
|
|
aColor = aModelColorEnum.SM;
|
|
pColor = pModelColorEnum.SM;
|
|
}
|
|
else if (s == EnumDiriveModel.RM) {
|
|
aColor = aModelColorEnum.RM;
|
|
pColor = pModelColorEnum.RM;
|
|
}
|
|
this.trainHead.arrowColor = aColor;
|
|
this.trainHead.pauseColor = pColor;
|
|
}
|
|
// 设置列车类型对应颜色
|
|
setTrainTypeColor(s) {
|
|
const typeColorEnum = this.constDatas.typeColorEnum;
|
|
const fillAColor = typeColorEnum.schedule;
|
|
let fillBColor = typeColorEnum.schedule;
|
|
if (s == EnumTrainType.late) {
|
|
fillBColor = typeColorEnum.late;
|
|
}
|
|
else if (s == EnumTrainType.early) {
|
|
fillBColor = typeColorEnum.early;
|
|
}
|
|
else if (s == EnumTrainType.head) {
|
|
fillBColor = typeColorEnum.head;
|
|
}
|
|
else if (s == EnumTrainType.manual) {
|
|
fillBColor = typeColorEnum.manual;
|
|
}
|
|
this.trainbody.codeAColor = fillAColor;
|
|
this.trainbody.codeBColor = fillBColor;
|
|
}
|
|
// 显示列车状态文字
|
|
showStatus(s) {
|
|
if (this.statusTextMap.has(s)) {
|
|
return;
|
|
}
|
|
const bodyWH = this.trainbody.getBodyWH();
|
|
const textD = new StatusText(this);
|
|
textD.doRepaint(s, bodyWH);
|
|
this.addChild(textD);
|
|
this.statusTextMap.set(s, textD);
|
|
}
|
|
// 隐藏列车状态文字
|
|
hideStatus(s) {
|
|
if (!this.statusTextMap.has(s)) {
|
|
return;
|
|
}
|
|
const textD = this.statusTextMap.get(s);
|
|
if (textD) {
|
|
textD.clear();
|
|
this.statusTextMap.delete(s);
|
|
}
|
|
}
|
|
}
|
|
class TrainTemplate extends JlGraphicTemplate {
|
|
updataConsts;
|
|
constructor(stateTemplate, data) {
|
|
super(Train.Type, { stateTemplate });
|
|
this.updataConsts = data;
|
|
}
|
|
new() {
|
|
const train = new Train(this.updataConsts);
|
|
train.id = GraphicIdGenerator.next();
|
|
train.loadState(this.states);
|
|
return train;
|
|
}
|
|
}
|
|
|
|
export { Train, TrainTemplate };
|