-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
237 lines (195 loc) · 12 KB
/
Copy pathindex.html
File metadata and controls
237 lines (195 loc) · 12 KB
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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8" />
<title>Калькулятор шкафа</title>
<style>
body { font-family: Arial, sans-serif; max-width:900px; margin:20px auto; }
label { display:block; margin-top:8px; }
input[type=number]{ width:140px; }
.row { display:flex; gap:12px; align-items:center; margin-top:8px; flex-wrap:wrap; }
.result { background:#f5f5f5; padding:12px; margin-top:12px; border-radius:6px; white-space:pre-wrap; }
.small { font-size:90%; color:#444; }
</style>
<!-- библиотеки для генерации PDF в браузере -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
</head>
<body>
<h2>Калькулятор шкафа</h2>
<!-- ...existing code... -->
<label>Ширина шкафа, мм <input id="width" type="number" value="1200"></label>
<label>Высота шкафа, мм <input id="height" type="number" value="2400"></label>
<label>Глубина шкафа, мм <input id="depth" type="number" value="600"></label>
<label>Толщина панели (ЛДСП/МДФ), мм <input id="thickness" type="number" value="18"></label>
<div class="row">
<label>Полок, шт <input id="shelves" type="number" value="4"></label>
<label>Дверей, шт <input id="doors" type="number" value="2"></label>
</div>
<h4>Ящики</h4>
<div class="row">
<label>Ящиков, шт <input id="drawers" type="number" value="2"></label>
<label>Высота фасада ящика, мм <input id="drawer_front_h" type="number" value="150"></label>
<span class="small">(для расчёта боковин/дна/фасада ящика)</span>
</div>
<h4>Штанги / Фурнитура</h4>
<div class="row">
<label>Штанг, шт <input id="rods" type="number" value="1"></label>
<label>Длина штанги, м <input id="rod_len" type="number" value="1.2" step="0.01"></label>
</div>
<h4>Цены</h4>
<label>Цена панели (ЛДСП/МДФ), руб/м² <input id="price_panel" type="number" value="1200"></label>
<label>Цена кромки, руб/м <input id="price_edgeband" type="number" value="30"></label>
<label>Стоимость петли, руб/шт <input id="price_hinge" type="number" value="150"></label>
<label>Стоимость направляющей (комплект) на ящик, руб <input id="price_runner" type="number" value="400"></label>
<label>Цена штанги, руб/м <input id="price_rod" type="number" value="200"></label>
<label>Работа, руб/м² <input id="price_labor" type="number" value="800"></label>
<label>Запас материалов, % <input id="waste" type="number" value="10"></label>
<label>Монтаж (процент от суммы), % <input id="assembly_pct" type="number" value="10"></label>
<div style="margin-top:12px;">
<button onclick="calculate()">Рассчитать</button>
</div>
<div id="output" class="result" style="display:none;"></div>
<!-- кнопка для скачивания PDF -->
<div style="margin-top:8px;">
<button id="downloadBtn" onclick="generatePdf()" disabled>Скачать PDF</button>
</div>
<script>
// Логика: объём H × W × D; считаем площадь материала для корпуса и ящиков, фурнитуру и монтаж.
function mm2m(v){ return v/1000; }
function mm2m2(a,b){ return (a*b)/1e6; } // mm * mm -> m2
function mm2m3(h,w,d){ return (h*w*d)/1e9; } // mm^3 -> m3
// calculate() — только рассчитывает и выводит результат, не создаёт PDF автоматически
function calculate(){
const W = +document.getElementById('width').value || 0;
const H = +document.getElementById('height').value || 0;
const D = +document.getElementById('depth').value || 0;
const T = +document.getElementById('thickness').value || 18;
const shelves = Math.max(0, +document.getElementById('shelves').value || 0);
const doors = Math.max(0, +document.getElementById('doors').value || 0);
const drawers = Math.max(0, +document.getElementById('drawers').value || 0);
const drawer_front_h = +document.getElementById('drawer_front_h').value || 150;
const rods = Math.max(0, +document.getElementById('rods').value || 0);
const rod_len = +document.getElementById('rod_len').value || 0;
const price_panel = +document.getElementById('price_panel').value || 0;
const price_edgeband = +document.getElementById('price_edgeband').value || 0;
const price_hinge = +document.getElementById('price_hinge').value || 0;
const price_runner = +document.getElementById('price_runner').value || 0;
const price_rod = +document.getElementById('price_rod').value || 0;
const price_labor = +document.getElementById('price_labor').value || 0;
const waste_pct = (+document.getElementById('waste').value || 0) / 100;
const assembly_pct = (+document.getElementById('assembly_pct').value || 0) / 100;
// Корпус: 2 боковины H x D, верх+низ W x D, задняя W x H, полки shelves * W x D, двери суммарно W x H
const area_sides = 2 * mm2m2(H, D);
const area_top_bottom = 2 * mm2m2(W, D);
const area_back = mm2m2(W, H);
const area_shelves = shelves * mm2m2(W, D);
const area_doors = mm2m2(W, H);
const panel_area_carcass = area_sides + area_top_bottom + area_back + area_shelves + area_doors;
// Внутренние размеры (приближённо)
const W_internal = Math.max(0, W - 2*T); // мм
const D_internal = Math.max(0, D - T); // убираем толщину задней панели
// Ящик: 2 боковины (height_drawer x depth_internal), дно (W_internal x D_internal), фасад (W_internal x drawer_front_h)
const drawer_side_area = 2 * mm2m2(drawer_front_h, D_internal);
const drawer_bottom_area = mm2m2(W_internal, D_internal);
const drawer_front_area = mm2m2(W_internal, drawer_front_h);
const area_per_drawer = drawer_side_area + drawer_bottom_area + drawer_front_area;
const total_drawer_area = drawers * area_per_drawer;
// Общая площадь панелей (каркас + ящики)
const total_area_m2 = panel_area_carcass + total_drawer_area;
const total_area_with_waste = total_area_m2 * (1 + waste_pct);
// Кромка (упрощённо)
const edgeband_m = (2*H*doors/1000)
+ (shelves * W / 1000)
+ (2 * W / 1000)
+ (drawers * (W_internal/1000));
const edgeband_with_waste = edgeband_m * (1 + waste_pct);
// Стоимости
const cost_panel = total_area_with_waste * price_panel;
const cost_edgeband = edgeband_with_waste * price_edgeband;
const cost_hinges = doors * price_hinge;
const cost_runners = drawers * price_runner;
const cost_rods = rods * rod_len * price_rod;
const cost_labor = total_area_m2 * price_labor;
const subtotal = cost_panel + cost_edgeband + cost_hinges + cost_runners + cost_rods + cost_labor;
const assembly_cost = subtotal * assembly_pct;
const total_cost = subtotal + assembly_cost;
const volume_m3 = mm2m3(H, W, D);
const out = document.getElementById('output');
out.style.display = 'block';
out.innerText =
`Результат расчёта
Объём (H × W × D): ${volume_m3.toFixed(3)} м³
Площадь панелей корпуса: ${panel_area_carcass.toFixed(3)} м²
Площадь панелей ящиков: ${total_drawer_area.toFixed(3)} м²
Общая площадь панелей (без запаса): ${total_area_m2.toFixed(3)} м²
С запасом ${Math.round(waste_pct*100)}%: ${total_area_with_waste.toFixed(3)} м²
Кромка (прибл.): ${edgeband_with_waste.toFixed(2)} м
Стоимость материалов:
ЛДСП/МДФ: ${cost_panel.toFixed(0)} руб
Кромка: ${cost_edgeband.toFixed(0)} руб
Фурнитура:
Петли: ${cost_hinges.toFixed(0)} руб
Направляющие (ящики): ${cost_runners.toFixed(0)} руб
Штанги: ${cost_rods.toFixed(0)} руб
Работа: ${cost_labor.toFixed(0)} руб
Промежуточная сумма: ${subtotal.toFixed(0)} руб
Монтаж (${Math.round(assembly_pct*100)}%): ${assembly_cost.toFixed(0)} руб
Итого: ${total_cost.toFixed(0)} руб
(Модель упрощённая — при необходимости добавлю более точную спецификация деталей и раскрой.)`;
// включаем кнопку скачивания после расчёта
document.getElementById('downloadBtn').disabled = false;
}
// Функция генерации PDF по содержимому блока #output
async function generatePdf(){
const out = document.getElementById('output');
if (out.style.display === 'none') {
// если результатов нет — сначала рассчитать
calculate();
// дождёмся отрисовки
await new Promise(r => setTimeout(r, 200));
}
try {
const canvas = await html2canvas(out, { scale: 2 });
const imgData = canvas.toDataURL('image/png');
const doc = new window.jspdf.jsPDF('p', 'mm', 'a4');
const pageWidth = doc.internal.pageSize.getWidth();
const pageHeight = doc.internal.pageSize.getHeight();
const margin = 10;
const usableWidth = pageWidth - margin * 2;
const imgProps = { width: canvas.width, height: canvas.height };
const imgHeightMm = (imgProps.height * usableWidth) / imgProps.width;
// если поместится на одну страницу
if (imgHeightMm <= (pageHeight - margin*2)) {
doc.addImage(imgData, 'PNG', margin, margin, usableWidth, imgHeightMm);
} else {
// разбиваем изображение на части по высоте
let remainingHeightPx = imgProps.height;
const pxPerMm = imgProps.width / usableWidth;
let offsetYpx = 0;
let first = true;
while (remainingHeightPx > 0) {
const sliceHeightPx = Math.min(Math.floor((pageHeight - margin*2) * pxPerMm), remainingHeightPx);
const canvasSlice = document.createElement('canvas');
canvasSlice.width = imgProps.width;
canvasSlice.height = sliceHeightPx;
const ctx = canvasSlice.getContext('2d');
ctx.drawImage(canvas, 0, offsetYpx, imgProps.width, sliceHeightPx, 0, 0, imgProps.width, sliceHeightPx);
const sliceData = canvasSlice.toDataURL('image/png');
if (!first) doc.addPage();
doc.addImage(sliceData, 'PNG', margin, margin, usableWidth, (sliceHeightPx / imgProps.width) * usableWidth);
remainingHeightPx -= sliceHeightPx;
offsetYpx += sliceHeightPx;
first = false;
}
}
const fileName = `wardrobe_calc_${Date.now()}.pdf`;
doc.save(fileName);
} catch (err) {
console.error('Ошибка при создании PDF:', err);
alert('Ошибка при создании PDF. Откройте консоль для деталей.');
}
}
</script>
</body>
</html>