tak*_*tak 2 html javascript jquery canvas
我可以在画布上画一些线。我想让每一行都可以拖动和放置。
但是,它是通过将不同行的位置存储在数组中来实现的,如何使它们中的每一个都像一个可拖放的实例?还是我弄错了?
你可以在这里查看代码
var storedLines = []
http://jsfiddle.net/m1erickson/NnZ7a/
非常感谢!
要制作可拖动的线,您需要保留一组端点和一组线作为端点的索引。
然后,当用户在端点或线附近单击并拖动时,您只需根据鼠标移动的量更新端点。
首先创建一个简单的点结构
const Point2 = (x,y) => ({x,y}); // creates a point
Run Code Online (Sandbox Code Playgroud)
然后是一个包含点数、添加点数以及您可能需要的其他内容的列表。
const list = {
items : null,
add(item) { this.items.push(item); return item },
eachItem(callback) {
var i;
while(i < this.items.length){
callback(this.items[i],i);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后从列表结构创建一个点列表
function createList(extend){
return Object.assign({},list,{items : []},extend);
}
const points = createList();
Run Code Online (Sandbox Code Playgroud)
线是一组点索引
const Line = (p1,p2) => ({p1,p2});
const lines = createList();
Run Code Online (Sandbox Code Playgroud)
要从鼠标坐标中选择一个点,您需要找到离鼠标最近的点。
// this will extend the points list
function getClosestPoint(from ,minDist) {
var closestPoint;
this.eachItem(point => {
const dist = Math.hypot(from.x - point.x, from.y - point.y);
if(dist < minDist){
closestPoint = point;
minDist = dist;
}
});
return closestPoint;
}
Run Code Online (Sandbox Code Playgroud)
线路也是如此,但这并不那么简单。您需要一个函数来查找点与线段的距离。
function distanceLineFromPoint(line,point){
const lx = points.items[line.p1].x;
const ly = points.items[line.p1].y;
const v1x = points.items[line.p2].x - lx;
const v1y = points.items[line.p2].y - ly;
const v2x = point.x - lx;
const v2y = point.y - ly;
// get unit dist of closest point
const u = (v2x * v1x + v2y * v1y)/(v1y * v1y + v1x * v1x);
if(u >= 0 && u <= 1){ // is the point on the line
return Math.hypot(lx + v1x * u - point.x, ly + v1y * u - point.y);
} else if ( u < 0 ) { // point is before start
return Math.hypot(lx - point.x, ly - point.y);
}
// point is after end of line
return Math.hypot(points.items[line.p2].x - point.x, points.items[line.p2].y - point.y);
}
// this will extend the lines list
function getClosestline(from ,minDist) {
var closestLine;
this.eachItem(line => {
const dist = distanceLineFromPoint(line,from);
if(dist < minDist){
closestLine = line;
minDist = dist;
}
});
return closestLine;
}
Run Code Online (Sandbox Code Playgroud)
使用这些函数,我们应该扩展列表对象,以便使用扩展重新创建它们。
const points = createList({getClosest : getClosestPoint});
const lines = createList({getClosest : getClosestline});
Run Code Online (Sandbox Code Playgroud)
然后剩下的就是实现一个鼠标界面和一个渲染功能。您可以添加可拖动的点和连接它们的线。如果在一条线或点附近单击,则可以拖动它们。该片段显示了其余部分。
显示正确的用户反馈也很重要。您需要设置光标、工具提示(通过 canvas.style.cursor 和 canvas.title)并突出显示将受到影响的对象,以便用户知道将发生什么操作以及单击和拖动时会发生什么。
此外,您应该将鼠标事件设置为文档而不是画布,因为这将捕获鼠标拖动,允许用户在您仍然获得 mouseup 和移动事件的同时拖动到画布之外。
const Point2 = (x,y) => ({x,y}); // creates a point
Run Code Online (Sandbox Code Playgroud)
const list = {
items : null,
add(item) { this.items.push(item); return item },
eachItem(callback) {
var i;
while(i < this.items.length){
callback(this.items[i],i);
}
}
}
Run Code Online (Sandbox Code Playgroud)
function createList(extend){
return Object.assign({},list,{items : []},extend);
}
const points = createList();
Run Code Online (Sandbox Code Playgroud)