Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Day224:多种方式实现圆形可点击区域(至少三种) #1043

Open
Genzhen opened this issue Jan 20, 2021 · 2 comments
Open

Day224:多种方式实现圆形可点击区域(至少三种) #1043

Genzhen opened this issue Jan 20, 2021 · 2 comments
Labels
JavaScript teach_tag

Comments

@Genzhen
Copy link
Collaborator

Genzhen commented Jan 20, 2021

每日一题会在下午四点在交流群集中讨论,五点小程序中更新答案
欢迎大家在下方发表自己的优质见解
二维码加载失败可点击 小程序二维码

扫描下方二维码,收藏关注,及时获取答案以及详细解析,同时可解锁800+道前端面试题。


参考实现

  • 方式一:border-radius
<style>
  #circle {
    background: red;
    width: 100px;
    height: 100px;
    border-radius: 50%;
  }
</style>
<div id="circle"></div>
<script>
  document.querySelector("#circle").onclick = function () {
    alert("ok");
  };
</script>
  • 方式二:map + area
    • map 标签用来定义一个客户端图像映射(带有可点击区域的一副图像);
    • area 标签用来定义图像映射中的区域,area 元素永远嵌套在 map 元素内部;
<img src="xxxxx.png" usemap="#Map" />
<map name="Map" id="Map">
  <area
    shape="circle"
    coords="100,100,50"
    href="https://www.yidengxuetang.com/"
    rel="external nofollow"
    target="_blank"
  />
</map>

area 属性

  • shape:表示热点区域的形状,支持 rect(矩形),circle(圆形),poly(多边形)
  • coords:表示热点区域的坐标,(0,0)表示图片左上角。rect 四个值分别表示左上角坐标和右下角坐标。circle 三个值分别表示圆心坐标和半径。poly 有若干个值,每两个表示一个坐标点。
  • href:表示链接到某个地址,和<a>标签差不多
  • alt:对该区域描述,类似于<img>的 alt
  • 方式三: JS 实现,获取鼠标点击位置坐标,判断其到圆点的距离是否不大于圆的半径,来判断点击位置是否在圆内。
document.onclick = function (e) {
  let [x, y, r] = [100, 100, 100], // x,y 坐标原点,r半径
    x1 = e.clientX, // 获取x坐标
    y1 = e.clientY, // 获取y坐标
    dis = Math.abs(Math.sqrt(Math.pow(x - x1, 2) + Math.pow(y - y1, 2)));
  if (dis < r) {
    alert("ok");
  }
};
  • 方式四:canvas 实现

canvas 是 HTML5 提供的,用来在浏览器中创建图形,它可以通过 JavaScript 绘制 2D 图形。

因此我们可以通过用 canvas 在浏览器中绘制一个圆形,然后给这个圆形添加区域内点击事件即可实现。

<canvas id="drawing" width="400" height="400"></canvas>
<script>
  window.onload = () => {
    let drawing = document.querySelector("#drawing"),
      ctx = drawing.getContext("2d");
    circle = new Shape(100, 100, 50);
    circle.click = () => {
      alert("ok");
    };
    drawing.onmousedown = function (event) {
      let { clientX, clientY } = event || window.event,
        point = {
          x: clientX - drawing.offsetLeft,
          y: clientY - drawing.offsetTop,
        };
      circle.reDraw(point);
    };

    function Shape(x, y, r) {
      this.x = x;
      this.y = y;
      this.r = r;
      ctx.fillStyle = "red";
      ctx.beginPath();
      ctx.arc(this.x, this.y, this.r, 2 * Math.PI, false);
      ctx.closePath();
      ctx.fill();
    }
    Shape.prototype.reDraw = function (point) {
      ctx.fillStyle = "red";
      ctx.beginPath();
      ctx.arc(this.x, this.y, this.r, 2 * Math.PI, false);
      ctx.closePath();
      ctx.fill();
      //   判断点击是否在圆形区域内
      if (ctx.isPointInPath(point.x, point.y)) {
        this.click();
      }
    };
  };
</script>
@Genzhen Genzhen added the JavaScript teach_tag label Jan 20, 2021
@chensiguo
Copy link

clip-path 会不会更好呢, css 和 svg 都有

@Genzhen
Copy link
Collaborator Author

Genzhen commented Jan 25, 2021

clip-path 会不会更好呢, css 和 svg 都有

@chensiguo 也是可以的

  • 方式五:clip-path
<style>
  .circle {
    width: 10vw;
    height: 10vw;
    background: gray;
    clip-path: circle();
  }
</style>
<div class="circle"></div>
<script>
  document.querySelector(".circle").onclick = function () {
    alert("ok");
  };
</script>
  • 方式六:svg background
<style>
  .circle {
    width: 10vw;
    height: 10vw;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='50%25' cy='50%25' r='50%25' fill='gray'/%3E%3C/svg%3E");
  }
</style>
<div class="circle"></div>
<script>
  document.querySelector(".circle").onclick = function () {
    alert("ok");
  };
</script>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
JavaScript teach_tag
Projects
None yet
Development

No branches or pull requests

2 participants