3D-модель · MakerWorld

Parametric Photo Frame with Backplate & Stand

Сведения о модели

Площадка
MakerWorld
Цена
Бесплатно
Лицензия
уточняйте на площадке
Условия задаёт автор — проверьте их на странице модели, прежде чем печатать на продажу.
Форматы
3MFSCADSTL
  • 5 Лайки
  • 17 Загрузки
  • 3 Напечатали
  • 12 В подборках
  • 0 Бусты
  • 0 Комментарии
  • 0 Просмотры

Автор:wpl

Опубликована

Описание

A fully parametric, print-in-place photo frame system I built as a weekend project. It generates a complete frame with an integrated backplate, spring-loaded retention snaps, wall-mounting keyholes, and an optional detachable stand — all from a single OpenSCAD file.

This started because I wanted a clean, custom frame for a few non-standard sized prints I had lying around. Instead of buying generic frames, I decided to design something that would fit any photo perfectly and could be printed in no time. Now you can generate a frame tailored to your exact photo dimensions in seconds.

Key Features

- Integrated Mechanical Retention: When enabled, the backplate includes flexure-style spring snaps that lock into the frame automatically — no screws, no glue, no separate hardware. A built-in finger hole makes removing the backplate easy. - Wall Mounting Ready: Optional keyhole slots let you hang the frame directly on standard screw heads. Slots are automatically placed based on your frame size. - Detachable Stand: An optional kick-stand with a triangular geometry can be generated as a separate piece. It plugs into dedicated slots on the backplate, allowing the frame to sit on a desk or shelf without any adhesives. - Internal Hollowing: To save filament and print time, the frame can be hollowed out with an internal cavity and reinforcement ribs. The ribs are strategically placed to preserve structural integrity, especially around mounting and snap zones. - Elephant Foot Compensation: The backplate base includes an integrated 45° chamfer to counteract first-layer bulge, ensuring a flush fit inside the pocket even on printers with slight elephant foot. - Optional Glass/Plexiglass Layer: You can specify the thickness of an acrylic or glass sheet to sit over the photo. The script automatically adjusts the backplate thickness to compensate, keeping everything flush. 📐 How to Customize

All parameters are located at the top of the .scad file and grouped by category.

Primary Geometric Parameters (Base)

- photo_width / photo_height: The physical width and height of your photo in mm. This is the core dimension everything else is calculated from. - frame_border: The width of the decorative border surrounding the photo. This directly affects the overall frame footprint. - total_depth: The total Z-axis thickness of the entire frame assembly in mm. - front_lip: The depth of the front bezel overlap that holds the photo in place and prevents it from sliding out. Aesthetic Details

- outer_radius: The corner radius applied to the external corners of the frame. - inner_radius: The corner radius applied to the internal viewport (the window opening). Pocket & Tolerances (Backplate Fit)

- pocket_depth: How deep the internal cavity is. This is the total space available for the photo, glass, and backplate combined. - plexiglass_thick: Thickness of an optional acrylic or glass sheet. Set to 0 if you are only using a photo and the backplate. - photo_clearance: An extra expansion applied to the pocket dimensions to make sliding the photo in easy and forgiving. - backplate_clearance: A per-side gap subtracted from the backplate dimensions so it fits smoothly inside the pocket without forcing it. Functional Features & Mechanics

- enable_snaps: Toggle the integrated spring-loaded latches and the finger removal hole on the backplate. Requires sufficient backplate thickness to work correctly. - enable_keyholes: Toggle keyhole mounting slots on the rear of the frame for wall hanging. - enable_stand: Toggle generation of the separate kick-stand piece and its matching slots on the backplate. Print Optimization (Advanced)

- enable_hollowing: Removes internal material from the frame body and replaces it with structural ribs. Great for saving filament on larger frames. - wall_thickness: Defines the wall thickness used for hollowed sections and reinforcement ribs. - elephant_foot_comp: A 45° chamfer height applied to the backplate bottom layer to compensate for first-layer squishing. - stand_tolerance: A negative offset applied to the stand plug geometry to guarantee an easy press-fit assembly. - keyhole_offset: Controls how far the wall-mounting keyholes are positioned from the inner edge of the frame border. - $fn: Global resolution of circular arcs and cylinders. Higher values produce smoother curves but increase render time. ⚠️ Important Notes on Sizing

