【问题标题】:Best way to programmatically manipulate an hand-drawn line以编程方式操作手绘线的最佳方法
【发布时间】:2013-12-17 12:16:02
【问题描述】:
请注意,我没有数学或计算机图形学背景。
如果可能的话,我想知道以编程方式操作手绘线的最佳方法。
绘制动作必须在 html 页面中完成。 (可能无关紧要)
我坚持的方法:
-
在画布上画一条线(有上下的手绘线)-> 转换为位图-> 以某种方式在位图上解释线并操纵其形式(这可能吗?)
李>
不是从位图解释,而是在绘图时有一种按钮来打开/关闭捕获,捕获后,生成某种我能够操作的数学函数并从中生成新的位图
【问题讨论】:
标签:
html
canvas
graphics
bitmap
2d
【解决方案1】:
是的,你可以。
这并不难,但是有很多小的编码方面需要学习。
如果您处于“绘图”模式,您将收集用户单击的鼠标点并从所有这些点画一条线。
如果您处于“编辑”模式,您可以让用户将其中一个收集的点拖动到新坐标,并从所有已编辑的点组成一条线。
以下是供您查看和学习的起始代码以及 Fiddle:http://jsfiddle.net/m1erickson/J5PrN/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
ctx.lineCap = "round";
ctx.lineJoin = "round";
ctx.lineWidth=3;
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var isDown=false;
var startX;
var startY;
var points=[];
var selected=-1;
var mode="draw";
function draw(){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.beginPath();
ctx.moveTo(points[0].x,points[0].y);
for(var i=1;i<points.length;i++){
ctx.lineTo(points[i].x,points[i].y);
}
ctx.stroke();
if(mode=="edit"){
for(var i=0;i<points.length;i++){
ctx.beginPath();
ctx.arc(points[i].x,points[i].y,10,0,Math.PI*2);
ctx.closePath();
ctx.fill();
}
}
}
function handleMouseDown(e){
startX=parseInt(e.clientX-offsetX);
startY=parseInt(e.clientY-offsetY);
if(mode=="draw"){
points.push({x:startX,y:startY});
draw();
}else if(mode=="edit"){
for(var i=0;i<points.length;i++){
var pt=points[i];
var dx=startX-pt.x;
var dy=startY-pt.y;
if(dx*dx+dy*dy<100){
selected=i;
return;
}
}
}
}
function handleMouseUp(e){
selected=-1;
}
function handleMouseOut(e){
selected=-1;
}
function handleMouseMove(e){
if(selected<0){return;}
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// Put your mousemove stuff here
if(selected<0){return;}
var dx=mouseX-startX;
var dy=mouseY-startY;
startX=mouseX;
startY=mouseY;
var pt=points[selected];
points[selected]={x:pt.x+dx,y:pt.y+dy};
draw();
}
$("#canvas").mousedown(function(e){handleMouseDown(e);});
$("#canvas").mousemove(function(e){handleMouseMove(e);});
$("#canvas").mouseup(function(e){handleMouseUp(e);});
$("#canvas").mouseout(function(e){handleMouseOut(e);});
$("#draw").click(function(){
mode="draw";
draw();
$instructions.text("Click points to draw a line");
});
$("#edit").click(function(){
mode="edit";
draw();
$instructions.text("Drag points to move the line");
});
$instructions=$("#instructions");
}); // end $(function(){});
</script>
</head>
<body>
<button id="draw">Add to Line</button>
<button id="edit">Change Line</button><br>
<p id="instructions">Click points to draw a line</p>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
【解决方案2】:
我不会说 HTML,但在我见过的大多数应用程序中 (such as this one),手绘线被分成小的直线段。这是因为传感系统(触摸或鼠标)为您的应用程序提供了(有点)连续的点流;它没有给出实际的线路。然后使用各个段来完成应用程序的目标。
在画线的情况下,当画线时,应用程序会获取点并对它们进行平滑处理(三次样条、最小二乘多项式拟合、b 样条等),然后将平滑的线绘制到屏幕上颜色和样式(钢笔、铅笔、粉笔等)。这可以让用户立即反馈他们的手在哪里移动等。
在手势控制的情况下,可能会绘制一些覆盖线来给用户反馈,但对这些片段进行不同的处理以确定手势(这可能非常复杂)。
将行缓存为一系列手势为您提供了撤消/重做的选项。您还可以将绘图存储为一系列手势,而不是固定的位图。
这有帮助吗?