如何使放置的图像在 canvas 内可拖动?
How can make a dropped image draggable within the canvas ?
http://jsfiddle.net/m1erickson/2Us2S/
**我正在使用这段代码,我怎样才能使拖放的图像成为可拖动的。我试过 jquery 但我需要在 canvas 中拖动相同的内容。开导我 。 **
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var $canvas = $("#canvas");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var image1 = new Image();
image1.src = "https://dl.dropboxusercontent.com/u/139992952/Whosebug/house32x32transparent.png";
var $house = $("#house");
var $canvas = $("#canvas");
$house.draggable({
helper: 'clone',
});
// set the data payload
$house.data("image", image1); // key-value pair
$canvas.droppable({
drop: dragDrop,
});
function dragDrop(e, ui) {
var element = ui.draggable;
var data = element.data("url");
var x = parseInt(ui.offset.left - offsetX);
var y = parseInt(ui.offset.top - offsetY);
ctx.drawImage(element.data("image"), x - 1, y);
}
一旦您将图像绘制到 canvas 上,房子就会在 canvas 上变成不可记忆的、不可移动的像素。不能再用jQuery拖房子了
Canvas "moves" 通过擦除 canvas 并在改变的位置重新绘制内容。
Canvas "drags" 通过监听鼠标事件:
In mousedown
,检查鼠标是否在 canvas 上绘制的任何房屋上。为此,您要记住房屋的绘制位置,然后使用鼠标位置使用房屋的边界框进行命中测试。设置一个 isDragging
标志以指示房子被鼠标击中并应被拖动。
In mousemove
,重新绘制自上次鼠标移动后鼠标移动距离的房子。
In mouseup & mouseout
,拖动操作结束,清除isDragging
标志。
要创建一个边界框来进行命中测试,您至少需要跟踪房屋图像的宽度和高度以及它在 canvas 上放置位置的 x、y 坐标。您通常将此信息保存在 javascript 对象中。
这是带注释的代码和演示:
// canvas related stuff
var canvas=document.getElementById("myCanvas");
var ctx=canvas.getContext("2d");
var WIDTH = canvas.width;
var HEIGHT = canvas.height;
ctx.fillStyle = "#A0DCE5";
$myCanvas=$('#myCanvas');
//drag
var isDragging = false;
var startX;
var startY;
//array of image objects
var images=[];
var NUM_IMAGES=0;
// queue up 4 test images
addImage(20,20,0.50,'https://dl.dropboxusercontent.com/u/139992952/Whosebug/house204-1.jpg');
addImage(240,20,0.50,'https://dl.dropboxusercontent.com/u/139992952/Whosebug/house204-2.jpg');
addImage(20,220,0.50,'https://dl.dropboxusercontent.com/u/139992952/Whosebug/house204-3.jpg');
addImage(240,220,0.50,'https://dl.dropboxusercontent.com/u/139992952/Whosebug/house204-4.jpg');
// trigger all images to load
for(var i=0;i<images.length;i++){
images[i].image.src=images[i].url;
}
//////////////////////////////
// functions
//////////////////////////////
// queue up another image
function addImage(x,y,scaleFactor,imgURL){
var img=new Image();
img.crossOrigin='anonymous';
img.onload=startInteraction;
images.push({image:img,x:x,y:y,scale:scaleFactor,isDragging:false,url:imgURL});
NUM_IMAGES++;
}
// called after each image fully loads
function startInteraction() {
// return until all images are loaded
if(--NUM_IMAGES>0){return;}
// set all images width/height
for(var i=0;i<images.length;i++){
var img=images[i];
img.width=img.image.width*img.scale;
img.height=img.image.height*img.scale;
}
// render all images
renderAll();
// listen for mouse events
$myCanvas.mousedown(onMouseDown);
$myCanvas.mouseup(onMouseUp);
$myCanvas.mouseout(onMouseUp);
$myCanvas.mousemove(onMouseMove);
}
// flood fill canvas and
// redraw all images in their assigned positions
function renderAll() {
ctx.fillRect(0,0,WIDTH,HEIGHT);
for(var i=0;i<images.length;i++){
var r=images[i];
ctx.drawImage(r.image,r.x,r.y,r.width,r.height);
}
}
// handle mousedown events
function onMouseDown(e){
// tell browser we're handling this mouse event
e.preventDefault();
e.stopPropagation();
//get current position
var mx=parseInt(e.clientX-$myCanvas.offset().left);
var my=parseInt(e.clientY-$myCanvas.offset().top);
//test to see if mouse is in 1+ images
isDragging = false;
for(var i=0;i<images.length;i++){
var r=images[i];
if(mx>r.x && mx<r.x+r.width && my>r.y && my<r.y+r.height){
//if true set r.isDragging=true
r.isDragging=true;
isDragging=true;
}
}
//save mouse position
startX=mx;
startY=my;
}
// handle mouseup and mouseout events
function onMouseUp(e){
//tell browser we're handling this mouse event
e.preventDefault();
e.stopPropagation();
// clear all the dragging flags
isDragging = false;
for(var i=0;i<images.length;i++){
images[i].isDragging=false;
}
}
// handle mousemove events
function onMouseMove(e){
// do nothing if we're not dragging
if(!isDragging){return;}
//tell browser we're handling this mouse event
e.preventDefault
e.stopPropagation
//get current mouseposition
var mx = parseInt(e.clientX-$myCanvas.offset().left);
var my = parseInt(e.clientY-$myCanvas.offset().top);
//calculate how far the mouse has moved;
var dx = mx - startX;
var dy = my - startY;
//move each image by how far the mouse moved
for(var i=0;i<images.length;i++){
var r=images[i];
if(r.isDragging){
r.x+=dx;
r.y+=dy;
}
}
//reset the mouse positions for next mouse move;
startX = mx;
startY = my;
//re render the images
renderAll();
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Drag a house with the mouse.</h4>
<canvas id="myCanvas" width=400 height=400></canvas>
http://jsfiddle.net/m1erickson/2Us2S/
**我正在使用这段代码,我怎样才能使拖放的图像成为可拖动的。我试过 jquery 但我需要在 canvas 中拖动相同的内容。开导我 。 **
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var $canvas = $("#canvas");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var image1 = new Image();
image1.src = "https://dl.dropboxusercontent.com/u/139992952/Whosebug/house32x32transparent.png";
var $house = $("#house");
var $canvas = $("#canvas");
$house.draggable({
helper: 'clone',
});
// set the data payload
$house.data("image", image1); // key-value pair
$canvas.droppable({
drop: dragDrop,
});
function dragDrop(e, ui) {
var element = ui.draggable;
var data = element.data("url");
var x = parseInt(ui.offset.left - offsetX);
var y = parseInt(ui.offset.top - offsetY);
ctx.drawImage(element.data("image"), x - 1, y);
}
一旦您将图像绘制到 canvas 上,房子就会在 canvas 上变成不可记忆的、不可移动的像素。不能再用jQuery拖房子了
Canvas "moves" 通过擦除 canvas 并在改变的位置重新绘制内容。
Canvas "drags" 通过监听鼠标事件:
In mousedown
,检查鼠标是否在 canvas 上绘制的任何房屋上。为此,您要记住房屋的绘制位置,然后使用鼠标位置使用房屋的边界框进行命中测试。设置一个isDragging
标志以指示房子被鼠标击中并应被拖动。In mousemove
,重新绘制自上次鼠标移动后鼠标移动距离的房子。In mouseup & mouseout
,拖动操作结束,清除isDragging
标志。
要创建一个边界框来进行命中测试,您至少需要跟踪房屋图像的宽度和高度以及它在 canvas 上放置位置的 x、y 坐标。您通常将此信息保存在 javascript 对象中。
这是带注释的代码和演示:
// canvas related stuff
var canvas=document.getElementById("myCanvas");
var ctx=canvas.getContext("2d");
var WIDTH = canvas.width;
var HEIGHT = canvas.height;
ctx.fillStyle = "#A0DCE5";
$myCanvas=$('#myCanvas');
//drag
var isDragging = false;
var startX;
var startY;
//array of image objects
var images=[];
var NUM_IMAGES=0;
// queue up 4 test images
addImage(20,20,0.50,'https://dl.dropboxusercontent.com/u/139992952/Whosebug/house204-1.jpg');
addImage(240,20,0.50,'https://dl.dropboxusercontent.com/u/139992952/Whosebug/house204-2.jpg');
addImage(20,220,0.50,'https://dl.dropboxusercontent.com/u/139992952/Whosebug/house204-3.jpg');
addImage(240,220,0.50,'https://dl.dropboxusercontent.com/u/139992952/Whosebug/house204-4.jpg');
// trigger all images to load
for(var i=0;i<images.length;i++){
images[i].image.src=images[i].url;
}
//////////////////////////////
// functions
//////////////////////////////
// queue up another image
function addImage(x,y,scaleFactor,imgURL){
var img=new Image();
img.crossOrigin='anonymous';
img.onload=startInteraction;
images.push({image:img,x:x,y:y,scale:scaleFactor,isDragging:false,url:imgURL});
NUM_IMAGES++;
}
// called after each image fully loads
function startInteraction() {
// return until all images are loaded
if(--NUM_IMAGES>0){return;}
// set all images width/height
for(var i=0;i<images.length;i++){
var img=images[i];
img.width=img.image.width*img.scale;
img.height=img.image.height*img.scale;
}
// render all images
renderAll();
// listen for mouse events
$myCanvas.mousedown(onMouseDown);
$myCanvas.mouseup(onMouseUp);
$myCanvas.mouseout(onMouseUp);
$myCanvas.mousemove(onMouseMove);
}
// flood fill canvas and
// redraw all images in their assigned positions
function renderAll() {
ctx.fillRect(0,0,WIDTH,HEIGHT);
for(var i=0;i<images.length;i++){
var r=images[i];
ctx.drawImage(r.image,r.x,r.y,r.width,r.height);
}
}
// handle mousedown events
function onMouseDown(e){
// tell browser we're handling this mouse event
e.preventDefault();
e.stopPropagation();
//get current position
var mx=parseInt(e.clientX-$myCanvas.offset().left);
var my=parseInt(e.clientY-$myCanvas.offset().top);
//test to see if mouse is in 1+ images
isDragging = false;
for(var i=0;i<images.length;i++){
var r=images[i];
if(mx>r.x && mx<r.x+r.width && my>r.y && my<r.y+r.height){
//if true set r.isDragging=true
r.isDragging=true;
isDragging=true;
}
}
//save mouse position
startX=mx;
startY=my;
}
// handle mouseup and mouseout events
function onMouseUp(e){
//tell browser we're handling this mouse event
e.preventDefault();
e.stopPropagation();
// clear all the dragging flags
isDragging = false;
for(var i=0;i<images.length;i++){
images[i].isDragging=false;
}
}
// handle mousemove events
function onMouseMove(e){
// do nothing if we're not dragging
if(!isDragging){return;}
//tell browser we're handling this mouse event
e.preventDefault
e.stopPropagation
//get current mouseposition
var mx = parseInt(e.clientX-$myCanvas.offset().left);
var my = parseInt(e.clientY-$myCanvas.offset().top);
//calculate how far the mouse has moved;
var dx = mx - startX;
var dy = my - startY;
//move each image by how far the mouse moved
for(var i=0;i<images.length;i++){
var r=images[i];
if(r.isDragging){
r.x+=dx;
r.y+=dy;
}
}
//reset the mouse positions for next mouse move;
startX = mx;
startY = my;
//re render the images
renderAll();
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Drag a house with the mouse.</h4>
<canvas id="myCanvas" width=400 height=400></canvas>