我正在努力寻找一种方法/策略来处理存储坐标的绘图,以及我的web应用程序在不同设备和屏幕大小上画布尺寸的变化。
基本上我想在画布上显示一个图像。用户将在图像区域上标记两个点,应用程序记录这些标记的放置位置。其想法是,用户将每隔一天使用该应用程序,能够看到之前绘制的X个点的位置,并能够在之前没有标记的地方添加两个新点。画布当前设置为高度=窗口。内部高度和宽度=窗口。内部宽度/2。
我最初的想法是记录每对点的坐标,并根据需要检索它们,以便重新绘制。但如果画布改变大小,这些坐标就不匹配,正如我在不同设备上测试网页时发现的那样。如何记录之前的坐标并使用它们标记图像的同一区域,而不考虑画布尺寸?
您必须定义一个虚拟画布。这是具有预定义大小的理想画布,所有坐标都相对于此画布。此虚拟画布的中心是坐标0,0
当输入坐标时,它会转换为虚拟坐标并存储。渲染时,它们会转换为设备屏幕坐标。
不同的设备具有不同的纵横比,甚至单个设备也可以倾斜,从而改变纵横比。这意味着虚拟画布不能完全适用于所有设备。你能做的最好的事情就是确保整个虚拟画布是可见的,而不必在x或y方向拉伸它。这被称为“比例匹配”。
要渲染到设备画布,您需要缩放坐标以适应整个虚拟画布。您使用画布转换来应用缩放。
创建设备规模矩阵
const vWidth = 1920; // virtual canvas size
const vHeight = 1080;
function scaleToFitMatrix(dWidth, dHeight) {
const scale = Math.min(dWidth / vWidth, dHeight / vHeight);
return [scale, 0, 0, scale, dWidth / 2, dHeight / 2];
}
const scaleMatrix = scaleToFitMatrix(innerWidth, innerHeight);
点定义为虚拟画布上的位置。但是,转换还会缩放线条宽度和特征大小,这是您在非常低或高分辨率设备上不希望看到的。
为了保持相同的像素大小,但仍然以像素大小渲染特征,您可以使用逆比例,并在您描边之前重置变换,如下所示(4个像素框居中于点)
const point = {x : 0, y : 0}; // center of virtual canvas
const point1 = {x : -vWidth / 2, y : -vHeight / 2}; // top left of virtual canvas
const point2 = {x : vWidth / 2, y : vHeight / 2}; // bottom right of virtual canvas
function drawPoint(ctx, matrix, vX, vY, pW, pH) { // vX, vY virtual coordinate
const invScale = 1 / matrix[0]; // to scale to pixel size
ctx.setTransform(...matrix);
ctx.lineWidth = 1; // width of line
ctx.beginPath();
ctx.rect(vX - pW * 0.5 * invScale, vY - pH * 0.5 * invScale, pW * invScale, pH * invScale);
ctx.setTransform(1,0,0,1,0,0); // reset transform for line width to be correct
ctx.fill();
ctx.stroke();
}
const ctx = canvas.getContext("2d");
drawPoint(ctx, scaleMatrix, point.x, point.y, 4, 4);
要将一个点从设备坐标转换为虚拟坐标,需要对该点应用逆矩阵。例如,从鼠标获取pageX,pageY坐标,使用比例矩阵进行转换,如下所示
function pointToVirtual(matrix, point) {
point.x = (point.x - matrix[4]) / matrix[0];
point.y = (point.y - matrix[5]) / matrix[3];
return point;
}
从虚拟设备转换为设备
function virtualToPoint(matrix, point) {
point.x = (point.x * matrix[0]) + matrix[4];
point.y = (point.y * matrix[3]) + matrix[5];
return point;
}
画布的上方/下方或左侧/右侧可能有一个区域在虚拟画布坐标之外。要检查虚拟画布内是否调用以下命令
function isInVritual(vPoint) {
return ! (vPoint.x < -vWidth / 2 ||
vPoint.y < -vHeight / 2 ||
vPoint.x >= vWidth / 2 ||
vPoint.y >= vHeight / 2);
}
const dPoint = {x: page.x, y: page.y}; // coordinate in device coords
if (isInVirtual(pointToVirtual(scaleMatrix,dPoint))) {
console.log("Point inside");
} else {
console.log("Point out of bounds.");
}
使用百分比!示例:
因此,假设在设备1上,画布大小为150x200
,
用户在像素25x30上放置标记。你可以做一些数学运算来得到这个百分比
然后保存百分比,而不是位置,
例如:
let userX = 25; //where the user placed a marker
let canvasWidth = 150;
//Use a calculator to verify :D
let percent = 100 / (canvasWidth / userX); //16.666%
现在你有了百分比
,你可以根据这个百分比设置标记的位置
示例:
let markerX = (canvasWidth * percent) / 100; //24.999
canvasWidth = 400; //Lets change the canvas size!
markerX = (canvasWidth * percent) / 100; //66.664;
瞧,只要抓取画布的大小,你就可以每次确定标记的位置。
我在FrameLayout中的SurfaceView画布上画线。我从相机预览中接收图像,对其进行处理,获取矩形的坐标并在画布上绘制线条。绘制时,我得到这些线在y轴上的位移,线越低,位移越大(见下面的照片): 用红线标记(使用Paint程序,而不是实际的应用程序)下线坐标坐标在位图上的大致位置,矩形的下部绿线(由实际的应用程序放置,在画布上绘制)以及红线显示,坐标移位了多少。顶部的坐标不能穿过屏幕,
我有一个包含坐标的.csv文件,我需要在我做过的地图上使用python绘制它们。有人能帮我吗?
在画布上画画是非常好的。即使橡皮擦也能工作得很好。问题是当画布保存为图像时,它画的是黑线,而不是橡皮擦。 为了更好地理解,我添加了屏幕、镜头和代码。 1.在擦除图的同时- 我不明白为什么橡皮移动被替换为黑色,而保存画布作为一个图像。
因此,我正在创建一个cordova应用程序,在该应用程序中,我从iphone库中拍摄一张照片,将其绘制到画布上,并向其添加另一张图像,以便将其保存为一张照片。到目前为止,我从iphone照片库中绘制的照片可以毫无问题地绘制到画布上,但是第二张图片没有。 当我加载第二张图像时,它首先被添加到具有绝对定位的div中,以便将其移动到我想要的任何位置。之后,我得到了实际的图像,它的来源和位置,并尝试将其绘
实际上,我可以使用函数来完成。我从“HTML5画布-如何在图像背景上画一条线?”中得到的东西。但是我需要在不使用from函数的情况下绘制图像,如下所示:
我有以下代码应该在图像中绘制线条。我的代码是: 如果我编写,它实际上可以工作。但是我的数组很长并且来自一个输入。