javascript - 在 Canvas 内点击按钮动态添加矩形

标签 javascript html canvas

function Shape(x, y, w, h, fill) {
  this.x = x || 0;
  this.y = y || 0;
  this.w = w || 1;
  this.h = h || 1;
  this.fill = fill || '#AAAAAA';
}

Shape.prototype.draw = function(ctx) {
  ctx.fillStyle = this.fill;
  ctx.fillRect(this.x, this.y, this.w, this.h);
}

Shape.prototype.contains = function(mx, my) {
  return  (this.x <= mx) && (this.x + this.w >= mx) &&
          (this.y <= my) && (this.y + this.h >= my);
}

function CanvasState(canvas) {
  
  this.canvas = canvas;
  this.width = canvas.width;
  this.height = canvas.height;
  this.ctx = canvas.getContext('2d');
  var stylePaddingLeft, stylePaddingTop, styleBorderLeft, styleBorderTop;
  if (document.defaultView && document.defaultView.getComputedStyle) {
    this.stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10)      || 0;
    this.stylePaddingTop  = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10)       || 0;
    this.styleBorderLeft  = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10)  || 0;
    this.styleBorderTop   = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10)   || 0;
  }
  var html = document.body.parentNode;
  this.htmlTop = html.offsetTop;
  this.htmlLeft = html.offsetLeft;

  
  this.valid = false; 
  this.shapes = [];  
  this.dragging = false; 
  this.selection = null;
  this.dragoffx = 0; 
  this.dragoffy = 0;
  
  var myState = this;
  
  canvas.addEventListener('selectstart', function(e) { e.preventDefault(); return false; }, false);
  canvas.addEventListener('mousedown', function(e) {
    var mouse = myState.getMouse(e);
    var mx = mouse.x;
    var my = mouse.y;
    var shapes = myState.shapes;
    var l = shapes.length;
    for (var i = l-1; i >= 0; i--) {
      if (shapes[i].contains(mx, my)) {
        var mySel = shapes[i];
        myState.dragoffx = mx - mySel.x;
        myState.dragoffy = my - mySel.y;
        myState.dragging = true;
        myState.selection = mySel;
        myState.valid = false;
        return;
      }
    }
    if (myState.selection) {
      myState.selection = null;
      myState.valid = false; 
    }
  }, true);
  canvas.addEventListener('mousemove', function(e) {
    if (myState.dragging){
      var mouse = myState.getMouse(e);
      myState.selection.x = mouse.x - myState.dragoffx;
      myState.selection.y = mouse.y - myState.dragoffy;   
      myState.valid = false; 
    }
  }, true);
  canvas.addEventListener('mouseup', function(e) {
    myState.dragging = false;
  }, true);
  canvas.addEventListener('dblclick', function(e) {
    var mouse = myState.getMouse(e);
    myState.addShape(new Shape(mouse.x - 10, mouse.y - 10, 20, 20, 'rgba(0,255,0,.6)'));
  }, true);
  
  
  this.selectionColor = '#CC0000';
  this.selectionWidth = 2;  
  this.interval = 30;
  setInterval(function() { myState.draw(); }, myState.interval);
}

CanvasState.prototype.addShape = function(shape) {
  this.shapes.push(shape);
  this.valid = false;
}

CanvasState.prototype.clear = function() {
  this.ctx.clearRect(0, 0, this.width, this.height);
}

CanvasState.prototype.draw = function() {
  if (!this.valid) {
    var ctx = this.ctx;
    var shapes = this.shapes;
    this.clear();
    
    var l = shapes.length;
    for (var i = 0; i < l; i++) {
      var shape = shapes[i];
      if (shape.x > this.width || shape.y > this.height ||
          shape.x + shape.w < 0 || shape.y + shape.h < 0) continue;
      shapes[i].draw(ctx);
    }
    
    if (this.selection != null) {
      ctx.strokeStyle = this.selectionColor;
      ctx.lineWidth = this.selectionWidth;
      var mySel = this.selection;
      ctx.strokeRect(mySel.x,mySel.y,mySel.w,mySel.h);
    }
    
    
    this.valid = true;
  }
}


CanvasState.prototype.getMouse = function(e) {
  var element = this.canvas, offsetX = 0, offsetY = 0, mx, my;
  
  if (element.offsetParent !== undefined) {
    do {
      offsetX += element.offsetLeft;
      offsetY += element.offsetTop;
    } while ((element = element.offsetParent));
  }

  offsetX += this.stylePaddingLeft + this.styleBorderLeft + this.htmlLeft;
  offsetY += this.stylePaddingTop + this.styleBorderTop + this.htmlTop;

  mx = e.pageX - offsetX;
  my = e.pageY - offsetY;
  
  return {x: mx, y: my};
}


function init() {
  var s = new CanvasState(document.getElementById('canvas1'));
  s.addShape(new Shape(40,40,50,50)); // The default is gray

}
<canvas id="canvas1" width="200" height="200" style="border:1px solid #000000;">
    This text is displayed if your browser does not support HTML5 Canvas.
   </canvas>
   
   <button onclick= "init()">click </button>

单击按钮后,我将创建一个矩形元素,可以将其拖放到 Canvas 元素限制区域内。 但是,是否可以在每次单击按钮时动态创建一个新的矩形元素,并可以进一步将其拖放到 Canvas 边界内。 并且之前的矩形元素不会丢失。

最佳答案

从头开始执行此操作将需要大量工作。我建议你使用像 fabric.js 这样的库其中包含您所要求的一切以及更多可提供的内容。这是demo page .

关于javascript - 在 Canvas 内点击按钮动态添加矩形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46961549/

相关文章:

javascript - 如何修改 Electron 浏览器窗口中使用的 HTML 文件?

javascript - Canvas 填充反射(reflect)在两个形状上

javascript - Chrome Canvas 渲染速度错误?

javascript - 错误代码 ELIFECYCLE,npm start 不起作用

javascript - html 5 nav 标签在 IE7 的 cakephp 中停止 ajax

html - 当我向右对齐 2 个链接时,水平滚动条变得可见

javascript - 如果数据相同,html 表跨度

javascript - 创建简单的游戏但 Canvas 上什么也没有显示

javascript - 如何改变:visited to its parent color on refresh of the page的颜色

java - 即使一个窗口仍然打开,如何强制删除cookie?