如何在一个画布上启用绘制和删除多个元素?

Tweakimp

我正在尝试为乒乓球运动图形编写生成器。我希望它为练习的每个集会显示一个表格,上面带有箭头,这些箭头表示球的运动路径和要玩的区域的矩形。

现在看起来像这样:https : //codepen.io/graNite/pen/grqXOo

您可以添加新表,删除最后一个表,并在第一个表的同一画布层上绘制两个固定箭头。

我要启用的功能是通过单击并拖动在每个表格上绘制箭头*,然后右键单击将其删除。

*(就像它们是在drawArrows函数中绘制的一样

做这个的最好方式是什么?

我已经为箭头实现了画布层,甚至可以为每个表上的每个单个箭头实现画布层,但是如果我右键单击它来删除它,如何访问中间层中的箭头呢?

的HTML

<button onclick="addTable()">Add table</button>
<button onclick="removeTable()">Remove table</button>
<button onclick="drawArrow(50, 50, 150, 250)">Draw arrow</button>
<button onclick="drawArrow(50, 300, 180, 20)">Draw arrow2</button>
</br>
<div id="tables">
</div>

的CSS

body {
    background-color: #982439;
}

#table {
    padding: 10px;
}

canvas {
    position: absolute;
}

JS

function drawTable(table) {
    "use strict";
    var draw = table.getContext("2d");
    draw.shadowBlur = 20;
    draw.shadowColor = 'rgba(0,0,0,0.3)';            // shadow
    draw.fillStyle = "#2e3f73";                      // table
    draw.fillRect(35.25,    20,      152.5,  274);
    draw.fillStyle = "#ffffff";                      // lines
    draw.fillRect(111.35,   20,      0.3,    274);   // middle line
    draw.fillRect(35.25,    20,      2,      274);   // lift side
    draw.fillRect(185.75,   20,      2,      274);   // right side
    draw.fillRect(35.25,    20,      152.5,  2);     // top base line
    draw.fillRect(35.25,    292,     152.5,  2);     // bottom base line
    draw.fillRect(20,       156,     183,    2);     // net
}

function addTable() {
    "use strict";
    var container = document.createElement("div"),
        table = document.createElement("canvas"),
        arrowLayer = document.createElement("canvas"),
        width = 223,
        height = 314;


    container.appendChild(table);
    container.appendChild(arrowLayer);
    container.style.width = width + "px";
    container.style.height = height + "px";
    container.style.display = "inline-block";
    document.getElementById("tables").appendChild(container);

    table.width = width;
    table.height = height;
    table.className = "table";
    table.style.zIndex = "0";
    drawTable(table);

    arrowLayer.width = width;
    arrowLayer.height = height;
    arrowLayer.className = "arrow";
    arrowLayer.style.zIndex = "1";
    arrowLayer.id = "arrow1";
}

function removeTable() {
    "use strict";
    var child = document.getElementById("tables").lastChild;
    child.parentNode.removeChild(child);
}

function drawArrow(start_x, start_y, end_x, end_y) {
    "use strict";
    var draw = document.getElementById('arrow1').getContext('2d'),
        angle = Math.atan((end_y - start_y) / (end_x - start_x)),
        length = Math.sqrt(Math.pow((end_x - start_x), 2) + Math.pow((end_y - start_y), 2));

    // set colors and style
    draw.strokeStyle = "#ffb900";
    draw.fillStyle = "#ffb900";
    draw.lineWidth = 9;

    // draw arrow line
    draw.beginPath();
    draw.translate(start_x, start_y);
    draw.moveTo(0, 0);
    draw.rotate(angle);
    draw.lineTo(length - 23, 0); // note: arrowhead is 24px long and total arrow is line+head   
    draw.stroke();
    draw.moveTo(-start_x, -start_y);

    // draw arrow head
    draw.beginPath();
    draw.moveTo(length, 0);
    draw.lineTo(length - 24, -7.5); // ^ see note above
    draw.lineTo(length - 24, 7.5);
    draw.fill();

    //reset context 
    draw.rotate(-angle);
    draw.moveTo(-start_x, -start_y);
    draw.translate(-start_x, -start_y);
}
盲人67

良好的界面设计

