【问题标题】:Mobile responsive design for complex process card复杂流程卡的移动响应式设计
【发布时间】:2021-08-23 01:52:06
【问题描述】:

该设计适用于基于 Angular 构建的网站。一直在使用 canvas 和 html 。 canvas 用于在 circle 周围构建虚线和实线箭头。 html用于设计圆圈。

HTML:

<div class="process-card-container">
  
  <div [style.margin-left.px]="canvasDivMargin" class="myCanvasDiv">
    <canvas id="myCanvas" width="2000" height="600">
      Your browser does not support the HTML5 canvas tag.</canvas>
  </div>

  <div class="all-cards">
    <div class="card-container" *ngFor="let card of data.cards;">
      <div (click)='onCTAClick(card.callToActions)'
        [ngClass]="{'each-process-card-without-pointer': card.callToActions == undefined, 'each-process-card' : card.callToActions !== undefined }"
        [ngStyle]="card.bgStyle">
        <div class="each-card-content-container">
          <span class="each-card-num">{{card.cardNumber}}</span>
          <span class="each-card-title">{{card.cardTitle}}</span>
        </div>
      </div>
    </div>
  </div>

</div>

SASS

.process-card-container {
  margin-top: 50px;
  margin-bottom: 20px;
  text-align: center;
  
}


.myCanvasDiv{
    padding-left: 0;
    padding-right: 0;
    margin-right: auto;
    display: block;
}

.card-container {
  display: inline-block;
  margin-right: 16px;
  margin-left: 75px;
}

.all-cards {
  margin-left: -8rem;
  margin-top: -553px;
}

.each-process-card {
  height: 250px;
  width: 250px;
  border-radius: 50%;
  text-align: center;
  cursor: pointer;
}

.each-process-card-without-pointer {
  height: 250px;
  width: 250px;
  border-radius: 50%;
  text-align: center;
}

.each-card-content-container {
  position: relative;
}

.each-card-num {
  position: absolute;
    color: #ffffff;
    font-size: 54px;
    top: 30px;
    left: 110px;
    padding-left: 0;
    padding-right: 0;
    margin-left: 0;
    margin-right: 0;
    display: block;
}

.each-card-title {
  font-size: 22px;
    font-family: "Metropolis", "Helvetica Neue", Helvetica, Arial, sans-serif;
    font-weight: bold;
    color: white;
    letter-spacing: 0.8px;
    width: 120px;
    position: absolute;
    top: 109px;
    left: 65px;
    height: 20px;
}

该设计在一个屏幕上运行良好,但在其他分辨率的屏幕上会中断,在放大/缩小时,箭头和圆圈会到处乱转。

TS 文件

import { Component, Input, OnInit } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-process-card',
  templateUrl: './process-card.component.html',
  styleUrls: ['./process-card.component.scss']
})
export class ProcessCardComponent implements OnInit {

  constructor(public router: Router) { }

  @Input()
  public data;

  public arrowColorArr = [];

  public dia = 170;
  public top_position = 180;
  public left_position = 180;
  public c;
  public ctx;

  public canvasDiv;
  public canvasDivMargin = 36;

 
  ngOnInit() {
    this.arrowColorArr = this.data.cards.map((cardIn) => {
      var eachBgColor = cardIn.bgStyle.background.includes("linear-gradient") ? cardIn.bgStyle.background.substring(35, 43) : cardIn.bgStyle.background;
      return eachBgColor.replace(/ /g, '')
    })
    
    this.c = document.getElementById('myCanvas');
    this.ctx = this.c.getContext("2d");

    this.ctx.setLineDash([0.5, 15]);
    this.ctx.lineWidth = 7;
    this.ctx.lineCap = "round";
    //1st down
    this.ctx.strokeStyle = this.arrowColorArr[1];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position, this.top_position + 4, this.dia, 0, 1 * Math.PI);
    this.ctx.stroke();

