The recent project is about "Augmented Reality"(Features: Information integration in the real world and the virtual world; Real-time interactivity; Adding a positioning virtual object in a three-dimensional scale space), we need to draw some graphics (including Point/Image, Line, Polygon, Text, Arrow, and Circle) with canvas in the videos.

//画线
function paintPolyline (ctx, points, attribute, bSelected, offsetX, offsetY) {
var ox = offsetX;
var oy = offsetY;
var i = 0;
if (points.length == 0) {
return;
}
var polylineWidth = lineWidth;
var lineColor = defaultColor;
if (!!attribute) {
if (attribute.lineWidth != undefined) {
polylineWidth = attribute.lineWidth;
}
if (attribute.color != undefined) {
lineColor = attribute.color;
}
}
if (bSelected) {
lineColor = selectedColor;
}
ctx.beginPath(); //开始新的路径
ctx.moveTo(points[0][0] + ox, points[0][1] + oy);
for (i = 1; i < points.length; i++) {
ctx.lineTo(points[i][0] + ox, points[i][1] + oy);
}
ctx.lineWidth = polylineWidth;
ctx.strokeStyle = lineColor;
ctx.stroke();
ctx.closePath(); //关闭路径
// 画出图形的所有点选中范围(半径为3的圆)
if (bSelected) {
ctx.beginPath();
ctx.lineWidth = polylineWidth;
ctx.globalAlpha = 1;
ctx.strokeStyle = lineColor;
ctx.fillStyle = nodeColor;
for (i = 0; i < points.length; i++) {
ctx.beginPath();
//选中时增加显示节点圆
ctx.arc(points[i][0] + ox, points[i][1] + oy, 3, 0, 2 * Math.PI, true);
ctx.stroke();
ctx.fill();
ctx.closePath(); //关闭路径
}
}
}
//画多边形
function paintPolygon(ctx, points, attribute, bSelected, offsetX, offsetY) {
var ox = offsetX;
var oy = offsetY;
var i = 0;
if (points.length == 0) {
return;
}
var polylineWidth = lineWidth;
var lineColor = defaultColor;
var fillColor = defaultFillColor;
var fillOpacity = defaultFillOpacity;
if (!!attribute) {
if (attribute.lineWidth != undefined) {
polylineWidth = attribute.lineWidth;
}
if (attribute.color != undefined) {
lineColor = attribute.color;
}
if (attribute.fillColor != undefined) {
fillColor = attribute.fillColor;
}
if (attribute.fillOpacity != undefined) {
fillOpacity = attribute.fillOpacity;
}
}
if (bSelected) {
lineColor = selectedColor;
}
ctx.beginPath(); //开始新的路径
ctx.moveTo(points[0][0] + ox, points[0][1] + oy);
for (i = 1; i < points.length - 1; i++) {
ctx.lineTo(points[i][0] + ox, points[i][1] + oy);
}
//封闭最后一个点成面
i = points.length - 1;
var xDis = points[i][0] - points[0][0];
var yDis = points[i][1] - points[0][1];
// 近似封闭
if (xDis < 3 && xDis > -3 && yDis < 3 && yDis > -3) {
ctx.lineTo(points[0][0] + ox, points[0][1] + oy);
}
// 严格封闭
else if (points[i][0] === points[0][0] && points[i][1] === points[0][1]) {
ctx.lineTo(points[i][0] + ox, points[i][1] + oy);
}
// 不封闭,自动补线
else {
ctx.lineTo(points[i][0] + ox, points[i][1] + oy);
ctx.lineTo(points[0][0] + ox, points[0][1] + oy);
}
ctx.lineWidth = polylineWidth;
ctx.strokeStyle = lineColor;
ctx.stroke();
ctx.closePath();
// 画出图形的所有点选中范围(半径为3的圆)
if (bSelected) {
ctx.globalAlpha = fillOpacity;
ctx.fillStyle = fillColor;
ctx.fill();
ctx.beginPath();
ctx.lineWidth = polylineWidth;
ctx.globalAlpha = 1; //选中节点不透明
ctx.strokeStyle = lineColor;
ctx.fillStyle = nodeColor;
for (i = 0; i < points.length; i++) {
ctx.beginPath();
//选中时增加显示节点圆
ctx.arc(points[i][0] + ox, points[i][1] + oy, 3, 0, 2 * Math.PI, true);
ctx.stroke();
ctx.fill();
ctx.closePath();
}
} else {
ctx.globalAlpha = fillOpacity;
ctx.fillStyle = fillColor;
ctx.fill();
}
}
/**
* 绘制带有箭头的直线
* @param ctx画布变量
* @param fromX/fromY 起点坐标
* @param toX/toY 终点坐标
* @param color 线与箭头颜色
**/
function drawLineArrow(ctx, points, attribute, bSelected) {
var ox = offsetX;
var oy = offsetY;
var lineArrowWidth = lineWidth;
var color = defaultColor;
var fillColor = defaultFillColor;
var fillOpacity = defaultFillOpacity;
if (!!attribute) {
if (attribute.lineWidth != undefined) {
lineArrowWidth = attribute.lineWidth;
}
if (attribute.color != undefined) {
color = attribute.color;
}
if (attribute.fillColor != undefined) {
fillColor = attribute.fillColor;
}
if (attribute.fillOpacity != undefined) {
fillOpacity = attribute.fillOpacity;
}
}
if (bSelected) {
color = selectedColor;
}
//console.log(JSON.stringify(points),"标记点位==============");
if (points.length === 0) {
return;
}
//fromX, fromY, toX, toY
var i = 0;
var fromX = points[0][0];
var fromY = points[0][1];
var toX, toY;
if (points.length === 1) {
toX = fromX;
toY = fromY;
} else {
for (i = 1; i < points.length; i++) {
toX = points[i][0];
toY = points[i][1];
}
}
var headlen = 50; //自定义箭头线的长度
var theta = 30; //自定义箭头线与直线的夹角
var arrowX_top, arrowY_top, arrowX_bottom, arrowY_bottom; //箭头线终点坐标
// 计算各角度和对应的箭头终点坐标(Math.atan2(y,x)得出的是弧度 再转为角度)
var angle;
if (fromX == toX && fromY == toY) {
angle = 90; //AR页面中在一个点鼠标按下并抬起,呈90°
} else {
angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI;
}
var angle1 = ((angle + theta) * Math.PI) / 180;
var angle2 = ((angle - theta) * Math.PI) / 180;
var topX = headlen * Math.cos(angle1);
var topY = headlen * Math.sin(angle1);
var botX = headlen * Math.cos(angle2);
var botY = headlen * Math.sin(angle2);
arrowX_top = toX + topX;
arrowY_top = toY + topY;
arrowX_bottom = toX + botX;
arrowY_bottom = toY + botY;
//中点坐标公式X=(X1+X2)/2 Y=(Y1+Y2)/2
//已知点A(arrowX_top,arrowY_top);
//已知点B(arrowX_bottom,arrowY_bottom);
//设C为中点(middle_x,middle_y)
var middle_c_x = (arrowX_top + arrowX_bottom) / 2;
var middle_c_y = (arrowY_top + arrowY_bottom) / 2;
// 设D为A,C中点(middle_d_x,middle_d_y)
var middle_d_x = (arrowX_top + middle_c_x) / 2;
var middle_d_y = (arrowY_top + middle_c_y) / 2;
// 设E为B,C中点(middle_e_x,middle_e_y)
var middle_e_x = (arrowX_bottom + middle_c_x) / 2;
var middle_e_y = (arrowY_bottom + middle_c_y) / 2;
//以起始点为圆心 画半径为5的实心圆
ctx.beginPath();
ctx.arc(fromX, fromY, 5, 0, 2 * Math.PI);
ctx.strokeStyle = color;
ctx.stroke();
ctx.fillStyle = color;
ctx.fill();
//虚线(中间那条长线)
ctx.beginPath();
// ctx.setLineDash([15, 5]);//虚线 ***************This method was introduced in QtQuick 2.11
//画虚直线(画到了三角形和虚线交点处,不是画到头的)
ctx.moveTo(fromX, fromY);
ctx.lineTo(middle_c_x, middle_c_y);
// ctx.strokeStyle = "rgb(130, 210, 210)";
ctx.strokeStyle = color; //"lightblue";//因为QtQuick 2.11 才支持虚线 先用不同色进行一个区分 看出效果
ctx.stroke();
//实线(所有边线)
ctx.beginPath();
ctx.lineWidth = lineArrowWidth;
// ctx.setLineDash([]);//实线 *******************This method was introduced in QtQuick 2.11
//画上边箭头线
ctx.moveTo(toX, toY);
ctx.lineTo(arrowX_top, arrowY_top); //上箭头坐标
ctx.lineTo(middle_d_x, middle_d_y); //上箭头中间点坐标
ctx.lineTo(fromX, fromY);
//画下边箭头线
ctx.lineTo(middle_e_x, middle_e_y); //下箭头中间点坐标
ctx.lineTo(arrowX_bottom, arrowY_bottom); //下箭头坐标
ctx.lineTo(toX, toY);
ctx.strokeStyle = color;
ctx.stroke();
// 画出图形的所有点选中范围(半径为3的圆)
if (bSelected) {
ctx.globalAlpha = fillOpacity;
ctx.fillStyle = fillColor;
ctx.fill();
ctx.beginPath();
ctx.lineWidth = lineArrowWidth;
ctx.globalAlpha = 1; //选中节点不透明
ctx.strokeStyle = color;
ctx.fillStyle = nodeColor;
//选中时增加显示节点圆
ctx.arc(fromX + ox, fromY + oy, 3, 0, 2 * Math.PI, true);
ctx.stroke();
ctx.fill();
ctx.closePath();
// ctx.beginPath();
// ctx.arc(middle_d_x + ox, middle_d_y + oy, 3, 0, 2*Math.PI, true)
// ctx.stroke();
// ctx.fill();
// ctx.closePath();
ctx.beginPath();
ctx.arc(arrowX_top + ox, arrowY_top + oy, 3, 0, 2 * Math.PI, true);
ctx.stroke();
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.arc(toX + ox, toY + oy, 3, 0, 2 * Math.PI, true);
ctx.stroke();
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.arc(arrowX_bottom + ox, arrowY_bottom + oy, 3, 0, 2 * Math.PI, true);
ctx.stroke();
ctx.fill();
ctx.closePath();
// ctx.beginPath();
// ctx.arc(middle_e_x + ox, middle_e_y + oy, 3, 0, 2*Math.PI, true)
// ctx.stroke();
// ctx.fill();
// ctx.closePath();
} else {
ctx.globalAlpha = fillOpacity;
ctx.fillStyle = fillColor;
ctx.fill();
}
}
//画圆形
function drawCircle(ctx, points, attribute, bSelected) {
if (bSelected) {
ctx.stroke();
ctx.globalAlpha = 0.5;
ctx.fillStyle = "lightgrey";
ctx.fill();
ctx.beginPath();
ctx.lineWidth = lineWidth;
ctx.globalAlpha = 1;
ctx.strokeStyle = "lightgrey";
ctx.fillStyle = "lightgrey";
for (i = 0; i < points.length; i++) {
ctx.arc(
points[i][0] + ox,
points[i][1] + oy,
3,
0,
2 * Math.PI,
true
);
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.lineWidth = lineWidth;
ctx.strokeStyle = "lightgrey";
ctx.fillStyle = "lightgrey";
}
ctx.fill();
} else {
ctx.stroke();
ctx.globalAlpha = 0.5;
ctx.fillStyle = "lightgrey";
ctx.fill();
}
}
//画点(图标、文字)
function paintPoint(ctx, points, attribute, bSelected) {
if (points.length == 0) {
return;
}
var left = points[0][0];
var top = points[0][1];
var type = "";
if (!!attribute) {
type = attribute.type;
//图标
if (type == "image") {
if (
!!attribute.icon &&
!!attribute.width &&
attribute.height &&
attribute.offset
) {
ctx.drawImage(
attribute.icon,
left + attribute.offset.x,
top + attribute.offset[1],
attribute.width,
attribute.height
);
}
if (!!attribute.name) {
}
} else if (type == "text") {
//文字
var text = attribute.text;
var font = defaultFont;
if (!!attribute.font) {
font = "";
if (!!attribute.font.size) {
font = attribute.font.size + "px";
}
if (!!attribute.font.family) {
font += " " + attribute.font.family;
} else {
font += " 微软雅黑";
}
}
// console.log("font", font);
var textAlign = !!attribute.textAlign
? attribute.textAlign
: defaultTextAlign;
var baseLine = !!attribute.textBaseline
? attribute.textBaseline
: defaultTextBaseline;
var color = !!attribute.color ? attribute.color : defaultColor;
ctx.beginPath();
ctx.textAlign = textAlign;
ctx.font = font;
ctx.textBaseline = baseLine;
ctx.fillStyle = color;
if (!!attribute.rotate) {
ctx.save(); //保存画笔当前状态
ctx.translate(left, top); // 将画布的原点移动到正中央
ctx.rotate((attribute.rotate * Math.PI) / 180);
ctx.fillText(text, 0, 0);
ctx.restore(); //复位画笔之前的状态
} else {
ctx.fillText(text, left, top);
}
ctx.closePath();
}
}
}
//判断一个点是否在多边形内
//isPointInPolygon(curPoint, pointsArr);
function isPointInPolygon(point, polygon) {
var x = point[0],
y = point[1];
var inside = false;
for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
var xi = polygon[i][0],
yi = polygon[i][1];
var xj = polygon[j][0],
yj = polygon[j][1];
var intersect =
yi > y != yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
if (intersect) inside = !inside;
}
return inside;
}
// 判断形状是否被选中
//(w = 20)
function checkInLine(x1, y1, x2, y2, x, y, w) {
var l = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
var l1 = Math.sqrt((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y));
var l2 = Math.sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
var l3 = Math.sqrt(w * w + l * l);
var h =
Math.abs((y2 - y1) * x + (x1 - x2) * y - x1 * y2 + x2 * y1) /
Math.sqrt((y2 - y1) * (y2 - y1) + (x1 - x2) * (x1 - x2));
if (
(l1 <= l3 && l2 <= l3 && h <= w) ||
(Math.abs(x1 - x) <= w && Math.abs(y1 - y) <= w) ||
(Math.abs(x2 - x) <= w && Math.abs(y2 - y) <= w)
) {
return true;
} else {
return false;
}
}
// 判断点是否被选中
//(d = 20)
function checkInPoint(x1, y1, x, y, d) {
if (Math.abs(x1 - x) <= d && Math.abs(y1 - y) <= d) {
return true;
} else {
return false;
}
}
function checkInImage(x1, y1, x, y, width, height) {
return x >= x1 && x <= x1 + width && y >= y1 && y <= y1 + height;
}
网友评论