{"id":8905,"date":"2026-08-19T06:23:19","date_gmt":"2026-08-19T06:23:19","guid":{"rendered":"https:\/\/aiper.com\/blogs\/?page_id=8905"},"modified":"2026-10-21T09:13:05","modified_gmt":"2026-10-21T09:13:05","slug":"pflanzenabstand-visualisierer","status":"publish","type":"page","link":"https:\/\/aiper.com\/blogs\/de\/pflanzenabstand-visualisierer\/","title":{"rendered":"Pflanzenabstand-Visualisierer \u2013 Gartengestaltung vor dem Pflanzen planen"},"content":{"rendered":"\n<style>\n\/* ==========================================================================\n   Plant & Tree Spacing Visualizer \u2014 Brand: #1ecad3 + #9486f7 blended\n   Pure DOM\/CSS visualization (no Canvas). WAF-compatible: no inline styles.\n   ========================================================================== *\/\n#plant-visualizer {\n    max-width: 750px;\n    margin: 20px auto;\n    padding: 0 16px;\n    font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n    box-sizing: border-box;\n}\n#plant-visualizer *, #plant-visualizer *::before, #plant-visualizer *::after { box-sizing: border-box; }\n\n\/* \u2500\u2500 Title \u2500\u2500 *\/\n.pv-title { text-align: center; font-size: 1.4rem; font-weight: 700; color: #1a202c; margin-bottom: 4px; }\n.pv-subtitle { text-align: center; font-size: 14px; color: #64748b; margin-bottom: 20px; }\n\n\/* \u2500\u2500 Unit Toggle \u2500\u2500 *\/\n.pv-unit-toggle { display: flex; justify-content: center; gap: 0; margin-bottom: 20px; }\n.pv-unit-btn {\n    padding: 10px 24px; font-size: 13px; font-weight: 600;\n    background: #f5f7fa; color: #64748b; border: 1px solid #e2e8f0;\n    cursor: pointer; transition: all 0.2s ease;\n}\n.pv-unit-btn:first-child { border-radius: 8px 0 0 8px; }\n.pv-unit-btn:last-child { border-radius: 0 8px 8px 0; }\n.pv-unit-btn:hover { background: #e8f7f8; color: #1ecad3; }\n.pv-unit-btn.active {\n    background: linear-gradient(135deg, #1ecad3, #9486f7);\n    color: #fff; border-color: transparent;\n}\n.pv-unit-btn:focus, .pv-unit-btn:active { outline: none; }\n\n\/* \u2500\u2500 Controls Grid \u2500\u2500 *\/\n.pv-controls {\n    display: grid; grid-template-columns: 1fr 1fr; gap: 14px;\n    margin-bottom: 16px;\n}\n.pv-field { display: flex; flex-direction: column; }\n.pv-field label {\n    font-size: 13px; font-weight: 600; color: #2c3e50; margin-bottom: 4px;\n}\n.pv-field input {\n    padding: 10px 12px; border: 1px solid #e2e8f0; border-radius: 8px;\n    font-size: 14px; color: #2c3e50; transition: border-color 0.2s ease;\n    background: #fff;\n}\n.pv-field input:focus { border-color: #9486f7; outline: none; box-shadow: 0 0 0 3px rgba(148,134,247,0.1); }\n.pv-unit-suffix { font-size: 11px; color: #94a3b8; margin-left: 2px; }\n\n\/* \u2500\u2500 Presets \u2500\u2500 *\/\n.pv-preset-label { font-size: 13px; font-weight: 600; color: #2c3e50; margin-bottom: 8px; }\n.pv-preset-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }\n.pv-preset-btn {\n    padding: 8px 14px; font-size: 12px; font-weight: 600;\n    border: 1px solid #e2e8f0; border-radius: 20px;\n    background: #fff; color: #475569; cursor: pointer;\n    transition: all 0.2s ease;\n}\n.pv-preset-btn:hover { border-color: #b2dfdb; background: #f8fdfc; }\n.pv-preset-btn:focus, .pv-preset-btn:active { color: #2c3e50; outline: none; }\n.pv-preset-btn.selected {\n    border-color: #9486f7; background: #f5f3ff; color: #2c3e50;\n    box-shadow: 0 0 0 2px rgba(148,134,247,0.12);\n}\n\n\/* \u2500\u2500 Pattern Selector \u2500\u2500 *\/\n.pv-pattern-label { font-size: 13px; font-weight: 600; color: #2c3e50; margin-bottom: 8px; }\n.pv-pattern-buttons { display: flex; gap: 10px; margin-bottom: 16px; }\n.pv-pattern-btn {\n    flex: 1; padding: 12px 16px; font-size: 13px; font-weight: 600;\n    border: 2px solid #e2e8f0; border-radius: 10px;\n    background: #fff; color: #475569; cursor: pointer;\n    transition: all 0.2s ease; text-align: center;\n}\n.pv-pattern-btn:hover { border-color: #b2dfdb; }\n.pv-pattern-btn:focus, .pv-pattern-btn:active { color: #2c3e50; outline: none; }\n.pv-pattern-btn.selected {\n    border-color: #9486f7; background: #f5f3ff; color: #2c3e50;\n}\n\n\/* \u2500\u2500 Bed Visualization Area \u2500\u2500 *\/\n.pv-canvas-wrapper {\n    text-align: center; margin-bottom: 16px;\n    background: #fafafa; border-radius: 12px; padding: 20px 16px 40px;\n    border: 1px solid #e2e8f0;\n}\n#pv-bed-frame {\n    position: relative; display: inline-block;\n    max-width: 100%;\n}\n#pv-dim-label {\n    text-align: center; font-size: 11px; color: #2c3e50; font-weight: 600;\n    margin-bottom: 6px;\n}\n#pv-bed-area {\n    position: relative; background: #f5ebe0;\n    border: 2px solid #8B7355; border-radius: 2px;\n    margin: 0 auto;\n}\n.pv-grid-line-h, .pv-grid-line-v {\n    position: absolute; pointer-events: none;\n}\n.pv-grid-line-h { left: 0; right: 0; border-top: 1px dashed #d5c4a1; }\n.pv-grid-line-v { top: 0; bottom: 0; border-left: 1px dashed #d5c4a1; }\n.pv-plant {\n    position: absolute; border-radius: 50%; transform: translate(-50%, -50%);\n}\n.pv-plant-canopy {\n    background: rgba(143, 188, 143, 0.45);\n    border: 1px solid #5b8c5a;\n}\n.pv-plant-stem {\n    background: #5b8c5a; z-index: 1;\n}\n#pv-scale-bar {\n    display: flex; align-items: center; justify-content: center;\n    margin-top: 10px; gap: 6px;\n}\n#pv-scale-line {\n    height: 1.5px; background: #2c3e50;\n}\n#pv-scale-label {\n    font-size: 11px; color: #2c3e50; white-space: nowrap;\n}\n\n\/* \u2500\u2500 Results \u2500\u2500 *\/\n.pv-results {\n    display: flex; flex-wrap: wrap; justify-content: center; gap: 12px 24px;\n    padding: 14px 20px; background: #f5f7fa; border-radius: 10px;\n    margin-bottom: 20px;\n}\n.pv-result-item { text-align: center; }\n.pv-result-value { font-size: 1.3rem; font-weight: 700; color: #1ecad3; }\n.pv-result-label { font-size: 11px; color: #64748b; text-transform: uppercase; letter-spacing: 0.5px; }\n\n\/* \u2500\u2500 Tool Links (cross-refs) \u2500\u2500 *\/\n.pv-tool-links { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-bottom: 20px; }\n.pv-tool-link {\n    display: inline-block; padding: 8px 16px;\n    background: #f5f7fa; color: #6b5ce7; border: 1px solid #e8e3fc;\n    border-radius: 22px; font-size: 12px; font-weight: 600;\n    text-decoration: none; transition: all 0.2s ease;\n}\n.pv-tool-link:hover { background: #ede9fe; color: #5a4bd1; border-color: #9486f7; }\n.pv-tool-link:focus, .pv-tool-link:active { color: #5a4bd1; outline: none; }\n\n\/* \u2500\u2500 CTA \u2500\u2500 *\/\n.pv-cta {\n    padding: 16px 20px; background: #f0fcfc; border-radius: 12px;\n    border: 1px solid #b2dfdb; text-align: center; margin-bottom: 20px;\n}\n.pv-cta p { margin: 0 0 8px; font-size: 13px; color: #475569; line-height: 1.5; }\n.pv-cta a {\n    display: inline-block; padding: 10px 24px;\n    background: linear-gradient(135deg, #1ecad3, #9486f7);\n    color: #fff; border-radius: 8px; text-decoration: none;\n    font-weight: 700; font-size: 14px;\n    transition: all 0.2s ease;\n}\n.pv-cta a:hover { transform: translateY(-1px); box-shadow: 0 4px 16px rgba(148,134,247,0.35); }\n\n\/* \u2500\u2500 Validation \u2500\u2500 *\/\n.pv-error { color: #e53e3e; font-size: 11px; margin-top: 2px; min-height: 16px; }\n\n\/* \u2500\u2500 JS Status \/ Error Banner \u2500\u2500 *\/\n#pv-js-status {\n    text-align: center; padding: 8px 12px; margin-bottom: 12px;\n    background: #fffbe6; border: 1px solid #f6e05e; border-radius: 8px;\n    font-size: 12px; font-weight: 600; color: #975a16;\n}\n#pv-error-msg {\n    display: none; padding: 12px 16px; background: #fff5f5;\n    border: 1px solid #feb2b2; border-radius: 8px;\n    color: #c53030; font-size: 13px; margin-bottom: 16px;\n}\n\n\/* \u2500\u2500 Responsive \u2500\u2500 *\/\n@media (max-width: 600px) {\n    .pv-controls { grid-template-columns: 1fr; }\n    .pv-preset-buttons { justify-content: center; }\n    .pv-preset-btn { flex: 1; min-width: 80px; text-align: center; }\n    .pv-results { flex-direction: column; gap: 8px; }\n    .pv-canvas-wrapper { padding: 12px 8px 32px; }\n    #plant-visualizer { padding: 0 8px; }\n}\n<\/style>\n\n<div id=\"plant-visualizer\">\n    <div id=\"pv-js-status\">LOADING&#8230; JS not yet executed<\/div>\n\n    <div class=\"pv-title\" id=\"pv-title\">Plant &amp; Tree Spacing Visualizer<\/div>\n    <div class=\"pv-subtitle\" id=\"pv-subtitle\">See how your plants will look before you dig<\/div>\n\n    <div id=\"pv-error-msg\"><\/div>\n\n    <!-- Unit Toggle -->\n    <div class=\"pv-unit-toggle\" role=\"radiogroup\" aria-label=\"Unit System\">\n        <button type=\"button\" class=\"pv-unit-btn active\" data-unit=\"imperial\" id=\"pv-unit-imp\">ft \/ in<\/button>\n        <button type=\"button\" class=\"pv-unit-btn\" data-unit=\"metric\" id=\"pv-unit-met\">m \/ cm<\/button>\n    <\/div>\n\n    <!-- Bed Dimensions -->\n    <div class=\"pv-controls\">\n        <div class=\"pv-field\">\n            <label for=\"pv-bed-width\" id=\"pv-label-width\">Bed Width (<span class=\"pv-unit-suffix\" id=\"pv-unit-w\">ft<\/span>)<\/label>\n            <input type=\"number\" id=\"pv-bed-width\" step=\"any\" min=\"0.1\" value=\"8\" placeholder=\"e.g. 8\" inputmode=\"decimal\">\n            <div class=\"pv-error\" id=\"pv-err-width\"><\/div>\n        <\/div>\n        <div class=\"pv-field\">\n            <label for=\"pv-bed-length\" id=\"pv-label-length\">Bed Length (<span class=\"pv-unit-suffix\" id=\"pv-unit-l\">ft<\/span>)<\/label>\n            <input type=\"number\" id=\"pv-bed-length\" step=\"any\" min=\"0.1\" value=\"12\" placeholder=\"e.g. 12\" inputmode=\"decimal\">\n            <div class=\"pv-error\" id=\"pv-err-length\"><\/div>\n        <\/div>\n    <\/div>\n\n    <!-- Plant Type Presets -->\n    <div class=\"pv-preset-label\" id=\"pv-preset-label\">Quick Presets<\/div>\n    <div class=\"pv-preset-buttons\" id=\"pv-presets\"><\/div>\n\n    <!-- Spacing + Canopy -->\n    <div class=\"pv-controls\">\n        <div class=\"pv-field\">\n            <label for=\"pv-spacing\" id=\"pv-label-spacing\">Plant Spacing (<span class=\"pv-unit-suffix\" id=\"pv-unit-s\">in<\/span>)<\/label>\n            <input type=\"number\" id=\"pv-spacing\" step=\"any\" min=\"0.1\" value=\"18\" placeholder=\"e.g. 18\" inputmode=\"decimal\">\n            <div class=\"pv-error\" id=\"pv-err-spacing\"><\/div>\n        <\/div>\n        <div class=\"pv-field\">\n            <label for=\"pv-canopy\" id=\"pv-label-canopy\">Canopy at Maturity (<span class=\"pv-unit-suffix\" id=\"pv-unit-c\">in<\/span>)<\/label>\n            <input type=\"number\" id=\"pv-canopy\" step=\"any\" min=\"0.1\" value=\"14\" placeholder=\"e.g. 14\" inputmode=\"decimal\">\n            <div class=\"pv-error\" id=\"pv-err-canopy\"><\/div>\n        <\/div>\n    <\/div>\n\n    <!-- Layout Pattern -->\n    <div class=\"pv-pattern-label\" id=\"pv-pattern-label\">Layout Pattern<\/div>\n    <div class=\"pv-pattern-buttons\" role=\"radiogroup\" aria-label=\"Layout Pattern\">\n        <button type=\"button\" class=\"pv-pattern-btn selected\" data-pattern=\"square\" id=\"pv-pat-square\">Square Grid<\/button>\n        <button type=\"button\" class=\"pv-pattern-btn\" data-pattern=\"staggered\" id=\"pv-pat-staggered\">Staggered \/ Triangular<\/button>\n    <\/div>\n\n    <!-- Bed Visualization (DOM-based, no Canvas) -->\n    <div class=\"pv-canvas-wrapper\">\n        <div id=\"pv-dim-label\"><\/div>\n        <div id=\"pv-bed-frame\">\n            <div id=\"pv-bed-area\"><\/div>\n        <\/div>\n        <div id=\"pv-scale-bar\">\n            <span id=\"pv-scale-left\"><\/span>\n            <span id=\"pv-scale-line\"><\/span>\n            <span id=\"pv-scale-right\"><\/span>\n            <span id=\"pv-scale-label\"><\/span>\n        <\/div>\n    <\/div>\n\n    <!-- Results -->\n    <div class=\"pv-results\" id=\"pv-results\">\n        <div class=\"pv-result-item\">\n            <div class=\"pv-result-value\" id=\"pv-val-total\">0<\/div>\n            <div class=\"pv-result-label\" id=\"pv-lbl-total\">Total Plants<\/div>\n        <\/div>\n        <div class=\"pv-result-item\">\n            <div class=\"pv-result-value\" id=\"pv-val-rows\">0<\/div>\n            <div class=\"pv-result-label\" id=\"pv-lbl-rows\">Rows<\/div>\n        <\/div>\n        <div class=\"pv-result-item\">\n            <div class=\"pv-result-value\" id=\"pv-val-cols\">0<\/div>\n            <div class=\"pv-result-label\" id=\"pv-lbl-cols\">Columns<\/div>\n        <\/div>\n        <div class=\"pv-result-item\">\n            <div class=\"pv-result-value\" id=\"pv-val-area\">0<\/div>\n            <div class=\"pv-result-label\" id=\"pv-lbl-area\">Bed Area<\/div>\n        <\/div>\n    <\/div>\n\n    <!-- CTA -->\n    <div class=\"pv-cta\" id=\"pv-cta\">\n        <p id=\"pv-cta-text\"><\/p>\n        <a href=\"https:\/\/aiper.com\/blogs\/plant-spacing-calculator\/\" id=\"pv-cta-link\">Calculate plant quantity<\/a>\n    <\/div>\n\n    <!-- Cross-reference tool links -->\n    <div class=\"pv-tool-links\" id=\"pv-tools\"><\/div>\n<\/div>\n\n<script>\n(function() {\n    \/\/ \u2500\u2500 Labels \u2500\u2500\n    var LABELS = {\"title\": \"Pflanzenabstand-Visualisierer\", \"subtitle\": \"Sehen Sie, wie Ihre Pflanzen aussehen werden, bevor Sie graben\", \"unitImperial\": \"ft \/ in\", \"unitMetric\": \"m \/ cm\", \"bedLabelWidth\": \"Beetbreite\", \"bedLabelLength\": \"Beetl\u00e4nge\", \"bedLabelWidthM\": \"Beetbreite (m)\", \"bedLabelLengthM\": \"Beetl\u00e4nge (m)\", \"unitFt\": \"ft\", \"unitIn\": \"in\", \"unitM\": \"m\", \"unitCm\": \"cm\", \"unitSqft\": \"ft\u00b2\", \"unitSqm\": \"m\u00b2\", \"presetLabel\": \"Schnellvorlagen\", \"presetKeys\": [\"vegetables\", \"root_veg\", \"leafy\", \"hedge\", \"shrubs\", \"trees_small\", \"custom\"], \"presets\": {\"vegetables\": {\"label\": \"Gem\u00fcse (Tomaten, Paprika)\", \"spacing_in\": 24, \"canopy_in\": 18}, \"root_veg\": {\"label\": \"Wurzelgem\u00fcse (Karotten, Zwiebeln)\", \"spacing_in\": 4, \"canopy_in\": 3}, \"leafy\": {\"label\": \"Blattgem\u00fcse (Salat, Gr\u00fcnkohl)\", \"spacing_in\": 12, \"canopy_in\": 10}, \"hedge\": {\"label\": \"Hecken \/ Randpflanzen\", \"spacing_in\": 16, \"canopy_in\": 14}, \"shrubs\": {\"label\": \"Str\u00e4ucher \/ B\u00fcsche\", \"spacing_in\": 36, \"canopy_in\": 30}, \"trees_small\": {\"label\": \"Kleine B\u00e4ume (1,8-2,4 m)\", \"spacing_in\": 84, \"canopy_in\": 72}, \"custom\": {\"label\": \"Benutzerdefiniert\", \"spacing_in\": 0, \"canopy_in\": 0}}, \"spacingLabel\": \"Pflanzabstand\", \"canopyLabel\": \"Kronendurchmesser\", \"patternLabel\": \"Pflanzmuster\", \"patternSquare\": \"Quadratisches Raster\", \"patternStaggered\": \"Versetzt \/ Dreieck\", \"resultTotalPlants\": \"Pflanzen gesamt\", \"resultRows\": \"Reihen\", \"resultCols\": \"Spalten\", \"resultArea\": \"Beetfl\u00e4che\", \"toolLinks\": {\"plantCalc\": {\"href\": \"https:\/\/aiper.com\/blogs\/de\/pflanzenabstand-rechner\/\", \"label\": \"pflanzenabstand rechner\"}, \"soilCalc\": {\"href\": \"https:\/\/aiper.com\/blogs\/de\/gartenerde-rechner\/\", \"label\": \"gartenerde rechner\"}, \"mulchCalc\": {\"href\": \"https:\/\/aiper.com\/blogs\/de\/mulch-rechner\/\", \"label\": \"mulch rechner\"}, \"grassSeed\": {\"href\": \"https:\/\/aiper.com\/blogs\/de\/grassamen-rechner\/\", \"label\": \"grassamen rechner\"}}, \"validationError\": \"Bitte eine positive Zahl eingeben\", \"canopyWarning\": \"Kronendurchmesser > Abstand: Pflanzen k\u00f6nnten sich \u00fcberlappen\", \"canvasPlaceholder\": \"Beetabmessungen und Abstand eingeben, um das Layout zu sehen\", \"ctaText\": \"Bereit zum Kauf? Nutzen Sie unseren <strong>Pflanzenabstand-Rechner<\/strong>, um die genaue Anzahl an Pflanzen, Samen oder Zwiebeln zu ermitteln \u2014 mit Puffer.\", \"ctaLink\": \"Pflanzenanzahl berechnen\"};\n\n    \/\/ \u2500\u2500 Helpers \u2500\u2500\n    var $ = function(id) { return document.getElementById(id); };\n    function L(path) {\n        var keys = path.split('.'), v = LABELS;\n        for (var i = 0; i < keys.length; i++) { v = v[keys[i]]; if (v === undefined) return ''; }\n        return v;\n    }\n    function setText(id, txt) { var e = $(id); if (e) e.textContent = txt; }\n    function _and() { var n = arguments.length; while (n--) { if (!arguments[n]) return false; } return true; }\n\n    \/\/ \u2500\u2500 State \u2500\u2500\n    var state = { unit: 'imperial', bedW: 8, bedL: 12, spacing: 18, canopy: 14, pattern: 'square' };\n\n    \/\/ \u2500\u2500 DOM refs \u2500\u2500\n    var bedAreaEl = $('pv-bed-area');\n    var bedFrameEl = $('pv-bed-frame');\n    var dimLabel = $('pv-dim-label');\n    var scaleBar = $('pv-scale-bar');\n    var scaleLine = $('pv-scale-line');\n    var scaleLabel = $('pv-scale-label');\n    var scaleLeft = $('pv-scale-left');\n    var scaleRight = $('pv-scale-right');\n\n    \/\/ \u2500\u2500 Set initial UI text \u2500\u2500\n    setText('pv-title', L('title'));\n    setText('pv-subtitle', L('subtitle'));\n    setText('pv-unit-imp', L('unitImperial'));\n    setText('pv-unit-met', L('unitMetric'));\n    setText('pv-preset-label', L('presetLabel'));\n    setText('pv-pattern-label', L('patternLabel'));\n    setText('pv-pat-square', L('patternSquare'));\n    setText('pv-pat-staggered', L('patternStaggered'));\n    setText('pv-lbl-total', L('resultTotalPlants'));\n    setText('pv-lbl-rows', L('resultRows'));\n    setText('pv-lbl-cols', L('resultCols'));\n    setText('pv-lbl-area', L('resultArea'));\n    var ctaTextEl = $('pv-cta-text');\n    if (ctaTextEl) ctaTextEl.innerHTML = L('ctaText');\n    setText('pv-cta-link', L('ctaLink'));\n\n    \/\/ \u2500\u2500 Build preset buttons \u2500\u2500\n    var presetDiv = $('pv-presets');\n    var pkeys = L('presetKeys');\n    if (_and(presetDiv, pkeys, pkeys.length)) {\n        presetDiv.innerHTML = '';\n        for (var i = 0; i < pkeys.length; i++) {\n            var key = pkeys[i];\n            var p = L('presets.' + key);\n            if (!p || !p.label) continue;\n            var btn = document.createElement('button');\n            btn.type = 'button';\n            btn.className = 'pv-preset-btn';\n            btn.setAttribute('data-preset', key);\n            btn.textContent = p.label;\n            btn.addEventListener('click', (function(k) { return function() { applyPreset(k); }; })(key));\n            presetDiv.appendChild(btn);\n        }\n    }\n\n    \/\/ \u2500\u2500 Build tool links \u2500\u2500\n    var toolsDiv = $('pv-tools');\n    if (toolsDiv) {\n        toolsDiv.innerHTML = '';\n        var tlKeys = Object.keys(LABELS.toolLinks || {});\n        for (var j = 0; j < tlKeys.length; j++) {\n            var tl = L('toolLinks.' + tlKeys[j]);\n            if (!tl || !tl.href) continue;\n            var a = document.createElement('a');\n            a.className = 'pv-tool-link';\n            a.href = tl.href;\n            a.textContent = tl.label;\n            toolsDiv.appendChild(a);\n        }\n    }\n\n    \/\/ \u2500\u2500 Unit labels \u2500\u2500\n    function updateUnitLabels() {\n        var isImp = state.unit === 'imperial';\n        var unitLen = isImp ? L('unitFt') : L('unitM');\n        var unitSmall = isImp ? L('unitIn') : L('unitCm');\n        var labelW = $('pv-label-width');\n        if (labelW) labelW.innerHTML = L('bedLabelWidth') + ' (<span class=\"pv-unit-suffix\" id=\"pv-unit-w\">' + unitLen + '<\/span>)';\n        var labelL = $('pv-label-length');\n        if (labelL) labelL.innerHTML = L('bedLabelLength') + ' (<span class=\"pv-unit-suffix\" id=\"pv-unit-l\">' + unitLen + '<\/span>)';\n        var spLabel = $('pv-label-spacing');\n        if (spLabel) spLabel.innerHTML = L('spacingLabel') + ' (<span class=\"pv-unit-suffix\" id=\"pv-unit-s\">' + unitSmall + '<\/span>)';\n        var cnLabel = $('pv-label-canopy');\n        if (cnLabel) cnLabel.innerHTML = L('canopyLabel') + ' (<span class=\"pv-unit-suffix\" id=\"pv-unit-c\">' + unitSmall + '<\/span>)';\n        var bwEl = $('pv-bed-width'); if (bwEl) bwEl.placeholder = isImp ? 'e.g. 8' : 'e.g. 2.5';\n        var blEl = $('pv-bed-length'); if (blEl) blEl.placeholder = isImp ? 'e.g. 12' : 'e.g. 3.5';\n        var spEl = $('pv-spacing'); if (spEl) spEl.placeholder = isImp ? 'e.g. 18' : 'e.g. 45';\n        var cnEl = $('pv-canopy'); if (cnEl) cnEl.placeholder = isImp ? 'e.g. 14' : 'e.g. 35';\n    }\n    updateUnitLabels();\n\n    \/\/ \u2500\u2500 Apply Preset \u2500\u2500\n    function applyPreset(key) {\n        var btns = document.querySelectorAll('.pv-preset-btn');\n        btns.forEach(function(b) { b.classList.remove('selected'); });\n        var active = document.querySelector('.pv-preset-btn[data-preset=\"' + key + '\"]');\n        if (active) active.classList.add('selected');\n        if (key === 'custom') return;\n        var p = L('presets.' + key);\n        if (!p) return;\n        if (state.unit === 'imperial') { state.spacing = p.spacing_in; state.canopy = p.canopy_in; }\n        else { state.spacing = Math.round(p.spacing_in * 2.54 * 10) \/ 10; state.canopy = Math.round(p.canopy_in * 2.54 * 10) \/ 10; }\n        var spEl = $('pv-spacing'); if (spEl) spEl.value = state.spacing;\n        var cnEl = $('pv-canopy'); if (cnEl) cnEl.value = state.canopy;\n        draw();\n    }\n\n    \/\/ \u2500\u2500 Unit Toggle \u2500\u2500\n    function setUnit(unit) {\n        if (state.unit === unit) return;\n        var wasImp = state.unit === 'imperial', nowImp = unit === 'imperial';\n        state.unit = unit;\n        var impBtn = $('pv-unit-imp'), metBtn = $('pv-unit-met');\n        if (impBtn) { impBtn.classList.remove('active'); if (nowImp) impBtn.classList.add('active'); }\n        if (metBtn) { metBtn.classList.remove('active'); if (!nowImp) metBtn.classList.add('active'); }\n        if (_and(wasImp, !nowImp)) {\n            state.bedW = Math.round(state.bedW * 0.3048 * 100) \/ 100;\n            state.bedL = Math.round(state.bedL * 0.3048 * 100) \/ 100;\n            state.spacing = Math.round(state.spacing * 2.54 * 10) \/ 10;\n            state.canopy = Math.round(state.canopy * 2.54 * 10) \/ 10;\n        } else if (_and(!wasImp, nowImp)) {\n            state.bedW = Math.round(state.bedW \/ 0.3048 * 100) \/ 100;\n            state.bedL = Math.round(state.bedL \/ 0.3048 * 100) \/ 100;\n            state.spacing = Math.round(state.spacing \/ 2.54 * 10) \/ 10;\n            state.canopy = Math.round(state.canopy \/ 2.54 * 10) \/ 10;\n        }\n        var bwEl = $('pv-bed-width'); if (bwEl) bwEl.value = state.bedW;\n        var blEl = $('pv-bed-length'); if (blEl) blEl.value = state.bedL;\n        var spEl = $('pv-spacing'); if (spEl) spEl.value = state.spacing;\n        var cnEl = $('pv-canopy'); if (cnEl) cnEl.value = state.canopy;\n        updateUnitLabels();\n        draw();\n    }\n\n    \/\/ \u2500\u2500 Event Listeners \u2500\u2500\n    $('pv-unit-imp').addEventListener('click', function() { setUnit('imperial'); });\n    $('pv-unit-met').addEventListener('click', function() { setUnit('metric'); });\n    $('pv-pat-square').addEventListener('click', function() {\n        state.pattern = 'square';\n        $('pv-pat-square').classList.add('selected');\n        $('pv-pat-staggered').classList.remove('selected');\n        draw();\n    });\n    $('pv-pat-staggered').addEventListener('click', function() {\n        state.pattern = 'staggered';\n        $('pv-pat-staggered').classList.add('selected');\n        $('pv-pat-square').classList.remove('selected');\n        draw();\n    });\n\n    function readInputs() {\n        var bwEl = $('pv-bed-width'), blEl = $('pv-bed-length');\n        var spEl = $('pv-spacing'), cnEl = $('pv-canopy');\n        if (!bwEl || !blEl || !spEl || !cnEl) return;\n        var bw = parseFloat(bwEl.value), bl = parseFloat(blEl.value);\n        var sp = parseFloat(spEl.value), cn = parseFloat(cnEl.value);\n        var valid = true;\n        var errW = $('pv-err-width'), errL = $('pv-err-length');\n        var errS = $('pv-err-spacing'), errC = $('pv-err-canopy');\n        if (isNaN(bw) || bw <= 0) { if (errW) errW.textContent = L('validationError'); valid = false; }\n        else { if (errW) errW.textContent = ''; state.bedW = bw; }\n        if (isNaN(bl) || bl <= 0) { if (errL) errL.textContent = L('validationError'); valid = false; }\n        else { if (errL) errL.textContent = ''; state.bedL = bl; }\n        if (isNaN(sp) || sp <= 0) { if (errS) errS.textContent = L('validationError'); valid = false; }\n        else { if (errS) errS.textContent = ''; state.spacing = sp; }\n        if (isNaN(cn) || cn <= 0) { if (errC) errC.textContent = L('validationError'); valid = false; }\n        else if (cn > sp) { if (errC) errC.textContent = L('canopyWarning'); state.canopy = cn; }\n        else { if (errC) errC.textContent = ''; state.canopy = cn; }\n        var btns = document.querySelectorAll('.pv-preset-btn');\n        btns.forEach(function(b) { b.classList.remove('selected'); });\n        if (valid) draw();\n    }\n\n    function debounce(fn, delay) { var t; return function() { clearTimeout(t); t = setTimeout(fn, delay); }; }\n    ['pv-bed-width','pv-bed-length','pv-spacing','pv-canopy'].forEach(function(id) {\n        var el = $(id); if (el) el.addEventListener('input', debounce(readInputs, 200));\n    });\n\n    \/\/ \u2500\u2500 DOM-based Drawing (no Canvas) \u2500\u2500\n    var MAX_PX = 550;  \/\/ max bed display width in px\n\n    function draw() {\n        if (!bedAreaEl || !bedFrameEl) return;\n\n        \/\/ Normalize to bed units (ft or m)\n        var unitFactor = state.unit === 'imperial' ? 12 : 100;\n        var spacingBU = state.spacing \/ unitFactor;\n        var canopyBU = state.canopy \/ unitFactor;\n\n        \/\/ Compute positions first (for results + draw)\n        var rows, cols, positions = [];\n        if (_and(state.bedW > 0, state.bedL > 0, spacingBU > 0)) {\n            if (state.pattern === 'square') {\n                cols = Math.floor(state.bedW \/ spacingBU);\n                rows = Math.floor(state.bedL \/ spacingBU);\n                if (_and(cols > 0, rows > 0)) {\n                    var edgeX = (state.bedW - (cols - 1) * spacingBU) \/ 2;\n                    var edgeY = (state.bedL - (rows - 1) * spacingBU) \/ 2;\n                    for (var r = 0; r < rows; r++) {\n                        for (var c = 0; c < cols; c++) {\n                            positions.push({ x: edgeX + c * spacingBU, y: edgeY + r * spacingBU });\n                        }\n                    }\n                }\n            } else {\n                var rowSpacing = spacingBU * Math.sqrt(3) \/ 2;\n                cols = Math.floor(state.bedW \/ spacingBU);\n                rows = Math.floor((state.bedL - spacingBU) \/ rowSpacing) + 1;\n                if (_and(cols > 0, rows > 0)) {\n                    var edgeX = (state.bedW - (cols - 1) * spacingBU) \/ 2;\n                    var edgeY = (state.bedL - (rows - 1) * rowSpacing) \/ 2;\n                    for (var r = 0; r < rows; r++) {\n                        var offset = (r % 2 === 1) ? spacingBU \/ 2 : 0;\n                        var colsInRow = (_and(r % 2 === 1, (edgeX + (cols - 1) * spacingBU + offset + spacingBU \/ 2) > state.bedW)) ? cols - 1 : cols;\n                        for (var c = 0; c < colsInRow; c++) {\n                            positions.push({ x: edgeX + c * spacingBU + offset, y: edgeY + r * rowSpacing });\n                        }\n                    }\n                }\n            }\n        }\n        if (cols < 1) cols = 0;\n        if (rows < 1) rows = 0;\n\n        \/\/ \u2500\u2500 Render bed area as DOM \u2500\u2500\n        var aspect = _and(state.bedW > 0, state.bedL > 0) ? state.bedW \/ state.bedL : 1.33;\n        var pxW, pxH;\n        if (aspect >= 1) { pxW = MAX_PX; pxH = Math.round(MAX_PX \/ aspect); }\n        else { pxH = MAX_PX; pxW = Math.round(MAX_PX * aspect); }\n\n        bedFrameEl.style.width = pxW + 'px';\n        bedAreaEl.style.width = pxW + 'px';\n        bedAreaEl.style.height = pxH + 'px';\n\n        \/\/ Scale factor: px per bed unit\n        var scale = pxW \/ state.bedW;\n\n        \/\/ Clear previous plants and grid lines\n        bedAreaEl.innerHTML = '';\n\n        \/\/ Draw grid lines\n        if (spacingBU > 0) {\n            var x = spacingBU;\n            while (x < state.bedW) {\n                var gx = Math.round(x * scale);\n                var line = document.createElement('div');\n                line.className = 'pv-grid-line-v';\n                line.style.left = gx + 'px';\n                bedAreaEl.appendChild(line);\n                x += spacingBU;\n            }\n            var y = spacingBU;\n            while (y < state.bedL) {\n                var gy = Math.round(y * scale);\n                var line = document.createElement('div');\n                line.className = 'pv-grid-line-h';\n                line.style.top = gy + 'px';\n                bedAreaEl.appendChild(line);\n                y += spacingBU;\n            }\n        }\n\n        \/\/ Draw plants\n        for (var i = 0; i < positions.length; i++) {\n            var px = Math.round(positions[i].x * scale);\n            var py = Math.round(positions[i].y * scale);\n            var canopyPx = Math.max(Math.round(canopyBU * scale), 3);\n\n            \/\/ Canopy circle\n            var canopy = document.createElement('div');\n            canopy.className = 'pv-plant pv-plant-canopy';\n            canopy.style.left = px + 'px';\n            canopy.style.top = py + 'px';\n            canopy.style.width = canopyPx + 'px';\n            canopy.style.height = canopyPx + 'px';\n            bedAreaEl.appendChild(canopy);\n\n            \/\/ Stem dot\n            var stemPx = Math.max(Math.round(canopyPx * 0.25), 2);\n            var stem = document.createElement('div');\n            stem.className = 'pv-plant pv-plant-stem';\n            stem.style.left = px + 'px';\n            stem.style.top = py + 'px';\n            stem.style.width = stemPx + 'px';\n            stem.style.height = stemPx + 'px';\n            bedAreaEl.appendChild(stem);\n        }\n\n        \/\/ Dimension label\n        var dimUnit = state.unit === 'imperial' ? L('unitFt') : L('unitM');\n        dimLabel.textContent = state.bedW + ' ' + dimUnit + ' x ' + state.bedL + ' ' + dimUnit;\n\n        \/\/ Scale bar\n        var scaleBarLen = Math.min(100, pxW * 0.35);\n        var scaleVal, scaleUnitLbl;\n        if (state.unit === 'imperial') {\n            var ftPer100 = 100 \/ scale;\n            if (ftPer100 < 1) { scaleVal = 1; scaleUnitLbl = L('unitFt'); scaleBarLen = Math.round(1 * scale); }\n            else if (ftPer100 < 5) { scaleVal = Math.round(ftPer100); scaleUnitLbl = L('unitFt'); scaleBarLen = Math.round(scaleVal * scale); }\n            else { scaleVal = Math.round(ftPer100 \/ 5) * 5; scaleUnitLbl = L('unitFt'); scaleBarLen = Math.round(scaleVal * scale); }\n        } else {\n            var mPer100 = 100 \/ scale;\n            if (mPer100 < 0.3) { scaleVal = Math.round(mPer100 * 100 \/ 10) * 10; scaleUnitLbl = L('unitCm'); scaleBarLen = Math.round(scaleVal \/ 100 * scale); }\n            else { scaleVal = Math.round(mPer100 * 10) \/ 10; scaleUnitLbl = L('unitM'); scaleBarLen = Math.round(scaleVal * scale); }\n        }\n        scaleLine.style.width = Math.max(scaleBarLen, 20) + 'px';\n        scaleLabel.textContent = scaleVal + ' ' + scaleUnitLbl;\n\n        \/\/ Results\n        updateResults(positions.length, rows, cols, state.bedW * state.bedL);\n    }\n\n    function updateResults(total, rows, cols, area) {\n        var vt = $('pv-val-total'); if (vt) vt.textContent = total;\n        var vr = $('pv-val-rows'); if (vr) vr.textContent = rows;\n        var vc = $('pv-val-cols'); if (vc) vc.textContent = cols;\n        var va = $('pv-val-area');\n        if (va) { var isImp = state.unit === 'imperial'; va.textContent = Math.round(area * 100) \/ 100 + ' ' + (isImp ? L('unitSqft') : L('unitSqm')); }\n    }\n\n    \/\/ \u2500\u2500 Initial draw \u2500\u2500\n    draw();\n\n    \/\/ Hide loading banner\n    var statusEl = $('pv-js-status');\n    if (statusEl) { statusEl.textContent = ''; statusEl.style.display = 'none'; }\n})();\n<\/script>\n<h2 class=\"wp-block-heading\">So funktioniert dieser Visualisierer<\/h2>\n\n<p class=\"wp-block-paragraph\">Dieses interaktive Tool zeichnet eine ma\u00dfstabsgetreue Draufsicht auf Ihr Gartenbeet und zeigt genau, wie Ihre Pflanzen, Str\u00e4ucher oder B\u00e4ume angeordnet sein werden. Passen Sie die Abmessungen, den Abstand und das Pflanzmuster an, um das Ergebnis in Echtzeit zu sehen \u2014 kein Ratespiel, kein Millimeterpapier n\u00f6tig.<\/p>\n\n<h3 class=\"wp-block-heading\">Schritt 1: Beetabmessungen festlegen<\/h3>\n\n<p class=\"wp-block-paragraph\">Geben Sie die Breite und L\u00e4nge Ihres Gartenbeets in Fu\u00df oder Metern ein. Die Zeichenfl\u00e4che skaliert automatisch, um sich den Proportionen Ihres Beets anzupassen \u2014 sowohl ein langes schmales Beet als auch ein quadratisches Beet werden korrekt dargestellt.<\/p>\n\n<h3 class=\"wp-block-heading\">Schritt 2: Pflanzenart und Abstand w\u00e4hlen<\/h3>\n\n<p class=\"wp-block-paragraph\">Nutzen Sie die <strong>Schnellvorlagen<\/strong>, um typische Abst\u00e4nde und Kronendurchmesser f\u00fcr g\u00e4ngige Pflanzenarten automatisch auszuf\u00fcllen \u2014 Gem\u00fcse wie Tomaten und Karotten, Str\u00e4ucher und kleine B\u00e4ume. Oder geben Sie benutzerdefinierte Werte manuell ein. Der Kronendurchmesser bestimmt, wie gro\u00df die Pflanzenkreise im Diagramm erscheinen.<\/p>\n\n<h3 class=\"wp-block-heading\">Schritt 3: Pflanzmuster ausw\u00e4hlen<\/h3>\n\n<p class=\"wp-block-paragraph\"><strong>Quadratisches Raster<\/strong> ordnet Pflanzen in geraden Reihen und Spalten an \u2014 ideal f\u00fcr Reihenkulturen und formale G\u00e4rten. <strong>Versetzt (Dreieck)<\/strong> versetzt jede zweite Reihe um die H\u00e4lfte des Abstands und erm\u00f6glicht so bis zu 15 % mehr Pflanzen auf derselben Fl\u00e4che. Dieses Muster wird von kommerziellen Anbauern verwendet.<\/p>\n\n<h3 class=\"wp-block-heading\">Schritt 4: Visualisieren und Anpassen<\/h3>\n\n<p class=\"wp-block-paragraph\">Die Zeichenfl\u00e4che aktualisiert sich sofort, wenn Sie einen Parameter \u00e4ndern. \u00c4ndern Sie den Abstand oder wechseln Sie das Muster, um zu sehen, wie sich die Pflanzenanzahl ver\u00e4ndert. Das Ergebnisfeld zeigt Gesamtzahl, Reihen, Spalten und Beetfl\u00e4che auf einen Blick.<\/p>\n\n<p class=\"wp-block-paragraph\">Wenn Sie mit dem Layout zufrieden sind, besuchen Sie unseren <a href=\"https:\/\/aiper.com\/blogs\/de\/pflanzenabstand-rechner\/\">Pflanzenabstand-Rechner<\/a>, um die genaue Anzahl an Pflanzen, Samen oder Zwiebeln zu ermitteln \u2014 inklusive Reserve f\u00fcr Verluste.<\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>LOADING&#8230; JS not yet executed Plant &amp; Tree Spacing Visualizer See how your plants will look before you dig ft \/ in m \/ cm Bed Width (ft) Bed Length (ft) Quick Presets Plant Spacing (in) Canopy at Maturity (in) Layout Pattern Square Grid Staggered \/ Triangular 0 Total Plants 0 Rows 0 Columns 0 [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"aiper_reading_time":2,"aiper_last_reviewed":"","aiper_reviewer":0,"aiper_related_ids":[],"aiper_layout":"","footnotes":""},"class_list":["post-8905","page","type-page","status-publish","hentry"],"lang":"de","translations":{"de":8905,"en":8904,"fr":8906,"es":8907},"_links":{"self":[{"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/pages\/8905","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/comments?post=8905"}],"version-history":[{"count":4,"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/pages\/8905\/revisions"}],"predecessor-version":[{"id":11853,"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/pages\/8905\/revisions\/11853"}],"wp:attachment":[{"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/media?parent=8905"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}