Today the designer gave me a problem, and I got it back

As a request recently, the designer drew a picture. Although the UI draft looks very simple, if it is realized by technical means, it cannot be brainless. cssThe picture is as follows

1.jpg

vue3The complete runnable code based on this component has been uploaded to Github , and an online

Let's call it a data funnel display card

  • Each card is a parallelogram, the left bevel of the first parallelogram is cut off, and the right bevel of the last parallelogram is cut off
  • The height of the latter parallelogram is the height of the former x%(ie the height is not fixed, it is related to the actual data)
  • The adjacent parallelograms are connected by a small suspended label element, which is also a parallelogram, and its inclination angle is the same as the inclination angle of the card. The position of the small label element on the x-axis is located in the middle of the front and rear parallelograms, y The axis is in the middle of the height of the next lower parallelogram
  • There is a fixed distance between adjacent parallelograms, and this distance is filled by an irregular polygon (used to visually connect two adjacent parallelograms smoothly), and the top closed line of this irregular polygon has a part It is an arc that just smoothly connects the upper right endpoint of the previous parallelogram with the upper left endpoint of the next parallelogram

Split it up, there are three kinds of graphics here:

  • Parallelogram (bevel front and rear can be cut off)

2.jpg

  • Floating small labels

3.jpg

  • Irregular arc top polygon

4.jpg

Parallelogram

There are many ways to implement parallelograms, here I use skewXthe way

<div class="parallelogram-wrapper">
  <div class="parallelogram-box"></div>
</div>
<style lang="less" scoped>
  .parallelogram-wrapper {
    width: 400px;
    height: 200px;
  }
  .parallelogram-box {
    height: 100%;
    border-radius: 4px;
    transform: skewX(-16deg);
    background: linear-gradient(263.65deg, rgb(142, 173, 255) 11.79%, rgb(194, 211, 255) 94.63%)
  }
</style>
复制代码

skewXThere is a feature that when you use skewXfor , the height of the resulting parallelogram is still equal to the height of the original rectangle, that is, the original rectangle heightis 400px, then skewXafter , the parallelogram is heightstill 400px, but relative to the original rectangle, the parallelogram is The occupied width has changed

例如对于本例,.parallelogram-box是一个 div元素,其默认宽度应该是和其父元素 .parallelogram-wrapper 宽度一样的,但实际上,作为平行四边形的 .parallelogram-box,在浏览器中查看其占据的宽度是 457.35px,长方形变形为平行四边形,按照正常的逻辑,变形后的平行四边形的宽度确实会变大,且是可计算的

5.jpg

上图,蓝色边长方形表示原长方形,红色边平行四边形表示原长方形经过 skewX 后得到的平行四边形

∠ACB是平行四边形的倾斜角度,平行四边形的宽度 = 长方形宽度 + AB

其中,AB = tan∠ACB * 长方形的高,本例中,∠ACB=16,长方形的高是 200,所以可得平行四边形的宽度是:平行四边形的宽度 = 400 + tan∠ACB * 200 = 457.35,与实际相符

一般情况下,设计稿上只会给你平行四边形的长和宽(毕竟设计稿不需要从长方形变形为平行四边形,不需要这一步),但是技术上实现得需要原长方形的宽高,既然能从长方形的宽高计算得到平行四边形的宽高,那么反过来当然也可以

例如,设计稿给定平行四边形的宽/高是 457.35px/200px,那么原长方形的高不变也是 200px,宽是 平行四边形的宽度 - AB,拿到了长方形的宽高之后,再 skewX一下,就得到和设计稿中一样的平行四边形了

如何将平行四边形的左边或右边的斜角切掉呢?

6.jpg

只需要给 .parallelogram-wrapper 加个 overflow: hidden;的属性,然后将 .parallelogram-box 向左平移 1/2 * AB 的距离,则得到左边斜角被切掉的图形;将 .parallelogram-box 向右平移 1/2 * AB 的距离,则得到右边斜角被切掉的图形

悬浮小标签

这是个平行四边形,所以还是用 skewX属性进行设置,其高度是固定的,但宽度跟随其内部文案的长度进行变动,想要找准其在x轴上位置,肯定是要得到其精确宽度的,这个用 js 测量一下就行了

7.jpg

o点是相邻两平行四边形中左边那个平行四边形的右下端点,设其坐标为(x1, y)p是右边那个平行四边形的左下端点,,设其坐标为(x2, y),根据上面一节的理论,这两个端点的位置都是可以计算得到的,那么op的中心点q的坐标也就可以得到了,设为 (x3, y),即 ((x1 + x2) / 2, y)

通过 js测量得到其宽度 width后,现在只需要将悬浮小标签的 left 属性设置为 x3 - width / 2,即可让此元素在水平方向上的中心点位于 x3了,至于其在 y轴上的位置(y3)也一样,这样一来就确定好了悬浮小标签的位置

但这个时候如果你仔细看的话,就会发现在 x轴上,悬浮小标签似乎并不是完美地位于相邻两个平行四边形的中间位置

8.jpg