优质的界面应该没有难看的按钮,它应该直观易用。始终应该有反馈(光标,突出显示,翻转效果)。效果并没有显示那么多,而是提供了用户与应用程序交互所需的信息。因此,FX不必是主要的,仅足以让用户看到一切正常,可点击的内容和不可点击的内容。

我本来会在没有帮助的情况下添加它,因为它应该有意义,但是我添加了帮助,以防万一。我们都有接口使用的不同方法。

更新:我添加了更多代码。现在仅在使用帮助功能之前显示帮助。一旦使用,该帮助将不会显示。

通过代码在我认为需要的地方添加了注释(基本上在所有地方)

代码

表位于数组中tableArray添加addTable()了表,表将返回表对象。表默认为非活动状态table.active=false要激活点击表鼠标或table.active = true; table.draw();箭头是在阵列中table.arrows作为{x:?,y?,xx:?,yy:?,highlight:false}以除去使用阵列剪接或经由接口。要删除表,请将其停用table.active = false;(或单击关闭),该表将保留在DOM中,直到updateTables()调用l (当由用户鼠标单击关闭时,更新将自动调用)

总是会有一个不活动的表可见,可以用来添加一个活动表。

数组中的每个表都具有执行其操作所需的一切。Mouseevent,渲染事件,关闭等。

每个表均以全帧速率渲染(当它具有内部鼠标焦点时),因此您可以根据需要添加漂亮的动画。当鼠标不在表格上时,除非您调用该table.draw()函数,否则它不会更新

该代码有点混乱,因为它有些失控。Consts定义了大多数东西(在代码顶部)。表,关闭图标和空表已预先渲染。箭头和帮助会根据需要呈现。

使用

单击一个空表以添加(激活)。单击活动表关闭图标以关闭。单击拖动以添加箭头,在靠近箭头时单击鼠标右键以删除。鼠标附近的箭头将突出显示。

注意表的数量没有限制。这不是一个好主意,您应该限制表的数量。当添加的表格导致页面滚动条出现时,也存在布局问题。删除表不会恢复原状。由于我不知道您想要什么,我将其留给您进行梳理。

还添加了GLOBAL_SCALEconst,该const只是出于乐趣而应用于所有常量,因此它比原始常量小一点。

// contains an array of tables.
var tableArray = [];

