作为一个假全栈开发者,遇到一个需求要在页面上显示地图,然后根据房间点击跳转,原生HTML有两种解决方法:SVG和Canvas,这两种都是在前端画图,但原理和实现完全不一样。
SVG和Canvas的区别
SVG和Canvas最大的区别是SVG是矢量图而Canvas是非矢量图,Canvas是HTML5内自带的标签,而SVG则其实并非必须基于HTML,它类似JPG、GIF,是一种定义的格式,甚至可以采用Adobe AI来画SVG。
在页面绘制方面,Canvas逻辑上是一块画布,我们在画布上通过js画我们想要的图案,因此若要做到动态效果,Canvas必须进行重绘,也就是Canvas是通过代码把每一帧写出来的方式做到的动画效果,而这样的开发也更多的依赖于前端工程师,因此Canvas更多的会用在复杂的场景上,如3D等。
而SVG则是仅采用HTML标签绘制,它也可以类似JPG一样采用image标签导入显示,SVG的动画效果采用标签animate实现,支持触发各种listener的事件,个人理解为通过HTML标签读取并执行相应js。SVG作为矢量图更多的用于一些动画渲染,比如loading图标,因为矢量且轻量,可以减少传输的数据量,又不会失真,而个人感觉SVG应该更多的是UX画的(?)。实际上我感觉SVG更像一个轻量级的Flash,因为AI里制作动画十分像Flash的模式。
Canvas基本入门
Canvas标签
Canvas在HTML部分只需要写一个标签,绘制部分全部交给js,所以必须要填id,而在标签内部,可以写一些文字,当canvas标签不支持时会显示。
1 | <canvas id="canvasLearning"> |
Canvas坐标
Canvas坐标和大部分CS坐标一样,左上角是0,0。图片来源:Canvas入门到高级详解(上)
Canvas绘制——Context
Canvas绘制需要通过js获取canvas的上下文(context),用context来画的,2d是二维画图,也就是我们一般用的,如果用3d则是WebGL。
1 | let canvas = document.getElementById('canvasLearning') |
一个小例子,画一个红色的正方形。
canvas画图和古老的MFC很像,首先定义画笔的颜色、粗细、样式等,也就是这里的fillStyle
,然后通过函数画图,这里是画一个实心的长方形。
1 | let canvas = document.getElementById('canvasLearning') |
绘制基本图形
矩形
矩形有三种画法,全填充的fillRect(x, y, width, height)
,描边的strokeRect(x, y, width, height)
和清空矩形内的画布clearRect(x, y, width, height)
。
这里的x和y是矩形左上角的点,也是在坐标轴内坐标最小的点。
一个例子,来自MDN
1 | let canvas = document.getElementById('canvasLearning') |
结果如下:
路径
这里的路径是指由很多个点或线组成的图案,可以绘制空心也可绘制实心。于矩形不同的是这里会需要beginPath()
作为开始绘制路径的命令,并且当使用stroke()
(空心)或fill()
(实心)时才会执行绘制。
移动画笔位置命令为moveTo(x, y)
下面的绘制是基于路径的绘制方法。
直线
lineTo(x, y)
会从当前位置绘制一条线到坐标(x,y)
例子,绘制三角形,来自MDN
1 | let canvas = document.getElementById('canvas') |
圆弧
arc(x, y, radius, startAngle, endAngle, anticlockwise)
绘制一个以(x, y)
为圆心,半径为radius的圆弧,圆弧的角度采用弧度制,x轴正方向为0,anticlockwise为true
或false
表示顺时针或逆时针。
例子,来自MDN
1 | ctx.beginPath() |
Style样式
最基本的就是设置绘制颜色,支持CSS中的颜色表达,命令为ctx.style = '...'
如果绘制线条,那么牵扯到线条的粗细,可以通过ctx.lineWidth
设置
此外还有很多可以设置的参数,而比较特殊的我认为是渐变效果,有线性渐变createLinearGradient(x1, y1, x2, y2)
和径向渐变createRadialGradient(x1, y1, r1, x2, y2, r2)
绘制文字
首先通过ctx.font
设置字体,然后通过fillText(text, x, y)
就可以绘制文字。
但是!这个文字很模糊,据说是绘制优化问题,它的绘制和HTML显示的绘制方法不一样,如果想要做到清晰,就需要设置一个高清画布,也就是一个实际画布大小很大,然后被缩小显示的方法。
我修改了别人的一个代码,但是找不到网址了。。
1 | function setHiDPICanvas (w, h, ratio) { |