This is an amateur project — I built it for my own use and decided to share it. While it works great for the sizes I have tested, please be aware of the following:

- Very small photos may break or weaken certain integrated mechanisms. The snap latches, flexure slots, and finger hole are sized relative to the overall dimensions. At very small scales, these features can become too thin to print reliably or function correctly. - I have not tested this script for absolutely every possible dimension combination. Extreme aspect ratios, very thin borders relative to photo size, or unusually deep pockets may produce unexpected geometry. - The built-in assert() checks will catch some obvious conflicts (for example, if your glass thickness exceeds your pocket depth, or if your corner radius is larger than your border), but they cannot catch every edge case. - OpenSCAD returns one .stl file so to fit it all on your printer, you might need to use Bambu cutting tool. 🖨️ Print Settings

- Supports: None required. - Orientation: Use Bambu automatic settings. - Material: PLA works good. - Infill and walls: Dosnt really matter.

👨💻 A Note from the Creator

I'm an amateur designer, so this model and its OpenSCAD code are definitely not perfect. The logic works for my needs, but there is always room for improvement — cleaner math, better feature logic, additional options, or just general optimization.

All files and the full source code are available and shared with the most permissive license possible. Feel free to do absolutely anything with them: remix, fix, optimize, fork, commercialize, or rewrite from scratch if that makes you happy. If you create a better version, I would love to see it.

Boost Me 🚀 Like this model? Boost Me (for free) If you found this project useful, please give it a boost! It is much appreciated and helps other makers discover it.

🖥️ Code

// === PHOTO FRAME + BACKPLATE + STAND (PARAMETRIC DESIGN) === // Optimized for 3D printing with integrated mechanical features.

// ========================================== // 1. PRIMARY GEOMETRIC PARAMETERS (BASE) // ========================================== photo_width = 90;      // Physical width of the photo [mm] photo_height = 125;    // Physical height of the photo [mm]

frame_border = 25;     // Width of the frame border around the photo [mm] total_depth = 10;      // Total Z-axis thickness (depth) of the entire frame [mm] front_lip = 4;         // Front bezel overlap that keeps the photo from falling out [mm]

// ========================================== // 2. AESTHETIC DETAILS // ========================================== outer_radius = 3;      // Radius for the external corners of the frame [mm] inner_radius = 2;      // Radius for the internal viewport (window) corners [mm]

// ========================================== // 3. POCKET & TOLERANCES (BACKPLATE FIT) // ========================================== pocket_depth = 5;      // Depth of the internal pocket for photo/glass/backplate [mm] plexiglass_thick = 0;  // Thickness of an optional acrylic/glass sheet [mm] photo_clearance = 1;   // Global expansion of the pocket for easy photo insertion [mm] backplate_clearance = 0.5; // Per-side gap for the backplate to ensure a smooth fit [mm]

// ========================================== // 4. FUNCTIONAL FEATURES & MECHANICS // ========================================== enable_snaps = true;      // Integrated spring-loaded latches and finger removal hole enable_keyholes = true;   // "Keyhole" slots for wall mounting on screw heads enable_stand = true;      // Generates a detachable stand and mounting sockets

// ========================================== // 5. PRINT OPTIMIZATION (ADVANCED) // ========================================== enable_hollowing = true;  // Removes internal material to save filament and time wall_thickness = 2;       // Wall thickness for hollowed sections [mm] elephant_foot_comp = 1;   // 45° chamfer to counteract first-layer expansion [mm] stand_tolerance = 0.4;    // Negative offset for the stand plug to ensure assembly [mm] keyhole_offset = 3;       // Distance of mounting holes from the inner frame edge [mm]

// Rendering resolution (number of segments for circular shapes) $fn = 64;

// ========================================== // VALIDATION & CALCULATED LOGIC // ========================================== assert(total_depth > pocket_depth, "Error: Frame must be deeper than the pocket."); assert(plexiglass_thick < pocket_depth, "Error: Plexiglass exceeds pocket depth."); assert(outer_radius <= frame_border, "Error: Corner radius cannot exceed border width.");