// App constants all up top
const GLOBAL_SCALE = 0.7;
const SHOW_HELP = true;  // set to false to have the help turned off
const SHADOW = 'rgba(0,0,0,0.8)';
const WHITE = "white";
const TABLE_REFRESH_DELAY = 50; // Time in millisecond befor updating DOM for table add and remove
const FONT = {
face : "px Arial",
size : Math.max(10,18 * GLOBAL_SCALE),
fill : WHITE,
};
const TABLE = {
width  : 223 * GLOBAL_SCALE,  // size of table
height : 314 * GLOBAL_SCALE,
tables : document.getElementById("tables"),
image : { // table image styles
    shadow : SHADOW,
    shadowBlur : 20 * GLOBAL_SCALE,
    fill :  "#2e3f73",
    lines : WHITE,
    font : FONT,
    cursor : "default",
},
empty : {  // empty table styles
    inset : 30 * GLOBAL_SCALE, // amount box is inset
    lines : 'rgba(255,255,255,0.5)',
    lineWidth : 8 * GLOBAL_SCALE,
    shadow : SHADOW,
    shadowBlur : 20 * GLOBAL_SCALE,
    font : FONT,   
    cursor : "pointer",
    highlightAmount : 0.3, // amount to highlight empty table when mouse over 0 none 1 full
},
arrow : {  // arrow styles
    width : 15 * GLOBAL_SCALE, // arrow width
    shadow : SHADOW,
    shadowBlur : 10 * GLOBAL_SCALE,
    // custom cursor
    cursor : "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADcAAAAVCAYAAADiv3Z7AAACtUlEQVRYha2Ye1NTMRDFf/KqLY/SlvIolAJFqSKOoqI4o+P3/1LXP3oi23XvTUrpzJm52Zxs9mRzczeFl/u9KkDp2FV5xb/IURT42hIoGbcsp1hMGrxegw1hU9gCWsDrDFriWrTc2FYDL/K1qZiS2KywdRO0DcAiTdIBtoEdYFfYC7Arzo7426a96+B53n/idBTDlha7VmAStiGyD9wjiegCPWAAHABDg0NhqL6B0BcGZpyF5fQM98D52lcc7SaBXlhbArrGeRTQEDgCKoNzwdsq4Aw4BUZqn8qWeGOhMryRGWt9jrRwfSMwbdF/72F6SFuxLXLPORppwspMPgYq+0v93mb63rh2OFbPU9sO5hlrcXtKRstnz2atxXwb9oCqEhYmWrRdR4F6mxdQIzqyfWjwOQOutMgHzF+RlL0FcTZrXaV77MU4YZ+EXIC/InuTuIL+B809Ay6UvX3mZ4TdmgviOiIdARPgxooywr4BX4TGbRkFvoo40/4MvHPi/HtXK+5CKxOJ+y6BXwsC/ePav18gcz+AeyeuS2ZbenFN2zJlLxuUa4fbtIkTtFfOnBfzENjum8TZbWQ4j5nt9jPgPEY+KXzn1ng6UPaYnz7p+1JphW7R6WVsM6FS/x1Ph41d5dT+KB+3at/JVrn+9/Jf6fnWjEm4ofC0jD4Fhxo4kZOpwxVwaTBl/g17q4lnDjfqnxp/17IlXMt+qYxc6NnyLafoO1f3ER8Cxyx+xG3lcKL+E9N/pknPtTATPY/VNwr8nbFYvRw7nDj+qWzZCsVnr6T8snVfj//rv1SaRbVlPxhj0Wf+/lhE3MTL1paRwFzh7Kv2qMqPbgUR3/vsOET+l7oVWIElV56Su9ky9znvczPjf+n7nBUZ3YKjW/FzbuO5MXV/U6x8E68TmrP5vuf+h1IaT5b7F+ZaSjBzrT+rAAAAAElFTkSuQmCC') 10 11, pointer",
    fill : "#ffb900",
    highlight : "#ffdc44",
    lineWidth : 1,
    line : "#ffdc44",
    lineHigh : "#ffed55",
    head : 30 * GLOBAL_SCALE, // arrow head width
    minSize : 5, // min size arrow can be if smaller then arrow is not created
},
DOM : {  // variouse dom setting for table canvas and div tags
    display : "inline-block",
    canvasClass : "table",
    zIndex : 1,
},
closeIcon : { // styles for reandering and display close icon
    size : 32 * GLOBAL_SCALE,
    fill : "red",
    lines : WHITE,
    lineWidth : Math.max(1,2 * GLOBAL_SCALE),
    shadow : SHADOW,
    shadowBlur : 20 * GLOBAL_SCALE,  
    cursor : "pointer",
    pos : {
        x : 1, // as fractions
        y : 0, 
    }
},
help : {  // text help
    empty : "Click here to|add a new table".split("|"),
    active : "Click to drag arrows".split("|"),
    activeArrow : "Right click on arrow|to remove it".split("|"),
    closeTable : "To close table|move to top right|click Close Icon".split("|"),
}
}
const MOUSE = {  // event contains a list of mouse event to listen to 
buttonMasks : [1, 2, 4, 6, 5, 3],
events : "mousemove,mousedown,mouseup,mouseout,mouseover,contextmenu".split(","),
};  // contextmenu is included as that needs to be blocked for right button events

