多Canvas矩形绘制对齐及输入加载、jsoclor插件适配问题求助
Hey there! Let's break down and fix your two main issues step by step, plus tweak your existing draw function to actually render multiple rectangles correctly.
1. Fixing the "Add Input" Button to Load New Fields
First, let's assume your existing input controls are wrapped in a reusable template (like a <div class="input-group"> containing width, height, and color inputs). Here's how to make the green button clone and add new input groups dynamically:
// Wait for the DOM to fully load before attaching events document.addEventListener('DOMContentLoaded', function() { const addBtn = document.getElementById('add-input-btn'); // Replace with your button's actual ID const inputContainer = document.getElementById('input-container'); // Replace with your input container's ID const inputTemplate = document.querySelector('.input-group'); // Your existing input group template addBtn.addEventListener('click', function() { // Clone the template (deep clone to copy all child inputs) const newInputGroup = inputTemplate.cloneNode(true); // Clear any pre-filled values in the cloned inputs newInputGroup.querySelectorAll('input').forEach(input => input.value = ''); // Add the new group to the page inputContainer.appendChild(newInputGroup); // Initialize jsColor on the new color input (we'll handle this next) initJsColorOnNewField(newInputGroup); }); });
Pro Tip: Make sure your HTML has a dedicated container for input groups and your button uses the correct ID. Adjust the selectors to match your actual markup if needed.
2. Initializing jsColor on Dynamically Added Fields
jsColor only auto-initializes elements that exist when the page loads. For new inputs added later, you need to manually trigger the plugin:
function initJsColorOnNewField(inputGroup) { // Find the color input in the new group (adjust selector to match your setup) const colorInput = inputGroup.querySelector('.jscolor'); // Initialize jsColor on this input new jscolor(colorInput); // If you use custom jsColor options, pass them here: // new jscolor(colorInput, {controlBorderColor: '#333', backgroundColor: '#fff'}); }
If your color inputs use a data-jscolor attribute instead of the jscolor class, just update the selector to inputGroup.querySelector('[data-jscolor]').
3. Fixing Your Existing Draw Function (Critical Bug!)
Looking at your current code, there's a major issue in the forEach loop: your arr is an array of single values ([x, y, boja]), but you're trying to access p.w and p.h which don't exist. Plus, you're only reading values from one input group. Let's rewrite this to support multiple rectangles and basic grid alignment:
var canvas = document.getElementById('canvasgrid'); canvas.width = 855; canvas.height = 500; var context = canvas.getContext('2d'); function draw(){ // Clear the canvas first to avoid overlapping old rectangles context.clearRect(0, 0, canvas.width, canvas.height); // Collect values from ALL input groups const inputGroups = document.querySelectorAll('.input-group'); const rectangles = []; inputGroups.forEach(group => { // Get values (add fallbacks for empty inputs) const width = parseInt(group.querySelector('[name="width"]').value) || 50; const height = parseInt(group.querySelector('[name="height"]').value) || 50; const color = group.querySelector('.jscolor').value || '#ff0000'; rectangles.push({w: width, h: height, color: color}); }); // Draw rectangles with basic grid wrapping (left-to-right, new row when hitting canvas edge) let currentX = 10; // Left padding let currentY = 10; // Top padding let rowMaxHeight = 0; rectangles.forEach(rect => { // Check if we need to start a new row if (currentX + rect.w > canvas.width - 10) { currentX = 10; currentY += rowMaxHeight + 10; // Add spacing between rows rowMaxHeight = 0; } // Draw the rectangle context.fillStyle = rect.color; context.fillRect(currentX, currentY, rect.w, rect.h); // Add a border for clarity context.strokeStyle = '#000'; context.strokeRect(currentX, currentY, rect.w, rect.h); // Add size label context.fillStyle = "white"; context.font="bold 10px sans-serif"; context.textAlign="center"; context.textBaseline = "middle"; context.fillText(`${rect.w}x${rect.h}`, currentX + rect.w/2, currentY + rect.h/2); // Update position and row height currentX += rect.w + 10; // Add spacing between rectangles rowMaxHeight = Math.max(rowMaxHeight, rect.h); }); }
Bonus: For true "minimal area alignment", you'd need a bin-packing algorithm to optimize the grid layout. Let me know if you want help implementing that!
内容的提问来源于stack exchange,提问作者djomlatan