// Computed dimensions for assembly logic A_outer_width = photo_width + 2 * frame_border; B_outer_height = photo_height + 2 * frame_border; view_width = photo_width - (2 * front_lip); view_height = photo_height - (2 * front_lip); insertion_width = photo_width + photo_clearance; insertion_height = photo_height + photo_clearance; backplate_width = insertion_width - (2 * backplate_clearance); backplate_height = insertion_height - (2 * backplate_clearance); backplate_thick = pocket_depth - plexiglass_thick; render_spacing = 10;

// Latch (snap) mechanics calculations snap_radius = min(1.5, backplate_thick / 2 - 0.1); snap_length = 15; snap_z_pos = (total_depth - pocket_depth) + plexiglass_thick + backplate_thick / 2; snap_y_pos = frame_border - (photo_clearance / 2) + backplate_clearance + backplate_height / 2; snap_x_left = frame_border - (photo_clearance / 2) + backplate_clearance; snap_x_right = frame_border - (photo_clearance / 2) + insertion_width - backplate_clearance;

// ========================================== // HELPER MODULES // ==========================================

// Standard rounded rectangle using offset logic (cleaner than Minkowski) module rounded_rect(w, h, r) { if (r > 0) { offset(r=r) offset(delta=-r) square([w, h]); } else { square([w, h]); } }

// Female socket for the spring-loaded snap mechanism module snap_socket() { socket_r = snap_radius + 0.3; // Added tolerance for smooth operation socket_l = snap_length + 2; hull() { translate([0, socket_l/2 - socket_r, 0]) sphere(r=socket_r); translate([0, -socket_l/2 + socket_r, 0]) sphere(r=socket_r); } }

// Wall-mounting keyhole (allows screw head entry and locking) module keyhole_slot() { translate([0, -8, -5.1]) cylinder(d=8, h=5.2); // Entrance translate([0, 0, -5.1]) cylinder(d=8, h=3.5);  // Head clearance translate([-4, -8, -5.1]) cube([8, 8, 3.5]);   // Slide clearance translate([0, 0, -5.1]) cylinder(d=4.5, h=5.2);// Shank channel translate([-2.25, -8, -5.1]) cube([4.5, 8, 5.2]); }

// Backplate base with elephant foot compensation (chamfer) module chamfered_backplate_base() { hull() { translate([0, 0, elephant_foot_comp]) cube([backplate_width, backplate_height, backplate_thick - elephant_foot_comp]); translate([elephant_foot_comp, elephant_foot_comp, 0]) cube([backplate_width - 2*elephant_foot_comp, backplate_height - 2*elephant_foot_comp, elephant_foot_comp]); } }

// Geometric stand with mounting plug module stand_geometry() { s_x = max(25, B_outer_height * 0.3); s_y = max(25, backplate_height * 0.25); plug_thick = backplate_thick - stand_tolerance; linear_extrude(11.4) { union() { translate([0, -1.8]) square([plug_thick, 3.6]); // The connector polygon([[0, 1.8], [-5, 1.8], [-s_x, -s_y + 8], [-s_x, -s_y], [-s_x + 15, -s_y], [0, -25]]); } } }