    //second circle up
    this.ctx.strokeStyle = "#0091da";
    this.ctx.strokeStyle = this.arrowColorArr[2];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 2), this.top_position, this.dia, 3.1, 2 * Math.PI);
    this.ctx.stroke();

    //3rd circle down
    this.ctx.strokeStyle = this.arrowColorArr[3];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 4), this.top_position, this.dia, 0, 1 * Math.PI);
    this.ctx.stroke();


    //4th circle up
    this.ctx.strokeStyle = this.arrowColorArr[2];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 6), this.top_position, this.dia, 3.15, 1.98 * Math.PI);
    this.ctx.stroke();

    this.ctx.lineWidth = 5;
    //1st up
    this.ctx.setLineDash([0, 0]);
    this.ctx.strokeStyle = this.arrowColorArr[0];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position, this.top_position, this.dia, 3.3, 1.8 * Math.PI);
    this.ctx.stroke();

    //2nd down
    this.ctx.strokeStyle = this.arrowColorArr[1];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 2), this.top_position, this.dia, 0.5, 0.9 * Math.PI);
    this.ctx.stroke();

    //3rd up
    this.ctx.strokeStyle = this.arrowColorArr[2];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 4), this.top_position, this.dia, 3.5, 1.8 * Math.PI);
    this.ctx.stroke();

    //4th down
    this.ctx.strokeStyle = this.arrowColorArr[3];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 6), this.top_position, this.dia, 0.1, 0.9 * Math.PI);
    this.ctx.stroke()

    //arrow mark 
    this.ctx.strokeStyle = this.arrowColorArr[0];

    this.ctx.beginPath();
    this.ctx.moveTo(330, 92);
    this.ctx.lineTo(327, 79);
    this.ctx.lineTo(317, 89);
    this.ctx.closePath();
    this.ctx.stroke();

    this.ctx.strokeStyle = this.arrowColorArr[1];
    this.ctx.beginPath();
    this.ctx.moveTo(677, 248);
    this.ctx.lineTo(678, 262);
    this.ctx.lineTo(667, 256);
    this.ctx.closePath();
    this.ctx.stroke();

    this.ctx.strokeStyle = this.arrowColorArr[2];
    this.ctx.beginPath();
    this.ctx.moveTo(1011, 90);
    this.ctx.lineTo(1007, 77);
    this.ctx.lineTo(997, 87);
    this.ctx.closePath();
    this.ctx.stroke();

    this.ctx.strokeStyle = this.arrowColorArr[3];
    this.ctx.beginPath();
    this.ctx.moveTo(1370, 183);
    this.ctx.lineTo(1375, 193);
    this.ctx.lineTo(1365, 193);
    this.ctx.closePath();
    this.ctx.stroke();
  }
}

【问题讨论】:

  • 我无法详细查看,但似乎有很多固定单位 (px) 尺寸在使用中。您是否考虑过将所有更改为仅使用相对单位。或者,可能更简单,您是否尝试过仅使用 CSS 和/或 CSS 加 SVG?
  • 您正在处理什么尺寸的屏幕(使布局正常的尺寸)?
  • @AHaworth 在 1920*1080 上运行良好。
  • 我认为最简单的方法是以适合您的尺寸绘制画布,然后将其(及其定位和 HTML 定位)缩放到当前视口。我会用一些代码把这个想法放在答案中。

标签: html css sass html5-canvas


【解决方案1】:

画布在视口尺寸 1920 x 1080 处绘制正常。

