【问题标题】:CSS/Javascript: Mark clicked Shapes with small Rectangles on CornersCSS/Javascript:用角上的小矩形标记单击的形状
【发布时间】:2022-06-17 06:43:23
【问题描述】:

对于一个大学项目,我目前正在尝试做一种“选择”——绘制矩形、圆形、直线或三角形等形状的函数。

相应形状的“OnClick”事件应该不是问题。但目前我不知道如何以最佳方式处理选择的可视化。

如果用户选择了其中一种形状,则角落应显示小矩形,就像在 Microsoft Word 等中一样 - 最终结果应如下所示:

但我不知道如何更改所绘制形状的边框或边框角以在其末端显示小矩形。

你能帮帮我吗?

提前感谢您!

var draw_area = document.getElementById('draw_area');


function drawRect(){

  var object = draw_area.getContext('2d');
  object.beginPath();
  object.rect(50, 50, 100, 100);
  object.stroke();

};

function drawLine(){

  var object = draw_area.getContext('2d');
  object.beginPath();
  object.moveTo(230, 100);
  object.lineTo(330, 100);
  object.stroke();

};

function drawTriangle(){

  var object = draw_area.getContext('2d');
  object.beginPath();
  object.moveTo(420, 50);
  object.lineTo(470, 150);
  object.lineTo(370, 150);
  object.lineTo(420, 50);
  object.stroke();

};

function drawCircle(){

  var object = draw_area.getContext('2d');
  object.beginPath();
  object.arc(600, 100, 50, 0, 2 * Math.PI);
  object.stroke(); 

}

drawRect();
drawLine();
drawTriangle();
drawCircle();
#draw_area{
  background-color: lightgrey;
}
<div>
  <canvas id="draw_area" height="700", width="700"> </canvas>
</div>

【问题讨论】:

  • 你能告诉我们你是如何处理点击事件的吗?我看不出你在哪里“记住”你在画布上有什么物体,或者你把它们放在哪里,或者它们的尺寸是多少——放置这些小方块所需的信息。

标签: javascript html css


【解决方案1】:

我画了一个矩形的角:

class Program
{
    constructor(draw_area)
  {
    this.draw_area = draw_area;
    this.ctx = draw_area.getContext('2d');
    this.objects = [];
    
    draw_area.addEventListener('click', this.handleClick.bind(this), false);
  }
  
  draw()
  {
    this.ctx.clearRect(0, 0, 700, 700);
    this.objects.forEach((o) => o.draw());
  }
  
  drawRect(x, y, w, h)
  {
    this.objects.push(new Rectangle(this.ctx, x, y, w, h));
  }
    
  handleClick(event)
  {
    var x = event.pageX - this.draw_area.offsetLeft + this.draw_area.clientLeft;
    var y = event.pageY - this.draw_area.offsetTop + this.draw_area.clientTop;

    this.objects.forEach((o) => 
    {
        if (y > o.y && y < o.y + o.h && x > o.x && x < o.x + o.w) 
        {
            o.selected = !o.selected;
        }
    });
    
    this.draw();
  }
}

class Rectangle
{
    constructor(ctx, x, y, w, h)
  {
    this.ctx = ctx;
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.cornerSize = 10;
    this.selected = false;
  }
  
  draw()
  {
    
    this.ctx.beginPath();
    this.ctx.rect(this.x, this.y, this.w, this.h);
    this.ctx.closePath();
    this.ctx.stroke();
    
    if(!this.selected)
        return;
    
    this.ctx.beginPath();

    this.ctx.fillStyle = "#FFFFFF";
    this.ctx.strokeStyle = "#000000";


        
    // Corner rects
    this.ctx.rect(
      this.x - this.cornerSize / 2,
      this.y - this.cornerSize / 2,
      this.cornerSize, 
      this.cornerSize
    );

    this.ctx.rect(
      this.x + this.w - this.cornerSize / 2,
      this.y - this.cornerSize / 2,
      this.cornerSize, 
      this.cornerSize
    );

    this.ctx.rect(
      this.x + this.w - this.cornerSize / 2,
      this.y + this.h - this.cornerSize / 2,
      this.cornerSize, 
      this.cornerSize
    );

    this.ctx.rect(
      this.x - this.cornerSize / 2,
      this.y + this.h - this.cornerSize / 2,
      this.cornerSize, 
      this.cornerSize
    );

    this.ctx.closePath();
    this.ctx.fill();
    this.ctx.stroke();
  }
}