var helpItemsUsed = {
empty : false,
active : false,
activeArrow : false,
closeTable : false,
};
const turnOffHelp = function(){
helpItemsUsed.empty = true;
helpItemsUsed.active  = true;
helpItemsUsed.activeArrow  = true;
helpItemsUsed.closeTable  = true;
};
if(!SHOW_HELP){turnOffHelp();};
// returns distance of point p to line segment x, y,xx,yy
const distFromLine = function(px,py,x,y,xx,yy){
var vx,vy,pvx,pvy,lx,ly,u;
vx = xx - x;
vy = yy - y;
pvx = px - x;
pvy = py - y;
u = (pvx * vx + pvy * vy)/(vy * vy + vx * vx);
if(u >= 0 && u <= 1){
    lx = vx * u;
    ly = vy * u;
    return Math.sqrt(Math.pow(ly - pvy,2) + Math.pow(lx - pvx,2));
}
// closest point past ends of line so get dist to closest end
return Math.min(
    Math.sqrt(Math.pow(xx - px,2)+ Math.pow(yy - py,2)),
    Math.sqrt(Math.pow(x - px,2)+ Math.pow(y - py,2))
);
}
// set up functions create images and do other general setup
function setupContext(ctx,descript){ // sets common context settings
ctx.shadowBlur = descript.shadowBlur;
ctx.shadowColor = descript.shadow;   
ctx.strokeStyle = descript.lines;          
ctx.fillStyle = descript.fill;          
ctx.lineWidth = descript.lineWidth;    
ctx.lineCap = "round";    
if(descript.font){
    ctx.font = descript.font.size + descript.font.face;
}
}
function createTableImage() {  // create image of table but why write a comment when the function tells it all???
var table = document.createElement("canvas");
table.width = TABLE.width;
table.height= TABLE.height;
var ctx = table.getContext("2d");
setupContext(ctx,TABLE.image);
var scaleX = table.width / 223; /// get the scale compared to original layout
var scaleY = table.height / 314; /// get the scale compared to original layout
ctx.fillStyle = TABLE.image.fill; 
ctx.fillRect(35.25 * scaleX,    20 * scaleY,      152.5 * scaleX,  274 * scaleY);
ctx.fillStyle = TABLE.image.lines;            // lines
ctx.fillRect(111.35 * scaleX,   20 * scaleY,      0.3,    274 * scaleY);   // middle line
ctx.fillRect(35.25 * scaleX,    20 * scaleY,      2,      274 * scaleY);   // lift side
ctx.fillRect(185.75 * scaleX,   20 * scaleY,      2,      274 * scaleY);   // right side
ctx.fillRect(35.25 * scaleX,    20 * scaleY,      152.5 * scaleX,  2);     // top base line
ctx.fillRect(35.25 * scaleX,    292 * scaleY,     152.5 * scaleX,  2);     // bottom base line
ctx.fillRect(20 * scaleX,       156 * scaleY,     183 * scaleX,    2);     // net
return table
}

function createEmptyImage() { // empty table image
var i = TABLE.empty.inset;
var image = document.createElement("canvas");
var w = image.width = TABLE.width;
var h = image.height = TABLE.height;
var ctx = image.getContext("2d");
setupContext(ctx,TABLE.empty);
ctx.strokeRect(i,    i, w - i * 2, h - i * 2);
ctx.beginPath();
ctx.moveTo(i * 2, i * 2);
ctx.lineTo(w - i * 2, h - i * 2);
ctx.moveTo(i * 2, h - i * 2);
ctx.lineTo(w - i * 2, i * 2);
ctx.stroke();
return image
}
function createCloseImage() {  // create close icon
var S = TABLE.closeIcon.size;
var s = S * 0.5;
var c = s * 0.4; // cross dist from center
var sb = TABLE.closeIcon.shadowBlur;
var l = TABLE.closeIcon.lineWidth;
var image = document.createElement("canvas");
// Image must include shadowblur
image.width = S+sb; // add blur to size
image.height= S+sb;
var ctx = image.getContext("2d");
setupContext(ctx,TABLE.closeIcon);
ctx.beginPath();
var cx = s + sb / 2;  // add half blur to get center
var cy = s + sb / 2;
ctx.arc(cx, cy, s - l, 0, Math.PI * 2);
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.moveTo(cx - c, cy - c)
ctx.lineTo(cx + c, cy + c)
ctx.moveTo(cx - c, cy + c)
ctx.lineTo(cx + c, cy - c)
ctx.stroke();
return image
}
// create the images
var tableImage = createTableImage();
var closeIcon = createCloseImage();
var emptyTableImage = createEmptyImage();


