区别概括
Canvas
通过 js 在画布上绘制像素图形(位图),放大会失真。
图象的变动需要重新绘制,但因为不涉及dom操作,性能极高,适合开发游戏、图表等。SVG
可伸缩矢量图形 (Scalable Vector Graphics),矢量意味着图像放大不会损失图形质量,适合地图、简单特效等。
通过 XML 格式直接定义,每一部分都是一个实际的DOM元素,可以方便地绑定事件。且其中的文字独立于图像,文字可保留,可编辑和可搜索。
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="100" cy="50" r="40" stroke="black"
stroke-width="2" fill="red" />
</svg>
以下重点介绍Canvas
html部分
<canvas width=400 height=400 id='mycanvas'>
您的浏览器不支持canvas
</canvas>
script部分
自定义形状
每次stroke
其实都是将从上一次beginPath
到现在所有的路径进行绘制。
var canvas=document.getElementById('mycanvas');
var cxt=canvas.getContext('2d');
cxt.beginPath();//隔离.stroke()和.fill()对之上内容的影响
cxt.moveTo(0,0);//设置起点,无起点则由第一个lineTo代替
cxt.lineTo(100,100);
cxt.lineTo(200,100);
cxt.closePath();//自动闭合当前内容到起点(并不意味着路线结束,和beginPath其实无关)
cxt.strokeStyle='red';//设置描边颜色
cxt.lineWidth=10;//设置描边粗,仅对各种stroke有影响
cxt.stroke();//描边
cxt.fillStyle='blue';//设置填充颜色
cxt.fill();//填充
矩形
cxt.beginPath();
cxt.rect(100,100,150,50)//依次为左上角的x,y坐标,x轴边长,y轴边长
cxt.stroke();
更直接的还有
cxt.beginPath();
cxt.strokeRect(100,100,150,50)//依次为左上角的x,y坐标,x轴边长,y轴边长
或
cxt.beginPath();
cxt.fillRect(100,100,150,50);//依次为左上角的x,y坐标,x轴边长,y轴边长
此外有清除指定矩形范围
cxt.clearRect(100,100,150,50);//依次为左上角的x,y坐标,x轴边长,y轴边长
圆弧
cxt.beginPath();
cxt.arc(100,100,150,0,Math.PI/3,false);//依次为圆心的x,y坐标,半径,起止角度(0为三点钟方向,均需用弧度表示),顺逆时针(默认为false,顺时针)
cxt.stroke();
复杂路径填充
- 非0环绕原则:区域中任意方向作射线,若相交的顺逆方向路径数量相等则视为不在区域中,不填充
内容
文字方法
- strokeText(text, x, y) 描边写字
- 受到strokeStyle,以及lineWidth的影响
- fillText(text, x, y) 填充写字
- 受到fillStyle的影响,不受lineWidth影响
- 以上两者中,x,y为定位,受到textAlign和textBaseline影响
- measureText(text) 返回对象文本的宽度
- font 属性 设置 大小、字体 如
cxt.font="100px MicrosoftYaHei"
; - textAlign 属性 水平对齐方式 start(默认)/end/center/left/right
- textBaseline 属性 垂直对齐方式 alphabetic(默认)/top/bottom/middle/hanging/ideographic
绘制图片(插入图片)
插入图片
drawImage(img, x, y, width, height)
- img image的dom元素
- 利用var img=document.createElement('img')和img.src=''
- 且应在img.onload触发后执行
- x,y 插入到画布的坐标(默认0)
- width,height默认为图片自身宽高
插入裁剪后的图片
drawImage(img, sx,sy,swidth,sheight, x, y, width, height)
- 先在原图中根据 sx,sy,swidth,sheight裁剪出一部分,然后根据 x, y, width, height放入画布中
- sx/sy: 图片上开始裁剪的位置
- swidth/sheight : 裁剪图片的大小
阴影(少用,性能差)
- 阴影的大小粗细和原型相等,不能改变
- shadowColor 阴影颜色
- shadowBlur 阴影的模糊值
- shadowOffsetX 阴影的左偏移量
- shadowOffsetY 阴影的右偏移量
渐变
线性渐变
- var grd = cxt.createLinearGradien(x, y, x1, y1);
- x,y为起点,x1,y1为终点
- 一经设置,等同于隐藏在画布下,所有.fillStyle或.strokeStyle为grd的目标会采用该渐变
- grd.addColorStop(位置, color)
- 位置范围为0~1
- 可设置多个
径向渐变
- createRadiaGradient(x1, y1, r1, x2, y2, r2)//第一个圆和第二个圆
- addColorStop()
把背景图片作为填充(同渐变,生成的图片相对于画布固定)
- var bg=createPattern(imgDom, repeate)
- 第二个参数 repeate/ repeat-x / repeat-y / no-repeat
变换(每次变换会在上一次的基础上进行)
缩放
- sacle(x, y)
位移(重新布置原点)
- translate(x, y)
旋转(弧度,围绕当前原点)
- rotate(angle)
环境的保存和恢复(包括变换,透明,限定区等)
- save()
- restore()//释放内存,不再能restore()
设置透明
- globalAlpha = number 设置不透明度
- 全局设置是对整个画布(绘图环境) 进行设置
限定绘图区域(跟随之前的闭合路径)
- clip()
输出base64编码
- canvas.toDataURL(type, encoder)
- type为mime类型 image/jpeg image/gif image/png image/webp
- encoder为0~1表示图片质量,1为无损,仅能jpeg和webp
画布渲染画布
把一个画布以图片的形式用 drawImage() 插入到另一个画布
这是一种canvas的优化手段
设置线条
- lineCap 属性 设置线条两端的形状 butt/round/square
- lineJoin 属性 设置线条夹角 miter/bevel/round
- miterLimit 属性 设置夹角斜角的最大长度 一般默认 10
贝塞尔曲线
创建梁切线的弧
判断点是否在路径(填充区)中
- cxt.isPointInPath(x,y)
使用canvas制作图片并分享的案例
<canvas id="cvs" style="width:74%;position:absolute;height:104vw;top:17vw;left:13%;">
当前浏览器不支持canvas
<!-- 如果浏览器支持canvas,则canvas标签里的内容不会显示出来 -->
</canvas>
<script>
var wWidth = $(window).width()*2;//canvas属性宽高设置为css的两倍,这样在多倍屏下显示更清晰
var wHeight = $(window).height()*2;
//获取canvas元素
var cvs = document.getElementById("cvs");
cvs.width = wWidth*0.74;
cvs.height = wWidth*1.04;
var ctx = cvs.getContext('2d');
//创建image对象
var imgBG = new Image();
imgBG.src='images/public/poster.jpg';
imgBG.onload = function(){//背景图
ctx.drawImage(this, 0, 0,wWidth*0.74,wWidth*1.04);//this即是imgObj
var imgObj = new Image();//二维码
imgObj.src = $scope.qrcodeImageUrl;
imgObj.onload = function(){
ctx.drawImage(this, wWidth*0.07, wWidth*0.82,wWidth*0.15,wWidth*0.15);
}
var imgHead = new Image();//头像
imgHead.setAttribute('crossOrigin', 'anonymous');//解决跨域问题
imgHead.src=$scope.userInfo.headImageUrl;
imgHead.onload = function(){//使用clip进行圆形头像的裁剪
ctx.arc(wWidth*0.37, wWidth*0.175, 0.095*wWidth, 0, 2 * Math.PI);
ctx.clip();
ctx.drawImage(this, wWidth*0.275, wWidth*0.075,wWidth*0.19,wWidth*0.19);
ctx.restore();
}
ctx.font = "6.6vw 'PingFangSC-Regular', '微软雅黑', Helvetica, STheiti, 'Microsoft YaHei'";
ctx.fillStyle = '#333';
ctx.textBaseline = "top";
ctx.fillText('保险经纪人:', wWidth*0.23, wWidth*0.82);
ctx.fillText($scope.userInfo.mobile, wWidth*0.23, wWidth*0.91);
ctx.font = "7.6vw 'PingFangSC-Regular', '微软雅黑', Helvetica, STheiti, 'Microsoft YaHei'";
ctx.fillText($scope.userInfo.nickName, wWidth*0.23, wWidth*0.865);
}
$scope.canvasDrawImage = function(ID){//微信分享和本地保存
var canvasBase64 = cvs.toDataURL().replace('data:image/png;base64,', '');//传给原生时需要去掉图片类型字段
if (ID === '3') {
nativeBridge.invoke('saveImage', { shareType: ID, imgData: canvasBase64 });
} else {
nativeBridge.invoke('pandaAppImgShare', { shareType: ID, imgData: canvasBase64 });
}
}
<script>
canvas第三方库使用
- Konva 全能
- echarts 专用于画图表
- egret 白鹭时代 游戏引擎
- threeJS 3D