70 lines
2.2 KiB
JavaScript
70 lines
2.2 KiB
JavaScript
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();
|
|
}
|