webgl 库中的清除圆圈
Clear circle in webgl library
您好,我正在为我的网站使用 javascript 库。库使用 webgl 生成动画。所以它在元素内部创建了一个 canvas 并显示了动画。但我希望该动画看起来像一个甜甜圈。我已经在 canvas 元素上设置了 border-radius 50% 并且它生成了一个圆,但是我需要在 canvas 内切另一个透明圆。这是我想要实现的目标的图像。
我已经尝试操作 html 个元素,但到目前为止没有成功。此外,由于 canvas 后面的背景图像,我无法使用重叠元素。
接下来我尝试的是覆盖库函数,但我从来没有在 webgl 中做过任何事情,所以它很糟糕。我添加了另一种在动画更新后应用的方法。我在 canvas 内切了一个正方形,但没有成功切圆。有没有简单的方法,如何在 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
你说你从来没有做过任何WebGL。这表明您需要 some tutorials,因为如何使用 WebGL 无法在堆栈溢出的单个答案中解释。
在 WebGL 中绘制带孔圆的最常见方法是生成三角形,形成带孔圆。这就是所有主要的 GPU 加速 2D 图形库所做的。
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 个三角形),其纹理为带孔的圆形。
我认为你不能在 Canvas 元素上打洞。
Also i cant use overlaping element due to background image behind canvas.
如果你能控制所有元素的绝对位置,这就不是问题了。
例如,我更改了您的初始 jsfiddle。
首先是 HTML 标记。 outer
class 用于控制内部元素的绝对位置。 ontop
class 在 canvas 上方创建一个圆圈以模仿透明度。
<div class="outer bg">
<div class="circle"></div>
<div class="ontop bg"></div>
</div>
在此 CSS 中,所有数字都是相对于您在示例中使用的原始 canvas 大小 (500px x 500px)。我为 canvas (20px) 使用了一些边距,只是为了表明可能有一些更高级的位置。
.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 元素加倍。这是文本示例,它位于背景级别(因此低于 canvas):click.
您好,我正在为我的网站使用 javascript 库。库使用 webgl 生成动画。所以它在元素内部创建了一个 canvas 并显示了动画。但我希望该动画看起来像一个甜甜圈。我已经在 canvas 元素上设置了 border-radius 50% 并且它生成了一个圆,但是我需要在 canvas 内切另一个透明圆。这是我想要实现的目标的图像。
我已经尝试操作 html 个元素,但到目前为止没有成功。此外,由于 canvas 后面的背景图像,我无法使用重叠元素。
接下来我尝试的是覆盖库函数,但我从来没有在 webgl 中做过任何事情,所以它很糟糕。我添加了另一种在动画更新后应用的方法。我在 canvas 内切了一个正方形,但没有成功切圆。有没有简单的方法,如何在 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
你说你从来没有做过任何WebGL。这表明您需要 some tutorials,因为如何使用 WebGL 无法在堆栈溢出的单个答案中解释。
在 WebGL 中绘制带孔圆的最常见方法是生成三角形,形成带孔圆。这就是所有主要的 GPU 加速 2D 图形库所做的。
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 个三角形),其纹理为带孔的圆形。
我认为你不能在 Canvas 元素上打洞。
Also i cant use overlaping element due to background image behind canvas.
如果你能控制所有元素的绝对位置,这就不是问题了。
例如,我更改了您的初始 jsfiddle。
首先是 HTML 标记。 outer
class 用于控制内部元素的绝对位置。 ontop
class 在 canvas 上方创建一个圆圈以模仿透明度。
<div class="outer bg">
<div class="circle"></div>
<div class="ontop bg"></div>
</div>
在此 CSS 中,所有数字都是相对于您在示例中使用的原始 canvas 大小 (500px x 500px)。我为 canvas (20px) 使用了一些边距,只是为了表明可能有一些更高级的位置。
.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 元素加倍。这是文本示例,它位于背景级别(因此低于 canvas):click.