| | |
| | | objectsContainer: null, |
| | | objectsContainer2: null, |
| | | tracksContainer: null, |
| | | tracksGraphics: null, |
| | | shelvesContainer: null, |
| | | graphicsCrn: null, |
| | | graphicsCrnTrack: null, |
| | |
| | | this.pixiApp.view.style.display = 'block'; |
| | | this.resizeToContainer(); |
| | | window.addEventListener('resize', this.resizeToContainer); |
| | | this.graphicsCrnTrack = this.createTrackTexture(25,25); |
| | | this.graphicsRgvTrack = this.createTrackTexture(25,25); |
| | | this.graphicsCrnTrack = this.createTrackTexture(25, 25, 10); |
| | | this.graphicsRgvTrack = this.createTrackTexture(25, 25, 10); |
| | | this.objectsContainer = new PIXI.Container(); |
| | | this.objectsContainer2 = new PIXI.Container(); |
| | | this.tracksContainer = new PIXI.ParticleContainer(10000, { scale: true, position: true, rotation: false, uvs: false, alpha: false }); |
| | | this.tracksGraphics = new PIXI.Graphics(); |
| | | this.shelvesContainer = new PIXI.ParticleContainer(10000, { scale: true, position: true, rotation: false, uvs: false, alpha: false }); |
| | | this.tracksContainer.autoResize = true; |
| | | this.shelvesContainer.autoResize = true; |
| | | this.pixiApp.stage.addChild(this.tracksGraphics); |
| | | this.pixiApp.stage.addChild(this.tracksContainer); |
| | | this.pixiApp.stage.addChild(this.shelvesContainer); |
| | | this.pixiApp.stage.addChild(this.objectsContainer); |
| | |
| | | this.objectsContainer.removeChildren(); |
| | | this.objectsContainer2.removeChildren(); |
| | | if (this.tracksContainer) { this.tracksContainer.removeChildren(); } |
| | | if (this.tracksGraphics) { this.tracksGraphics.clear(); } |
| | | if (this.shelvesContainer) { this.shelvesContainer.removeChildren(); } |
| | | this.crnList = []; |
| | | this.dualCrnList = []; |
| | |
| | | this.objectsContainer.removeChildren(); |
| | | this.objectsContainer2.removeChildren(); |
| | | if (this.tracksContainer) { this.tracksContainer.removeChildren(); } |
| | | if (this.tracksGraphics) { this.tracksGraphics.clear(); } |
| | | if (this.shelvesContainer) { this.shelvesContainer.removeChildren(); } |
| | | this.crnList = []; |
| | | this.dualCrnList = []; |
| | |
| | | } |
| | | }); |
| | | |
| | | this.drawTracks(map); |
| | | |
| | | map.forEach((item, index) => { |
| | | this.pixiStageList[index] = [item.length]; |
| | | for (let idx = 0; idx < item.length; idx++) { |
| | | let val = item[idx]; |
| | | if (val.type === 'merge') { continue; } |
| | | if (val.type == undefined || val.type === 'none') { continue; } |
| | | if (this.isTrackType(val)) { |
| | | this.collectTrackItem(val); |
| | | continue; |
| | | } |
| | | let sprite = this.getSprite(val, (e) => { |
| | | //回调 |
| | | }); |
| | | if (sprite == null) { continue; } |
| | | if (sprite._kind === 'shelf') { |
| | | this.shelvesContainer.addChild(sprite); |
| | | } else if (sprite._kind === 'crn-track' || sprite._kind === 'rgv-track') { |
| | | this.tracksContainer.addChild(sprite); |
| | | } else { |
| | | this.objectsContainer.addChild(sprite); |
| | | } |
| | |
| | | } |
| | | return new PIXI.Sprite(texture); |
| | | }, |
| | | createTrackSprite(width, height) { |
| | | let idx = width + "-" + height; |
| | | createTrackSprite(width, height, mask) { |
| | | const trackMask = mask != null ? mask : 10; |
| | | let idx = width + "-" + height + "-" + trackMask; |
| | | let texture = this.pixiTrackMap.get(idx); |
| | | if (texture == undefined) { |
| | | texture = this.createTrackTexture(width, height); |
| | | texture = this.createTrackTexture(width, height, trackMask); |
| | | this.pixiTrackMap.set(idx, texture); |
| | | } |
| | | return new PIXI.Sprite(texture); |
| | |
| | | graphics.endFill(); |
| | | return graphics; |
| | | }, |
| | | createTrackTexture(width, height) { |
| | | createTrackTexture(width, height, mask) { |
| | | const TRACK_N = 1; |
| | | const TRACK_E = 2; |
| | | const TRACK_S = 4; |
| | | const TRACK_W = 8; |
| | | const trackMask = mask != null ? mask : (TRACK_E | TRACK_W); |
| | | const g = new PIXI.Graphics(); |
| | | const t = Math.max(2, Math.round(height * 0.08)); |
| | | const gap = Math.round(height * 0.30); |
| | | const mid = Math.round(height / 2); |
| | | const y1 = mid - Math.round(gap / 2); |
| | | const y2 = mid + Math.round(gap / 2); |
| | | const tHalf = Math.round(t / 2); |
| | | const topRailTopY = y1 - tHalf; |
| | | const bottomRailTopY = y2 - tHalf; |
| | | g.beginFill(0x666666); |
| | | g.drawRect(0, topRailTopY, width, t); |
| | | g.drawRect(0, bottomRailTopY, width, t); |
| | | g.endFill(); |
| | | g.beginFill(0x777777); |
| | | const sTop = topRailTopY + t; |
| | | const sBottom = bottomRailTopY; |
| | | const sHeight = Math.max(1, sBottom - sTop); |
| | | for (let i = 0; i < width; i += 5) { g.drawRect(i, sTop, 2, sHeight); } |
| | | g.endFill(); |
| | | const size = Math.max(1, Math.min(width, height)); |
| | | const rail = Math.max(2, Math.round(size * 0.12)); |
| | | const gap = Math.max(4, Math.round(size * 0.38)); |
| | | const midX = Math.round(width / 2); |
| | | const midY = Math.round(height / 2); |
| | | const y1 = midY - Math.round(gap / 2); |
| | | const y2 = midY + Math.round(gap / 2); |
| | | const x1 = midX - Math.round(gap / 2); |
| | | const x2 = midX + Math.round(gap / 2); |
| | | |
| | | const hasN = (trackMask & TRACK_N) !== 0; |
| | | const hasE = (trackMask & TRACK_E) !== 0; |
| | | const hasS = (trackMask & TRACK_S) !== 0; |
| | | const hasW = (trackMask & TRACK_W) !== 0; |
| | | |
| | | const hStart = hasW ? 0 : midX; |
| | | const hEnd = hasE ? width : midX; |
| | | const vStart = hasN ? 0 : midY; |
| | | const vEnd = hasS ? height : midY; |
| | | |
| | | const railColor = 0x555555; |
| | | const drawLine = (x1p, y1p, x2p, y2p, w, color) => { |
| | | g.lineStyle(w, color, 1); |
| | | g.moveTo(x1p, y1p); |
| | | g.lineTo(x2p, y2p); |
| | | }; |
| | | |
| | | const hasH = hasW || hasE; |
| | | const hasV = hasN || hasS; |
| | | const isCorner = hasH && hasV && !(hasW && hasE) && !(hasN && hasS); |
| | | if (hasH && !isCorner) { |
| | | const w = Math.max(1, hEnd - hStart); |
| | | g.beginFill(railColor); |
| | | g.drawRect(hStart, midY - Math.round(rail / 2), w, rail); |
| | | g.endFill(); |
| | | } |
| | | if (hasV && !isCorner) { |
| | | const h = Math.max(1, vEnd - vStart); |
| | | g.beginFill(railColor); |
| | | g.drawRect(midX - Math.round(rail / 2), vStart, rail, h); |
| | | g.endFill(); |
| | | } |
| | | if (isCorner) { |
| | | const cw = hasE; |
| | | const ch = hasS; |
| | | const cx = cw ? (width - 1) : 0; |
| | | const cy = ch ? (height - 1) : 0; |
| | | const angStart = (cw && ch) ? Math.PI : (cw ? Math.PI / 2 : (ch ? -Math.PI / 2 : 0)); |
| | | const angEnd = (cw && ch) ? Math.PI * 1.5 : (cw ? Math.PI : (ch ? 0 : Math.PI / 2)); |
| | | const rX = Math.abs(cx - midX); |
| | | const rY = Math.abs(cy - midY); |
| | | const rMid = Math.min(rX, rY); |
| | | g.lineStyle(rail, railColor, 1); |
| | | g.arc(cx, cy, rMid, angStart, angEnd); |
| | | g.lineStyle(0, 0, 0); |
| | | } |
| | | |
| | | // no sleepers; keep a single continuous line |
| | | const rt = PIXI.RenderTexture.create({ width: width, height: height }); |
| | | this.pixiApp.renderer.render(g, rt); |
| | | return rt; |
| | |
| | | if (!isNaN(id)) { this.$emit('station-click', id); } |
| | | }); |
| | | } else if (item.type == 'crn') { |
| | | sprite = this.createTrackSprite(item.width, item.height); |
| | | sprite = this.createTrackSprite(item.width, item.height, item.trackMask); |
| | | sprite._kind = 'crn-track'; |
| | | if (this.getDeviceNo(value) > 0) { this.crnList.push(item); } |
| | | } else if (item.type == 'dualCrn') { |
| | | sprite = this.createTrackSprite(item.width, item.height); |
| | | sprite = this.createTrackSprite(item.width, item.height, item.trackMask); |
| | | sprite._kind = 'crn-track'; |
| | | if (this.getDeviceNo(value) > 0) { this.dualCrnList.push(item); } |
| | | } else if (item.type == 'rgv') { |
| | | sprite = this.createTrackSprite(item.width, item.height); |
| | | sprite = this.createTrackSprite(item.width, item.height, item.trackMask); |
| | | sprite._kind = 'rgv-track'; |
| | | if (this.getDeviceNo(value) > 0) { this.rgvList.push(item); } |
| | | } else { |
| | |
| | | sprite.position.set(item.posX, item.posY); |
| | | return sprite; |
| | | }, |
| | | collectTrackItem(item) { |
| | | const value = item.value; |
| | | if (item.type === 'crn') { |
| | | if (this.getDeviceNo(value) > 0) { this.crnList.push(item); } |
| | | } else if (item.type === 'dualCrn') { |
| | | if (this.getDeviceNo(value) > 0) { this.dualCrnList.push(item); } |
| | | } else if (item.type === 'rgv') { |
| | | if (this.getDeviceNo(value) > 0) { this.rgvList.push(item); } |
| | | } |
| | | }, |
| | | isTrackType(cell) { |
| | | return cell && (cell.type === 'crn' || cell.type === 'dualCrn' || cell.type === 'rgv'); |
| | | }, |
| | | resolveMergedCell(map, rowIndex, colIndex) { |
| | | if (!map || rowIndex < 0 || colIndex < 0) { return null; } |
| | | const row = map[rowIndex]; |
| | | if (!row || colIndex >= row.length) { return null; } |
| | | const cell = row[colIndex]; |
| | | if (!cell) { return null; } |
| | | if (!cell.isMergedPart && cell.type !== 'merge') { return cell; } |
| | | if (cell.isMergedPart) { |
| | | for (let c = colIndex - 1; c >= 0; c--) { |
| | | const left = row[c]; |
| | | if (!left) { continue; } |
| | | if (!left.isMergedPart && left.type !== 'merge' && left.posX === cell.posX) { return left; } |
| | | } |
| | | } |
| | | if (cell.type === 'merge') { |
| | | for (let r = rowIndex - 1; r >= 0; r--) { |
| | | const upRow = map[r]; |
| | | if (!upRow || colIndex >= upRow.length) { continue; } |
| | | const up = upRow[colIndex]; |
| | | if (!up) { continue; } |
| | | if (up.type !== 'merge') { return up; } |
| | | } |
| | | } |
| | | return null; |
| | | }, |
| | | getTrackMask(map, rowIndex, colIndex) { |
| | | const TRACK_N = 1; |
| | | const TRACK_E = 2; |
| | | const TRACK_S = 4; |
| | | const TRACK_W = 8; |
| | | const baseRow = map[rowIndex]; |
| | | if (!baseRow) { return 0; } |
| | | const base = baseRow[colIndex]; |
| | | if (!this.isTrackType(base)) { return 0; } |
| | | const rowSpan = base.rowSpan || 1; |
| | | const colSpan = base.colSpan || 1; |
| | | let mask = 0; |
| | | const n = this.resolveMergedCell(map, rowIndex - 1, colIndex); |
| | | const s = this.resolveMergedCell(map, rowIndex + rowSpan, colIndex); |
| | | const w = this.resolveMergedCell(map, rowIndex, colIndex - 1); |
| | | const e = this.resolveMergedCell(map, rowIndex, colIndex + colSpan); |
| | | if (n && n !== base && this.isTrackType(n)) { mask |= TRACK_N; } |
| | | if (e && e !== base && this.isTrackType(e)) { mask |= TRACK_E; } |
| | | if (s && s !== base && this.isTrackType(s)) { mask |= TRACK_S; } |
| | | if (w && w !== base && this.isTrackType(w)) { mask |= TRACK_W; } |
| | | if (mask === 0) { mask = TRACK_E | TRACK_W; } |
| | | return mask; |
| | | }, |
| | | drawTracks(map) { |
| | | if (!this.tracksGraphics) { return; } |
| | | this.tracksGraphics.clear(); |
| | | const rail = 3; |
| | | const color = 0x555555; |
| | | this.tracksGraphics.lineStyle({ width: rail, color: color, alpha: 1, cap: PIXI.LINE_CAP.ROUND, join: PIXI.LINE_JOIN.ROUND }); |
| | | const drawn = new Set(); |
| | | const toKey = (p) => { |
| | | const x = Math.round(p.x * 100) / 100; |
| | | const y = Math.round(p.y * 100) / 100; |
| | | return x + "," + y; |
| | | }; |
| | | const edgeKey = (a, b) => { |
| | | const ka = toKey(a); |
| | | const kb = toKey(b); |
| | | return ka < kb ? (ka + "|" + kb) : (kb + "|" + ka); |
| | | }; |
| | | const centerOf = (cell) => ({ x: cell.posX + cell.width / 2, y: cell.posY + cell.height / 2 }); |
| | | |
| | | for (let r = 0; r < map.length; r++) { |
| | | const row = map[r]; |
| | | if (!row) { continue; } |
| | | for (let c = 0; c < row.length; c++) { |
| | | const cell = row[c]; |
| | | if (!cell || cell.type === 'merge' || !this.isTrackType(cell) || cell.isMergedPart) { continue; } |
| | | const rowSpan = cell.rowSpan || 1; |
| | | const colSpan = cell.colSpan || 1; |
| | | const n = this.resolveMergedCell(map, r - 1, c); |
| | | const s = this.resolveMergedCell(map, r + rowSpan, c); |
| | | const w = this.resolveMergedCell(map, r, c - 1); |
| | | const e = this.resolveMergedCell(map, r, c + colSpan); |
| | | const hasN = n && this.isTrackType(n); |
| | | const hasE = e && this.isTrackType(e); |
| | | const hasS = s && this.isTrackType(s); |
| | | const hasW = w && this.isTrackType(w); |
| | | const count = (hasN ? 1 : 0) + (hasE ? 1 : 0) + (hasS ? 1 : 0) + (hasW ? 1 : 0); |
| | | const straight = (hasN && hasS) || (hasE && hasW); |
| | | if (count === 2 && !straight) { |
| | | const cPos = centerOf(cell); |
| | | let p1 = null; |
| | | let p2 = null; |
| | | if (hasN && hasE) { p1 = centerOf(n); p2 = centerOf(e); } |
| | | else if (hasE && hasS) { p1 = centerOf(e); p2 = centerOf(s); } |
| | | else if (hasS && hasW) { p1 = centerOf(s); p2 = centerOf(w); } |
| | | else if (hasW && hasN) { p1 = centerOf(w); p2 = centerOf(n); } |
| | | if (p1 && p2) { |
| | | const k1 = edgeKey(cPos, p1); |
| | | const k2 = edgeKey(cPos, p2); |
| | | if (!drawn.has(k1) || !drawn.has(k2)) { |
| | | this.tracksGraphics.moveTo(p1.x, p1.y); |
| | | this.tracksGraphics.lineTo(cPos.x, cPos.y); |
| | | this.tracksGraphics.lineTo(p2.x, p2.y); |
| | | } |
| | | drawn.add(k1); |
| | | drawn.add(k2); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | for (let r = 0; r < map.length; r++) { |
| | | const row = map[r]; |
| | | if (!row) { continue; } |
| | | for (let c = 0; c < row.length; c++) { |
| | | const cell = row[c]; |
| | | if (!cell || cell.type === 'merge' || !this.isTrackType(cell) || cell.isMergedPart) { continue; } |
| | | const cPos = centerOf(cell); |
| | | const rowSpan = cell.rowSpan || 1; |
| | | const colSpan = cell.colSpan || 1; |
| | | const e = this.resolveMergedCell(map, r, c + colSpan); |
| | | const s = this.resolveMergedCell(map, r + rowSpan, c); |
| | | if (e && this.isTrackType(e)) { |
| | | const p = centerOf(e); |
| | | const k = edgeKey(cPos, p); |
| | | if (!drawn.has(k)) { |
| | | this.tracksGraphics.moveTo(cPos.x, cPos.y); |
| | | this.tracksGraphics.lineTo(p.x, p.y); |
| | | drawn.add(k); |
| | | } |
| | | } |
| | | if (s && this.isTrackType(s)) { |
| | | const p = centerOf(s); |
| | | const k = edgeKey(cPos, p); |
| | | if (!drawn.has(k)) { |
| | | this.tracksGraphics.moveTo(cPos.x, cPos.y); |
| | | this.tracksGraphics.lineTo(p.x, p.y); |
| | | drawn.add(k); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | updateColor(sprite, color) { |
| | | if (sprite && sprite._kind === 'devp') { |
| | | const key = sprite.width + '-' + sprite.height + '-' + color; |