这个 sn-p(这是用于演示目的的 vanilla JS)绘制问题中代码中给出的画布,然后缩放它及其位置以适合当前视口。

  let arrowColorArr = ["red", "green", "blue", "grey"];

  const dia = 170;
  const top_position = 180;
  const left_position = 180;

 
 function OnInit() {
    // for vanilla JS demo only we need to set up the values
    this.arrowColorArr = arrowColorArr; 
    this.dia = dia;
    this.top_position = top_position;
    this.left_position = left_position;
    this.c = document.getElementById('myCanvas');
    
    //ADDED - RESTORE CANVAS TO INITIAL SCALE
    c.style.transform = "scale(1)";
    
    this.ctx = this.c.getContext("2d");
    this.ctx.clearRect(0, 0, 1920, 600); //ADDED
    
    this.ctx.setLineDash([0.5, 15]);
    this.ctx.lineWidth = 7;
    this.ctx.lineCap = "round";
    //1st down
    this.ctx.strokeStyle = this.arrowColorArr[1];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position, this.top_position + 4, this.dia, 0, 1 * Math.PI);
    this.ctx.stroke();

    //second circle up
    this.ctx.strokeStyle = "#0091da";
    this.ctx.strokeStyle = this.arrowColorArr[2];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 2), this.top_position, this.dia, 3.1, 2 * Math.PI);
    this.ctx.stroke();

    //3rd circle down
    this.ctx.strokeStyle = this.arrowColorArr[3];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 4), this.top_position, this.dia, 0, 1 * Math.PI);
    this.ctx.stroke();


    //4th circle up
    this.ctx.strokeStyle = this.arrowColorArr[2];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 6), this.top_position, this.dia, 3.15, 1.98 * Math.PI);
    this.ctx.stroke();

    this.ctx.lineWidth = 5;
    //1st up
    this.ctx.setLineDash([0, 0]);
    this.ctx.strokeStyle = this.arrowColorArr[0];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position, this.top_position, this.dia, 3.3, 1.8 * Math.PI);
    this.ctx.stroke();

    //2nd down
    this.ctx.strokeStyle = this.arrowColorArr[1];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 2), this.top_position, this.dia, 0.5, 0.9 * Math.PI);
    this.ctx.stroke();

    //3rd up
    this.ctx.strokeStyle = this.arrowColorArr[2];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 4), this.top_position, this.dia, 3.5, 1.8 * Math.PI);
    this.ctx.stroke();

    //4th down
    this.ctx.strokeStyle = this.arrowColorArr[3];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 6), this.top_position, this.dia, 0.1, 0.9 * Math.PI);
    this.ctx.stroke()

    //arrow mark 
    this.ctx.strokeStyle = this.arrowColorArr[0];

    this.ctx.beginPath();
    this.ctx.moveTo(330, 92);
    this.ctx.lineTo(327, 79);
    this.ctx.lineTo(317, 89);
    this.ctx.closePath();
    this.ctx.stroke();

    this.ctx.strokeStyle = this.arrowColorArr[1];
    this.ctx.beginPath();
    this.ctx.moveTo(677, 248);
    this.ctx.lineTo(678, 262);
    this.ctx.lineTo(667, 256);
    this.ctx.closePath();
    this.ctx.stroke();

    this.ctx.strokeStyle = this.arrowColorArr[2];
    this.ctx.beginPath();
    this.ctx.moveTo(1011, 90);
    this.ctx.lineTo(1007, 77);
    this.ctx.lineTo(997, 87);
    this.ctx.closePath();
    this.ctx.stroke();

    this.ctx.strokeStyle = this.arrowColorArr[3];
    this.ctx.beginPath();
    this.ctx.moveTo(1370, 183);
    this.ctx.lineTo(1375, 193);
    this.ctx.lineTo(1365, 193);
    this.ctx.closePath();
    this.ctx.stroke();
    //ADDED SO CANVAS SCALES TO WINDOW WIDTH
    const scale = window.innerWidth/1920;// 1920 because it draws the canvas OK at that viewport width
    c.style.transform = "scale(" + scale + ")";
    c.style.top = this.top_position * scale + "px";
    c.style.left = this.left_position * scale + "px";
  }
window.onload = OnInit;
window.onresize = OnInit;
* {
  margin: 0;
  padding: 0;
  }
canvas {
  position: relative;
  transform-origin: 0 0;
}
&lt;canvas id="myCanvas" width="1500" height="600"&gt;&lt;/canvas&gt;&lt;!-- was 2000 wide, reduced so doesn't cause X overflow when scaled --&gt;

插入这些更改后,您的画布绘图代码将变为:

<canvas id="myCanvas" width="1500" height="600"></canvas><!-- was 2000 wide, reduced so doesn't cause X overflow when scaled -->

TS 代码:

import { Component, Input, OnInit } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-process-card',
  templateUrl: './process-card.component.html',
  styleUrls: ['./process-card.component.scss']
})
export class ProcessCardComponent implements OnInit {

  constructor(public router: Router) { }

  @Input()
  public data;

  public arrowColorArr = [];

  public dia = 170;
  public top_position = 180;
  public left_position = 180;
  public c;
  public ctx;