// draws a arrow a is the arrow object
function drawArrow(ctx,a){
var s = TABLE.arrow; // get arrow style
var vx,vy;
var x,y;
x = a.x;
y = a.y;
vx = a.xx-x;
vy = a.yy-y;
var dir = Math.atan2(vy,vx);
var len = Math.sqrt(vx * vx + vy * vy);
// ctx.save();
ctx.setTransform(1,0,0,1,x,y);
ctx.rotate(dir);
var w = s.width/2;
var h = Math.min(len,s.head); // ensure arrow head no bigger than arrow length
h /=2;
if(a.highlight){
    ctx.fillStyle = s.highlight;
    ctx.strokeStyle = s.lineHigh;
}else{
    ctx.fillStyle = s.fill;
    ctx.strokeStyle = s.line;
}
ctx.lineWidth = s.lineWidth;
ctx.save();
ctx.shadowBlur = s.shadowBlur;
ctx.shadowColor = s.shadow;       
ctx.beginPath();
ctx.moveTo(0,-w/2);
ctx.lineTo(len-h-h,-w);
ctx.lineTo(len-h-h,-h);
ctx.lineTo(len,0);
ctx.lineTo(len-h-h,h);
ctx.lineTo(len-h-h,w);
ctx.lineTo(0,w/2);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
}

