Strengthen the material in bambu 3d
📦 BAMU LAB
✨ The Prompt Phrase
how to strengthen the material using bamboo look at the image and the preview
💻 Code Preview
📦 All-in-One Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Printer Settings</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;
background: #f5f5f5;
padding: 20px;
display: flex;
gap: 20px;
justify-content: center;
align-items: flex-start;
}
.main-wrapper {
display: flex;
gap: 30px;
max-width: 900px;
position: relative;
}
.container {
max-width: 320px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
flex-shrink: 0;
}
.explanation-panel {
width: 420px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 12px;
padding: 24px;
box-shadow: 0 4px 20px rgba(102, 126, 234, 0.3);
color: white;
position: relative;
}
.explanation-panel h2 {
font-size: 20px;
margin-bottom: 16px;
display: flex;
align-items: center;
gap: 8px;
}
.explanation-panel h2::before {
content: '💡';
font-size: 24px;
}
.info-box {
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 16px;
margin-bottom: 16px;
border: 1px solid rgba(255, 255, 255, 0.2);
}
.info-box h3 {
font-size: 14px;
margin-bottom: 8px;
color: #ffd700;
display: flex;
align-items: center;
gap: 6px;
}
.info-box p {
font-size: 13px;
line-height: 1.6;
opacity: 0.95;
}
.visual-comparison {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
margin-top: 16px;
}
.comparison-item {
background: rgba(255, 255, 255, 0.1);
border-radius: 6px;
padding: 12px;
text-align: center;
}
.comparison-item .title {
font-size: 11px;
margin-bottom: 8px;
opacity: 0.9;
font-weight: 600;
}
.grid-visual {
width: 100%;
height: 80px;
background: white;
border-radius: 4px;
position: relative;
overflow: hidden;
}
.grid-lines {
position: absolute;
inset: 0;
background-image:
repeating-linear-gradient(0deg, #667eea 0px, #667eea 2px, transparent 2px, transparent 20px),
repeating-linear-gradient(90deg, #667eea 0px, #667eea 2px, transparent 2px, transparent 20px);
}
.grid-lines.sparse {
background-image:
repeating-linear-gradient(0deg, #ccc 0px, #ccc 2px, transparent 2px, transparent 30px),
repeating-linear-gradient(90deg, #ccc 0px, #ccc 2px, transparent 2px, transparent 30px);
}
.strength-indicator {
margin-top: 6px;
font-size: 11px;
font-weight: 600;
}
.strength-bar {
width: 100%;
height: 6px;
background: rgba(255, 255, 255, 0.3);
border-radius: 3px;
overflow: hidden;
margin-top: 4px;
}
.strength-fill {
height: 100%;
background: linear-gradient(90deg, #4CAF50, #8BC34A);
border-radius: 3px;
transition: width 0.3s ease;
}
.key-insight {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
padding: 16px;
border-radius: 8px;
margin-top: 16px;
font-size: 13px;
line-height: 1.6;
font-weight: 500;
box-shadow: 0 2px 10px rgba(245, 87, 108, 0.3);
}
.key-insight::before {
content: '⚡ ';
font-size: 16px;
}
.curved-arrow {
position: absolute;
width: 80px;
height: 80px;
left: -50px;
}
.curved-arrow.arrow1 {
top: 180px;
}
.curved-arrow.arrow2 {
top: 260px;
}
.curved-arrow svg {
width: 100%;
height: 100%;
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2));
}
/* Speech Bubble Animation */
.speech-bubble {
position: fixed;
bottom: 30px;
right: 30px;
background: white;
border-radius: 16px;
padding: 20px 24px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
max-width: 320px;
display: flex;
gap: 16px;
align-items: flex-start;
animation: bubbleSlideIn 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
z-index: 1000;
border: 2px solid #667eea;
}
.speech-bubble::before {
content: '';
position: absolute;
bottom: -10px;
right: 40px;
width: 0;
height: 0;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
border-top: 10px solid white;
}
.speaker-icon {
width: 50px;
height: 50px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 50%;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
animation: speakerPulse 2s infinite;
position: relative;
}
.speaker-icon.speaking::before {
content: '';
position: absolute;
inset: -5px;
border-radius: 50%;
border: 3px solid #ffd700;
animation: soundWave 0.8s ease-in-out infinite;
}
.speaker-icon.speaking::after {
content: '';
position: absolute;
inset: -12px;
border-radius: 50%;
border: 2px solid #ffd700;
animation: soundWave 0.8s ease-in-out infinite 0.2s;
opacity: 0.5;
}
/* Audio Control Button */
.audio-control {
position: fixed;
top: 80px;
right: 20px;
background: linear-gradient(135deg, #4CAF50 0%, #45a049 100%);
color: white;
border: none;
padding: 10px 20px;
border-radius: 20px;
font-weight: 600;
cursor: pointer;
box-shadow: 0 4px 15px rgba(76, 175, 80, 0.4);
z-index: 1001;
transition: all 0.2s;
font-size: 13px;
display: flex;
align-items: center;
gap: 8px;
}
.audio-control:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(76, 175, 80, 0.5);
}
.audio-control.muted {
background: linear-gradient(135deg, #999 0%, #777 100%);
}
.bubble-content {
flex: 1;
}
.bubble-content h4 {
margin: 0 0 8px 0;
color: #667eea;
font-size: 14px;
font-weight: 600;
}
.bubble-content p {
margin: 0;
font-size: 13px;
line-height: 1.6;
color: #333;
}
.bubble-progress {
width: 100%;
height: 3px;
background: #e0e0e0;
border-radius: 2px;
margin-top: 12px;
overflow: hidden;
}
.bubble-progress-fill {
height: 100%;
background: linear-gradient(90deg, #667eea, #764ba2);
width: 0%;
transition: width linear;
}
/* Highlight Animation */
.setting-row.animated-highlight {
position: relative;
animation: highlightPulse 2s ease-in-out infinite;
background: rgba(102, 126, 234, 0.1) !important;
border-radius: 4px;
}
.setting-row.animated-highlight::before {
content: '';
position: absolute;
inset: -4px;
border: 2px solid #667eea;
border-radius: 6px;
animation: borderGlow 2s ease-in-out infinite;
}
/* Hand Pointer */
.pointer-hand {
position: absolute;
font-size: 30px;
z-index: 200;
pointer-events: none;
opacity: 0;
}
.pointer-hand.clicking {
animation: clickAnimation 2s ease-in-out;
}
/* Tutorial Control Button */
.tutorial-button {
position: fixed;
top: 20px;
right: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 12px 24px;
border-radius: 25px;
font-weight: 600;
cursor: pointer;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
z-index: 1001;
transition: transform 0.2s, box-shadow 0.2s;
font-size: 14px;
display: flex;
align-items: center;
gap: 8px;
}
.tutorial-button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.5);
}
.tutorial-button.playing {
background: linear-gradient(135deg, #f5576c 0%, #f093fb 100%);
}
/* Keyframe Animations */
@keyframes bubbleSlideIn {
from {
opacity: 0;
transform: translateY(50px) scale(0.8);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
@keyframes speakerPulse {
0%,
100% {
transform: scale(1);
box-shadow: 0 0 0 0 rgba(102, 126, 234, 0.7);
}
50% {
transform: scale(1.05);
box-shadow: 0 0 0 10px rgba(102, 126, 234, 0);
}
}
@keyframes progressFill {
0% {
width: 0%;
}
100% {
width: 100%;
}
}
@keyframes highlightPulse {
0%,
100% {
box-shadow: 0 0 0 0 rgba(102, 126, 234, 0.4);
}
50% {
box-shadow: 0 0 20px 5px rgba(102, 126, 234, 0.6);
}
}
@keyframes borderGlow {
0%,
100% {
opacity: 0.5;
}
50% {
opacity: 1;
}
}
@keyframes clickAnimation {
0% {
opacity: 0;
transform: scale(0);
}
10% {
opacity: 1;
transform: scale(1.2);
}
15% {
transform: scale(0.9);
}
20% {
transform: scale(1);
}
80% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes soundWave {
0% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.3;
transform: scale(1.3);
}
100% {
opacity: 1;
transform: scale(1);
}
}
.setting-input.changing {
animation: valueChange 0.5s ease;
background: #fffbcc;
}
@keyframes valueChange {
0% {
transform: scale(1);
}
50% {
transform: scale(1.1);
background: #fff4a3;
}
100% {
transform: scale(1);
}
}
.header {
padding: 12px;
border-bottom: 1px solid #e0e0e0;
display: flex;
align-items: center;
gap: 8px;
font-weight: 600;
}
.nozzle-section {
padding: 16px;
border-bottom: 1px solid #e0e0e0;
}
.nozzle-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
margin-top: 12px;
}
.nozzle-card {
text-align: center;
position: relative;
}
.nozzle-icon {
width: 60px;
height: 60px;
background: #333;
margin: 0 auto 8px;
border-radius: 4px;
}
.badge {
position: absolute;
top: -5px;
right: 20px;
background: #4CAF50;
color: white;
width: 20px;
height: 20px;
border-radius: 50%;
font-size: 12px;
display: flex;
align-items: center;
justify-content: center;
}
.nozzle-label {
font-size: 11px;
color: #666;
margin-bottom: 8px;
}
.nozzle-title {
font-weight: 600;
margin-bottom: 8px;
}
.nozzle-status {
font-size: 12px;
color: #999;
}
.param-row {
display: flex;
justify-content: space-between;
margin-top: 6px;
font-size: 12px;
}
.param-label {
color: #666;
}
.param-value {
color: #333;
}
.section {
padding: 16px;
border-bottom: 1px solid #e0e0e0;
}
.section-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
}
.section-title {
font-weight: 600;
font-size: 13px;
display: flex;
align-items: center;
gap: 6px;
}
.filament-list {
display: flex;
flex-direction: column;
gap: 8px;
}
.filament-item {
display: flex;
align-items: center;
gap: 8px;
padding: 6px;
border-radius: 4px;
}
.filament-color {
width: 24px;
height: 24px;
border-radius: 4px;
}
.filament-number {
width: 24px;
height: 24px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 12px;
}
.tabs {
display: flex;
gap: 8px;
margin-bottom: 12px;
}
.tab {
padding: 6px 16px;
border-radius: 16px;
font-size: 12px;
cursor: pointer;
border: 1px solid #e0e0e0;
}
.tab.active {
background: #4CAF50;
color: white;
border-color: #4CAF50;
}
.process-title {
font-size: 13px;
margin-bottom: 12px;
}
.quality-tabs {
display: flex;
gap: 16px;
margin-bottom: 16px;
font-size: 12px;
}
.quality-tab {
color: #999;
cursor: pointer;
padding-bottom: 4px;
}
.quality-tab.active {
color: #333;
font-weight: 600;
border-bottom: 2px solid #4CAF50;
}
.settings-group {
margin-bottom: 16px;
}
.settings-group-title {
font-size: 12px;
font-weight: 600;
margin-bottom: 8px;
}
.setting-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 0;
font-size: 12px;
}
.setting-label {
color: #333;
}
.setting-value {
display: flex;
align-items: center;
gap: 8px;
}
.setting-input {
width: 60px;
padding: 4px 8px;
border: 1px solid #e0e0e0;
border-radius: 4px;
text-align: right;
}
.setting-unit {
color: #999;
font-size: 11px;
}
.pattern-icon {
width: 20px;
height: 20px;
background: #f0f0f0;
border: 1px solid #ddd;
border-radius: 2px;
}
.checkbox {
width: 16px;
height: 16px;
accent-color: #4CAF50;
}
.highlight {
position: relative;
}
.arrow {
position: absolute;
width: 0;
height: 0;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
border-top: 20px solid #ff5722;
right: -30px;
top: 50%;
transform: translateY(-50%) rotate(45deg);
}
.btn-group {
display: flex;
gap: 8px;
}
.btn {
padding: 4px 8px;
border: 1px solid #e0e0e0;
background: white;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
}
.btn-orange {
background: #ff9800;
color: white;
border: none;
}
.toggle {
position: relative;
width: 40px;
height: 20px;
background: #4CAF50;
border-radius: 10px;
cursor: pointer;
}
.toggle::after {
content: '';
position: absolute;
width: 16px;
height: 16px;
background: white;
border-radius: 50%;
top: 2px;
right: 2px;
}
/* Language Toggle Switch */
.language-toggle-container {
position: absolute;
top: 16px;
right: 16px;
display: flex;
align-items: center;
gap: 12px;
background: rgba(255, 255, 255, 0.2);
backdrop-filter: blur(10px);
padding: 8px 16px;
border-radius: 25px;
border: 1px solid rgba(255, 255, 255, 0.3);
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
}
.lang-label {
font-size: 13px;
font-weight: 600;
color: white;
opacity: 0.7;
transition: opacity 0.3s ease;
}
.lang-label.active {
opacity: 1;
text-shadow: 0 2px 8px rgba(255, 255, 255, 0.5);
}
.toggle-switch {
position: relative;
width: 56px;
height: 28px;
background: rgba(255, 255, 255, 0.3);
border-radius: 14px;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
border: 2px solid rgba(255, 255, 255, 0.4);
}
.toggle-switch:hover {
background: rgba(255, 255, 255, 0.4);
box-shadow: 0 0 15px rgba(255, 255, 255, 0.3);
}
.toggle-slider {
position: absolute;
width: 22px;
height: 22px;
background: linear-gradient(135deg, #fff 0%, #f0f0f0 100%);
border-radius: 50%;
top: 1px;
left: 2px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
}
.toggle-switch.arabic .toggle-slider {
left: 30px;
background: linear-gradient(135deg, #ffd700 0%, #ffed4e 100%);
box-shadow: 0 2px 12px rgba(255, 215, 0, 0.4);
}
.toggle-slider::before {
content: '🇬🇧';
font-size: 10px;
}
.toggle-switch.arabic .toggle-slider::before {
content: '🇸🇦';
}
/* Content transition */
.content-text {
opacity: 1;
transition: opacity 0.3s ease;
}
.content-text.fading {
opacity: 0;
}
</style>
</head>
<body>
<div class="main-wrapper">
<!-- Curved Arrows pointing to the settings -->
<div class="curved-arrow arrow1">
<svg viewBox="0 0 80 80" xmlns="http://www.w3.org/2000/svg">
<path d="M 5 40 Q 40 20, 75 40" stroke="#ffd700" stroke-width="3" fill="none" stroke-linecap="round" />
<polygon points="75,40 68,35 68,45" fill="#ffd700" />
</svg>
</div>
<div class="curved-arrow arrow2">
<svg viewBox="0 0 80 80" xmlns="http://www.w3.org/2000/svg">
<path d="M 5 40 Q 40 20, 75 40" stroke="#ff6b6b" stroke-width="3" fill="none" stroke-linecap="round" />
<polygon points="75,40 68,35 68,45" fill="#ff6b6b" />
</svg>
</div>
<div class="container">
<!-- Header -->
<div class="header">
🖨️ Printer
</div>
<!-- Nozzle Section -->
<div class="nozzle-section">
<div class="nozzle-grid">
<div class="nozzle-card">
<div class="nozzle-icon"></div>
<div class="badge">✓</div>
<div class="nozzle-title">Bambu Lab H2D</div>
<div class="nozzle-label">Left Nozzle</div>
<div class="nozzle-status">AMS Not installed</div>
<div class="param-row">
<span class="param-label">Diameter</span>
<span class="param-value">0.4</span>
</div>
<div class="param-row">
<span class="param-label">Flow</span>
<span class="param-value">Standard</span>
</div>
</div>
<div class="nozzle-card">
<div class="nozzle-icon" style="background: #d4a574;"></div>
<div class="nozzle-title">Texture...</div>
<div class="nozzle-label">Right Nozzle</div>
<div class="nozzle-status">AMS Not installed</div>
<div class="param-row">
<span class="param-label">Diameter</span>
<span class="param-value">0.4</span>
</div>
<div class="param-row">
<span class="param-label">Flow</span>
<span class="param-value">Standard</span>
</div>
</div>
</div>
</div>
<!-- Project Filaments -->
<div class="section">
<div class="section-header">
<div class="section-title">
🎨 Project Filaments
</div>
<div class="btn-group">
<button class="btn btn-orange">Flushing volumes</button>
<button class="btn">+</button>
<button class="btn">-</button>
<button class="btn">⚙️</button>
</div>
</div>
<div class="filament-list">
<div class="filament-item">
<div class="filament-color" style="background: #2196F3;"></div>
<span>■ PLA Basic</span>
<span style="margin-left: auto;">⊙</span>
<div class="filament-number" style="background: #FFD700; color: #333;">2</div>
<span>■ PLA Glow</span>
</div>
<div class="filament-item">
<div class="filament-color" style="background: #4CAF50;"></div>
<span>■ PLA Glow</span>
<span style="margin-left: auto;">⊙</span>
<div class="filament-number" style="background: #2196F3; color: white;">4</div>
<span>■ PLA Basic</span>
</div>
<div class="filament-item">
<div class="filament-number" style="background: #f5f5f5; color: #333;">5</div>
<span>■ PLA Basic</span>
<span style="margin-left: auto;">⊙</span>
</div>
</div>
</div>
<!-- Process Section -->
<div class="section">
<div class="tabs">
<div class="tab active">Global</div>
<div class="tab">Objects</div>
<div style="margin-left: auto; display: flex; align-items: center; gap: 8px;">
<span style="font-size: 12px;">Advanced</span>
<div class="toggle"></div>
</div>
</div>
<div class="process-title">0.16mm Standard @BBL H2D</div>
<div class="quality-tabs">
<div class="quality-tab">Quality</div>
<div class="quality-tab active">Strength</div>
<div class="quality-tab">Speed</div>
<div class="quality-tab">Support</div>
<div class="quality-tab">Others</div>
</div>
<!-- Bottom Shell Settings -->
<div class="settings-group">
<div class="setting-row">
<span class="setting-label">Bottom shell layers</span>
<div class="setting-value">
<input type="text" class="setting-input" value="4">
</div>
</div>
<div class="setting-row">
<span class="setting-label">Bottom shell thickness</span>
<div class="setting-value">
<input type="text" class="setting-input" value="0">
<span class="setting-unit">mm</span>
</div>
</div>
<div class="setting-row">
<span class="setting-label">Bottom solid infill layers</span>
<div class="setting-value">
<input type="text" class="setting-input" value="4">
</div>
</div>
<div class="setting-row">
<span class="setting-label">Internal solid infill pattern</span>
<div class="setting-value">
<div class="pattern-icon"></div>
<span>Rectilinear</span>
</div>
</div>
</div>
<!-- Sparse Infill Settings (Highlighted) -->
<div class="settings-group">
<div class="settings-group-title">Sparse infill</div>
<div class="setting-row highlight">
<span class="setting-label">Sparse infill density</span>
<div class="setting-value">
<input type="text" class="setting-input" value="15">
<span class="setting-unit">%</span>
</div>
<div class="arrow"></div>
</div>
<div class="setting-row">
<span class="setting-label">Fill multiline</span>
<div class="setting-value">
<input type="text" class="setting-input" value="1">
</div>
</div>
<div class="setting-row highlight">
<span class="setting-label">Sparse infill pattern</span>
<div class="setting-value">
<div class="pattern-icon"></div>
<span>Grid</span>
</div>
<div class="arrow"></div>
</div>
<div class="setting-row">
<span class="setting-label">Length of sparse infill anchor</span>
<div class="setting-value">
<input type="text" class="setting-input" value="400%">
<span class="setting-unit">mm or %</span>
</div>
</div>
<div class="setting-row">
<span class="setting-label">Maximum length of sparse infill anchor</span>
<div class="setting-value">
<input type="text" class="setting-input" value="20">
<span class="setting-unit">mm or %</span>
</div>
</div>
</div>
<!-- Advanced Settings -->
<div class="settings-group">
<div class="settings-group-title">⚙️ Advanced</div>
<div class="setting-row">
<span class="setting-label">Infill/Wall overlap</span>
<div class="setting-value">
<input type="text" class="setting-input" value="15">
<span class="setting-unit">%</span>
</div>
</div>
<div class="setting-row">
<span class="setting-label">Infill direction</span>
<div class="setting-value">
<input type="text" class="setting-input" value="45">
<span class="setting-unit">°</span>
</div>
</div>
<div class="setting-row">
<span class="setting-label">Bridge direction</span>
<div class="setting-value">
<input type="text" class="setting-input" value="0">
<span class="setting-unit">°</span>
</div>
</div>
<div class="setting-row">
<span class="setting-label">Minimum sparse infill threshold</span>
<div class="setting-value">
<input type="text" class="setting-input" value="15">
<span class="setting-unit">mm²</span>
</div>
</div>
<div class="setting-row">
<span class="setting-label">Infill combination</span>
</div>
<div class="setting-row">
<span class="setting-label">Detect narrow internal solid infill</span>
<div class="setting-value">
<input type="checkbox" class="checkbox" checked>
</div>
</div>
<div class="setting-row">
<span class="setting-label">Ensure vertical shell thickness</span>
<div class="setting-value">
<span>Enabled</span>
</div>
</div>
<div class="setting-row">
<span class="setting-label">Detect floating vertical shells</span>
<div class="setting-value">
<input type="checkbox" class="checkbox" checked>
</div>
</div>
</div>
</div>
</div>
<!-- Educational Explanation Panel -->
<div class="explanation-panel">
<!-- Language Toggle -->
<div class="language-toggle-container">
<span class="lang-label active" id="engLabel">EN</span>
<div class="toggle-switch" id="langToggle">
<div class="toggle-slider"></div>
</div>
<span class="lang-label" id="arLabel">AR</span>
</div>
<!-- English Content -->
<div class="content-text" id="englishContent">
<h2>Understanding Infill Strength</h2>
<div class="info-box">
<h3>🎯 Sparse Infill Density (15%)</h3>
<p>
This controls <strong>how much material fills the inside</strong> of your 3D print.
Think of it like the density of a sponge:
</p>
<ul style="margin-top: 8px; padding-left: 20px; font-size: 12px;">
<li><strong>Low (10-20%):</strong> Lighter, uses less material, faster printing, but weaker</li>
<li><strong>Medium (30-50%):</strong> Balanced strength and weight</li>
<li><strong>High (70-100%):</strong> Very strong and heavy, uses more material</li>
</ul>
</div>
<div class="info-box">
<h3>📐 Sparse Infill Pattern (Grid)</h3>
<p>
This defines <strong>the structure</strong> of the internal filling. Different patterns provide different
strength:
</p>
<ul style="margin-top: 8px; padding-left: 20px; font-size: 12px;">
<li><strong>Grid:</strong> Strong in all directions, good for general use</li>
<li><strong>Honeycomb:</strong> Best strength-to-weight ratio</li>
<li><strong>Lines:</strong> Fast but weaker</li>
<li><strong>Gyroid:</strong> Excellent for flexible parts</li>
</ul>
</div>
<div class="visual-comparison">
<div class="comparison-item">
<div class="title">15% DENSITY</div>
<div class="grid-visual">
<div class="grid-lines sparse"></div>
</div>
<div class="strength-indicator">Strength: Moderate</div>
<div class="strength-bar">
<div class="strength-fill" style="width: 40%;"></div>
</div>
</div>
<div class="comparison-item">
<div class="title">50% DENSITY</div>
<div class="grid-visual">
<div class="grid-lines"></div>
</div>
<div class="strength-indicator">Strength: High</div>
<div class="strength-bar">
<div class="strength-fill" style="width: 85%;"></div>
</div>
</div>
</div>
<div class="key-insight">
<strong>How They Work Together:</strong><br>
Increasing both the <strong>density percentage</strong> (more material) and choosing a <strong>stronger
pattern</strong> (like Grid or Honeycomb) creates a much more solid and durable 3D print. The pattern
creates
the structure, while the density fills it with material—together they make your print nearly unbreakable!
</div>
</div>
<!-- Arabic Content (Hidden by default) -->
<div class="content-text fading" id="arabicContent" style="display: none; direction: rtl;">
<h2>فهم قوة الحشو الداخلي</h2>
<div class="info-box">
<h3>🎯 كثافة الحشو المتفرق (15%)</h3>
<p>
هذا الإعداد يتحكم في <strong>كمية المادة التي تملأ الجزء الداخلي</strong> من طباعتك ثلاثية الأبعاد.
فكر فيه مثل كثافة الإسفنج:
</p>
<ul style="margin-top: 8px; padding-right: 20px; font-size: 12px;">
<li><strong>منخفض (10-20%):</strong> أخف وزناً، يستخدم مواد أقل، طباعة أسرع، ولكن أضعف</li>
<li><strong>متوسط (30-50%):</strong> توازن بين القوة والوزن</li>
<li><strong>عالي (70-100%):</strong> قوي جداً وثقيل، يستخدم مواد أكثر</li>
</ul>
</div>
<div class="info-box">
<h3>📐 نمط الحشو المتفرق (شبكة)</h3>
<p>
هذا يحدد <strong>البنية الهيكلية</strong> للحشو الداخلي. الأنماط المختلفة توفر قوة مختلفة:
</p>
<ul style="margin-top: 8px; padding-right: 20px; font-size: 12px;">
<li><strong>الشبكة (Grid):</strong> قوي في جميع الاتجاهات، جيد للاستخدام العام</li>
<li><strong>قرص العسل (Honeycomb):</strong> أفضل نسبة قوة إلى وزن</li>
<li><strong>الخطوط (Lines):</strong> سريع لكن أضعف</li>
<li><strong>الجيرويد (Gyroid):</strong> ممتاز للأجزاء المرنة</li>
</ul>
</div>
<div class="visual-comparison">
<div class="comparison-item">
<div class="title">كثافة 15%</div>
<div class="grid-visual">
<div class="grid-lines sparse"></div>
</div>
<div class="strength-indicator">القوة: متوسطة</div>
<div class="strength-bar">
<div class="strength-fill" style="width: 40%;"></div>
</div>
</div>
<div class="comparison-item">
<div class="title">كثافة 50%</div>
<div class="grid-visual">
<div class="grid-lines"></div>
</div>
<div class="strength-indicator">القوة: عالية</div>
<div class="strength-bar">
<div class="strength-fill" style="width: 85%;"></div>
</div>
</div>
</div>
<div class="key-insight">
<strong>كيف يعملان معاً:</strong><br>
زيادة كل من <strong>نسبة الكثافة</strong> (المزيد من المواد) واختيار <strong>نمط أقوى</strong> (مثل الشبكة أو
قرص العسل) يخلق طباعة ثلاثية الأبعاد أكثر صلابة ومتانة. النمط يخلق البنية، بينما الكثافة تملؤها بالمواد—معاً
يجعلان طباعتك شبه غير قابلة للكسر!
</div>
</div>
</div>
</div>
<!-- Tutorial Button -->
<button class="tutorial-button" id="tutorialBtn">
<span>▶</span>
<span id="btnText">Play Tutorial</span>
</button>
<!-- Audio Control Button -->
<button class="audio-control" id="audioBtn">
<span id="audioIcon">🔊</span>
<span id="audioText">Audio On</span>
</button>
<!-- Speech Bubble (Hidden by default) -->
<div class="speech-bubble" id="speechBubble" style="display: none;">
<div class="speaker-icon">🎓</div>
<div class="bubble-content">
<h4 id="bubbleTitle">Step 1: Infill Density</h4>
<p id="bubbleText">Watch as we increase the infill density from 15% to 50% for a stronger print!</p>
<div class="bubble-progress">
<div class="bubble-progress-fill" id="bubbleProgress"></div>
</div>
</div>
</div>
<!-- Hand Pointer -->
<div class="pointer-hand" id="pointerHand">👆</div>
<script>
// Tutorial Animation Controller
let isPlaying = false;
let animationTimeout;
let audioEnabled = true;
let currentSpeech = null;
const tutorialBtn = document.getElementById('tutorialBtn');
const btnText = document.getElementById('btnText');
const speechBubble = document.getElementById('speechBubble');
const bubbleTitle = document.getElementById('bubbleTitle');
const bubbleText = document.getElementById('bubbleText');
const pointerHand = document.getElementById('pointerHand');
const explanationPanel = document.querySelector('.explanation-panel');
const speakerIcon = document.querySelector('.speaker-icon');
// Audio Control Elements
const audioBtn = document.getElementById('audioBtn');
const audioIcon = document.getElementById('audioIcon');
const audioText = document.getElementById('audioText');
// Get the two important setting rows
const densityRow = document.querySelector('.setting-row.highlight');
const patternRow = document.querySelectorAll('.setting-row.highlight')[1];
const densityInput = densityRow.querySelector('.setting-input');
const patternSpan = patternRow.querySelector('.setting-value span');
// Get strength indicators in explanation panel
const strengthFill = document.querySelector('.strength-fill');
const strengthIndicator = document.querySelector('.strength-indicator');
const densityTitle = document.querySelector('.comparison-item .title');
// Text-to-Speech Setup
const speechSynthesis = window.speechSynthesis;
let selectedVoice = null;
// Load and select British female voice
function loadVoices() {
const voices = speechSynthesis.getVoices();
// Try to find a British English female voice
selectedVoice = voices.find(voice =>
voice.lang.startsWith('en-GB') && voice.name.toLowerCase().includes('female')
);
// Fallback: any British English voice
if (!selectedVoice) {
selectedVoice = voices.find(voice => voice.lang.startsWith('en-GB'));
}
// Fallback: any female voice
if (!selectedVoice) {
selectedVoice = voices.find(voice => voice.name.toLowerCase().includes('female'));
}
// Last fallback: first available voice
if (!selectedVoice && voices.length > 0) {
selectedVoice = voices[0];
}
}
// Load voices on init and when they change
speechSynthesis.onvoiceschanged = loadVoices;
loadVoices();
function speak(text) {
// Stop any ongoing speech
if (currentSpeech) {
speechSynthesis.cancel();
}
if (!audioEnabled) return;
// Ensure voices are loaded
if (!selectedVoice) {
loadVoices();
}
currentSpeech = new SpeechSynthesisUtterance(text);
currentSpeech.lang = 'en-GB'; // British English
currentSpeech.rate = 0.9; // Slightly slower for clarity
currentSpeech.pitch = 1.1; // Slightly higher for female voice
// Use selected voice if available
if (selectedVoice) {
currentSpeech.voice = selectedVoice;
}
// Add visual feedback when speaking
currentSpeech.onstart = () => {
speakerIcon.classList.add('speaking');
};
currentSpeech.onend = () => {
speakerIcon.classList.remove('speaking');
};
currentSpeech.onerror = () => {
speakerIcon.classList.remove('speaking');
};
speechSynthesis.speak(currentSpeech);
}
function stopSpeaking() {
if (currentSpeech) {
speechSynthesis.cancel();
speakerIcon.classList.remove('speaking');
currentSpeech = null;
}
}
// Audio Control Toggle
audioBtn.addEventListener('click', () => {
audioEnabled = !audioEnabled;
if (audioEnabled) {
audioIcon.textContent = '🔊';
audioText.textContent = 'Audio On';
audioBtn.classList.remove('muted');
} else {
audioIcon.textContent = '🔇';
audioText.textContent = 'Audio Off';
audioBtn.classList.add('muted');
stopSpeaking();
}
});
// Language Toggle Functionality
const langToggle = document.getElementById('langToggle');
const engLabel = document.getElementById('engLabel');
const arLabel = document.getElementById('arLabel');
const englishContent = document.getElementById('englishContent');
const arabicContent = document.getElementById('arabicContent');
let isArabic = false;
langToggle.addEventListener('click', () => {
isArabic = !isArabic;
if (isArabic) {
// Switch to Arabic
langToggle.classList.add('arabic');
engLabel.classList.remove('active');
arLabel.classList.add('active');
// Fade out English content
englishContent.classList.add('fading');
setTimeout(() => {
englishContent.style.display = 'none';
arabicContent.style.display = 'block';
// Fade in Arabic content
setTimeout(() => {
arabicContent.classList.remove('fading');
}, 50);
}, 300);
} else {
// Switch to English
langToggle.classList.remove('arabic');
arLabel.classList.remove('active');
engLabel.classList.add('active');
// Fade out Arabic content
arabicContent.classList.add('fading');
setTimeout(() => {
arabicContent.style.display = 'none';
englishContent.style.display = 'block';
// Fade in English content
setTimeout(() => {
englishContent.classList.remove('fading');
}, 50);
}, 300);
}
});
// Calculate duration based on text length (average reading speed: ~150 words per minute)
function calculateDuration(text) {
const words = text.split(' ').length;
const readingTimeMs = (words / 150) * 60 * 1000; // Convert to milliseconds
const bufferTime = 2000; // Add 2 seconds buffer for animations
return Math.max(readingTimeMs + bufferTime, 4000); // Minimum 4 seconds
}
const tutorialSteps = [
{
title: "Step 1: Understanding Infill Density",
text: "The infill density controls how much material fills the inside of your print. Currently it's at 15%.",
speechText: "Step 1: Understanding Infill Density. The infill density controls how much material fills the inside of your print. Currently it's at 15%.",
action: () => {
densityRow.classList.add('animated-highlight');
positionPointer(densityInput);
}
},
{
title: "Step 2: Increasing Density",
text: "Let's increase it to 50% for much stronger results!",
speechText: "Step 2: Increasing Density. Let's increase it to 50% for much stronger results!",
action: () => {
densityInput.classList.add('changing');
setTimeout(() => {
densityInput.value = '50';
densityInput.classList.remove('changing');
}, 500);
}
},
{
title: "Step 3: Infill Pattern",
text: "The pattern determines the internal structure. Grid pattern provides strength in all directions.",
speechText: "Step 3: Infill Pattern. The pattern determines the internal structure. Grid pattern provides strength in all directions.",
action: () => {
densityRow.classList.remove('animated-highlight');
patternRow.classList.add('animated-highlight');
positionPointer(patternSpan);
}
},
{
title: "Step 4: Combining Both Settings",
text: "When you combine higher density with a strong pattern, you get maximum strength!",
speechText: "Step 4: Combining Both Settings. When you combine higher density with a strong pattern, you get maximum strength!",
action: () => {
explanationPanel.classList.add('strengthening');
setTimeout(() => {
strengthFill.style.width = '85%';
strengthFill.style.background = 'linear-gradient(90deg, #4CAF50, #8BC34A)';
strengthIndicator.textContent = 'Strength: High';
densityTitle.textContent = '50% DENSITY';
}, 500);
}
},
{
title: "Step 5: Final Result",
text: "Your 3D print is now much stronger and more durable! Perfect for functional parts.",
speechText: "Step 5: Final Result. Your 3D print is now much stronger and more durable! Perfect for functional parts.",
action: () => {
patternRow.classList.remove('animated-highlight');
pointerHand.style.opacity = '0';
}
}
];
function positionPointer(element) {
const rect = element.getBoundingClientRect();
pointerHand.style.left = (rect.left - 40) + 'px';
pointerHand.style.top = (rect.top + rect.height / 2 - 15) + 'px';
pointerHand.classList.remove('clicking');
void pointerHand.offsetWidth; // Trigger reflow
pointerHand.classList.add('clicking');
pointerHand.style.opacity = '1';
}
function resetAnimation() {
densityRow.classList.remove('animated-highlight');
patternRow.classList.remove('animated-highlight');
explanationPanel.classList.remove('strengthening');
densityInput.value = '15';
strengthFill.style.width = '40%';
strengthFill.style.background = 'linear-gradient(90deg, #ff9800, #ff5722)';
strengthIndicator.textContent = 'Strength: Moderate';
densityTitle.textContent = '15% DENSITY';
pointerHand.style.opacity = '0';
stopSpeaking();
}
async function playTutorial() {
if (isPlaying) {
// Stop the tutorial
clearTimeout(animationTimeout);
isPlaying = false;
tutorialBtn.classList.remove('playing');
btnText.textContent = 'Play Tutorial';
tutorialBtn.querySelector('span:first-child').textContent = '▶';
speechBubble.style.display = 'none';
resetAnimation();
return;
}
isPlaying = true;
tutorialBtn.classList.add('playing');
btnText.textContent = 'Stop Tutorial';
tutorialBtn.querySelector('span:first-child').textContent = '⏸';
speechBubble.style.display = 'flex';
resetAnimation();
const bubbleProgressFill = document.getElementById('bubbleProgress');
for (let i = 0; i < tutorialSteps.length; i++) {
if (!isPlaying) break;
const step = tutorialSteps[i];
bubbleTitle.textContent = step.title;
bubbleText.textContent = step.text;
// Calculate duration based on speech text length
const duration = calculateDuration(step.speechText);
// Reset progress bar
bubbleProgressFill.style.transition = 'none';
bubbleProgressFill.style.width = '0%';
// Force reflow to apply the reset
void bubbleProgressFill.offsetWidth;
// Start progress bar animation
bubbleProgressFill.style.transition = `width ${duration}ms linear`;
bubbleProgressFill.style.width = '100%';
// Execute the action
step.action();
// Speak the text
speak(step.speechText);
await new Promise(resolve => {
animationTimeout = setTimeout(resolve, duration);
});
}
if (isPlaying) {
// Tutorial completed
setTimeout(() => {
isPlaying = false;
tutorialBtn.classList.remove('playing');
btnText.textContent = 'Play Tutorial';
tutorialBtn.querySelector('span:first-child').textContent = '▶';
speechBubble.style.display = 'none';
}, 1000);
}
}
tutorialBtn.addEventListener('click', playTutorial);
// Clean up speech on page unload
window.addEventListener('beforeunload', () => {
stopSpeaking();
});
</script>
</body>
</html>
Live Preview