  public canvasDiv;
  public canvasDivMargin = 36;

 
  ngOnInit() {
    this.arrowColorArr = this.data.cards.map((cardIn) => {
      var eachBgColor = cardIn.bgStyle.background.includes("linear-gradient") ? cardIn.bgStyle.background.substring(35, 43) : cardIn.bgStyle.background;
      return eachBgColor.replace(/ /g, '')
    })
    
    this.c = document.getElementById('myCanvas');

    
    //ADDED - RESTORE CANVAS TO INITIAL SCALE
    c.style.transform = "scale(1)";

    this.ctx = this.c.getContext("2d");
    // ADDED TO CLEAR THE CANVAS EACH TIME (ON A RESIZE E.G.)
    this.ctx.clearRect(0, 0, 1500, 600);

    this.ctx.setLineDash([0.5, 15]);
    this.ctx.lineWidth = 7;
    this.ctx.lineCap = "round";
    //1st down
    this.ctx.strokeStyle = this.arrowColorArr[1];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position, this.top_position + 4, this.dia, 0, 1 * Math.PI);
    this.ctx.stroke();

    //second circle up
    this.ctx.strokeStyle = "#0091da";
    this.ctx.strokeStyle = this.arrowColorArr[2];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 2), this.top_position, this.dia, 3.1, 2 * Math.PI);
    this.ctx.stroke();

    //3rd circle down
    this.ctx.strokeStyle = this.arrowColorArr[3];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 4), this.top_position, this.dia, 0, 1 * Math.PI);
    this.ctx.stroke();


    //4th circle up
    this.ctx.strokeStyle = this.arrowColorArr[2];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 6), this.top_position, this.dia, 3.15, 1.98 * Math.PI);
    this.ctx.stroke();

    this.ctx.lineWidth = 5;
    //1st up
    this.ctx.setLineDash([0, 0]);
    this.ctx.strokeStyle = this.arrowColorArr[0];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position, this.top_position, this.dia, 3.3, 1.8 * Math.PI);
    this.ctx.stroke();

    //2nd down
    this.ctx.strokeStyle = this.arrowColorArr[1];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 2), this.top_position, this.dia, 0.5, 0.9 * Math.PI);
    this.ctx.stroke();

    //3rd up
    this.ctx.strokeStyle = this.arrowColorArr[2];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 4), this.top_position, this.dia, 3.5, 1.8 * Math.PI);
    this.ctx.stroke();

    //4th down
    this.ctx.strokeStyle = this.arrowColorArr[3];
    this.ctx.beginPath();
    this.ctx.arc(this.left_position + (this.dia * 6), this.top_position, this.dia, 0.1, 0.9 * Math.PI);
    this.ctx.stroke()

    //arrow mark 
    this.ctx.strokeStyle = this.arrowColorArr[0];

    this.ctx.beginPath();
    this.ctx.moveTo(330, 92);
    this.ctx.lineTo(327, 79);
    this.ctx.lineTo(317, 89);
    this.ctx.closePath();
    this.ctx.stroke();

    this.ctx.strokeStyle = this.arrowColorArr[1];
    this.ctx.beginPath();
    this.ctx.moveTo(677, 248);
    this.ctx.lineTo(678, 262);
    this.ctx.lineTo(667, 256);
    this.ctx.closePath();
    this.ctx.stroke();

    this.ctx.strokeStyle = this.arrowColorArr[2];
    this.ctx.beginPath();
    this.ctx.moveTo(1011, 90);
    this.ctx.lineTo(1007, 77);
    this.ctx.lineTo(997, 87);
    this.ctx.closePath();
    this.ctx.stroke();

    this.ctx.strokeStyle = this.arrowColorArr[3];
    this.ctx.beginPath();
    this.ctx.moveTo(1370, 183);
    this.ctx.lineTo(1375, 193);
    this.ctx.lineTo(1365, 193);
    this.ctx.closePath();
    this.ctx.stroke();


    //ADDED SO CANVAS SCALES TO WINDOW WIDTH
    const scale = window.innerWidth/1920;// 1920 because it draws the canvas OK at that viewport width
    c.style.transform = "scale(" + scale + ")";
    c.style.top = this.top_position * scale + "px";
    c.style.left = this.left_position * scale + "px";
  }
}

您同样需要缩放 HTML 元素的大小和位置。如果您需要这方面的帮助,请告诉我。

记得添加任何需要的东西来在调整大小事件中重新计算画布。

