Очистить кружок в библиотеке webgl - PullRequest
0 голосов
/ 18 июня 2020

Привет, я использую библиотеку javascript для своего веб-сайта. Библиотека использует webgl для создания анимации. Таким образом, он создает холст внутри элемента и показывает анимацию. Но я хочу, чтобы эта анимация выглядела как пончик. Я уже установил радиус границы 50% для элемента холста, и он генерирует круг, но мне нужно вырезать еще один прозрачный круг внутри холста. Вот изображение того, чего я хочу достичь. enter image description here

Я уже пробовал манипулировать элементами html, но пока безуспешно. Также я не могу использовать перекрывающийся элемент из-за фонового изображения за холстом.

Затем я попробовал переопределить библиотечную функцию, но я никогда ничего не делал в webgl, поэтому все прошло плохо. Я добавляю еще один метод, который применяется после обновления анимации. И я вырезал квадрат внутри холста, но без круга. Есть ли простой способ вырезать круг в webgl, который я могу поместить в свой метод drawEmptyCircle без каких-либо сложных правок в библиотеке?

    drawEmptyCircle: function(){
         gl.enable(gl.SCISSOR_TEST);
         gl.scissor(150, 150, 200, 200);
         gl.clearColor(0, 0, 0, 0);
         gl.clear(gl.COLOR_BUFFER_BIT);
         gl.disable(gl.SCISSOR_TEST);
     },

вот fiddle

Ответы [ 2 ]

1 голос
/ 20 июня 2020

Я думаю, вы не можете сделать отверстия в элементе Canvas.

Также я не могу использовать перекрывающийся элемент из-за фонового изображения за холстом.

Если можете контролировать абсолютные позиции всех элементов, это не будет проблемой.

В качестве примера я изменил ваш начальный jsfiddle.

Сначала разметка HTML. Класс outer используется для управления абсолютным положением внутренних элементов. Класс ontop создает круг над холстом для имитации прозрачности.

<div class="outer bg">
  <div class="circle"></div>
  <div class="ontop bg"></div>
</div>

В этом CSS все числа относятся к исходному размеру холста, который вы использовали в своем примере (500 пикселей x 500 пикселей). Я использовал поле для холста (20 пикселей), чтобы показать, что возможно более продвинутое положение.

.bg {
  background-image: url(-your-image-here-);
}
.ontop {
  background-position: -145px -145px;
  position: absolute;
  left: 145px;
  top: 145px;
  width: 250px;
  height: 250px;
  background-color: white;
  border-radius:50%;
}
.outer {
  position:relative;
  background-position: 0 0;
  width: 540px;
  height: 540px;
  padding: 20px;
}

Вот рабочий jsfiddle: click .

Чтобы сделать все остальные элементы (текст) видимыми, я должен использовать трюк с удвоением его HTML элементов. Вот пример с текстом, который находится на уровне фона (то есть ниже холста): щелкните .

1 голос
/ 19 июня 2020

Вы говорите, что никогда не использовали WebGL. Это говорит о том, что вам нужны несколько руководств , потому что как использовать WebGL не то, что можно объяснить одним ответом на переполнение стека.

Самый распространенный способ нарисовать круг с отверстием в нем. в WebGL - это создание треугольников, образующих круг с отверстием в нем. Это то, что делают все основные библиотеки 2D-графики с ускорением на GPU.

function makeCircleTriangles(innerRadius, outerRadius, divisions, start = 0, end = Math.PI * 2) {
  const positions = [];
  for (let d = 0; d <= divisions; ++d) {
    const u = d / divisions;
    const angle = start + (end - start) * u;
    const s = Math.sin(angle);
    const c = Math.cos(angle);
    positions.push(c * innerRadius, s * innerRadius);
    positions.push(c * outerRadius, s * outerRadius);
  }
  const indices = [];
  for (let d = 0; d < divisions; ++d) {
    const offset = d * 2;
    indices.push(offset + 0, offset + 1, offset + 2);
    indices.push(offset + 2, offset + 1, offset + 3);
  }
  return {position, indices};
}

const gl = document.querySelector('canvas').getContext('webgl');

const vs = `
attribute vec4 position;
uniform mat4 matrix;
void main() {
  gl_Position = matrix * position;
}
`;

const fs = `
precision highp float;
void main() {
  gl_FragColor = vec4(0, .6, 0, 1);
}
`;

// compile shaders, link progrma, look up locations
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);

const {positions, indices} = makeCircleTriangles(30, 70, 64);

// calls gl.createBuffer, gl.bindBuffer, gl.bufferData for each array
const bufferInfo = twgl.createBufferInfoFromArrays(gl, {
  position: { numComponents: 2, data: positions },
  indices,
});

gl.useProgram(programInfo.program);

// calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);

// calls gl.uniform
twgl.setUniforms(programInfo, {
  matrix: [
    2 / gl.canvas.clientWidth, 0, 0, 0,
    0, 2 / gl.canvas.clientHeight, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1,
  ],
});

gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);

function makeCircleTriangles(innerRadius, outerRadius, divisions, start = 0, end = Math.PI * 2) {
  const positions = [];
  for (let d = 0; d <= divisions; ++d) {
    const u = d / divisions;
    const angle = start + (end - start) * u;
    const s = Math.sin(angle);
    const c = Math.cos(angle);
    positions.push(c * innerRadius, s * innerRadius);
    positions.push(c * outerRadius, s * outerRadius);
  }
  const indices = [];
  for (let d = 0; d < divisions; ++d) {
    const offset = d * 2;
    indices.push(offset + 0, offset + 1, offset + 2);
    indices.push(offset + 2, offset + 1, offset + 3);
  }
  return {positions, indices};
}
<canvas></canvas>
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>

Второй наиболее распространенный способ - нарисовать четырехугольник (2 треугольника) с текстурой круга с отверстием в нем.

...