// display help text for table
function drawHelpText(ctx,text,style){
ctx.font = style.font.size + style.font.face;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
var i,len;
len = text.length;
var y = ctx.canvas.height / 2 - len * style.font.size * 1.2;
var yy = y + 1;
ctx.strokeStyle = "#000";
ctx.lineWidth = 2;
for(i = 0; i < len; i++){
    ctx.strokeText(text[i], ctx.canvas.width / 2 + 1, yy);
    yy += TABLE.empty.font.size * 1.2;
}     
ctx.fillStyle = style.font.fill;
for(i = 0; i < len; i++){
    ctx.fillText(text[i], ctx.canvas.width / 2, y);
    y += TABLE.empty.font.size * 1.2;
} 

}
//------------------------------------------------------------
// functions for table
function drawClose(){ // draws close icon. Fades in the close mouse is
var ctx = this.ctx;
var w = closeIcon.width;
var grow = w * 0.1;
var x = (this.width - w) * TABLE.closeIcon.pos.x ;
var y = (this.height - w) * TABLE.closeIcon.pos.y ;

x += w/2; // get icon center 
y += w/2;
var dist = Math.sqrt(Math.pow(this.mouse.x - x, 2) + Math.pow(this.mouse.y - y, 2));
if(dist < TABLE.closeIcon.size / 2){
    this.mouseOverClose = true;
}else{
    this.mouseOverClose = false;
}
x -= w/2; // back to icon top left
y -= w/2;
ctx.globalAlpha = 1-(Math.min(100,(dist - w * 2)) / 100);
if(this.mouseOverClose){
    ctx.drawImage(closeIcon,x-grow,y-grow,w + grow * 2,w + grow * 2);
}else{
    ctx.drawImage(closeIcon,x,y);
}
ctx.globalAlpha = 1;
}
function drawEmpty(){ // draw empty table and handle click on empty table
var ctx = this.ctx;
ctx.drawImage(emptyTableImage,0,0);
if(this.mouse.over){
    ctx.globalCompositeOperation = "lighter"; 
    ctx.globalAlpha = TABLE.empty.highlightAmount;
    ctx.drawImage(emptyTableImage,0,0);
    ctx.globalAlpha = 1;
    ctx.globalCompositeOperation = "source-over"; 
    
    if(!helpItemsUsed.empty){ // show help is the help action has not yet been done
        drawHelpText(ctx,TABLE.help.empty,TABLE.empty);
    }
    this.cursor = TABLE.empty.cursor;
    if(this.mouse.button & 1){ // bit field
        this.buttonDown = true;
    }else if( this.buttonDown){
        this.active = true;
        setTimeout(addTable,TABLE_REFRESH_DELAY);
        this.buttonDown = false;
        helpItemsUsed.empty = true; // flag this help as not needed as user has complete that task
    }
}else{
    this.cursor = "default";
}
}
function drawTable(){  // darw the table all states
var ctx = this.ctx;
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
if(this.active){
    ctx.drawImage(tableImage,0,0);
    if(this.mouse.over){
        if(!this.dragging){ // Dont draw close icon while draggin
            this.drawCloseIcon();
        }
        if(this.mouseOverClose && ! this.dragging){ // if not dragging and mouse over close
            this.cursor = TABLE.closeIcon.cursor;   // set cursor
            if(this.mouse.button & 1){ // bit field  is mouse left down
                this.buttonDown = true;
            }else if(this.buttonDown){ // only close if mouse moves up while over close.
                this.active = false;
                helpItemsUsed.closeTable = true;
                this.buttonDown = false;
                setTimeout(updateTables,TABLE_REFRESH_DELAY);
            }
        }else{ // not over close
            // if near a arrow and mouse button right is down delete the arrow
            if(this.closestArrowIndex > -1 && (this.mouse.button & 4) === 4){ // but field Only button right down
                this.arrows.splice(this.closestArrowIndex,1);
                this.closestArrowIndex = -1;
                this.mouse.button = 0;  // turn mouse click off
                helpItemsUsed.activeArrow = true; // flag arrow delete help as used
            
            }else  // if not near line or close then check for mouse left 
            if(this.mouse.button & 1){ // bit field  if down start dragging new arroe
                if(!this.dragging){ // Start of drag create arrow
                    this.arrows.push({
                        x: this.mouse.x,
                        y: this.mouse.y,
                        xx : this.mouse.x,
                        yy : this.mouse.y,
                    });
                    this.currentArrow = this.arrows[this.arrows.length-1];
                    this.dragging = true;
                    
                }else{   // during drag move arrow endpoint
                    helpItemsUsed.active = true; // flag arrow help as used
                    this.currentArrow.xx = this.mouse.x;
                    this.currentArrow.yy = this.mouse.y;
                }
            }else{ // mouse up
                if(this.dragging){ // is dragging then must be a arrow
                    // if arrow added is smaller than 2 pixels then remove it;
                    if(Math.abs(this.currentArrow.xx-this.currentArrow.x) < TABLE.arrow.minSize && Math.abs(this.currentArrow.y-this.currentArrow.yy) < TABLE.arrow.minSize){
                        this.arrows.length -= 1;
                    }
                    this.currentArrow = null;
                    this.dragging = false;
                }
            }
            this.cursor = TABLE.image.cursor; // set cursor tp table standard
        }
    }  
    if(this.closestArrowIndex > -1 && ! this.dragging){ // is mouse near arrow 
        this.cursor = TABLE.arrow.cursor;  // yes set cursor for arrow
     
    }
    // find arrow closest to mouse
    var minDist = TABLE.arrow.width; // this sets the max distance mouse can be for it to highlight an arrow
    var dist = 0;
    this.closestArrowIndex = -1;
    for(var i = 0; i < this.arrows.length; i++){ // test all arrow
        var a = this.arrows[i];
        drawArrow(ctx,a);  // draw the arrow
        a.highlight = false;  // turn off highlight
        dist = distFromLine(this.mouse.x,this.mouse.y,a.x,a.y,a.xx,a.yy); // get distance from mouse
        if(dist < minDist){  // is closer than any other arrow
            this.closestArrowIndex = i; // yes remember the index
            minDist = dist;
        }
    }
    if(this.closestArrowIndex > -1 && this.mouse.over){ // is a arror close to mouse
        this.arrows[this.closestArrowIndex].highlight = true; // highlight it
    }
    
    ctx.setTransform(1,0,0,1,0,0); // reset transform after arrows drawn
    // show help
    if(this.mouse.over){
        if(this.arrows.length === 0 && !helpItemsUsed.active){
            drawHelpText(ctx,TABLE.help.active,TABLE.image);
        }else
        if(this.closestArrowIndex > -1 && !helpItemsUsed.activeArrow){
            drawHelpText(ctx,TABLE.help.activeArrow,TABLE.image);
        }else
        if(this.closestArrowIndex === -1 && !helpItemsUsed.closeTable){
            drawHelpText(ctx,TABLE.help.closeTable,TABLE.image);
        }
    }
}else{
    this.drawEmpty();
}
}
// renders a table. Stops rendering if the mouse is not over
function tableUpdate(){
if(this.mouse.over){
    this.updating = true;
    requestAnimationFrame(this.update);
}else{
    this.buttonDown = false; // turn of button if dragged off
    this.div.style.cursor = "default";
    this.updating = false;
    this.draw(); // draw another time. This alows for the visual state to be correct
}
this.draw();    
this.div.style.cursor = this.cursor;
}
// Mousecallback starts a table rendering if not allready doing so.
function mouseInOutCallback(){
if(this.mouse.over){
    if(!this.updating){
        this.update();
    }
}else{
    this.div.style.cursor = "default";
}
}
// function to handle mouse events
function mouseEvent(e) {
var m =this; // lazy programer short cut
var t = e.type;
var bounds = m.element.getBoundingClientRect();
m.x = e.clientX - bounds.left;
m.y = e.clientY - bounds.top;
if (t === "mousedown") {
    m.button |= MOUSE.buttonMasks[e.which-1];
} else if (t === "mouseup") { 
    m.button &= MOUSE.buttonMasks[e.which + 2];
} else if (t === "mouseout") { 
    m.button = 0; 
    m.over = false;
    m.table.mouseOver();
} else if (t === "mouseover") { 
    m.over = true;
    m.table.mouseOver();
}
e.preventDefault();
}
// create the mouse inteface for a table
function createMouse(table){
var mouse = {
    x : 0,
    y : 0, 
    over : false,
    table : table,
    element : table.div,
    button : 0,
};
mouse.event = mouseEvent.bind(mouse);
mouse.start = function(){
    MOUSE.events.forEach( n => { this.element.addEventListener(n, this.event); } );
}
mouse.remove = function(){
    MOUSE.events.forEach( n => { this.element.removeEventListener(n, this.event); } );
}
return mouse;
}
function createAddTable(){ // Creates a table. Tables default in inactive
var table = {};
var div = document.createElement("div");
div.style.width =  TABLE.width+ "px";
div.style.height = TABLE.height + "px";
div.style.display = TABLE.DOM.display;
var canvas = document.createElement("canvas");
canvas.width = TABLE.width;
canvas.height = TABLE.height;
canvas.className = TABLE.DOM.tableClass
canvas.style.zIndex = TABLE.DOM.zIndex;
var ctx = canvas.getContext("2d");
table.div = div;
table.canvas = canvas;
table.ctx = ctx;
table.arrows = [];
table.width = TABLE.width;
table.height = TABLE.height;
table.mouseOverClose = false
table.drawCloseIcon = drawClose;
table.draw = drawTable;
table.dragging = false;
table.active = false;
table.update = tableUpdate.bind(table);
table.mouseOver = mouseInOutCallback;  // called by mouseEvent when mouse over out
table.drawEmpty = drawEmpty.bind(table);
table.dead = false; // when removed and not needed it is dead and can then be removed from table array
table.updating = false; // true is animation requests are happening
div.appendChild(canvas); // add canvas
table.mouse = createMouse(table);    
table.draw();
return table;
}
function removeTable(table){ // remove table from dom
table.mouse.remove();  // deactivate moue events
TABLE.tables.removeChild(table.div); // remove from DOM
table.dead = true;// flag as dead to be removed from table array
}
function addTable(){ // Adds a table to table array and DOM
var table = createAddTable();  // create new table
TABLE.tables.appendChild(table.div); // add to the dom
table.mouse.start();  // start the mouse
tableArray.push(table); // add to table array
return table;
}
function updateTables(){ // Updates tables. Removes any dead tables from table array
var closeTables = [];
closeTables = tableArray.filter(t => !t.active);
while(closeTables.length > 1){
    removeTable(closeTables.shift());
}
for(var i = 0; i < tableArray.length; i ++){
    if(tableArray[i].dead){
        tableArray.splice(i,1);
        i -= 1;
    }
}
}
addTable();
body {
    background-color: #982439;
}

