如何生成具有两个圆形边的细长六边形?

How to generate a elongated hexagon shape with two circular sides?

我正在尝试在我的设计中生成这种形状:

其中一个canvas元素出现在圆的中间部分,这种拉长的六边形出现在外面。

但是,我在形状方面遇到了一些问题 - 主要是我如何使用渐变或背景图像制作形状(即内部拼图看起来有点像图像)。外部背景将是纯色背景(#222)。

当前尝试

我目前的尝试是使用背景渐变来生成大部分形状,并为两侧的两个圆形部分使用伪元素::

var a = 100; // size of the black hole.
var b = 200; // distance of black hole from canvas center.
var c = 1; // speed of black hole rotation.
var d = 20; // the amount of stars to spawn every frame.

// ---------------------------------------------

var canvas = document.getElementById('c'),
  ctx = canvas.getContext('2d'),
  stars = [],
  m = {},
  r = 0

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

m.x = null;
m.y = null;

ctx.strokeStyle = '#fff';
ctx.translate(0.5, 0.5);

// create stars
function createStars(n) {

  if (m.x == null) return;

  for (var i = 0; i < n; i++) {
    var shape = {
      x: m.x,
      y: m.y,
      r: 1,
      speed: 1,
      accel: 1.01,
      accel2: 0.001,
      angle: Math.random() * 360
    }

    var vel = {
      x: a * Math.cos(shape.angle * Math.PI / 180),
      y: a * Math.sin(shape.angle * Math.PI / 180)
    };

    shape.x += vel.x;
    shape.y += vel.y;

    stars.push(shape);
  }
}

function render() {
  createStars(d);

  var bench = [];
  // ctx.save();
  // ctx.fillStyle = 'rgba(0,0,0,0.5)';
  // ctx.fillRect(0, 0, canvas.width, canvas.height);
  // ctx.restore();

  ctx.clearRect(0, 0, canvas.width, canvas.height);

  r += c;
  if (r < 360) {
    m = {
      x: canvas.width / 2,
      y: canvas.height / 2,
      angle: r
    }

    var targetAngle = m.angle * Math.PI / 180;

    m.x += b * Math.cos(targetAngle);
    m.y += b * Math.sin(targetAngle);
  } else {
    r = 0;
  }

  while (stars.length) {
    var star = stars.pop();

    var vel = {
      x: star.speed * Math.cos(star.angle * Math.PI / 180),
      y: star.speed * Math.sin(star.angle * Math.PI / 180)
    };

    ctx.beginPath();
    ctx.moveTo(star.x, star.y);
    ctx.lineTo(star.x + vel.x, star.y + vel.y);
    ctx.closePath();
    ctx.stroke();

    star.x += vel.x;
    star.y += vel.y;

    star.speed *= star.accel;

    star.accel += star.accel2;

    if (star.x < canvas.width && star.x > 0 && star.y < canvas.height && star.y > 0) {
      bench.push(star);
    }
  }

  stars = bench.slice(0).reverse();
}

window.requestAnimFrame = (function() {
  return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) {
    window.setTimeout(callback, 1000 / 60);
  };
})();

(function animloop() {
  requestAnimFrame(animloop);
  render();
})();
@import url(https://fonts.googleapis.com/css?family=Hammersmith+One);
 html {
   margin: 0;
   padding: 0;
   height: 100vh;
   background: #222;
   color: cornflowerblue;
   overflow-x: hidden;
   font-size: 18px;
   font-family: 'Hammersmith One', sans-serif;
 }
 /************************************/
 #c {
   height: 200px;
   width: 200px;
   border-radius: 50%;
   border: 5px double lightgray;
   margin-left: 150px;
   margin-right: 150px;
   background: #222;
   z-index: 10;
   position: absolute;
   left: 0px;
   top: 50px;
 }
 .canwrap {
   background: url(http://placekitten.com/g/300/300);
   height: 300px;
   width: 500px;
   position: relative;
   z-index: 0;
   margin-left: 50px;
   margin-right: 50px;
 }
 .canwrap:before {
   content: "";
   position: absolute;
   width: 150px;
   height: 100%;
   top: 0;
   left: 50%;
   transform: translateX(-50%);
   background: #222;
   z-index: -1;
 }
 .canwrap:after {
   content: "";
   position: absolute;
   height: 100px;
   width: 100px;
   top: 100px;
   left: -50px;
   background: red;
   border-radius: 50%;
   box-shadow: 500px 0 20px -5px red;
 }
<div class="canwrap">
  <canvas id="c" class="img"></canvas>
</div>

但是,这给我留下了一些问题:

我真的很感激能再 view/angle 构建这个形状,因为我无法以我需要的方式制作它。

我知道 svg 可能是做到这一点的方法,但与 css 相比,我一直很难让 svg 正确地制作动画 - 但如果任何一个工作,我会很高兴(看到因为我的设计不完全允许我的图像设计)!

一如既往,任何建议都会很棒。

虽然这不是针对 canvas 而是针对 html 元素,但您可以在 canvas 中执行相同的技术。 我假设你已经知道基本的 css 3,现在因为编码工作量很大,我会给你说明:

1) 前往 this link

2) 创建 2 个梯形并将它们旋转 90 度

3) 创建 2 个小圆圈并将每个小圆圈 (relative/absolute) 放置在梯形的边缘,z-index 小于梯形

4) 中间画 1 个圆圈,大功告成!

我用 svg 这样的东西怎么样 Fiddle

<svg width="1000" height="500">
  <polygon points="100 10, 50 245, 100 500, 200 500, 200 10,100 10" fill="orange" />
  <polygon points="400 10, 460 245, 400 500, 300 500, 300 10,200 10" fill="orange" />
  <circle r="50" cx="50" cy="245" fill="orange" />
  <circle r="50" cx="460" cy="245" fill="orange" />
  <circle r="100" cx="255" cy="245" fill="midnightblue" />
</svg>

你也可以用图片做背景

<svg width="1000" height="500">
     <defs>
    <pattern id="pattern" patternUnits="userSpaceOnUse" width="1000" height="1000">
        <image xlink:href="https://placekitten.com/g/200/300" x="-200" y="-10" width="1000" height="1000" />
    </pattern>
</defs>
    <polygon points="100 10, 50 245, 100 500, 200 500, 200 10,100 10" fill="url(#pattern)"/> 
         <polygon points="400 10, 460 245, 400 500, 300 500, 300 10,200 10" fill="url(#pattern)"/> 
    <circle r="50" cx="50" cy="245" fill="url(#pattern)"/>
     <circle r="50" cx="460" cy="245" fill="url(#pattern)"/>
    <circle r="100" cx="255" cy="245" fill="midnightblue"/>

你可以使用svg,它在很大程度上简化了形状的创建。

创建路径,填充图案

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" height="100%" width="100%" viewBox="0 0 65 50" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
    <pattern id="image" patternUnits="userSpaceOnUse" width="100" height="100">
        <image xlink:href="http://www.placecage.com/g/200/300" width="50" x="-10" y="0" height="50"/>
        <image xlink:href="http://www.placekitten.com/g/200/300" width="50" x="30" y="0" height="50"/>
    </pattern>
</defs>
<path d="M 25 0 H 15 L 10 20 A 5.3 5.3 0 1 0 10 30 L15 50 H25 z M 40 0 H 50 L 55 20 A 5.3 5.3 0 1 1 55 30 L 50 50 H 40 z" fill="url(#image)" stroke="none"/>
</svg>

高度和宽度已设置为 100%,因此这应该是响应式的。此外,可以使用 x,y 属性更改图像的位置。