const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const drawElement = document.getElementById('draw-element'); const statusPanel = document.getElementById('support-status'); const demoForm = document.getElementById('demo-form'); const hasHtmlInCanvas = typeof ctx.drawElementImage === 'function' && typeof canvas.requestPaint === 'function'; function setStatus(state, message) { statusPanel.dataset.state = state; statusPanel.textContent = message; } function resizeCanvas(entry) { const dpcSize = entry.devicePixelContentBoxSize?.[0]; const nextWidth = dpcSize?.inlineSize ?? Math.round(entry.contentRect.width * window.devicePixelRatio); const nextHeight = dpcSize?.blockSize ?? Math.round(entry.contentRect.height * window.devicePixelRatio); if (canvas.width !== nextWidth) { canvas.width = nextWidth; } if (canvas.height !== nextHeight) { canvas.height = nextHeight; } } function paint() { ctx.reset(); ctx.fillStyle = '#101820'; ctx.fillRect(0, 0, canvas.width, canvas.height); const x = canvas.width / 25; const y = canvas.height / 25; const transform = ctx.drawElementImage(drawElement, x, y); drawElement.style.transform = transform.toString(); } demoForm.addEventListener('submit', (event) => { event.preventDefault(); setStatus('ok', '表单提交事件来自真实 DOM:发射指令已拦截,demo 仍停留在当前页面。'); }); if (!hasHtmlInCanvas) { document.body.dataset.api = 'fallback'; setStatus( 'fail', '当前浏览器未暴露 drawElementImage/requestPaint。请使用 Chrome Canary 149+ 并开启 canvas-draw-element flag。' ); } else { document.body.dataset.api = 'native'; setStatus('ok', '已检测到 HTML-in-Canvas 实验 API,可以操作 canvas 中绘制的 DOM 表单。'); canvas.onpaint = paint; const supportsDevicePixelContentBox = typeof ResizeObserverEntry !== 'undefined' && 'devicePixelContentBoxSize' in ResizeObserverEntry.prototype; const resizeOptions = supportsDevicePixelContentBox ? { box: 'device-pixel-content-box' } : {}; const observer = new ResizeObserver(([entry]) => { resizeCanvas(entry); canvas.requestPaint(); }); observer.observe(canvas, resizeOptions); canvas.requestPaint(); }