HTML帆布
这是到目前为止在这篇文章中提到的一个选项。用于Canvas绘图的命令与SVG非常相似(web-tiki在这个回答中使用的基本思想值得赞扬)。
所讨论的形状可以使用canvas自己的曲线命令(二次曲线或Bezier曲线)或路径API创建。答案包含了所有三种方法的示例。
浏览器对Canvas的支持非常好。
使用二次曲线
window.onload = function() {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.lineJoin = 'miter';
ctx.moveTo(120, 20);
ctx.quadraticCurveTo(117.5, 30, 148, 68);
ctx.arc(120, 88, 34.5, 5.75, 3.66, false);
ctx.quadraticCurveTo(117.5, 35, 120, 20);
ctx.closePath();
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.fillStyle = '#77CCEE'
ctx.stroke();
ctx.fill();
}
}
canvas {
margin: 50px;
height: 100px;
width: 200px;
transform: scale(1.5);
}
body{
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<canvas id='canvas'></canvas>
下面是带有渐变填充和阴影的高级版本。我还在形状上添加了悬停效果,以说明Canvas与SVG相比的一个缺点。画布是基于光栅(像素)的,因此当缩放超过某一点时看起来会模糊/像素化。唯一的解决方案是在每次浏览器调整大小时重新绘制形状,这是一种开销。
window.onload = function() {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
var lineargradient = ctx.createRadialGradient(135, 95, 1, 135, 95, 10);
lineargradient.addColorStop(0, 'white');
lineargradient.addColorStop(1, '#77CCEE');
ctx.beginPath();
ctx.lineJoin = 'miter';
ctx.moveTo(120, 20);
ctx.quadraticCurveTo(117.5, 30, 148, 68);
ctx.arc(120, 88, 34.5, 5.75, 3.66, false);
ctx.quadraticCurveTo(117.5, 35, 120, 20);
ctx.closePath();
ctx.strokeStyle = '#333';
ctx.lineWidth = 3;
ctx.fillStyle = lineargradient;
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.shadowBlur = 2;
ctx.shadowColor = "rgba(50, 50, 50, 0.5)";
ctx.stroke();
ctx.fill();
}
}
canvas {
margin: 50px;
height: 100px;
width: 200px;
transform: scale(1.5);
}
/* Just for demo */
body{
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
canvas{
transition: all 1s;
}
canvas:hover{
transform: scale(2);
}
<canvas id='canvas'></canvas>
使用贝塞尔曲线
window.onload = function() {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
var lineargradient = ctx.createRadialGradient(135, 95, 1, 135, 95, 10);
lineargradient.addColorStop(0, 'white');
lineargradient.addColorStop(1, '#77CCEE');
ctx.beginPath();
ctx.lineJoin = 'miter';
ctx.arc(120, 88, 35, 5.74, 3.66, false);
ctx.bezierCurveTo(100, 55, 122, 27.5, 120, 20);
ctx.bezierCurveTo(122, 27.5, 121, 31.5, 150, 70);
ctx.closePath();
ctx.strokeStyle = 'rgba(109,195,250,0.2)';
ctx.lineWidth = 1;
ctx.fillStyle = lineargradient;
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.shadowBlur = 2;
ctx.shadowColor = "rgba(50, 50, 50, 0.5)";
ctx.stroke();
ctx.fill();
}
}
canvas {
margin: 75px;
height: 300px;
width: 300px;
transform: scale(1.5);
}
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<canvas id='canvas' height='300' width='300'></canvas>
使用Path API
window.onload = function() {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.lineJoin = 'miter';
var p = new Path2D("M120 20 Q117.5 30 146 68 A34 34 0 1 1 92 68 Q117.5 35 120 20z");
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.fillStyle = '#77CCEE'
ctx.stroke(p);
ctx.fill(p);
}
}
canvas {
margin: 50px;
height: 100px;
width: 200px;
transform: scale(1.5);
}
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<canvas id='canvas'></canvas>
注意:正如我在回答中提到的,IE和Safari还不支持Path API。
进一步阅读:
考虑svg而非Canvas的7大理由
HTML5 Canvas vs. SVG:选择最佳工具
SVG和HTML5 Canvas之间的区别是什么?