#table {
    padding: 10px;
}

canvas {
	position: absolute;
}
<div id="tables">
</div>

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在画布上绘制一个简单的五角大楼

来自分类Dev

如何在画布元素上绘制视频?

来自分类Dev

在画布上绘制多个元素

来自分类Dev

如何在画布上创建一个悬停按钮?

来自分类Dev

如何在没有alpha堆栈的情况下在globalAlpha <1的画布上绘制多个元素?

来自分类Dev

Matplotlib:如何从轴上仅删除一个轮廓元素以及其他绘制的元素?

来自分类Dev

如何在一个图中绘制多个numpy数组?

来自分类Dev

如何在一个图中绘制多个线图

来自分类Dev

如何在一个图上绘制多个密度?

来自分类Dev

如何在画布绘制的元素上添加材质样式的阴影?

来自分类Dev

如何在画布绘制的元素上添加材质样式的阴影?

来自分类Dev

如何在多个画布HTML5上绘制圆?

来自分类Dev

如何在画布上绘制多个半透明矩形?

来自分类Dev

如何使用一个循环删除多个XML元素?

来自分类Dev

在最后一个画布上绘制线条

来自分类Dev

如何在不同的 html 元素上但在一个 jQuery 函数内触发多个事件

来自分类Dev

如何在 HTML 中的一个元素上使用多个样式规则?

