我把canvas的坐标系,变换成了笛卡尔坐标系(直角坐标系),但是变换之后,图形是对的,文字是倒着呢。图片 展示与代码展如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="canvas" width="1000" height="1000"></canvas>
<script>
const canvas = document.querySelector('#canvas');
var ctx = canvas.getContext('2d');
const data = JSON.parse(JSON.stringify({ "action": "submitResult", "data": { "flag": 1, "presetShape": { "points": [[2, 2], [5, 2]], "pointColor": "#FF0000", "sengmentColor": "#0000FF" }, "operation": [{ "type": "point", "point": [5, 5] }, { "type": "midpoint", "point": [5, 3.5], "text": 3 }, { "type": "midpoint", "point": [3.5, 2], "text": 3 }, { "type": "midpoint", "point": [3.5, 3.5], "text": 4.242640687119285 }], "widgetId": "exploreRelationshipBetweenPointsAndLines-123456" }, "time": 1713933866449 }));
console.log(data);
canvas.width = 400;
canvas.height = 320;
var squareSize = 20;
ctx.setLineDash([5, 3]); // 设置虚线的样式,参数为实线长度和间隔长
// 绘制横向虚线
for (var i = 0; i <= 16; i++) {
var y = i * squareSize;
ctx.strokeStyle = "#cc7a7a";
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(canvas.width, y);
ctx.stroke();
}
// 绘制纵向虚线
for (var j = 0; j <= 22; j++) {
var x = j * squareSize;
ctx.strokeStyle = "#cc7a7a";
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas.height);
ctx.stroke();
}
ctx.setLineDash([]); // 设置为实线样式,参数为空数组
ctx.strokeStyle = "#ff0000";
ctx.beginPath();
ctx.moveTo(140, 0);
ctx.lineTo(140, canvas.height);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(0, 200);
ctx.lineTo(400, 200);
ctx.stroke();
ctx.save();
ctx.translate(140, 200);
ctx.scale(1, -1);
ctx.fillStyle = '#d65c5c';
const pointRaidus = 2;
ctx.beginPath();
ctx.arc(0, 0, pointRaidus, 0, 2 * Math.PI);
ctx.fill();
let pointColor = data.data.presetShape.pointColor;
const sengmentColor = data.data.presetShape.sengmentColor;
const points = data.data.presetShape.points;
const operation = data.data.operation;
ctx.setLineDash([]); // 设置为实线样式,参数为空数组
ctx.strokeStyle = sengmentColor;
ctx.lineWidth = 2
ctx.beginPath();
ctx.moveTo(points[0][0] * 20, points[0][1] * 20);
ctx.lineTo(points[1][0] * 20, points[1][1] * 20);
ctx.stroke();
for (let i = 0; i < points.length; i++) {
const element = points[i];
console.log(element);
ctx.fillStyle = pointColor;
const pointRaidus = 3;
ctx.beginPath();
ctx.arc(element[0] * 20, element[1] * 20, pointRaidus, 0, 2 * Math.PI);
ctx.fill();
}
for (let i = 0; i < operation.length; i++) {
const element = operation[i];
if (element.type == 'point') {
ctx.strokeStyle = sengmentColor;
ctx.lineWidth = 2
ctx.beginPath();
ctx.moveTo(element.point[0] * 20, element.point[1] * 20);
ctx.lineTo(points[1][0] * 20, points[1][1] * 20);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(element.point[0] * 20, element.point[1] * 20);
ctx.lineTo(points[0][0] * 20, points[0][1] * 20);
ctx.stroke();
console.log(element);
const pointRaidus = 3;
ctx.beginPath();
ctx.arc(element.point[0] * 20, element.point[1] * 20, pointRaidus, 0, 2 * Math.PI);
ctx.fill();
}
if (element.type == 'midpoint') {
ctx.font = '10px Arial'; // 设置字体大小和字体样式
ctx.fillStyle = 'black'; // 设置填充颜色
const text = element.text.toFixed(2);
ctx.fillText(text, element.point[0] * 20, element.point[1] * 20); // 在 (50, 50) 处填充文本
}
}
</script>
</body>
</html>
解决这个问题的关键,就是 在平移和缩放之前,先保存一下前一个状态,
第一步
ctx.save()
当绘制文本之前 绘制平移旋转之前的状态,
第二步
ctx.restore()
然后重新计算坐标平移旋转缩放之后的位置,不计算直接绘制,文字不倒置了,但是文本显示的位置是错的,所以说我们重新计算 坐标的位置。
第三步
它接受参数包括文本内容、文本左下角的原始坐标、平移和缩放的偏移量,并返回在新坐标系中的文本位置:
function calculateTextPosition(text, originalX, originalY, translateX, translateY, scaleX, scaleY) {
// 计算在新坐标系中的文本位置
const newX = originalX * scaleX + translateX;
const newY = originalY * scaleY + translateY;
return { x: newX, y: newY };
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="canvas" width="1000" height="1000"></canvas>
<script>
const canvas = document.querySelector('#canvas');
var ctx = canvas.getContext('2d');
const data = JSON.parse(JSON.stringify({ "action": "submitResult", "data": { "flag": 1, "presetShape": { "points": [[2, 2], [5, 2]], "pointColor": "#FF0000", "sengmentColor": "#0000FF" }, "operation": [{ "type": "point", "point": [5, 5] }, { "type": "midpoint", "point": [5, 3.5], "text": 3 }, { "type": "midpoint", "point": [3.5, 2], "text": 3 }, { "type": "midpoint", "point": [3.5, 3.5], "text": 4.242640687119285 }], "widgetId": "exploreRelationshipBetweenPointsAndLines-123456" }, "time": 1713933866449 }));
console.log(data);
canvas.width = 400;
canvas.height = 320;
var squareSize = 20;
ctx.setLineDash([5, 3]); // 设置虚线的样式,参数为实线长度和间隔长
// 绘制横向虚线
for (var i = 0; i <= 16; i++) {
var y = i * squareSize;
ctx.strokeStyle = "#cc7a7a";
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(canvas.width, y);
ctx.stroke();
}
// 绘制纵向虚线
for (var j = 0; j <= 22; j++) {
var x = j * squareSize;
ctx.strokeStyle = "#cc7a7a";
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas.height);
ctx.stroke();
}
ctx.setLineDash([]); // 设置为实线样式,参数为空数组
ctx.strokeStyle = "#ff0000";
ctx.beginPath();
ctx.moveTo(140, 0);
ctx.lineTo(140, canvas.height);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(0, 200);
ctx.lineTo(400, 200);
ctx.stroke();
ctx.save();
ctx.translate(140, 200);
ctx.scale(1, -1);
ctx.fillStyle = '#d65c5c';
const pointRaidus = 2;
ctx.beginPath();
ctx.arc(0, 0, pointRaidus, 0, 2 * Math.PI);
ctx.fill();
let pointColor = data.data.presetShape.pointColor;
const sengmentColor = data.data.presetShape.sengmentColor;
const points = data.data.presetShape.points;
const operation = data.data.operation;
ctx.setLineDash([]); // 设置为实线样式,参数为空数组
ctx.strokeStyle = sengmentColor;
ctx.lineWidth = 2
ctx.beginPath();
ctx.moveTo(points[0][0] * 20, points[0][1] * 20);
ctx.lineTo(points[1][0] * 20, points[1][1] * 20);
ctx.stroke();
for (let i = 0; i < points.length; i++) {
const element = points[i];
console.log(element);
ctx.fillStyle = pointColor;
const pointRaidus = 3;
ctx.beginPath();
ctx.arc(element[0] * 20, element[1] * 20, pointRaidus, 0, 2 * Math.PI);
ctx.fill();
}
for (let i = 0; i < operation.length; i++) {
const element = operation[i];
if (element.type == 'point') {
ctx.strokeStyle = sengmentColor;
ctx.lineWidth = 2
ctx.beginPath();
ctx.moveTo(element.point[0] * 20, element.point[1] * 20);
ctx.lineTo(points[1][0] * 20, points[1][1] * 20);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(element.point[0] * 20, element.point[1] * 20);
ctx.lineTo(points[0][0] * 20, points[0][1] * 20);
ctx.stroke();
console.log(element);
const pointRaidus = 3;
ctx.beginPath();
ctx.arc(element.point[0] * 20, element.point[1] * 20, pointRaidus, 0, 2 * Math.PI);
ctx.fill();
}
ctx.restore();
if (element.type == 'midpoint') {
ctx.font = '10px Arial'; // 设置字体大小和字体样式
ctx.fillStyle = 'black'; // 设置填充颜色
// const text = element.text.toFixed(2);
// ctx.fillText(text, element.point[0] * 20, element.point[1] * 20); // 在 (50, 50) 处填充文本
const text = element.text.toFixed(2);
const textPosition = calculateTextPosition(text, element.point[0] * 20, element.point[1] * 20, 140, 200, 1, -1);
ctx.fillText(text, textPosition.x, textPosition.y);
}
}
function calculateTextPosition(text, originalX, originalY, translateX, translateY, scaleX, scaleY) {
// 计算在新坐标系中的文本位置
const newX = originalX * scaleX + translateX;
const newY = originalY * scaleY + translateY;
return { x: newX, y: newY };
}
</script>
</body>
</html>