Поменять обычный ввод исходных элементов массивов на динамический
24.07.2025, 09:25. Показов 786. Ответов 3
Помогите заменить BEAM_LENGTH на zmx. Создать нормальный plotter.js, где можно будет масштабировать на холстах 2, 3, 4 ось X по zmax, масштабировать на холстах 2, 3, 4 ось Y по максимальному и минимальному значению ординат линий влияния. нарисовать тонкие чёрные вертикальные линии на всех холстах в местах расположения элементов балки - шарниров, опор, неподвижной опоры и заделок, нанести на линиях влияния значения ординат. | JavaScript | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
| // Импорт класса Plotter для отрисовки графики
import { Plotter } from "./plotter.js";
// ===================== КОНСТАНТЫ И НАСТРОЙКИ =====================
// Основные параметры системы
const BEAM_LENGTH = 20; // Длина балки в условных единицах
const PLOT_RANGE = 8; // Диапазон отображения по оси Y (-8 до 8)
// Конфигурация canvas элементов
const CANVAS_CONFIG = [
{ id: "beam", label: "Балка с опорами" }, // Основной canvas
{ id: "canvas-2", label: "Линия влияния Q" }, // Для поперечных сил
{ id: "canvas-3", label: "Линия влияния M" }, // Для изгибающих моментов
{ id: "canvas-4", label: "Линия влияния R" } // Для реакций опор
];
// ===================== ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ =====================
let canvases = []; // Массив для хранения всех canvas элементов
// ===================== КЛАСС ДЛЯ РАБОТЫ С ОПОРАМИ =====================
class SupportSystem {
constructor() {
// Исходные данные по опорам
this.supportTypes = ['K', 'O', 'S', 'O', 'O', 'S', 'O', 'S', 'OH', 'K'];
this.supportPositions = [0, 2, 5, 7, 9, 12, 14, 16, 19, 20];
// Соответствие типов опор
this.typeMapping = {
'O': 'support', // Подвижная опора
'S': 'hinge', // Шарнир
'OH': 'fixed', // Неподвижная опора
'Zl': 'sealLeft', // Левая заделка
'ZR': 'sealRight', // Правая заделка
'K': null // Нет опоры
};
// Пути к изображениям опор
this.images = {
support: "./images/support.svg",
hinge: "./images/hinge.svg",
fixed: "./images/fixedSupport.svg",
sealLeft: "./images/sealingLeft.svg",
sealRight: "./images/sealingRight.svg"
};
}
/**
* Генерирует массив опор на основе исходных данных
* @returns {Array} Массив объектов опор
*/
generateSupports() {
return this.supportTypes.reduce((result, type, index) => {
// Пропускаем опоры типа 'K' (отсутствие опоры)
if (type !== 'K' && this.typeMapping[type]) {
// Проверяем наличие координаты для данной опоры
if (index < this.supportPositions.length) {
result.push({
type: this.typeMapping[type],
x: this.supportPositions[index],
originalType: type // Сохраняем исходный тип
});
}
}
return result;
}, []);
}
/**
* Рисует опору на указанном canvas
* @param {Object} ctx - Контекст canvas
* @param {Object} plotter - Экземпляр Plotter
* @param {Object} support - Объект опоры
*/
drawSupport(ctx, plotter, support) {
// Проверяем наличие типа и изображения для опоры
if (!support.type || !this.images[support.type]) return;
const img = new Image();
img.onload = () => {
// Рассчитываем координаты для отрисовки
const x = plotter.x0 + support.x / plotter.xScale;
const y = plotter.y0;
const width = 30; // Ширина изображения
const height = 30; // Высота изображения
// Корректируем позицию для шарниров (центрирование)
const drawX = x - width/2;
const drawY = support.type === "hinge" ? y - height/2 : y;
// Рисуем изображение опоры
ctx.drawImage(img, drawX, drawY, width, height);
};
img.src = this.images[support.type];
}
}
// ===================== КЛАСС ДЛЯ ЛИНИЙ ВЛИЯНИЯ =====================
class InfluenceLines {
constructor() {
// Данные для линий влияния
this.data = {
Q: { // Поперечная сила
x: [0, 5, 7, 8, 8, 9, 12, 16, BEAM_LENGTH],
y: [-0.677, 1, 0, -0.5, 0.5, 0, -1.5, 1.5, -0.5]
},
M: { // Изгибающий момент
x: [0, 5, 7, 8, 9, 12, 16, BEAM_LENGTH],
y: [0.677, -1, 0, 0.5, 0, -1.5, 1.5, -0.5]
},
R: { // Реакции опор
x: [0, 7, 12, 16, BEAM_LENGTH],
y: [0, 0, 2.5, -2.5, 0.833]
}
};
}
/**
* Рисует все линии влияния на соответствующих canvas
*/
drawAll() {
// Проверяем наличие всех необходимых canvas
if (canvases.length < 4) {
console.error("Недостаточно canvas элементов для рисования линий влияния");
return;
}
// Линия влияния поперечной силы (Q)
canvases[1].plotter.drawGraph(this.data.Q.x, this.data.Q.y);
// Линия влияния изгибающего момента (M)
canvases[2].plotter.drawGraph(this.data.M.x, this.data.M.y);
// Линия влияния реакций опор (R)
canvases[3].plotter.drawGraph(this.data.R.x, this.data.R.y);
}
}
// ===================== ОСНОВНЫЕ ФУНКЦИИ =====================
/**
* Инициализирует все canvas элементы
* @returns {Array} Массив инициализированных canvas
*/
function initCanvases() {
return CANVAS_CONFIG.map(config => {
try {
const canvas = document.getElementById(config.id);
if (!canvas) throw new Error(`Canvas "${config.id}" не найден`);
const ctx = canvas.getContext("2d");
if (!ctx) throw new Error(`Не удалось получить контекст для "${config.id}"`);
// Создаем экземпляр Plotter для каждого canvas
const plotter = new Plotter(
ctx,
740, 310, // Ширина и высота canvas
30, 200, // Отступы
0, BEAM_LENGTH, // Диапазон по X
-PLOT_RANGE, PLOT_RANGE // Диапазон по Y
);
// Базовая настройка графики
plotter.drawGrid(1, 1);
plotter.drawAxes("X", "Y");
plotter.drawTicks(1, 1);
plotter.drawUnits(1, 1);
return {
el: canvas,
ctx: ctx,
plotter: plotter,
label: config.label
};
} catch (error) {
console.error(error.message);
return null;
}
}).filter(canvas => canvas !== null);
}
/**
* Основная функция инициализации системы
*/
function initSystem() {
try {
// 1. Инициализация canvas
canvases = initCanvases();
if (canvases.length === 0) {
throw new Error("Не удалось инициализировать ни одного canvas");
}
// 2. Создаем экземпляры классов
const supportSystem = new SupportSystem();
const influenceLines = new InfluenceLines();
// 3. Рисуем опоры на основном canvas
const supports = supportSystem.generateSupports();
supports.forEach(support => {
supportSystem.drawSupport(canvases[0].ctx, canvases[0].plotter, support);
});
// 4. Рисуем линии влияния с небольшой задержкой
setTimeout(() => {
influenceLines.drawAll();
}, 100);
} catch (error) {
console.error("Ошибка инициализации системы:", error.message);
}
}
// Запускаем инициализацию после загрузки страницы
window.addEventListener('load', initSystem); |
|
Вот существующий плоттер: | JavaScript | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
| export class Plotter {
// Параметры:
// ctx - контекст канваса
// width, height - ширина и высота рабочей области
// x0, y0 - начало координат
// xMin, xMax - минимум и максимум по оси X
// yMin, yMax - минимум и максимум по оси Y
constructor(ctx, width, height, x0, y0, xMin, xMax, yMin, yMax) {
// Свойства:
this.ctx = ctx;
this.x0 = x0;
this.y0 = y0;
this.xScale = (xMax - xMin) / width;
this.yScale = (yMax - yMin) / height;
this.xMin = xMin / this.xScale;
this.xMax = xMax / this.xScale;
this.yMin = yMin / this.yScale;
this.yMax = yMax / this.yScale;
}
// Метод: Нарисовать сетку
// Параметры:
// xCell - ширина клетки
// yCell - высота клетки
// color - цвет сетки (по умолчанию светло-серый)
drawGrid(xCell, yCell, color = "lightgray") {
this.ctx.save(); // сохранить состояние контекста по умолчанию
this.ctx.translate(this.x0, this.y0); // перевести начало контекста
this.ctx.scale(1, -1); // перевернуть контекст по вертикали
this.ctx.lineWidth = 1;
this.ctx.strokeStyle = color;
this.ctx.beginPath();
xCell /= this.xScale;
yCell /= this.yScale;
let x = this.xMin;
do {
this.ctx.moveTo(x, this.yMin);
this.ctx.lineTo(x, this.yMax);
x += xCell;
} while (x <= this.xMax);
let y = this.yMin;
do {
this.ctx.moveTo(this.xMin, y);
this.ctx.lineTo(this.xMax, y);
y += yCell;
} while (y <= this.yMax);
this.ctx.stroke();
this.ctx.restore(); // восстановить состояние контекста по умолчанию
}
// Метод: Нарисовать оси
// Параметры:
// xLabel - метка оси X
// yLabel - метка оси Y
// color - цвет осей и меток
// font - шрифт меток
drawAxes(xLabel = "x", yLabel = "y", color = "black", font = "12px Arial") {
this.ctx.save();
this.ctx.translate(this.x0, this.y0);
this.ctx.scale(1, -1);
this.ctx.lineWidth = 2;
this.ctx.strokeStyle = color;
this.ctx.beginPath();
this.ctx.moveTo(this.xMin, 0);
this.ctx.lineTo(this.xMax, 0);
this.ctx.moveTo(0, this.yMin);
this.ctx.lineTo(0, this.yMax);
this.ctx.stroke();
this.ctx.scale(1, -1);
this.ctx.fillStyle = color;
this.ctx.font = font;
this.ctx.textAlign = "center";
this.ctx.textBaseline = "middle";
this.ctx.fillText(xLabel, this.xMax + 10, -10);
this.ctx.fillText(yLabel, 0, -this.yMax - 10);
this.ctx.restore();
}
// Метод: Нарисовать насечки
// Параметры:
// xCell - ширина клетки
// yCell - высота клетки
// color - цвет насечек
drawTicks(xCell, yCell, color = "black") {
this.ctx.save();
this.ctx.translate(this.x0, this.y0);
this.ctx.scale(1, -1);
this.ctx.lineWidth = 1;
this.ctx.strokeStyle = color;
this.ctx.beginPath();
xCell /= this.xScale;
yCell /= this.yScale;
let x = this.xMin;
do {
this.ctx.moveTo(x, -4);
this.ctx.lineTo(x, 4);
x += xCell;
} while (x <= this.xMax);
let y = this.yMin;
do {
this.ctx.moveTo(-4, y);
this.ctx.lineTo(4, y);
y += yCell;
} while (y <= this.yMax);
this.ctx.stroke();
this.ctx.restore();
}
// Метод: Нарисовать единицы
// Параметры:
// xCell - ширина клетки
// yCell - высота клетки
// color - цвет единиц
// font - шрифт единиц
drawUnits(xCell, yCell, color = "black", font = "10px Arial") {
this.ctx.save();
this.ctx.translate(this.x0, this.y0);
this.ctx.fillStyle = color;
this.ctx.font = font;
xCell /= this.xScale;
yCell /= this.yScale;
this.ctx.textAlign = "left";
this.ctx.textBaseline = "top";
let x = this.xMin;
do {
this.ctx.fillText(x * this.xScale, x + 4, 4);
x += xCell;
} while (x <= this.xMax);
let y = this.yMin;
do {
this.ctx.fillText(y * this.yScale, 4, -y + 4);
y += yCell;
} while (y <= this.yMax);
this.ctx.restore();
}
// Метод: Нарисовать график
// Параметры:
// xArray - массив X-координат
// yArray - массив Y-координат
// color - цвет графика
// dots - показать точки?
// line - показать линию?
drawGraph(xArray, yArray, color = "blue", dots = 0 * true, line = true) {
this.ctx.save();
this.ctx.translate(this.x0, this.y0);
this.ctx.scale(1, -1);
this.ctx.lineWidth = 1;
this.ctx.strokeStyle = color;
this.ctx.beginPath();
let angle2PI = 2 * Math.PI;
for (let i = 0; i < xArray.length; i++) {
let x = xArray[i] / this.xScale;
let y = yArray[i] / this.yScale;
if (line && i != 0) {
this.ctx.lineTo(x, y);
} else {
this.ctx.moveTo(x, y);
}
if (dots) {
this.ctx.arc(x, y, 1, 0, angle2PI);
this.ctx.moveTo(x, y);
}
}
this.ctx.stroke();
this.ctx.restore();
}
// Для пунктирной линии
drawDashedLine(x1, y1, x2, y2, color = "red", pattern = [5, 3]) {
this.ctx.save();
this.ctx.translate(this.x0, this.y0);
this.ctx.scale(1, -1); // Инвертируем ось Y
this.ctx.strokeStyle = color;
this.ctx.lineWidth = 1;
this.ctx.setLineDash(pattern);
this.ctx.beginPath();
this.ctx.moveTo(x1 / this.xScale, y1 / this.yScale);
this.ctx.lineTo(x2 / this.xScale, y2 / this.yScale);
this.ctx.stroke();
this.ctx.restore();
}
} |
|
Вот файл html: | HTML5 | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./css/index.css">
<script type="module" src="./js/LV.js" defer></script>
<title>Линии влияния балок</title>
</head>
<body>
<!-- <header class="header">
<button class="btn">Ввод данных</button>
<button class="btn">Добавить</button>
<button class="btn">Изменить</button>
<button class="btn">Очистить</button>
</header> -->
<main class="main">
<div class="container">
<h2 class="title">Балка</h2>
<canvas id="beam" width="800" height="400"></canvas>
</div>
<div class="container">
<h2 class="title">Линия влияния поперечной силы</h2>
<canvas id="canvas-2" width="800" height="400"></canvas>
</div>
<div class="container">
<h2 class="title">Линия влияния изгибающего момента</h2>
<canvas id="canvas-3" width="800" height="400"></canvas>
</div>
<div class="container">
<h2 class="title">Линия влияния реакции опор</h2>
<canvas id="canvas-4" width="800" height="400"></canvas>
</div>
</main>
</body>
</html> |
|
Вот файл CSS: | CSS | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
min-height: 100vh;
background-color: dimgray;
font-size: 16px;
color: #333;
}
.container {
max-width: 1230px;
margin: auto;
padding: 0 15px;
margin-bottom: 15px;
text-align: center;
}
.canvas-container {
width: 100%;
height: 100%;
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
canvas {
width: 800px;
height: 400px;
background-color: #fff;
margin: 0 auto;
} |
|
0
|