var draw_area = document.getElementById('draw_area');
let program = new Program(draw_area);

program.drawRect(50, 50, 100, 100);
program.drawRect(200, 50, 100, 100);
program.draw();
#draw_area{
  background-color: lightgrey;
}
<div>
  <canvas id="draw_area" height="700", width="700"> </canvas>
</div>

如果我们看一下drawRect函数:

function drawRect(x, y, w, h){
    const cornerSize = 10;
  var object = draw_area.getContext('2d');
  object.beginPath();
  object.rect(x, y, w, h);
  object.closePath();

  object.stroke();
  object.beginPath();
  
  object.fillStyle = "#FFFFFF";
  object.strokeStyle = "#000000";

  
  // Corner rects
  object.rect(
    x - cornerSize / 2,
    y - cornerSize / 2,
    cornerSize, 
    cornerSize
  );
  
  object.rect(
    x + w - cornerSize / 2,
    y - cornerSize / 2,
    cornerSize, 
    cornerSize
  );
  
  object.rect(
    x + w - cornerSize / 2,
    y + h - cornerSize / 2,
    cornerSize, 
    cornerSize
  );
  
  object.rect(
    x - cornerSize / 2,
    y + h - cornerSize / 2,
    cornerSize, 
    cornerSize
  );
  
  object.closePath();
  object.fill();
  object.stroke();

};

这些线用于首先绘制主矩形:

object.beginPath();
object.rect(x, y, w, h);
object.closePath();    
object.stroke();

这里调用 closePath 很重要,这样画布才能理解这个矩形是与角矩形分开的东西。

然后我们只需进行一些计算,然后在正确的位置绘制角矩形,如下所示:

// top-left corner
object.rect(
    x - cornerSize / 2,
    y - cornerSize / 2,
    cornerSize, 
    cornerSize
);

我们最后使用closePathfill 来应用顶部的着色规则:

object.fillStyle = "#FFFFFF";
object.strokeStyle = "#000000";

请注意,由于您使用的是纯画布而不是使用像 Fabric.js 这样的任何画布库,因此您将不得不手动完成所有操作。尽管即使使用库,您也可能不得不手动计算每个形状的小矩形位置。

【讨论】:

  • 哇 - 非常感谢!所以我真的需要自己绘制所选形状的每个小矩形吗? CSS 或 Javascript 中没有“border-corner”-选项来简单地添加自定义角?
  • 如何在不记住已绘制对象的情况下单击时绘制(和不绘制)角?
  • @Cptain_Whitebeard 不是真的没有。如果幸运的话,一些图书馆可能会想到这一点。 Canvas API 只为您提供在画布上绘制东西的非常基本的工具,其他一切都必须以这种或另一种方式构建。把它想象成一家笔店——它唯一的工作就是为您提供笔和纸,图纸在您身上,笔店不可能适应每个客户和情况,但是有了他们出售的笔,客户就是可以做任何他们需要的事情。
  • @AHaworth 帖子说点击和选择部分超出了这里的范围,所以我不在乎。您必须进行大量更改才能实现选择。
  • @AHaworth 为了好玩,我实现了一个简单的“选择”:jsfiddle.net/ahvonenj/u1bqh90v/22
猜你喜欢
  • 1970-01-01
  • 2016-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-07
  • 2014-10-05
  • 2014-07-28
  • 1970-01-01
相关资源
最近更新 更多