在网页内容下方的 HTML Canvas 上绘制线条

问题描述 投票:0回答:1

我正在开发一个项目,用于在网页内容下方的 HTML 画布上绘制线条。我的目标是实现与所附屏幕截图类似的结果。这是我到目前为止所做的:

let container = document.querySelector(".container");
let canvas = document.querySelector("canvas");

canvas.width = container.offsetWidth;
canvas.height = container.offsetHeight;

let ctx = canvas.getContext("2d");

let photo = document.querySelector(".photo");
let levels = document.querySelectorAll(".levels div");
let colors = getComputedStyle(document.documentElement);

levels.forEach((level, index) => {
  index++;
  ctx.beginPath();
  ctx.strokeStyle = colors.getPropertyValue(`--level-${index}`);
  ctx.moveTo(photo.offsetWidth + index * 10, photo.offsetTop + level.offsetTop - level.offsetHeight / 2);
  ctx.lineTo(photo.offsetWidth, photo.offsetTop + level.offsetTop - level.offsetHeight / 2);
  ctx.stroke();
});

let person = document.querySelector(".person");
let boxes = document.querySelectorAll(".box");
let total = boxes.length;
boxes.forEach((box, index) => {
  let dot = box.querySelector(".dot");
  index++;
  ctx.beginPath();
  ctx.strokeStyle = colors.getPropertyValue(`--level-${index}`);
  ctx.moveTo(person.offsetWidth + dot.offsetLeft + dot.offsetWidth, box.offsetTop - dot.offsetTop + dot.offsetHeight);
  ctx.lineTo(
    person.offsetWidth + dot.offsetLeft + dot.offsetWidth / 2 - total * 10,
    box.offsetTop - dot.offsetTop + dot.offsetHeight
  );
  ctx.stroke();
  total--;
});
:root {
  --level-1: #39a3aa;
  --level-2: #32a993;
  --level-3: #5cb793;
  --level-4: #dbb00c;
  --level-5: #d8750e;
  --level-6: #d4181c;
  --level-7: #b1111d;
}
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
body {
  font-family: "Roboto", sans-serif;
  font-weight: 400;
  font-style: normal;
  color: rgba(0, 0, 0, 0.87);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
.container {
  width: 1080px;
  height: 100%;
  margin: 0 auto;
  padding: 40px 0;
  display: flex;
  position: relative;
}
.person {
  flex-basis: 42%;
  display: flex;
  align-items: center;
}
.person .photo {
  width: 280px;
  height: 280px;
  position: relative;
}
.person .photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.person .photo .levels {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  position: absolute;
  top: 0;
}
.person .photo .levels [class^="level"] {
  flex: 1;
  opacity: 0.8;
}
.questions {
  flex-basis: 58%;
}
.questions .box {
  border: 1px solid;
  padding: 15px 10px;
  position: relative;
  margin-bottom: 24px;
}
.questions .box .dot {
  width: 10px;
  height: 10px;
  border-radius: 100%;
  position: absolute;
  top: 22px;
  left: -24px;
}
.questions .box .arrow {
  border-style: solid;
  border-width: 0 1px 1px 0;
  transform: rotate(45deg);
  padding: 12px;
  position: absolute;
  left: calc(50% - 6px);
  top: calc(100% - 12px);
  background-color: #fff;
}
.questions .box .question {
  margin-bottom: 5px;
}
.questions .box .question span {
  font-weight: 600;
}
.questions .box .answer input {
  padding: 6px 0;
  border: 0;
  outline: 0;
  width: 100%;
  font-family: inherit;
  font-size: inherit;
  position: relative;
  z-index: 1;
  color: inherit;
}
.questions .box .answer input::placeholder {
  color: #acacac;
}
canvas {
  position: absolute;
  z-index: -1;
}
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,600;&display=swap" rel="stylesheet" />

<div id="app">
  <div class="container">
    <div class="person">
      <div class="photo">
        <img src="headshot.jpeg" alt="" />
        <div class="levels">
          <div class="level-1" style="background-color: var(--level-1)"></div>
          <div class="level-2" style="background-color: var(--level-2)"></div>
          <div class="level-3" style="background-color: var(--level-3)"></div>
          <div class="level-4" style="background-color: var(--level-4)"></div>
          <div class="level-5" style="background-color: var(--level-5)"></div>
          <div class="level-6" style="background-color: var(--level-6)"></div>
          <div class="level-7" style="background-color: var(--level-7)"></div>
        </div>
      </div>
    </div>
    <div class="questions">
      <div class="box question-1" style="border-color: var(--level-1)">
        <div class="dot" style="background-color: var(--level-1)"></div>
        <p class="question">
          <span style="color: var(--level-1)">Level 1: </span>Lorem ipsum dolor sit amet, consectetur adipiscing elit?
        </p>
        <div class="answer">
          <input type="text" placeholder="Type your answer here and press Enter." />
        </div>
        <div class="arrow" style="border-color: var(--level-1)"></div>
      </div>

      <div class="box question-2" style="border-color: var(--level-2)">
        <div class="dot" style="background-color: var(--level-2)"></div>
        <p class="question">
          <span style="color: var(--level-2)">Level 2: </span>Lorem ipsum dolor sit amet, consectetur adipiscing elit?
        </p>
        <div class="answer">
          <input type="text" placeholder="Type your answer here and press Enter." />
        </div>
        <div class="arrow" style="border-color: var(--level-2)"></div>
      </div>

      <div class="box question-3" style="border-color: var(--level-3)">
        <div class="dot" style="background-color: var(--level-3)"></div>
        <p class="question">
          <span style="color: var(--level-3)">Level 3: </span>Lorem ipsum dolor sit amet, consectetur adipiscing elit?
        </p>
        <div class="answer">
          <input type="text" placeholder="Type your answer here and press Enter." />
        </div>
        <div class="arrow" style="border-color: var(--level-3)"></div>
      </div>

      <div class="box question-4" style="border-color: var(--level-4)">
        <div class="dot" style="background-color: var(--level-4)"></div>
        <p class="question">
          <span style="color: var(--level-4)">Level 4: </span>Lorem ipsum dolor sit amet, consectetur adipiscing elit?
        </p>
        <div class="answer">
          <input type="text" placeholder="Type your answer here and press Enter." />
        </div>
        <div class="arrow" style="border-color: var(--level-4)"></div>
      </div>

      <div class="box question-5" style="border-color: var(--level-5)">
        <div class="dot" style="background-color: var(--level-5)"></div>
        <p class="question">
          <span style="color: var(--level-5)">Level 5: </span>Lorem ipsum dolor sit amet, consectetur adipiscing elit?
        </p>
        <div class="answer">
          <input type="text" placeholder="Type your answer here and press Enter." />
        </div>
        <div class="arrow" style="border-color: var(--level-5)"></div>
      </div>

      <div class="box question-6" style="border-color: var(--level-6)">
        <div class="dot" style="background-color: var(--level-6)"></div>
        <p class="question">
          <span style="color: var(--level-6)">Level 6: </span>Lorem ipsum dolor sit amet, consectetur adipiscing elit?
        </p>
        <div class="answer">
          <input type="text" placeholder="Type your answer here and press Enter." />
        </div>
        <div class="arrow" style="border-color: var(--level-6)"></div>
      </div>

      <div class="box question-7" style="border-color: var(--level-7)">
        <div class="dot" style="background-color: var(--level-7)"></div>
        <p class="question">
          <span style="color: var(--level-7)">Level 7: </span>Lorem ipsum dolor sit amet, consectetur adipiscing elit?
        </p>
        <div class="answer">
          <input type="text" placeholder="Type your answer here and press Enter." />
        </div>
        <div class="arrow" style="border-color: var(--level-7)"></div>
      </div>
    </div>
    <canvas></canvas>
  </div>
</div>

但是,我很难让线条看起来正确。有人可以帮助我改进我的代码,使其达到我想要的效果吗?另外,如果有比在网页下使用画布更简单的方法来做到这一点,我愿意接受建议。

javascript canvas html5-canvas
1个回答
0
投票

我稍微调整了你的 JS 代码。请检查是否符合您的要求。

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,600;&display=swap"
      rel="stylesheet"
    />
    <style>
      :root {
        --level-1: #39a3aa;
        --level-2: #32a993;
        --level-3: #5cb793;
        --level-4: #dbb00c;
        --level-5: #d8750e;
        --level-6: #d4181c;
        --level-7: #b1111d;
      }
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      body {
        font-family: "Roboto", sans-serif;
        font-weight: 400;
        font-style: normal;
        color: rgba(0, 0, 0, 0.87);
        line-height: 1.5;
        -webkit-font-smoothing: antialiased;
      }
      .container {
        width: 1080px;
        height: 100%;
        margin: 0 auto;
        padding: 40px 0;
        display: flex;
        position: relative;
      }
      .person {
        flex-basis: 42%;
        display: flex;
        align-items: center;
      }
      .person .photo {
        width: 280px;
        height: 280px;
        position: relative;
      }
      .person .photo img {
        width: 100%;
        height: 100%;
        object-fit: cover;
      }
      .person .photo .levels {
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: column;
        position: absolute;
        top: 0;
      }
      .person .photo .levels [class^="level"] {
        flex: 1;
        opacity: 0.8;
      }
      .questions {
        flex-basis: 58%;
      }
      .questions .box {
        border: 1px solid;
        padding: 15px 10px;
        position: relative;
        margin-bottom: 24px;
      }
      .questions .box .dot {
        width: 10px;
        height: 10px;
        border-radius: 100%;
        position: absolute;
        top: 22px;
        left: -24px;
      }
      .questions .box .arrow {
        border-style: solid;
        border-width: 0 1px 1px 0;
        transform: rotate(45deg);
        padding: 12px;
        position: absolute;
        left: calc(50% - 6px);
        top: calc(100% - 12px);
        background-color: #fff;
      }
      .questions .box .question {
        margin-bottom: 5px;
      }
      .questions .box .question span {
        font-weight: 600;
      }
      .questions .box .answer input {
        padding: 6px 0;
        border: 0;
        outline: 0;
        width: 100%;
        font-family: inherit;
        font-size: inherit;
        position: relative;
        z-index: 1;
        color: inherit;
      }
      .questions .box .answer input::placeholder {
        color: #acacac;
      }
      canvas {
        position: absolute;
        z-index: -1;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="container">
        <div class="person">
          <div class="photo">
            <img src="headshot.jpeg" alt="" />
            <div class="levels">
              <div
                class="level-1"
                style="background-color: var(--level-1)"
              ></div>
              <div
                class="level-2"
                style="background-color: var(--level-2)"
              ></div>
              <div
                class="level-3"
                style="background-color: var(--level-3)"
              ></div>
              <div
                class="level-4"
                style="background-color: var(--level-4)"
              ></div>
              <div
                class="level-5"
                style="background-color: var(--level-5)"
              ></div>
              <div
                class="level-6"
                style="background-color: var(--level-6)"
              ></div>
              <div
                class="level-7"
                style="background-color: var(--level-7)"
              ></div>
            </div>
          </div>
        </div>
        <div class="questions">
          <div class="box question-1" style="border-color: var(--level-1)">
            <div class="dot" style="background-color: var(--level-1)"></div>
            <p class="question">
              <span style="color: var(--level-1)">Level 1: </span>Lorem ipsum
              dolor sit amet, consectetur adipiscing elit?
            </p>
            <div class="answer">
              <input
                type="text"
                placeholder="Type your answer here and press Enter."
              />
            </div>
            <div class="arrow" style="border-color: var(--level-1)"></div>
          </div>

          <div class="box question-2" style="border-color: var(--level-2)">
            <div class="dot" style="background-color: var(--level-2)"></div>
            <p class="question">
              <span style="color: var(--level-2)">Level 2: </span>Lorem ipsum
              dolor sit amet, consectetur adipiscing elit?
            </p>
            <div class="answer">
              <input
                type="text"
                placeholder="Type your answer here and press Enter."
              />
            </div>
            <div class="arrow" style="border-color: var(--level-2)"></div>
          </div>

          <div class="box question-3" style="border-color: var(--level-3)">
            <div class="dot" style="background-color: var(--level-3)"></div>
            <p class="question">
              <span style="color: var(--level-3)">Level 3: </span>Lorem ipsum
              dolor sit amet, consectetur adipiscing elit?
            </p>
            <div class="answer">
              <input
                type="text"
                placeholder="Type your answer here and press Enter."
              />
            </div>
            <div class="arrow" style="border-color: var(--level-3)"></div>
          </div>

          <div class="box question-4" style="border-color: var(--level-4)">
            <div class="dot" style="background-color: var(--level-4)"></div>
            <p class="question">
              <span style="color: var(--level-4)">Level 4: </span>Lorem ipsum
              dolor sit amet, consectetur adipiscing elit?
            </p>
            <div class="answer">
              <input
                type="text"
                placeholder="Type your answer here and press Enter."
              />
            </div>
            <div class="arrow" style="border-color: var(--level-4)"></div>
          </div>

          <div class="box question-5" style="border-color: var(--level-5)">
            <div class="dot" style="background-color: var(--level-5)"></div>
            <p class="question">
              <span style="color: var(--level-5)">Level 5: </span>Lorem ipsum
              dolor sit amet, consectetur adipiscing elit?
            </p>
            <div class="answer">
              <input
                type="text"
                placeholder="Type your answer here and press Enter."
              />
            </div>
            <div class="arrow" style="border-color: var(--level-5)"></div>
          </div>

          <div class="box question-6" style="border-color: var(--level-6)">
            <div class="dot" style="background-color: var(--level-6)"></div>
            <p class="question">
              <span style="color: var(--level-6)">Level 6: </span>Lorem ipsum
              dolor sit amet, consectetur adipiscing elit?
            </p>
            <div class="answer">
              <input
                type="text"
                placeholder="Type your answer here and press Enter."
              />
            </div>
            <div class="arrow" style="border-color: var(--level-6)"></div>
          </div>

          <div class="box question-7" style="border-color: var(--level-7)">
            <div class="dot" style="background-color: var(--level-7)"></div>
            <p class="question">
              <span style="color: var(--level-7)">Level 7: </span>Lorem ipsum
              dolor sit amet, consectetur adipiscing elit?
            </p>
            <div class="answer">
              <input
                type="text"
                placeholder="Type your answer here and press Enter."
              />
            </div>
            <div class="arrow" style="border-color: var(--level-7)"></div>
          </div>
        </div>
        <canvas></canvas>
      </div>
    </div>
  </body>
  <script type="text/javascript">
    let container = document.querySelector(".container");
    let canvas = document.querySelector("canvas");

    canvas.width = container.offsetWidth;
    canvas.height = container.offsetHeight;

    let ctx = canvas.getContext("2d");

    let photo = document.querySelector(".photo");
    let levels = document.querySelectorAll(".levels div");
    let colors = getComputedStyle(document.documentElement);

    levels.forEach((level, index) => {
      index++;
      ctx.beginPath();
      ctx.strokeStyle = colors.getPropertyValue(`--level-${index}`);
      ctx.moveTo(
        photo.offsetWidth + (index > 5 ? index - 2 * (index - 5) : index) * 15,
        photo.offsetTop + level.offsetTop - level.offsetHeight / 2
      );
      ctx.lineTo(
        photo.offsetWidth,
        photo.offsetTop + level.offsetTop - level.offsetHeight / 2
      );
      ctx.stroke();
    });

    let person = document.querySelector(".person");
    let boxes = document.querySelectorAll(".box");
    let total = boxes.length;
    boxes.forEach((box, index) => {
      let dot = box.querySelector(".dot");
      index++;
      ctx.beginPath();
      ctx.strokeStyle = colors.getPropertyValue(`--level-${index}`);
      ctx.moveTo(
        person.offsetWidth + dot.offsetLeft + dot.offsetWidth,
        box.offsetTop - dot.offsetTop + dot.offsetHeight
      );
      ctx.lineTo(
        photo.offsetWidth + (index > 5 ? index - 2 * (index - 5) : index) * 15,
        box.offsetTop - dot.offsetTop + dot.offsetHeight
      );
      ctx.lineTo(
        photo.offsetWidth + (index > 5 ? index - 2 * (index - 5) : index) * 15,
        photo.offsetTop +
          levels[index - 1].offsetTop -
          levels[index - 1].offsetHeight / 2
      );
      ctx.stroke();
      total--;
    });
  </script>
</html>

© www.soinside.com 2019 - 2024. All rights reserved.