// Complete backplate with functional slots and flexure snaps module backplate() { difference() { union() { if(elephant_foot_comp > 0 && elephant_foot_comp < backplate_thick) { chamfered_backplate_base(); } else { cube([backplate_width, backplate_height, backplate_thick]); } if (enable_snaps && backplate_thick > 1.5) { translate([0, backplate_height/2, backplate_thick/2]) hull() { translate([0, snap_length/2 - snap_radius, 0]) sphere(r=snap_radius); translate([0, -snap_length/2 + snap_radius, 0]) sphere(r=snap_radius); } translate([backplate_width, backplate_height/2, backplate_thick/2]) hull() { translate([0, snap_length/2 - snap_radius, 0]) sphere(r=snap_radius); translate([0, -snap_length/2 + snap_radius, 0]) sphere(r=snap_radius); } } } // Flexure slots for snap tension if (enable_snaps && backplate_thick > 1.5) { slot_l = min(35, backplate_height - 10); translate([2, backplate_height/2 - slot_l/2, -1]) cube([2, slot_l, backplate_thick + 2]); translate([backplate_width - 4, backplate_height/2 - slot_l/2, -1]) cube([2, slot_l, backplate_thick + 2]); } // Finger hole for removal if (enable_snaps) { translate([backplate_width/2, max(12, backplate_height * 0.15), -1]) cylinder(d=min(15, backplate_width/3), h=backplate_thick+2); } // Stand mounting slots if (enable_stand) { translate([backplate_width/2 - 6, backplate_height * 0.35 - 2, -1]) cube([12, 4, backplate_thick + 2]); translate([backplate_width * 0.25 - 2, backplate_height/2 - 6, -1]) cube([4, 12, backplate_thick + 2]); } } }

// ========================================== // 6. FINAL RENDER (FRAME FABRICATION) // ========================================== difference() { // 1. External Frame Shape linear_extrude(total_depth) rounded_rect(A_outer_width, B_outer_height, outer_radius); // 2. Viewport Cutout (Window) translate([frame_border + front_lip, frame_border + front_lip, -0.1]) linear_extrude(total_depth + 0.2) rounded_rect(view_width, view_height, inner_radius); // 3. Internal Pocket (For Photo & Plate) translate([frame_border - (photo_clearance / 2), frame_border - (photo_clearance / 2), total_depth - pocket_depth]) cube([insertion_width, insertion_height, pocket_depth + 0.1]); // 4. Latch Sockets if (enable_snaps && backplate_thick > 1.5) { translate([snap_x_left, snap_y_pos, snap_z_pos]) snap_socket(); translate([snap_x_right, snap_y_pos, snap_z_pos]) snap_socket(); } // 5. Wall Mounting Slots if (enable_keyholes && (total_depth >= 7) && (frame_border >= 15)) { translate([A_outer_width/2, B_outer_height - frame_border/2 + keyhole_offset, total_depth]) keyhole_slot(); translate([frame_border/2 - keyhole_offset, B_outer_height / 3, total_depth]) rotate([0,0,90]) keyhole_slot(); translate([frame_border/2 - keyhole_offset, B_outer_height * 2 / 3, total_depth]) rotate([0,0,90]) keyhole_slot(); } // 6. Hollowing (Material Savings & Structural Ribs) if (enable_hollowing) { translate([0, 0, wall_thickness]) linear_extrude(total_depth - wall_thickness + 0.1) difference() { translate([wall_thickness, wall_thickness]) rounded_rect(A_outer_width - 2*wall_thickness, B_outer_height - 2*wall_thickness, max(0, outer_radius - wall_thickness)); translate([frame_border - (photo_clearance / 2) - wall_thickness, frame_border - (photo_clearance / 2) - wall_thickness]) square([insertion_width + 2*wall_thickness, insertion_height + 2*wall_thickness]); // Reinforcement ribs translate([A_outer_width/2 - wall_thickness/2, 0]) square([wall_thickness, B_outer_height]); translate([0, B_outer_height/2 - wall_thickness/2]) square([A_outer_width, wall_thickness]); if (enable_keyholes) { translate([A_outer_width/2 - 12, B_outer_height - frame_border - 1]) square([24, frame_border + 2]); translate([-1, B_outer_height / 3 - 12]) square([frame_border + 2, 24]); translate([-1, B_outer_height * 2 / 3 - 12]) square([frame_border + 2, 24]); } } } }

// Generate separate components for printing layout translate([frame_border - (photo_clearance / 2) + backplate_clearance, B_outer_height + render_spacing, 0]) backplate(); if (enable_stand) { translate([A_outer_width + max(40, B_outer_height * 0.3) + render_spacing, B_outer_height / 2 + 25, 0]) stand_geometry(); }

Руководства и профили печати

Профили печати и шаги

0.28mm layer, 2 walls, 3% infill

Теги

Ещё по теме

Похожие модели

Названия используются только для указания источника результата. Polyzon не аффилирован с перечисленными площадками.