今日、デザイナーは私に問題を与えました、そして私はそれを取り戻しました

最近の要望で、デザイナーが絵を描きました。UIドラフトはとてもシンプルに見えますが、技術的な手段で実現すれば、頭がおかしくなることはありませんcss。絵は次のとおりです。

1.jpg

このコンポーネントにvue3基づく完全な実行可能なコードがGithubにアップロードされ、オンライン

それをデータファンネルディスプレイカードと呼びましょう

  • 各カードは平行四辺形であり、最初の平行四辺形の左斜角が切り取られ、最後の平行四辺形の右斜角が切り取られます
  • 後者の平行四辺形の高さは前者の高x%さです(つまり、高さは固定されておらず、実際のデータに関連しています)
  • 隣接する平行四辺形は、平行四辺形でもある小さな吊り下げられたラベル要素によって接続されており、その傾斜角度はカードの傾斜角度と同じです。x軸上の小さなラベル要素の位置は中央にあります。前部と後部の平行四辺形のy軸は、次に下の平行四辺形の高さの中央にあります
  • 隣接する平行四辺形の間には一定の距離があり、不規則な多角形(2つの隣接する平行四辺形を視覚的に接続するために使用)で埋められ、この不規則な多角形の上部の閉じた線には一部があります。右上の端点をスムーズに接続する円弧です。前の平行四辺形と次の平行四辺形の左上端の

分割すると、ここには3種類のグラフィックがあります。

  • 平行四辺形(斜角前後を切り落とすことができます)

2.jpg

  • フローティングの小さなラベル

3.jpg

  • 不規則なアークトップポリゴン

4.jpg

平行四辺形

平行四辺形を実装する方法はたくさんありますが、ここではその方法を使用skewXします

<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>
复制代码

skewX長方形に使用skewXする、結果の平行四辺形の高さは元の長方形の高さに等しい、つまり元の長方形height400pxskewXその後、平行四辺形はheightまだ元の長方形400pxに相対的であるという機能があります。長方形、平行四辺形は占有幅が変更されました

例如对于本例,.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
复制代码

2つの方程式には2つの未知数があるため、方程式を解くことができ、それを取得できます。関数(a, b)として表すと、次のようになります。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 }
}
复制代码

上記の方程式は、実際には2つの中心座標に対応する2セットの解を得ることができますが、実際の状況に応じて1つの解をとることができます。

まとめ

コンポーネントの実装のアイデアは複雑ではなく、実装手順は少し面倒ですが、より多くの時間を費やした後、段階的に完了することができます。

やっと……

ByteDanceライブストリーミングの実現とQianchuanチームの募集〜

経験は限られていません。北京と上海にはピットがあります。興味のある履歴書[email protected]に送信して、プロセス全体の面接の進捗状況に関するタイムリーなフィードバックを確保し、海に再開

チーム紹介

ライブストリーミング収益化とQianchuanは、中国でのByteDanceのライブブロードキャスト広告とショートビデオeコマース広告の最適化を担当し、プラットフォームの構築、アルゴリズムの最適化、広告製品、および大量のQianchuanの運用戦略を担当しています。主な目標は、Byteの強力なアルゴリズムエンジニアリング機能を使用して、ライブブロードキャストのジャンルと電子商取引の閉ループの自然な利点を十分に活用し、中国での商業化収益をさらに増やすことです。

ライフサービス事業は、DouyinやDouyin Expressなどのプラットフォームに依存しており、ユーザーとローカルサービス間の接続を促進することに取り組んでいます。

昨年、ライフサービス事業はまったく新しいビデオ草の植え付けと取引体験を生み出し、より多くのユーザーがDouyinを通じて良いオフラインの場所を発見できるようにし、多くの地元企業が新しい事業の地位を拡大するのを支援しました。

皆様のご参加をお待ちしております。次に、何百万もの商人にサービスを提供し、何億もの消費者に影響を与え、マーケティング革命をリードすることに参加していただければ幸いです。

チームアドバンテージ

  1. テクノロジー:ビジネスを究極の方向性として、R&Dの役割としても、技術的なソリューションを通じて最前線の顧客にリーチし、顧客の問題を解決することができます。技術的なソリューションには、リコール、大まかな並べ替え、細かい並べ替え、入札、広告システムでの並べ替えが含まれます。広告収益化システムの各リンクの内部原則の詳細かつ包括的な理解。

  2. 成長:バイトeコマースGMVは依然として高速で改善されています。購入需要を満たす場合、短いビデオとライブブロードキャストのジャンルには破壊的な利点があり、ビジネスの成長スペースは非常に大きくなります。

  3. 機会:バイトeコマースの購入体験は、製品、ビデオ、ライブストリーミング、有名人、ファンとの関係、ライブインタラクションなど、より多様です。従来のシェルフベースのeコマースと比較すると、範囲が広く、個人的な成長のためのより多くの機会。

おすすめ

転載: juejin.im/post/7101199648856997896