在 2 个画布之间拖放多个项目
以下是代码的作用:
- 单击以从顶部源画布中选择一个或多个图像
- 再次单击图像以打开/关闭其选择
- 完成所有选择后,从顶部画布拖动到底部画布
- 您的选择将移动到底部画布
关于代码的一些解释:
- 每个图像都存储在一个名为 Images 的数组中
- 每个图像的 item-object 存储在一个名为 items 的数组中
- item-object 包含一个 item 的描述、image-url、一个 isSelected 标志和一个 isDropped 标志。
- 顶部源画布的 mouseup 事件处理程序检查图像上的命中并切换它们的 isSelected 标志。
- mouseup 事件处理程序响应拖放到底部放置画布上。它检查选定的项目并通过设置它们的 isDropped 标志将它们记录为已丢弃。
- drawContainer 函数根据它们的 isDropped 标志在源画布和放置画布之间分配项目(isDropped==false 在顶部源画布中绘制 - isDropped==true 在底部放置画布中绘制)
这是代码和小提琴:http: //jsfiddle.net/m1erickson/3KqgX/
<!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; padding:10px; }
canvas{border:1px solid red;}
#canvas {
}
#canvas:active {
cursor: move;
}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var drop=document.getElementById("dropzone");
var dropCtx=drop.getContext("2d");
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var mouseIsDown=false;
var frameWidth=128;
var frameHeight=128;
// checkmark for selected
var checkmark=document.createElement("img");
checkmark.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/smallCheckmark.png";
var images=[];
var items=[];
items.push({description:"House#1",url:"https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house1.jpg",isSelected:false,isDropped:false,x:0,y:0});
items.push({description:"House#2",url:"https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house2.jpg",isSelected:false,isDropped:false,x:0,y:0});
items.push({description:"House#3",url:"https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house3.jpg",isSelected:false,isDropped:false,x:0,y:0});
var imgLoadCount=0;
for(var i=0;i<items.length;i++){
images[i]=document.createElement("img");
images[i].onload=function(){
if(++imgLoadCount>=items.length){ draw(); }
}
images[i].src=items[i].url;
}
function draw(){
ctx.clearRect(0,0,canvas.width,canvas.height);
dropCtx.clearRect(0,0,drop.width,drop.height);
var canvasX=0;
var dropX=0;
//
for(var i=0;i<items.length;i++){
if(items[i].isDropped){
x=dropX*160+10;
drawContainer(dropCtx,i,x,20);
dropX++;
items[i].x=x;
}else{
x=canvasX*160+10;
drawContainer(ctx,i,x,20);
canvasX++;
items[i].x=x;
}
}
}
// draw image container
function drawContainer(context,index,x,y){
context.beginPath();
context.rect(x,y+frameHeight,frameWidth,30);
context.fillStyle="black";
context.fill();
context.beginPath();
context.fillStyle="white";
context.font="10pt Verdana";
context.fillText(items[index].description,x+10,y+frameHeight+18);
// draw a thumbnail of the image
var img=images[index];
if(img.width>=img.height){
context.drawImage(img,0,0,img.width,img.height,
x,y,128,128*img.height/img.width);
}else{
context.drawImage(img,0,0,img.width,img.height,
x,y,128*img.width/img.height,128); // edited s/b [,128], not [/128]
}
// outer frame (green if selected)
context.beginPath();
context.rect(x-2,y-2,frameWidth+4,frameHeight+30+4);
context.lineWidth=3;
context.strokeStyle="lightgray";
if(items[index].isSelected){
context.strokeStyle="green";
context.drawImage(checkmark,x+frameWidth-30,y+frameHeight+3);
}
context.stroke();
}
function handleMouseDown(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// Put your mousedown stuff here
mouseIsDown=true;
}
function handleMouseUp(e){
mouseIsDown=false;
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// Put your mouseup stuff here
for(var i=0;i<items.length;i++){
var item=items[i];
// have we clicked on something?
if(!item.isDropped && mouseX>=item.x && mouseX<=item.x+frameWidth){
// if so, toggle its selection
items[i].isSelected=!(items[i].isSelected);
draw();
}
}
}
function handleMouseOut(e){
if(!mouseIsDown){return;}
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// Put your mouseOut stuff here
}
function handleMouseMove(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// Put your mousemove stuff here
}
function handleDrop(e){
for(var i=0;i<items.length;i++){
if(items[i].isSelected){
items[i].isDropped=true;
items[i].isSelected=false;
console.log(i);
}
}
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);});
$("#dropzone").mouseup(function(e){handleDrop(e);});
}); // end $(function(){});
</script>
</head>
<body>
<p>Click an item to toggle it's selection</p>
<p>Drag from top to bottom canvas to drop selected items</p>
<canvas id="canvas" width=500 height=200></canvas><br>
<canvas id="dropzone" width=500 height=200></canvas>
</body>
</html>
[补充:按删除顺序对底部画布进行排序的替代代码]
function handleDrop(e){
for(var i=items.length-1;i>=0;i--){
if(items[i].isSelected){
items[i].isDropped=true;
items[i].isSelected=false;
// sort the bottom canvas by order dropped
var move=items[i];
items.splice(i,1);
items.push(move);
}
}
draw();
}
[编辑以在 KineticJS 中提出解决方案]
这是代码和小提琴:http: //jsfiddle.net/m1erickson/bSpBF/
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.1.min.js"></script>
<style>
body{ background-color: ivory; padding:10px;}
#container1,#container2{
border:solid 1px #ccc;
margin-top: 10px;
width:300px;
height:100px;
}
#container2{
height:300px;
}
</style>
<script>
$(function(){
var highlightWidth=8;
var stage = new Kinetic.Stage({
container: 'container1',
width: 300,
height: 100
});
var layer = new Kinetic.Layer();
stage.add(layer);
var dropzone = new Kinetic.Stage({
container: 'container2',
width: 300,
height: 300
});
var dropLayer = new Kinetic.Layer();
dropzone.add(dropLayer);
// these must go after the creation of stages & layers
addBackground(stage,layer,dropLayer);
layer.draw();
addBackground(dropzone,dropLayer,layer);
dropLayer.draw();
// get images & then trigger start()
var images={};
var URLs = {
house1: 'https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-3.jpg',
house2: 'https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-4.jpg',
house3: 'https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-1.jpg'
};
loadImages(URLs,start);
function start(){
var house1=kImage(images.house1,10,10,50,50,layer);
var house2=kImage(images.house2,75,10,50,50,layer);
var house3=kImage(images.house3,140,10,50,50,layer);
layer.draw();
}
function swapStagesIfSelected(sourceLayer,destinationLayer,startX,startY){
// get all elements on the source layer
var elements=sourceLayer.get("Image");
// don't let dropped elements fall off the stage
var totalWidth=0;
var maxHeight=-999;
var layerWidth=destinationLayer.getStage().getWidth();
var layerHeight=destinationLayer.getStage().getHeight();
for(var i=0;i<elements.length;i++){
if(elements[i].isSelected){
totalWidth+=elements[i].getWidth();
maxHeight=Math.max(elements[i].getHeight(),maxHeight);
}
}
if(startX+totalWidth>layerWidth){
startX=layerWidth-totalWidth-15;
}
if(startY+maxHeight>layerHeight){
startY=layerHeight-maxHeight-15;
}
// move all selected images
// to the clicked x/y of the destination layer
for(var i=0;i<elements.length;i++){
var element=elements[i];
if(element.isSelected){
var img=element.getImage();
kImage(img,startX,startY,element.getWidth(),element.getHeight(),destinationLayer);
startX+=element.getWidth()+10;
element.remove();
}
}
sourceLayer.draw();
destinationLayer.draw();
}
// build the specified KineticJS Image and add it to the specified layer
function kImage(image,x,y,width,height,theLayer){
var image=new Kinetic.Image({
image:image,
x:x,
y:y,
width:width,
height:height,
strokeWidth:0.1,
stroke:"green",
draggable:true
});
image.myLayer=theLayer;
image.isSelected=false;
image.on("click",function(){
highlight(this);
this.myLayer.draw();
});
image.myLayer.add(image);
return(image);
}
// build a background image and add it to the specified stage
function addBackground(theStage,theLayer,otherLayer){
var background = new Kinetic.Rect({
x: 0,
y: 0,
width: theStage.getWidth(),
height: theStage.getHeight(),
fill: "white",
stroke: "green",
strokeWidth: 1
});
background.on("click",function(){
var pos=theStage.getMousePosition();
var mouseX=parseInt(pos.x);
var mouseY=parseInt(pos.y);
swapStagesIfSelected(otherLayer,theLayer,mouseX,mouseY);
});
theLayer.add(background);
}
///////////// Image loader
function loadImages(URLs, callback) {
var loaded = 0;
var needed = 0;
for(var url in URLs) { needed++; console.log(url); }
for(var url in URLs) {
images[url] = new Image();
images[url].onload = function() {
if(++loaded >= needed) {
callback(images);
}
};
images[url].src = URLs[url];
}
}
///////////// Toggle Highlighting
function highlight(element,setStrokeWidth){
if(setStrokeWidth){
element.setStrokeWidth(setStrokeWidth);
}else{
if(element.getStrokeWidth()>5){
element.setStrokeWidth(0.1);
element.isSelected=false;
}else{
element.setStrokeWidth(highlightWidth);
element.isSelected=true;
}
}
}
}); // end $(function(){});
</script>
</head>
<body>
<p>Click on image(s) to toggle selection</p>
<p>Then click in the other canvas to drop</p>
<div id="container1"></div>
<div id="container2"></div>
<button id="clear">Clear Hightlights</button>
<button id="swap">Swap Selected</button>
</body>
</html>