一般情况下简单的绘制,其实canvas原生方法也可以满足,比如画个线,绘制个圆形、正方形、加个文案。
let canvas = document.getElementById('canvas');
canvas.width = 1200;
canvas.height = 600;
canvas.style.width = '1200px';
canvas.style.height = '600px';
let ctx = canvas.getContext('2d');
ctx.moveTo(400, 100);
ctx.lineTo(400, 200);
ctx.lineTo(500, 200);
ctx.strokeStyle = "#00F";
ctx.stroke();
ctx.beginPath();
ctx.arc(150, 150, 100, 0, 2 * Math.PI, true);
ctx.fillStyle = '#ccc';
ctx.fill();
ctx.beginPath();
let str1 = '苟利国家生死以,';
let str2 = '岂因祸福避趋之!';
ctx.font = '50px Microsoft Yahei';
ctx.strokeStyle = 'red';
ctx.textAlign = 'center';
ctx.strokeText(str1, 800, 50);
ctx.font = '50px SimHei';
ctx.fillStyle = 'blue';
ctx.textAlign = 'center';
ctx.fillText(str2, 800, 100);
//获取文本的宽度,以便以后能动态的使文本居中。
let strWidth = ctx.measureText(str2).width;
console.log(strWidth);
看效果图
如果真的只是这点需求,原生方法也很好,省的加载一个js库。不过现实往往还是很残酷的,怎么可能这么简单,这里都没有交互,比如在现有的图形上做位移、拖拽等等,复杂度就上来了,这时一个好的canvas js库就很有必要了。
fabric.js 算是我用到过的比较全面且好用的一个canvas js库;
先上代码:
const data = {
line: [
'1648.607594936709', '654.1772151898734', '2100.253164556962', '1290.126582278481'
],
area: [
"1604.0506329113923", "607.5949367088607", "1648.607594936709", "654.1772151898734", "2100.253164556962", "1290.126582278481"
, "2211.645569620253", "1429.873417721519", "285.56962025316454" , "1429.873417721519" , "617.7215189873417" , "662.2784810126582"
]
};
// 可以看出上面数据一个是画线,一个是画不规则区域,这是实际项目中用到的数据,拿到这里自有妙处,后面会说
fabric.js使用
import { fabric } from ‘fabric’;
// canvasDraw是canvas的 id
const canvasBox = new fabric.StaticCanvas('canvasDraw', {
backgroundColor: "transparent"
});
// 这个是设置
// canvas.style.width 和 canvas.width
// canvas.style.height 和 canvas.height
canvasBox.setDimensions({
width: 600,
height: 300
});
// 下面方法等同于 setDimensions
// canvasBox.setWidth(width);
// canvasBox.setHeight(height);
// 这个是设置的 canvas.style.width 和 canvas.style.height
canvasBox._setCssDimension('width', 2400);
canvasBox._setCssDimension('height', 1500);
到此fabric初始化就算完成了,这里有个很重要的点,官方文档和几乎所有写fabric教学的博客都没有讲,那就是如何将canvas.style.width 和 canvas.width 赋予不同的数值,这是个很实用的点,因为坐标点是按canvas.width来的,但是我们的canvas.style.width必须和设计保持一致
比如说:我们需要在一张图片上做绘制,那坐标点是从图片原图上标注的,而设计不可能按原图大小展示,这时就会出现坐标点和canvas.style.width不一致,有两个方法解决这个问题:
1、坐标点根据 canvas.style.width / img.width 的比率做调整
2、canvas.width 和 img.width保持一致,canvas.style.width 和 设计稿 width一致
很显然第二个方案更简单且实用
既然官网没提供方法那我们就看源码都做了什么,因为canvas.width是必然要设置的
我们发现setDimensions时调用了 _setBackstoreDimension 和 _setCssDimension
很明显这里是canvas.width
而这里是canvas.style.width
今天先简单点,只看画线和画不规则图形
function drawLine(arr, color, opacity) {
// [x1, y1, x2, y2]
const line = new fabric.Line(arr, {
strokeWidth: 10, //线宽
stroke: color, //线的颜色
selectable: false,
opacity: opacity
});
this.canvasBox.add(line);
}
function drawPolygon(arr, color, opacity) {
const newArr = formatData(arr);
const polygon = new fabric.Polygon(
newArr,
{
fill: color,
strokeWidth: 1,
stroke: "#000",
opacity: opacity
}
);
this.canvasBox.add(polygon);
}
function formatData(arr) {
// 将 [100,50,200,40] 坐标点转为 {x: 100, y: 50}
let newArr = [];
arr.forEach((val, i) => {
i = i + 1;
// 偶数不操作
if ((i % 2) !== 0) {
newArr.push({
x: parseInt(val),
y: parseInt(arr[i])
});
}
});
return newArr;
}
这时大家就会看到 我有个 parseInt的操作,因为当我使用原数据绘制时,线可以出来但Polygon却没有,搞得很郁闷,查了很长时间,最后当我盯着数据发呆时,看着长长的小数位 突发奇想,于是parseInt诞生了,页面也能看到区域了,真的是坑,这个点不做项目是绝无可能发现的。
也是我今天冒着延期项目也要搞这么一篇文章的原因,虽然fabric知识点不多但绝对满满的干货,更是告诉大家遇到问题后不要怕、更不能放弃,永远都能找到解题的方法,条条大路通罗马,一条不行就换一条,总会解决的!!!