【讨论】:

    【解决方案2】:

    您可以非常非常接近纯 HTML 和 CSS!我使用有序列表border-radiusborder-style 完成了这项工作,外加一个用于指针箭头的小SVG。这有几个优点:

    ##Edit - 请参阅下面的所有装饰元素都使用 SVG 的版本...

    • 更简单的代码
    • 使用浏览器的布局和渲染引擎
    • 语义正确的 HTML 和实时文本
    • 自动步骤编号
    • 根据列表位置自动着色
    • 能够根据需要调整大小/响应
    • 能够根据需要轻松添加/删除步骤

    缺点主要是您无法对像素位置、间距和点线等事物的样式进行绝对精细的控制。我认为这是对优势的相当合理的权衡,但这取决于您的情况。对我来说,结果如下所示:

    这是代码

    .disc-list {
      counter-reset: step; /* Allows us to show the step number */
      list-style: none;
      padding: 0;
      margin: 0;
      display: flex;
      flex-direction: row; /* Put the discs in a row */
      flex-wrap: wrap; /* Allow them to wrap around as required */
    }
    
    .disc-list li {
      counter-increment: step; /* Increment the list number */
      position: relative;
      width: 8.5rem;
      height: 8.5rem;
      text-align: center;
      border-radius: 50%; /* Make it a circle */
      background: #888;
      color: #888;
      display: flex;
      flex-shrink: 0; /* Don't allow the discs to squash inside the container */
      flex-direction: column;
      align-items: center;
      justify-content: center;
      margin: 1.5rem 1.25rem 1.5rem 1.5rem; /* Right margin is the normal width - the border-width */
      overflow: visible;
    }
    
    /* Setup the rainbow colours on the discs 
      - #00AFC0
      - #00A3E1
      - #27579C
      - #934FC0
      - #C04F8E
      - #C04F5D
      - #C07E4F
      - #C0B54F
    */
    
    .disc-list li:nth-child(1) {
      background: #00AFC0;
      color: #00AFC0;
    }
    
    .disc-list li:nth-child(2) {
      background: #00A3E1;
      color: #00A3E1;
    }
    
    .disc-list li:nth-child(3) {
      background: #27579C;
      color: #27579C;
    }
    
    .disc-list li:nth-child(4) {
      background: #934FC0;
      color: #934FC0;
    }
    
    .disc-list li:nth-child(5) {
      background: #C04F8E;
      color: #C04F8E;
    }
    
    .disc-list li:nth-child(6) {
      background: #C04F5D;
      color: #C04F5D;
    }
    
    .disc-list li:nth-child(7) {
      background: #C07E4F;
      color: #C07E4F;
    }
    
    .disc-list li:nth-child(8) {
      background: #C0B54F;
      color: #C0B54F;
    }
    
    /* The text inside the disc */
    .disc-list li span {
      color: #FFF;
      display: block;
      font-weight: bold;
      font-size: 0.8rem;
      max-width: 5rem;
      margin-left: auto;
      margin-right: auto;
    }
    
    /* The step number */
    .disc-list li span::before {
      content: counter(step);
      display: block;
      font-size: 1.65rem;
      margin-bottom: 0.1rem;
      font-weight: 200;
    }
    
    /* The pointer container */
    .disc-list li .pointer {
      position: absolute;
      right: -1.6rem;
      width: 1rem;
      height: 1rem;
    }
    
    /* The arrow-head itself */
    .disc-list li .pointer path {
     fill: none;
     stroke-linejoin: round;
     stroke-width: 3px;
     stroke: currentcolor; /* This allows the outline to inherit the text color automatically */
    }
    
    /* Move the arrow head into position depending if it's an odd/even disc */
    .disc-list li:nth-child(even) .pointer {
      bottom: 20%;
      transform: rotate(22.5deg);
    }
    
    .disc-list li:nth-child(odd) .pointer {
      top: 20%;
      transform: rotate(22.5deg);
    }
    
    .disc-list li::before,
    .disc-list li::after {
      content: '';  
      position: absolute;
      border: 0.25rem solid;
      left: -1.5rem; /* Same as the disc-list li margin */
      right: -1.5rem;
    }
    
    /* The dotted elements */
    .disc-list li:nth-child(even)::before {
      border-top-style: dotted;
      border-left-style: dotted;
      border-radius: 50%/100% 100% 0 0;
      border-bottom-color: transparent;
      top: -1.5rem;
      bottom: 50%;
    }
    
    .disc-list li:nth-child(odd)::before {
      border-bottom-style: dotted;
      border-right-style: dotted;
      border-top-color: transparent;
      border-radius: 50%/0 0 100% 100%;
      bottom: -1.5rem;
      top: 50%;
    }
    
    /* The solid line elements */
    .disc-list li:nth-child(odd)::after {
      transform-origin: bottom center;
      transform: rotate(22.5deg);
      border-width: 0.2rem;
      border-style: solid;
      border-color: transparent;
      border-top-color: inherit;
      border-left-color: inherit;
      border-radius: 50%/100% 100% 0 0;
      border-bottom-color: transparent;
      top: -1.5rem;
      bottom: 50%;
    }
    
    .disc-list li:nth-child(even)::after {
      transform-origin: top center;
      transform: rotate(22.5deg);
      border-style: solid;
      border-width: 0.2rem;
      border-color: transparent;
      border-bottom-color: inherit;
      border-right-color: inherit;
      border-radius: 50%/0 0 100% 100%;
      bottom: -1.5rem;
      top: 50%;
    }
    <ol class="disc-list">
      
      <li>
        <span>Login to Workday</span>
        <svg class="pointer">
          <path d="M6.25,1.25L11.25,11.25L1.25,11.25L6.25,1.25Z" />
        </svg>
      </li>
      <li>
        <span>Upload to Receipts</span>
        <svg class="pointer">
          <path d="M6.25,1.25L11.25,11.25L1.25,11.25L6.25,1.25Z" />
        </svg>
      </li>
      <li>
        <span>Submit Report</span>
        <svg class="pointer">
          <path d="M6.25,1.25L11.25,11.25L1.25,11.25L6.25,1.25Z" />
        </svg>
      </li>
      <li>
        <span>Get Reimbursed</span>
        <svg class="pointer">
          <path d="M6.25,1.25L11.25,11.25L1.25,11.25L6.25,1.25Z"/>
        </svg>
      </li> 
      <li>
        <span>Do a Dance</span>
        <svg class="pointer">
          <path d="M6.25,1.25L11.25,11.25L1.25,11.25L6.25,1.25Z"/>
        </svg>
      </li>
      <li>
        <span>Make Sandwiches</span>
        <svg class="pointer">
          <path d="M6.25,1.25L11.25,11.25L1.25,11.25L6.25,1.25Z"/>
        </svg>
      </li>
      <li>
        <span>Take a nap</span>
        <svg class="pointer">
          <path d="M6.25,1.25L11.25,11.25L1.25,11.25L6.25,1.25Z"/>
        </svg>
      </li>
      <li>
        <span>Go again!</span>
        <svg class="pointer">
          <path d="M6.25,1.25L11.25,11.25L1.25,11.25L6.25,1.25Z"/>
        </svg>
      </li>
      
    </ol>

    我相信您可以进一步微调它,并优化 CSS 以使其更整洁 - 不过,这应该是一个不错的起点。如果需要,请随时询问更多详细信息!

    SVG 版本

    这个版本对装饰元素使用内联 SVG,而不是边框​​样式。这应该会产生更一致的结果,并允许您微调破折号等内容。为了简洁起见,我用 SASS 重写了这个,SO 的代码 sn-p 不支持,所以这是在 CodePen 上:https://codepen.io/companionstudio/pen/BaWqBmm

    这不会改变包装/缩放要求,但如果您需要包装,我强烈建议您使用这样的基于 HTML 的解决方案。

    【讨论】:

    • 解决方案很棒,但是在放大弯曲箭头时会失去它的点,箭头会变形。对于我们的用例,即使在放大/缩小之后,我们也需要每个元素都是像素完美的。
    • 您考虑使用画布而不是 SVG 有什么原因吗?
    • @Laduanand 你能否定义更多你想要在放大/缩小时发生的事情,因为在你给定的代码中,画布可能会缩放但不是 HTML 元素,除非我误解了(这就是我没有在我的回答中没有继续扩展的想法)。
    • @BenHull 基本上所有元素都应该放大以适应宽度。随着您的回答,在放大时,弧线不会保留它们的破折号。只显示可以在屏幕宽度上完全显示的圆圈,其余圆圈应该转到下一行,就像我们在移动设备上一样,每行应该显示一个圆圈
    • 那么在狭窄的视口上画布会发生什么?什么阶段的视口太窄了?圆圈是否必须始终为 250 像素?这与扩展解决方案不同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    • 1970-01-01
    • 2012-07-14
    相关资源
    最近更新 更多