class ClothesSelector extends HTMLElement { constructor() { super(); this.selectionPoints = []; this.selectionMode = false; this.segmentationActive = false; this.selfieSegmentation = null; this.attachShadow({ mode: 'open' }); } connectedCallback() { this.render(); this.setupEventListeners(); } render() { this.shadowRoot.innerHTML = `
Clothing Preview
`; } async setupSegmentation() { this.selfieSegmentation = new SelfieSegmentation({ locateFile: (file) => { return `https://cdn.jsdelivr.net/npm/@mediapipe/selfie_segmentation/${file}`; } }); this.selfieSegmentation.setOptions({ modelSelection: 1, selfieMode: false }); await this.selfieSegmentation.initialize(); } async processSegmentation() { if (!this.selfieSegmentation || !this.shadowRoot.getElementById('previewImage').complete) return; const img = this.shadowRoot.getElementById('previewImage'); const canvas = this.shadowRoot.getElementById('selectionCanvas'); const ctx = canvas.getContext('2d'); try { const result = await this.selfieSegmentation.send({image: img}); const mask = result.segmentationMask; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(mask, 0, 0, canvas.width, canvas.height); ctx.globalCompositeOperation = 'source-in'; ctx.fillStyle = 'rgba(59, 130, 246, 0.5)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.globalCompositeOperation = 'source-over'; } catch (error) { console.error('Segmentation error:', error); } } setupEventListeners() { const img = this.shadowRoot.getElementById('previewImage'); const canvas = this.shadowRoot.getElementById('selectionCanvas'); const ctx = canvas.getContext('2d'); const selectBtn = this.shadowRoot.getElementById('selectBtn'); const clearBtn = this.shadowRoot.getElementById('clearBtn'); const downloadBtn = this.shadowRoot.getElementById('downloadBtn'); selectBtn.addEventListener('click', async () => { if (!this.selfieSegmentation) { await this.setupSegmentation(); } this.selectionMode = true; this.segmentationActive = true; this.selectionPoints = []; ctx.clearRect(0, 0, canvas.width, canvas.height); img.style.cursor = 'crosshair'; if (img.complete) { await this.processSegmentation(); } }); clearBtn.addEventListener('click', () => { this.selectionPoints = []; ctx.clearRect(0, 0, canvas.width, canvas.height); img.style.cursor = 'default'; this.selectionMode = false; this.segmentationActive = false; }); downloadBtn.addEventListener('click', () => { if (this.selectionPoints.length > 0) { const tempCanvas = document.createElement('canvas'); const tempCtx = tempCanvas.getContext('2d'); tempCanvas.width = img.naturalWidth; tempCanvas.height = img.naturalHeight; tempCtx.drawImage(img, 0, 0); tempCtx.globalCompositeOperation = 'destination-in'; tempCtx.fillStyle = 'black'; tempCtx.beginPath(); tempCtx.moveTo(this.selectionPoints[0].x, this.selectionPoints[0].y); for (let i = 1; i < this.selectionPoints.length; i++) { tempCtx.lineTo(this.selectionPoints[i].x, this.selectionPoints[i].y); } tempCtx.closePath(); tempCtx.fill(); const link = document.createElement('a'); link.download = 'selected-clothing.png'; link.href = tempCanvas.toDataURL('image/png'); link.click(); } }); img.addEventListener('click', (e) => { if (!this.selectionMode) return; const rect = img.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; this.selectionPoints.push({x, y}); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.strokeStyle = '#3B82F6'; ctx.lineWidth = 2; ctx.fillStyle = 'rgba(59, 130, 246, 0.2)'; if (this.selectionPoints.length > 0) { ctx.beginPath(); ctx.moveTo(this.selectionPoints[0].x, this.selectionPoints[0].y); for (let i = 1; i < this.selectionPoints.length; i++) { ctx.lineTo(this.selectionPoints[i].x, this.selectionPoints[i].y); } if (this.selectionPoints.length > 2) { ctx.closePath(); ctx.fill(); } ctx.stroke(); } }); img.addEventListener('load', async () => { canvas.width = img.naturalWidth; canvas.height = img.naturalHeight; if (this.segmentationActive) { await this.processSegmentation(); } }); } setImage(src) { const img = this.shadowRoot.getElementById('previewImage'); img.src = src; } } customElements.define('clothes-selector', ClothesSelector);