我尝试复制fabric's manage selection
为此 我创建了一个“绘画应用程序”,在其中可以绘制线条绘制矩形并拖动 目的是在单击拖动输入时,将矩形内的所有行与矩形本身拖放在一起
我将行协调存储在storedLines中 在mousedown中:
我获得了当前鼠标的位置,将isDragging标志设置在鼠标下方的任何形状上
保存当前鼠标位置,并在storedLines中循环浏览以查看矩形内的所有线
if(that.type == "drag"){
dragok=false;
for(var i=0;i<storedLines.length;i++){
var r=storedLines[i];
if(r.x1>startX && r.x2<(mouseX + startX) && r.y1>startY && r.y2<(mouseY + startY)){
// if yes, set that rects isDragging=true
dragok=true;
r.isDragging=true;
ctx.strokeStyle = "blue";
}
}
}
在mousemove中:
我得到了当前的鼠标位置
计算鼠标移动了多远(distance = newMousePosition-oldMousePosition)
将距离添加到isDragging的任何形状的位置
保存当前鼠标位置
使用新位置的形状重绘场景
但是问题是我无法将其拖放,因为即使在鼠标按下时单击下拉按钮,我仍会继续绘制矩形
var storedLines = [];
var startX = 0;
var startY = 0;
var isDown;
var type = "line"; // current type
var dragok = false;
class CanvasState{
// **** First some setup! ****
constructor(canvas){
this.canvas = canvas;
this.type = type;
this.width = canvas.width;
this.height = canvas.height;
this.ctx = canvas.getContext('2d');
var offsetX = canvas.offsetLeft;
var offsetY = canvas.offsetTop;
this.valid = false; // when set to false, the canvas will redraw everything
this.shapes = []; // the collection of things to be drawn
this.dragging = false; // Keep track of when we are dragging
this.selection = null;
this.dragoffx = 0; // See mousedown and mousemove events for explanation
this.dragoffy = 0;
var myState = this;
this.selectionColor = '#CC0000';
this.selectionWidth = 2;
var that = this;
canvas.addEventListener('selectstart', function(e) { e.preventDefault(); return false; }, false);
// Up, down, and move are for dragging
canvas.addEventListener('mousedown', function(e) {
e.preventDefault();
e.stopPropagation();
canvas.style.cursor = "crosshair";
var mouseX = parseInt(e.clientX - offsetX);
var mouseY = parseInt(e.clientY - offsetY);
isDown = true;
startX = mouseX;
startY = mouseY;
// test each rect to see if lines are inside
if(that.type == "drag"){
dragok=false;
for(var i=0;i<storedLines.length;i++){
var r=storedLines[i];
if(r.x1>startX && r.x2<(mouseX + startX) && r.y1>startY && r.y2<(mouseY + startY)){
// if yes, set that rects isDragging=true
dragok=true;
r.isDragging=true;
ctx.strokeStyle = "blue";
}
}
}
}, true);
canvas.addEventListener('mousemove', function(e) {
e.preventDefault();
e.stopPropagation();
var ctx = canvas.getContext('2d');
if (!isDown) return;
myState.redrawStoredLines();
var mouseX = parseInt(e.clientX - offsetX);
var mouseY = parseInt(e.clientY - offsetY);
if(that.type == "rect"){
ctx.beginPath();
ctx.rect(startX, startY, mouseX - startX, mouseY - startY);
ctx.stroke();
}
// if we're dragging anything...
if (that.type == "drag"){
// tell the browser we're handling this mouse event
e.preventDefault();
e.stopPropagation();
// get the current mouse position
var mx=parseInt(e.clientX-offsetX);
var my=parseInt(e.clientY-offsetY);
// calculate the distance the mouse has moved
// since the last mousemove
var dx=mx-startX;
var dy=my-startY;
// move each line that isDragging
// by the distance the mouse has moved
// since the last mousemove
myState.redrawStoredLines();
}
if(that.type == "line"){
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.lineTo(mouseX, mouseY);
ctx.stroke();
}
}, true);
canvas.addEventListener('mouseup', function(e) {
canvas.style.cursor = "default";
e.preventDefault();
e.stopPropagation();
isDown = false;
var mouseX = parseInt(e.clientX - offsetX);
var mouseY = parseInt(e.clientY - offsetY);
storedLines.push({
type: that.type,
x1: startX,
y1: startY,
x2: mouseX,
y2: mouseY
});
console.log(storedLines);
myState.redrawStoredLines();
}, true);
canvas.addEventListener('handleMouseOut', function(e) {
e.preventDefault();
e.stopPropagation();
if (!isDown) return;
isDown = false;
var mouseX = parseInt(e.clientX - offsetX);
var mouseY = parseInt(e.clientY - offsetY);
storedLines.push({
type: that.type,
x1: startX,
y1: startY,
x2: mouseX,
y2: mouseY
});
myState.redrawStoredLines();
}, true);
}
setType(newtype){
if ( newtype === 'line' ) {
this.type = "line";
}
if ( newtype === 'rect' ) {
this.type = "rect";
console.log('settype:' + this.type);
}
}
redrawStoredLines() {
var ctx = this.canvas.getContext('2d');
ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
if (storedLines.length == 0) return;
// redraw each stored line
for (var i = 0; i < storedLines.length; i++) {
if(storedLines[i].type === "line"){
ctx.beginPath();
ctx.moveTo(storedLines[i].x1, storedLines[i].y1);
ctx.lineTo(storedLines[i].x2, storedLines[i].y2);
ctx.stroke();
}
if(storedLines[i].type === "rect"){
ctx.beginPath();
ctx.rect(storedLines[i].x1, storedLines[i].y1,
storedLines[i].x2 - storedLines[i].x1, storedLines[i].y2 - storedLines[i].y1);
ctx.stroke();
}
if (storedLines[i].type === "drag"){
// move each line that isDragging
// by the distance the mouse has moved
// since the last mousemove
for(var i=0;i<storedLines.length;i++){
var r=storedLines[i];
if(r.x1>startX && r.x2<(mouseX + startX) && r.y1>startY && r.y2<(mouseY + startY)){
if(r.isDragging){
r.x+=dx;
r.y+=dy;
}
}
}
}
}
}
}
var radios = document.querySelectorAll('input[type=radio][name="shape"]');
function changeHandler(event) {
console.log(event.srcElement.value);
mycanvas.setType(event.srcElement.value);
}
Array.prototype.forEach.call(radios, function(radio) {
radio.addEventListener('change', changeHandler);
});
var mycanvas = new CanvasState(document.getElementById('mainCanvas'));
body{
font-family: Arial, Helvetica, sans-serif;
font-weight: 16px;
}
.container{
margin: 10px;
padding: 2px;
border: solid 1px black;
background-color: #505050
}
h3{
margin: 10px;
padding: 2px;
}
.toolbox{
display: inline;
list-style-type: none;
}
.toolbox > li{
display: inline-block;
margin: 0;
vertical-align: middle;
}
div.sliders div{
/*margin-top: 20px; */
display: inline-block;
}
.in-line p{
font-size: 14px;
display: block;
}
.in-line input{
margin: 5px;
display: block;
}
#square{
margin-top: 20px;
margin-left: 48%;
width: 50px;
height: 50px;
background-color: rgb(127, 127, 127);
}
#rgbcolor{
font-size: 14px;
text-align: center;
}
#clearbtn{
width: 50px;
margin-left: 48%;
margin-top: 10px;
}
.canvas{
margin: 10px;
position: relative;
width: 600px;
height: 400px;
border: solid 1px black;
background-color: #ffffff;
cursor: crosshair;
}
#coords{
text-align: center;
}
<div class="container">
<h3>Drawing Shapes</h3>
<div>
<ul class="toolbox">
<li id="btns">
<div >
<input type="radio" name="shape" id="line" value="line">Line<br>
<input type="radio" name="shape" id="drag" value="drag">Drag<br>
<input type="radio" name="shape" id="rect" value="rect">Rectangle<br>
</div>
<div class="sliders">
<div class="in-line">
<p>Red</p>
<p>Green</p>
<p>Blue</p>
</div>
<div class="in-line">
<input type="range" min="0" max="255" value="127" name="Red" id="red" >
<input type="range" min="0" max="255" value="127" name="Green" id="green" >
<input type="range" min="0" max="255" value="127" name="Blue" id="blue" >
</div>
</div>
<div><p id="rgbcolor">RGB(127, 127, 127)</p><div id="square"></div></div>
</li>
<li id="cnvs">
<div>
<canvas id="mainCanvas" class="canvas" width="600" height="400"></canvas>
<h3 id="coords">(X, Y) : (0 , 0)</h3>
</div>
</li>
</ul>
</div>
</div>