我正在尝试为乒乓球运动图形编码。 我想让它为每个练习的集会展示一张桌子,上面有箭头,表示球的运动路径和可以玩的区域的矩形。
现在它看起来像这样: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);
}
答案 0 :(得分:2)
良好的界面设计
优质的界面不应该有丑陋的按钮,它应该直观且易于使用。应始终有反馈(光标,突出显示,翻转效果)。效果并不像节目那么多,而是提供用户与应用程序交互所需的信息。因此,FX不必是主要的,只需足以让用户看到一切正常,可点击的和不可点的。
我打算在没有帮助的情况下添加它,因为它应该有意义,但我已经添加了帮助,只是它没有。我们都有不同的界面使用方法。
更新:我添加了更多代码。现在只有在使用帮助功能之前才会显示帮助。一旦使用,帮助不会显示。
通过我认为需要它的代码添加注释(基本上无处不在)
<强>代码强>
表位于数组tableArray
中。使用addTable()
添加表,返回表对象。表默认为非活动table.active=false
。要激活,请单击表格上的鼠标或table.active = true; table.draw();
箭头在数组table.arrows
中作为{x:?,y?,xx:?,yy:?,highlight:false}
以删除使用阵列拼接或通过界面。要删除表,请将其停用table.active = false;
(或单击关闭),它将保留在DOM中,直到updateTables()
被调用。 (当用户点击关闭时,会自动调用点击更新)
总会有一个非活动表可见,可用于添加活动表。
数组中的每个表都包含完成所需操作所需的一切。 Mouseevent,渲染事件,关闭等
每个表都以全帧速率渲染(当它具有内部鼠标焦点时),因此您可以根据需要添加漂亮的动画。当鼠标未在表上时,除非您调用table.draw()
函数,否则不会更新。
代码有点乱,因为它有点失控。 Consts定义了大多数东西(代码顶部)。表,关闭图标和空表是预先渲染的。根据需要渲染箭头和帮助。
使用
单击空表以添加(激活)。单击活动表关闭图标以关闭。单击拖动以添加箭头,在近箭头处单击鼠标右键以删除。鼠标附近的箭头会突出显示。
注意表的数量没有限制。这不是一个好主意,你应该限制表的数量。当添加的表导致页面滚动条出现时,还会出现一些布局问题。删除表不会恢复到原来的状态。因为我不知道你想要什么,所以我把它留给了你。
还添加了
GLOBAL_SCALE
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>
答案 1 :(得分:0)
您的代码中使用静态ID的问题是错误的,您需要对表或div进行计数,然后您需要使用id传递该计数。
我解决这个问题检查代码:
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;
var top_level_div = document.getElementById('tables');
var count = top_level_div.getElementsByTagName('div').length;
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"+count;
}
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 top_level_div = document.getElementById('tables');
var count = top_level_div.getElementsByTagName('div').length;
//alert(count);
count = count-1;
var draw = document.getElementById('arrow1'+count).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);
}
&#13;
body {
background-color: #982439;
}
#table {
padding: 10px;
}
canvas {
position: absolute;
}
&#13;
<button onclick="addTable()">Add table</button>
<button onclick="removeTable()">Remove table</button>
<button onclick="drawArrow(42, 25, 186, 293)">Draw arrow</button>
<button onclick="drawArrow(41, 290, 186, 20)">Draw arrow2</button>
</br>
<div id="tables">
</div>
&#13;
希望此代码可以帮助您