编辑路径点或线的选择 [英] Editing Selections of Path Points or line

查看:47
本文介绍了编辑路径点或线的选择的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找到一种方法,通过使用鼠标单击选择路径点来在html5画布中使用javascript拖放多边形点或线

I'm trying to find a way to drag and drop polygon point or line with javascript in html5 canvas by selecting a path points with mouse click on it

如下图所示

通过单击并将其拖动到新位置来移动所选点

the selected points are moved by clicking and dragging them into new position

var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
  var BB=canvas.getBoundingClientRect();
  offsetX=BB.left;
  offsetY=BB.top;        
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }

context.lineWidth=2;
context.strokeStyle='blue';

var coordinates = [];
var isDone=false;

$('#done').click(function(){
  isDone=true;
});

$("#canvas").mousedown(function(e){handleMouseDown(e);});

function handleMouseDown(e){
  if(isDone || coordinates.length>10){return;}

  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();

  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);
  coordinates.push({x:mouseX,y:mouseY});
  drawPolygon();
}

function drawPolygon(){
  context.clearRect(0,0,cw,ch);
  context.beginPath();
  context.moveTo(coordinates[0].x, coordinates[0].y);
  for(index=1; index<coordinates.length;index++) {
    context.lineTo(coordinates[index].x, coordinates[index].y);
  }
  context.closePath();
  context.stroke();
}

body{ background-color: ivory; }
#canvas{border:1px solid red;}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h4>Click to assign polygon vertices</h4>
<button id=done>Click when done assigning points</button>
<br><canvas id="canvas" width=300 height=300></canvas>

推荐答案

给出的答案是有关处理鼠标和呈现内容的一种不良做法的示例.

The answer given is an example of bad practice in regard to handling the mouse and rendering content.

鼠标事件的渲染会消耗能量,并在不需要时强制画布渲染.鼠标可以以每秒1000次的速度发射,而最大显示速度仅为每秒60次.

Rendering from mouse events will chew power and force canvas renders when not needed. The mouse can fire at rates up to 1000 times a second while the max display rate is only 60 times a second.

使用鼠标移动事件意味着许多渲染的更新将不会被用户看到,并且充其量只是在浪费CPU/GPU周期,最糟糕的是会浪费大量电池.

Using mouse move events means that many of the rendered updates will not be seen by the user, and are just wasted CPU/GPU cycles at best, at worst a major battery drain.

始终使用 requestAnimationFrame 呈现任何经常更改的内容.

Always use requestAnimationFrame to render any content that is frequently changing.

下面的示例使用requestAnimationFrame从输入事件中取消渲染渲染,仅在需要时才渲染内容.它还通过光标和突出显示的点为用户添加了一些反馈.

The example below decoples the rendering from input events using requestAnimationFrame to render content only when needed. It also adds some feedback for the user via the cursor and highlighting points.

var ctx = canvas.getContext("2d");
requestAnimationFrame(update)

mouse = {x : 0, y : 0, button : 0, lx : 0, ly : 0, update : true};
function mouseEvents(e){
	const bounds = canvas.getBoundingClientRect();
	mouse.x = e.pageX - bounds.left - scrollX;
	mouse.y = e.pageY - bounds.top - scrollY;
	mouse.button = e.type === "mousedown" ? true : e.type === "mouseup" ? false : mouse.button;
  mouse.update = true;
}
["mousedown","mouseup","mousemove"].forEach(name => document.addEventListener(name,mouseEvents));



ctx.lineWidth = 2;
ctx.strokeStyle = "blue";
const point = (x,y) => ({x,y});
const poly = () => ({
    points : [],
    addPoint(p){ this.points.push(point(p.x,p.y)) },
    draw() {
        ctx.lineWidth = 2;
        ctx.strokeStyle = "blue";
        ctx.beginPath();
        for (const p of this.points) { ctx.lineTo(p.x,p.y) }
        ctx.closePath();
        for (const p of this.points) {
            ctx.moveTo(p.x + 4,p.y);
            ctx.arc(p.x,p.y,4,0,Math.PI *2);
        }
        ctx.stroke();
    },
    closest(pos, dist = 8) {
        var i = 0, index = -1;
        dist *= dist;
        for (const p of this.points) {
            var x = pos.x - p.x;
            var y = pos.y - p.y;
            var d2 =  x * x + y * y;
            if (d2 < dist) {
                dist = d2;
                index = i;
            }
            i++;
        }
        if (index > -1) { return this.points[index] }
    }
});
function drawCircle(pos,color="red",size=8){
    ctx.strokeStyle = color;
    ctx.beginPath();
    ctx.arc(pos.x,pos.y,size,0,Math.PI *2);
    ctx.stroke();
}
const polygon = poly();
var activePoint,cursor;
var dragging= false;
function update(){
    if (mouse.update) {
        cursor = "crosshair";
        ctx.clearRect(0,0,canvas.width,canvas.height);
        if (!dragging) {  activePoint = polygon.closest(mouse) }
        if (activePoint === undefined && mouse.button) {
            polygon.addPoint(mouse);
            mouse.button = false;
        } else if(activePoint) {
            if (mouse.button) {
                if(dragging) {
                    activePoint.x += mouse.x - mouse.lx;
                    activePoint.y += mouse.y - mouse.ly;
                } else {  dragging = true }
            } else { dragging = false }
        }
        polygon.draw();
        if (activePoint) { 
            drawCircle(activePoint);
            cursor = "move";
        }

        mouse.lx = mouse.x;
        mouse.ly = mouse.y;
        canvas.style.cursor = cursor;
        mouse.update = false;
    }
    requestAnimationFrame(update)
}

#canvas{
  border:1px 
  solid black;
}

<canvas id="canvas" width=300 height=300></canvas>

这篇关于编辑路径点或线的选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