实际上,其确实不在中间位置,上面的 x3 - width / 2x坐标值,如果是在 op这条线上,那么其实 op的中间点,但是由于悬浮小标签的参照物是左右两个平行四边形,平行四边形在 y方向上的边并不是完全与 y轴重合的,而是存在一定的倾角,那么随一旦悬浮小标签不在 op这条线上了,那么其中心点也就不再是 x3 - width / 2了,还需要在此基础上,再减掉偏移的距离,这段偏移距离 mn 也是可以计算出来的,即 mn = tan∠mqn * y3,其中 ∠mqn 也就是平行四边形的倾斜角度,是已知的

不规则圆弧顶多边形

9.jpg

可以将其看做是一个长方形内部的一个图形,即上图中粉红色长方形,这个长方形的长、宽以及四个端点的坐标都是可以确定的(与平行四边形端点相关),只需要让这个粉红长方形的 z-index 小于相邻两个平行四边形的 z-index,那么粉红长方形左右两块三角形就被遮掉了

10.jpg

现在还剩下顶部的那块圆弧要稍微复杂点,圆弧就是圆的一部分,肯定存在一个圆,其一部分(也就是扇形)遮在粉红长方形上,刚好可以形成一种粉红长方形被切掉一块扇形的结果,也就是我们想要的结果

假设这个圆的圆心位于k点,坐标是 (a, b)w点是左平行四边形右上端点,坐标为 (x4, y4)e是右平行四边形左上端点,坐标为 (x5, y5),这两个点坐标是可以计算得到的,圆的半径可以按照我们自己对弧度的要求进行主观调整,也就是我们可以自行决定,那么现在问题就转变为:已知圆的半径 R 和圆上两点的坐标,求圆心坐标

11.jpg

这是个数学问题,可以列出两个方程式:

(x4-a)^2 + (y4-b)^2 = R^2
(x5-a)^2 + (y5-b)^2 = R^2
复制代码

There are two unknowns in the two equations, so the equation can be solved, which can be obtained . If it is expressed by the function(a, b) , it is as follows:js

/**
 * 计算圆心坐标
 * @param x1 圆上一点的x坐标
 * @param y1 圆上一点的y坐标
 * @param x2 圆上另一点的x坐标
 * @param y2 圆上另一点的y坐标
 * @param r 圆半径
 */
const genCircleCenter = (x1: number, y1: number, x2: number, y2: number, r: number) => {
  const c1 = (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) / (2 * (x2 - x1))
  const c2 = (y2 - y1) / (x2 - x1)
  const A = c2 * c2 + 1
  const B = (2 * x1 * c2 - 2 * c1 * c2 - 2 * y1)
  const C = x1 * x1 - 2 * x1 * c1 + c1 * c1 + y1 * y1 - r * r
  // const y = (-B + Math.sqrt(B * B - 4 * A * C)) / (2 * A)
  const y = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A)
  return { x: c1 - c2 * y, y }
}
复制代码

In fact, two sets of solutions can be obtained from the above equation, corresponding to the two center coordinates. We can just take one of the solutions according to the actual situation.

summary

The implementation idea of ​​the component is not complicated, and the implementation steps are slightly cumbersome, but it can be completed step by step after spending more time.

At last……

ByteDance Live Streaming Realization and Qianchuan Team Recruitment~

Experience is not limited, there are pits in Beijing and Shanghai, and interested resumes can be sent to me at [email protected] to ensure timely feedback on the progress of the interview throughout the process, and to prevent the bad experience of throwing your resume into the sea

team introduction

Live Streaming Monetization and Qianchuan, responsible for optimizing ByteDance's live broadcast advertising and short video e-commerce advertising in China, responsible for the platform construction, algorithm optimization, advertising products and operational strategies of a huge amount of Qianchuan. The primary goal is to use the powerful algorithm engineering capabilities of Byte to give full play to the natural advantages of the live broadcast genre and the closed loop of e-commerce, and further increase the commercialization revenue in China.

The life service business relies on platforms such as Douyin and Douyin Express, and is committed to promoting the connection between users and local services;

In the past year, the life service business has created a brand-new video grass planting and transaction experience, allowing more users to discover good offline places through Douyin, and helping many local businesses expand new business positions.

We look forward to your joining, and we hope that you will be the next to participate in serving millions of merchants, influencing hundreds of millions of consumers, and leading the marketing revolution!

Team Advantage

  1. Technology: With business as the ultimate orientation, even as a R&D role, it can reach front-line customers and solve customer problems through technical solutions. The technical solutions involve recalling, rough sorting, fine sorting, bidding, and sorting in the advertising system In-depth and comprehensive understanding of the internal principles of each link of the advertising monetization system.

  2. Growth: Byte e-commerce GMV is still improving at a high speed. When meeting the purchase demand, short video and live broadcast genres have subversive advantages, and the business growth space is very large.

  3. Opportunities: The purchase experience of byte e-commerce is more diverse, including: products, videos, live streaming, celebrities, fan relations, live interaction, etc. Compared with traditional shelf-based e-commerce, the scope is larger and there are more opportunities for personal development .

Guess you like

Origin juejin.im/post/7101199648856997896