javascript - 在javascript中测量在图像上绘制的线条的长度
问题描述
我想测量在以 html 代码上传的图像上绘制的线条的长度。我找到了一个使用画布元素的脚本,使我能够绘制一条线、矩形或自由线。我想实现的下一步是能够在上传的图像上画一条线、矩形或自由线,但如果我选择画一条线,则可以通过设置比例来测量线的长度手动。
我知道在 js 中有字符串 string.length 但这对我的目的不利。下面是我找到的两个代码,我正在尝试修改和组合但没有任何成功,即使我不是很实用。如果有人能帮我把这两个代码放在一起,或者给我一些建议,我将非常感激。
这是在矩形中绘制的 html 代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Canvas Paint - Example 5</title>
<style type="text/css">
#container { position: relative; }
#imageView { border: 1px solid #000; }
#imageTemp { position: absolute; top: 1px; left: 1px; }
</style>
</head>
<body>
<p><label>Drawing tool: <select id="dtool">
<option value="line">Line</option>
<option value="rect">Rectangle</option>
<option value="pencil">Pencil</option>
</select></label></p>
<div id="container">
<canvas id="imageView" width="400" height="300">
<p>Unfortunately, your browser is currently unsupported by our web
application. We are sorry for the inconvenience.</p>
</canvas>
</div>
<script type="text/javascript" src="example-5.js"></script>
</body>
</html>
这是相关的js代码:
// Keep everything in anonymous function, called on window load.
if(window.addEventListener) {
window.addEventListener('load', function () {
var canvas, context, canvaso, contexto;
// The active tool instance.
var tool;
var tool_default = 'line';
function init () {
// Find the canvas element.
canvaso = document.getElementById('imageView');
if (!canvaso) {
alert('Error: I cannot find the canvas element!');
return;
}
if (!canvaso.getContext) {
alert('Error: no canvas.getContext!');
return;
}
// Get the 2D canvas context.
contexto = canvaso.getContext('2d');
if (!contexto) {
alert('Error: failed to getContext!');
return;
}
// Add the temporary canvas.
var container = canvaso.parentNode;
canvas = document.createElement('canvas');
if (!canvas) {
alert('Error: I cannot create a new canvas element!');
return;
}
canvas.id = 'imageTemp';
canvas.width = canvaso.width;
canvas.height = canvaso.height;
container.appendChild(canvas);
context = canvas.getContext('2d');
// Get the tool select input.
var tool_select = document.getElementById('dtool');
if (!tool_select) {
alert('Error: failed to get the dtool element!');
return;
}
tool_select.addEventListener('change', ev_tool_change, false);
// Activate the default tool.
if (tools[tool_default]) {
tool = new tools[tool_default]();
tool_select.value = tool_default;
}
// Attach the mousedown, mousemove and mouseup event listeners.
canvas.addEventListener('mousedown', ev_canvas, false);
canvas.addEventListener('mousemove', ev_canvas, false);
canvas.addEventListener('mouseup', ev_canvas, false);
}
// The general-purpose event handler. This function just determines the mouse
// position relative to the canvas element.
function ev_canvas (ev) {
if (ev.layerX || ev.layerX == 0) { // Firefox
ev._x = ev.layerX;
ev._y = ev.layerY;
} else if (ev.offsetX || ev.offsetX == 0) { // Opera
ev._x = ev.offsetX;
ev._y = ev.offsetY;
}
// Call the event handler of the tool.
var func = tool[ev.type];
if (func) {
func(ev);
}
}
// The event handler for any changes made to the tool selector.
function ev_tool_change (ev) {
if (tools[this.value]) {
tool = new tools[this.value]();
}
}
// This function draws the #imageTemp canvas on top of #imageView, after which
// #imageTemp is cleared. This function is called each time when the user
// completes a drawing operation.
function img_update () {
contexto.drawImage(canvas, 0, 0);
context.clearRect(0, 0, canvas.width, canvas.height);
}
// This object holds the implementation of each drawing tool.
var tools = {};
// The drawing pencil.
tools.pencil = function () {
var tool = this;
this.started = false;
// This is called when you start holding down the mouse button.
// This starts the pencil drawing.
this.mousedown = function (ev) {
context.beginPath();
context.moveTo(ev._x, ev._y);
tool.started = true;
};
// This function is called every time you move the mouse. Obviously, it only
// draws if the tool.started state is set to true (when you are holding down
// the mouse button).
this.mousemove = function (ev) {
if (tool.started) {
context.lineTo(ev._x, ev._y);
context.stroke();
}
};
// This is called when you release the mouse button.
this.mouseup = function (ev) {
if (tool.started) {
tool.mousemove(ev);
tool.started = false;
img_update();
}
};
};
// The rectangle tool.
tools.rect = function () {
var tool = this;
this.started = false;
this.mousedown = function (ev) {
tool.started = true;
tool.x0 = ev._x;
tool.y0 = ev._y;
};
this.mousemove = function (ev) {
if (!tool.started) {
return;
}
var x = Math.min(ev._x, tool.x0),
y = Math.min(ev._y, tool.y0),
w = Math.abs(ev._x - tool.x0),
h = Math.abs(ev._y - tool.y0);
context.clearRect(0, 0, canvas.width, canvas.height);
if (!w || !h) {
return;
}
context.strokeRect(x, y, w, h);
};
this.mouseup = function (ev) {
if (tool.started) {
tool.mousemove(ev);
tool.started = false;
img_update();
}
};
};
// The line tool.
tools.line = function () {
var tool = this;
this.started = false;
this.mousedown = function (ev) {
tool.started = true;
tool.x0 = ev._x;
tool.y0 = ev._y;
};
this.mousemove = function (ev) {
if (!tool.started) {
return;
}
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.moveTo(tool.x0, tool.y0);
context.lineTo(ev._x, ev._y);
context.stroke();
context.closePath();
};
this.mouseup = function (ev) {
if (tool.started) {
tool.mousemove(ev);
tool.started = false;
img_update();
}
};
};
init();
}, false); }
// vim:set spell spl=en fo=wan1croql tw=80 ts=2 sw=2 sts=2 sta et ai cin fenc=utf-8 ff=unix:
虽然绘制一条线并测量长度的代码位于此链接: https ://openlayers.org/en/latest/examples/measure.html?q=measure+line
解决方案
假设正在渲染图像的画布是 x 像素宽和 y 像素高,纵横比为 x/y,图像的原始尺寸是 w 像素和 h 像素,纵横比为 w/h。
现在取两点 (x1,y1), (x2,y2)
x 图像单位的距离 = abs(x1 - x2) * w / x; // 现在单位是图像维度
以图像为单位的 y 距离 = abs(y1- y2) * h / y;// 现在单位是图像维度
当我说单位是图像尺寸时
例如 200 米的图像适合 100 像素宽度的画布,现在 50 像素的长度是 50 * (200/100) 米 = 100 米
所以来回答你原来的问题
两点之间的线长度现在是 s = Math.sqrt(Math.pow(x 图像单位距离,2) + Math.pow(y 图像单位距离,2))
注意:我没有放代码,因为我觉得用概念的方式更好地解释它,尽管我觉得这个问题在 math.stackexchange 中更好
推荐阅读
- javascript - AJAX GET 请求未向 Django 发送数据
- python - 制定一个函数,该函数采用列表 T 和 R 以及阈值温度 Q 并返回超过 Q 的时间戳列表
- macos - macos WKWebView - 归档应用程序后无法再进行调试
- java - 无法使用 ICEpdf 打开远程 pdf
- azure - Azure 管道 - Sql150DatabaseSchemaProvider
- javascript - 显示现有对象的属性时控制台显示未定义
- inno-setup - 在安装程序运行时更改安装程序语言 (Inno Setup)
- node.js - 将承诺值存储到变量中不解析 nodejs
- node.js - 无法获取 / 使用 node.js + socket.io 将客户端连接到服务器
- python - 向列表中的图像添加黑框