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

如何画一个只能在已显示区域进行事件绑定的三角形 #3

Open
vortesnail opened this issue Sep 24, 2019 · 5 comments
Open
Labels

Comments

@vortesnail
Copy link
Owner

如何画一个只能在已显示区域进行事件绑定的三角形

前言: 这个问题是去一家公司面试的时候,技术经理问到我的,我第一想法是用CSS中的border去画,但是我们现在的要求是在那个三角形区域,才能进行事件的绑定,比如:click事件,那border所用到的transparent仅仅是透明度为0,那个区域还是在的,这就无法完成特定区域的事件绑定。

1.先来试试border方法到底行不行吧!

Html:

<div className="triangle"></div>

Css:

.triangle {
  width: 0px;
  height: 0px;
  border-left: 50px solid yellow;
  border-right: 50px solid blue;
  border-top: 50px solid red;
  border-bottom: 50px solid black;
}

现在我们可以看到如下:
image.png
我们就选一个指向右边的箭头吧,修改Css样式:
Css:

.triangle {
  width: 0px;
  height: 0px;
  border-left: 50px solid yellow;
  border-right: 50px solid transparent;
  border-top: 50px solid transparent;
  border-bottom: 50px solid transparent;
}

现在我们得到了想要的三角形(具体形状自行调整border-size就行):
image.png

接下来,我们给这个 div 添加一个 onmouseover 事件:

const triangle = document.querySelector('.triangle');
triangle.addEventListener('mouseover', () => {
  console.log('你碰到我了!');
})

结果我们去测试的时候,不出所料地,透明的部分也会触发事件,如下所示:

1.gif

那可咋办呢??

2.换个思路,用遮罩!

这个思路很简单,但是面试官坐在面前的时候,却怎么也想不出来。。

step1: 我们先画三个矩形:

Html:

<div class="rectangle-1"></div>
<div class="rectangle-2"></div>
<div class="rectangle-3"></div>

Css:

.reactangle-container {
  position: relative;
}

.rectangle-mask1,
.rectangle-mask2 {
  width: 200px;
  height: 80px;
  position: absolute;
}

.rectangle-mask1 {
  top: 11px;
  left: -5px;
  transform: rotate(50deg);
  background-color: lightblue;
  z-index: 2;
}

.rectangle-mask2 {
  bottom: 11px;
  left: -5px;
  transform: rotate(-50deg);
  background-color: lightgreen;
  z-index: 2;
}

.rectangle-tri {
  width: 100px;
  height: 100px;
  background-color: lightcoral;
  z-index: 1;
}

得到如下图:
image.png
其中粉红的区域就是我们要的三角形区域,理论上你可以通过两个或许多个矩形构建出你想要的任何三角形!

step2: 进行绑定

那这个时候,我们怎么绑定事件到这个三角形上呢?
思路:rectangle-tri 这个矩形绑定事件,也给 rectangle-mask1 和 rectangle-mask2 绑定事件,但是不做操作,这样的话,因为rectangle-tri 在最下面,移动非三角形区域的时候,触发的事件监听是另外两个遮罩矩形的事件。

const reactangleContainer = document.querySelector('.reactangle-container');
const rectangleMask1 = reactangleContainer.querySelector('.rectangle-mask1');
const rectangleMask2 = reactangleContainer.querySelector('.rectangle-mask2');
const rectangleTri = reactangleContainer.querySelector('.rectangle-tri');

rectangleTri.addEventListener('mouseover', () => {
  console.log('你碰到我了!');
})

rectangleMask1.addEventListener('mouseover', () => {
	// 不做任何行为
})

rectangleMask2.addEventListener('mouseover', () => {
	// 不做任何行为
})

此时,特定的区域才有事件绑定了:
2.gif

现在,我们怎么把这两个遮罩矩形去掉呢????设置背景色为白色?那就是自欺欺人

step3: 只显示三角形

这里我真的还找不到方法啊,有哪位大佬能来说说吗???

3.用CSS3中的clip-path试试吧!

clip-path CSS 属性可以创建一个只有元素的部分区域可以显示的剪切区域。区域内的部分显示,区域外的隐藏。剪切区域是被引用内嵌的URL定义的路径或者外部svg的路径,或者作为一个形状例如circle().。clip-path属性代替了现在已经弃用的剪切 clip属性。

上看的引用出自MDN,我们只需要知道,这个属性可以让我们裁剪出想要的形状

基本形状裁剪:

.clip-me {
  clip-path: inset();
  clip-path: circle();
  clip-path: ellipse();
  clip-path: polygon();
}

其中inset是矩形的剪切,circle是圆形的剪切,ellipse是椭圆的剪切,polygon是多边形的剪切。对于我们想要把矩形剪切成三角形,应该使用polygon这个语法。
Html:

<div class="triangle"></div>

Css:

.triangle {
  width: 100px;
  height: 100px;
  background-color: lightcoral;
  clip-path: polygon(0px 0px, 0px 100px, 100px 50px);
}

clip-path: polygon(0px 0px, 0px 100px, 100px 50px); 这句话意思是,根据坐标轴上确定的三个点来进行裁剪:(0px, 0px),(0px 100px),(100px, 50px) ,这三个点构成了一个我们如下三角形:
image.png

现在我们可以来试试绑定事件好不好用来:

const tri = document.querySelector('.triangle');
tri.addEventListener('mouseover', () => {
  console.log("你碰到我了!");
})

以下为测试结果:
3.gif

我只能说,这个真是太好用了,不过这个属性兼容性会有些不好,酌情使用把!

@vortesnail vortesnail added the CSS label Sep 24, 2019
@SlahserZ
Copy link

SlahserZ commented Jun 6, 2022

wonderful!

@Linsanshu
Copy link

整挺好👍🏾

@Arisguy
Copy link

Arisguy commented Jun 19, 2022

听我朋友说他 面试的时候碰到过一个这样类似的机试题,然后给我说了 我也想半天想不出来, 长见识了

@Brandy2333
Copy link

牛!

@cucurbitboy
Copy link

长见识了

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

No branches or pull requests

6 participants