Canvas作为HTML5的核心特性,在现代浏览器中得到了广泛支持。但了解兼容性细节,能帮助你更好地处理边界情况。
| 浏览器 | 最低支持版本 | 发布时间 |
|---|---|---|
| Chrome | 4.0 | 2010年 |
| Firefox | 2.0 | 2006年 |
| Safari | 3.1 | 2008年 |
| Opera | 9.0 | 2006年 |
| Edge | 12.0 | 2015年 |
| IE | 9.0 | 2011年 |
简单来说,几乎所有现代浏览器都支持Canvas。
IE8及以下版本不支持Canvas,需要使用兼容库:
<!--[if lt IE 9]>
<script src="excanvas.js"></script>
<![endif]-->
<canvas id="myCanvas" width="400" height="300">
您的浏览器不支持Canvas,请升级浏览器。
</canvas>
excanvas.js使用VML模拟Canvas功能,但有以下限制:
<canvas id="myCanvas" width="400" height="300">
<!-- 不支持Canvas时显示的替代内容 -->
<img src="fallback-image.png" alt="图表">
</canvas>
Canvas标签内的内容只在不支持Canvas时显示。
function isCanvasSupported() {
return !!document.createElement('canvas').getContext
}
if (isCanvasSupported()) {
initCanvas()
} else {
showFallback()
}
function isCanvas2DSupported() {
const canvas = document.createElement('canvas')
return !!(canvas.getContext && canvas.getContext('2d'))
}
function checkCanvasFeatures() {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
return {
canvas: !!ctx,
text: typeof ctx.fillText === 'function',
imageData: typeof ctx.getImageData === 'function',
toDataURL: typeof canvas.toDataURL === 'function'
}
}
移动端浏览器对Canvas支持良好,但需要注意:
移动端没有鼠标事件,需要处理触摸事件:
// 桌面端
canvas.addEventListener('mousedown', handleStart)
canvas.addEventListener('mousemove', handleMove)
canvas.addEventListener('mouseup', handleEnd)
// 移动端
canvas.addEventListener('touchstart', handleStart)
canvas.addEventListener('touchmove', handleMove)
canvas.addEventListener('touchend', handleEnd)
高清屏(Retina)上Canvas会模糊,需要适配:
function setupCanvas(canvas, width, height) {
const dpr = window.devicePixelRatio || 1
canvas.width = width * dpr
canvas.height = height * dpr
canvas.style.width = width + 'px'
canvas.style.height = height + 'px'
const ctx = canvas.getContext('2d')
ctx.scale(dpr, dpr)
return ctx
}
移动设备性能有限,需要注意:
// 减少绑制区域
const visibleArea = getVisibleBounds()
ctx.clearRect(visibleArea.x, visibleArea.y, visibleArea.width, visibleArea.height)
// 降低帧率
let lastTime = 0
const fps = 30
const interval = 1000 / fps
function animate(currentTime) {
requestAnimationFrame(animate)
if (currentTime - lastTime < interval) return
lastTime = currentTime
render()
}
Canvas还支持WebGL上下文(3D绑制):
function isWebGLSupported() {
const canvas = document.createElement('canvas')
return !!(
canvas.getContext('webgl') ||
canvas.getContext('experimental-webgl')
)
}
WebGL的支持情况:
| 浏览器 | WebGL支持 |
|---|---|
| Chrome | 9+ |
| Firefox | 4+ |
| Safari | 5.1+ |
| Edge | 12+ |
| IE | 11+ |
const CanvasSupport = {
canvas: false,
text: false,
imageData: false,
webgl: false,
init() {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
this.canvas = !!ctx
if (!this.canvas) return
this.text = typeof ctx.fillText === 'function'
this.imageData = typeof ctx.getImageData === 'function'
this.webgl = !!(
canvas.getContext('webgl') ||
canvas.getContext('experimental-webgl')
)
}
}
CanvasSupport.init()
// 使用
if (!CanvasSupport.canvas) {
alert('您的浏览器不支持Canvas')
}
跨域图片会导致toDataURL报错:
const img = new Image()
img.crossOrigin = 'Anonymous' // 设置跨域
img.src = 'https://example.com/image.png'
img.onload = function() {
ctx.drawImage(img, 0, 0)
const dataURL = canvas.toDataURL() // 现在可以正常工作
}
自定义字体需要等待加载完成:
document.fonts.ready.then(() => {
ctx.font = '20px CustomFont'
ctx.fillText('Hello', 100, 100)
})
某些浏览器对Canvas尺寸有限制:
const MAX_SIZE = 8192 // 安全的最大尺寸
function createCanvas(width, height) {
width = Math.min(width, MAX_SIZE)
height = Math.min(height, MAX_SIZE)
const canvas = document.createElement('canvas')
canvas.width = width
canvas.height = height
return canvas
}