来自分类Dev

如何在第一个和最后一个div上删除左边距和右边距

来自分类Dev

在多个画布上绘制的HTML5图像没有显示在其中一个图像上

来自分类Dev

如何在画布上的两个点之间绘制一条曲线?

来自分类Dev

如何在一个选择器jQuery中显示和隐藏多个元素?

来自分类Dev

如何使一个MutationObserver侦听多个元素上的更改?

来自分类Dev

如何在我的列表元素上添加一个按钮来删除 CRUD 应用程序的相应元素?

来自分类Dev

如何在一个轴上绘制一个区间

来自分类Dev

如何在同一个子域上启用 WordPress 安装和 Mediawiki 安装?

来自分类Dev

单击按钮后如何在画布中再添加一个元素?

来自分类Dev

如何在Fabric JS中的画布的一个角添加删除图标功能?

来自分类Dev

如何在包含多个画布的部分之后添加一个部分?

来自分类Dev

如何在Windows Phone 8应用程序中以编程方式从一个画布上获取客感以在另一个画布上设置

Related 相关文章

  1. 1

    如何在画布上绘制一个简单的五角大楼

  2. 2

    如何在画布元素上绘制视频?

  3. 3

    在画布上绘制多个元素

  4. 4

    如何在画布上创建一个悬停按钮?

  5. 5

    如何在没有alpha堆栈的情况下在globalAlpha <1的画布上绘制多个元素?

  6. 6

    Matplotlib:如何从轴上仅删除一个轮廓元素以及其他绘制的元素?

  7. 7

    如何在一个图中绘制多个numpy数组?

  8. 8

    如何在一个图中绘制多个线图

  9. 9

    如何在一个图上绘制多个密度?

  10. 10

    如何在画布绘制的元素上添加材质样式的阴影?

  11. 11

    如何在画布绘制的元素上添加材质样式的阴影?

  12. 12

    如何在多个画布HTML5上绘制圆?

  13. 13

    如何在画布上绘制多个半透明矩形?

  14. 14

    如何使用一个循环删除多个XML元素?

  15. 15

    在最后一个画布上绘制线条

  16. 16

    如何在不同的 html 元素上但在一个 jQuery 函数内触发多个事件

  17. 17

    如何在 HTML 中的一个元素上使用多个样式规则?

  18. 18

    如何在第一个和最后一个div上删除左边距和右边距

  19. 19

    在多个画布上绘制的HTML5图像没有显示在其中一个图像上

  20. 20

    如何在画布上的两个点之间绘制一条曲线?

  21. 21

    如何在一个选择器jQuery中显示和隐藏多个元素?

  22. 22

    如何使一个MutationObserver侦听多个元素上的更改?

  23. 23

    如何在我的列表元素上添加一个按钮来删除 CRUD 应用程序的相应元素?

  24. 24

    如何在一个轴上绘制一个区间

  25. 25

    如何在同一个子域上启用 WordPress 安装和 Mediawiki 安装?

  26. 26

    单击按钮后如何在画布中再添加一个元素?

  27. 27

    如何在Fabric JS中的画布的一个角添加删除图标功能?

  28. 28

    如何在包含多个画布的部分之后添加一个部分?

  29. 29

    如何在Windows Phone 8应用程序中以编程方式从一个画布上获取客感以在另一个画布上设置

热门标签

归档